2013-06-05 78 views
0

我有一个简单的问题。我需要管理域对象上的hasMany集合。我认为我做的是正确的,但没有奏效。我发现了另一篇文章,但它是非常过时和不工作(Handling parameters from dynamic form for one-to-many relationships in grails如何管理一对多关系 - grails

class User{ 
    static hasMany = ['prefs': Preference] 
} 
class Preference{ 
    Boolean email 
    Boolean site 
    Date dateCreated 
    Date lastUpdated 

} 

GSP

<g:each var="t" in="${user.prefs}" status="idx">    
    <li> 
    <input type='hidden' name="prefs[${idx}].id" value="${t.id}"/> 
    Email: <g:checkBox name="prefs[${idx}].email" value="${t.email}" /> 
    Site: <g:checkBox name="prefs[${idx}].site" value="${t.site}" />< 
    </li> 
</g:each> 

控制器:

log.info(user.prefs) 
user.properties = params 
if(!user.save()){ ... } 

然后它的错误了:

UserController - [首选项:3,首选项:4]

错误2013年6月4日21:54:41405 [HTTP-BIO-8080-EXEC-12] ERROR errors.GrailsExceptionResolver

IndexOutOfBoundsException异常发生处理时请求:[POST] /用户/首选项 - 参数: 首选项[0] .email:
ID:2个
偏好设定[1] .site:上
偏好设定[0] .email:上
_prefs [1] .site:
_prefs [1] .email:
prefs [1] .id:3
_prefs [0] .site:
p参考文献[0] .site:上
偏好设定[0] .ID:4
索引:1,尺寸:1.堆栈跟踪如下:
消息:索引:1,尺寸:1


+0

是否在设置属性后错误地保存用户?'user.prefs'的日志从不显示'id' 1和2.你能显示控制器代码和POST URL吗?顺便说一句,如果你担心某个特定顺序必须在gsp中显示,那么在'User'域中添加'List prefs'。将'prefs'作为项目添加到'User'的列表中维护索引。 – dmahapatro

+0

user.prefs的日志显示'UserController - [Preference:3,Preference:4]'恰好是分配的两个。它没有显示idx,它显示surroget键。 – Nix

+0

我们还可以看看控制器的动作吗? – dmahapatro

回答

0

所以我最终解决了这个问题,这是一个混合的方法。 @Meam是正确的,这是一个排序问题,但不用担心排序,我只是使用了@dmahapatro的方法,并将Preference设置为一个列表。关于此的一个附注是List preference的定义必须在static hasMany定义之前出现。或者当您尝试创建用户时,您会收到一个随机错误。最后,当您最初设置,您必须使用addTo的关系,把两者联系起来...

class User{ 
    List preference 
    static hasMany = ['prefs': Preference] 
} 

//another thing I did not know in order to originaly link 
//the two when using lists, you have to use addTo... 
user.addToPrefs(
    new Preference(email: true, site:false) 
) 

最后我想提的是存在<g:checkbox>一个错误,如果你喜欢我一个的hasMany用它的东西如果您尝试取消选中该值,它会无法正常工作。我能够通过应对来自github的代码FormTagLib解决它。然后更新代码与另一个职位,我读https://stackoverflow.com/a/2942667/256793有一个解决方案,但它有点过时。所以这是更新后的版本:

//old code 
//out << "<input type=\"hidden\" name=\"_${name}\"" 
//new... 
def begin = name.lastIndexOf('.') +1 
def tail = name.substring(begin); 
out << "<input type=\"hidden\" name=\"${name.replace( tail, "_" + tail )}\" " 
1

几天前我发现了这个问题。花了2天时间来修复它。

您必须确保params中的子索引与父对象的排序相同。在这种情况下,孩子的顺序是[首选项:3,首选项:4]。但params顺序是prefs [0] .id = 4,prefs [1] .id = 3。顺序不同。

我必须在绑定它们之前重新对params中的子索引进行重新排序。

+0

你是对的,必须有更好的方式来做到这一点。如果他们按照正确的顺序,我会成功,但如果他们没有成功,我会失败。它看起来像它的随机排序我updateDate。 – Nix