私の問題は次のとおりです。grails ドメイン インスタンスを作成し、それが持つ別のドメインの「多くの」インスタンスを定義したいと考えています。Google Code Projectに実際のソースがありますが、以下で問題を説明する必要があります。
class Person {
String name
static hasMany[skills:Skill]
static constraints = {
id (visible:false)
skills (nullable:false, blank:false)
}
}
class Skill {
String name
String description
static constraints = {
id (visible:false)
name (nullable:false, blank:false)
description (nullable:false, blank:false)
}
}
このモデルをdef scaffold
2 つのコントローラーで使用すると、このようなフォームは機能しません。
これを機能させるための私自身の試みは、スキルをチェックボックスとして列挙し、次のように表示します。
しかし、ボランティアを救うと、スキルが無効になります!
これは私の save メソッドのコードです。
def save = {
log.info "Saving: " + params.toString()
def skills = params.skills
log.info "Skills: " + skills
def volunteerInstance = new Volunteer(params)
log.info volunteerInstance
if (volunteerInstance.save(flush: true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'volunteer.label', default: 'Volunteer'), volunteerInstance.id])}"
redirect(action: "show", id: volunteerInstance.id)
log.info volunteerInstance
}
else {
render(view: "create", model: [volunteerInstance: volunteerInstance])
}
}
これは私のログ出力です (カスタムの toString() メソッドがあります)。
2010-05-10 21:06:41,494 [http-8080-3] INFO bumbumtrain.VolunteerController - Saving: ["skills":["1", "2"], "name":"Ian", "_skills":["", ""], "create":"Create", "action":"save", "controller":"volunteer"]
2010-05-10 21:06:41,495 [http-8080-3] INFO bumbumtrain.VolunteerController - Skills: [1, 2]
2010-05-10 21:06:41,508 [http-8080-3] INFO bumbumtrain.VolunteerController - Volunteer[ id: null | Name: Ian | Skills [Skill[ id: 1 | Name: Carpenter ] , Skill[ id: 2 | Name: Sound Engineer ] ]]
ログの最後の行では、適切なスキルが選択されており、オブジェクト インスタンスの一部であることに注意してください。ボランティアが保存されると、「スキル」は無視され、作成されたメモリ内バージョンには明らかにアイテムが含まれているにもかかわらず、データベースにコミットされません。建設時にスキルを渡すことはできませんか?これを回避する方法があるはずですか?個人が登録できる単一のフォームが必要ですが、後でスキルを追加できるようにデータを正規化したいと考えています。
これが「うまくいく」と思われる場合は、実際の例へのリンクが役立ちます。
HTML Select を使用すると、正常に動作します。次のような作成ページを作成します。
<tr class="prop">
<td valign="top" class="name">
<label for="skills"><g:message code="volunteer.skills.label" default="Skills" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: volunteerInstance, field: 'skills', 'errors')}">
<g:select name="skills" from="${uk.co.bumbumtrain.Skill.list()}" multiple="yes" optionKey="id" size="5" value="${volunteerInstance?.skills}" />
</td>
</tr>
しかし、このようなチェックボックスを操作するには必要です。
<tr class="prop">
<td valign="top" class="name">
<label for="skills"><g:message code="volunteer.skills.label" default="Skills" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: volunteerInstance, field: 'skills', 'errors')}">
<g:each in="${skillInstanceList}" status="i" var="skillInstance">
<label for="${skillInstance?.name}"><g:message code="${skillInstance?.name}.label" default="${skillInstance?.name}" /></label>
<g:checkBox name="skills" value="${skillInstance?.id.toString()}"/>
</g:each>
</td>
</tr>
ログ出力はまったく同じです。フォームの両方のスタイルで、Volunteer インスタンスは、'Skills' 変数で正しく参照されているスキルで作成されます。保存すると、この質問の上部に示されているように、後者は null 参照例外で失敗します。
これが理にかなっていることを願っています、事前に感謝します!
ガブ