我所拥有的是一组用户和一组网络,这些用户需要在各种网络上拥有不同的电子邮件地址 - 一些是内部的,一些是外部的,一些是开发的,他们是所有人都有自己的命名和寻址方案。
到目前为止,我所做的是简化,删除了无关的代码:
class Network {
String name
static hasMany = [email: Email]
}
class User {
String login
static hasMany = [email: Email]
}
class Email {
string address
static belongsTo = [user: User, network: Network]
}
我正在苦苦挣扎,假设这是建立这种关系的正确方法,那就是如何解决给定用户和网络的电子邮件地址。例如,在用户创建页面中:
<g:each
in="${com.damascusgrp.dto.Network.findAll()}">
<div class="fieldcontain ${hasErrors(bean: userInstance, field: 'email', 'error')} required">
<label for="email">
${it.name}
<span class="required-indicator">*</span>
</label>
<g:field type="email" name="email" required="" value="${userInstance?.email}"/>
</div>
</g:each>
但我确定&#34;价值&#34;是不正确的,我只是无法绕过应有的东西。称之为Java阻止我在Groovy中正确思考。
或者,我完全错过了完全没有这种方法吗?我将此代码从单个电子邮件地址升级为User类的一部分,当我考虑制作一个居住在User中的HashMap时,我想先尝试一下。
- - - - - - - - 更新
我创建了一个空项目,只有上面列出的三个类,让Grails构建控制器&amp;让他们看到它会做什么。我从中修改过的内容如下所示:
<ul class="one-to-many">
<g:each in="${userInstance?.email?}" var="e">
<li><g:link controller="email" action="show" id="${e.id}">${e?.encodeAsHTML()}</g:link></li>
</g:each>
<li class="add">
<g:link controller="email" action="create" params="['user.id': userInstance?.id]">${message(code: 'default.add.label', args: [message(code: 'email.label', default: 'Email')])}</g:link>
</li>
</ul>
我基本上逐字逐句地从脚手架视图中将其折叠到我的代码中。我现在需要弄清楚如何隐藏&#34;来自电子邮件创建页面的用户字段,或者更好的是使用JQuery或类似的东西在一个页面上完成所有操作。或按照建议切换到地图。
------第二次更新-----
实例化是唯一剩下的问题。当我尝试实例化它并向其添加新的电子邮件时,我得到了一个NPE:
java.lang.NullPointerException: Cannot invoke method collectEntries() on null object
at com.damascusgrp.dto.User.getEmailsByNetwork(User.groovy:37)
at com.damascusgrp.dto.UserSpec.Fully constructed user is good(UserSpec.groovy:44)
我已经尝试了各种方法来预加载它,或者为每个已定义的网络设置空白条目,但还没有任何工作正常。这里是现在的代码,在Ian的帮助下。
class User {
String login
String password
String firstName
String lastName
String filePath
static hasMany = [requests:Request, email: Email]
static transients = ['emailsByNetwork']
def User(String l) {
login = l
}
def getName() {
"${firstName} ${lastName}"
}
String toString() {
login
}
static constraints = {
login blank:false, size:5..15, matches:/[\S]+/, unique:true
password blank:false, size:5..15, matches:/[\S]+/
firstName blank:false
lastName blank:false
filePath blank:false
}
Map getEmailsByNetwork() {
email.collectEntries { [(it.network.id), it] }
}
def addToEmail(Email em) {
email[em.network.id] = em
}
}
答案 0 :(得分:1)
您的示例GSP表明,每个User
的域模型都有Email
只有一个Network
- User
不能有两个Email
Network
同一User
上的对象。所以我要在class User {
String login
static hasMany = [email: Email]
Map getEmailsByNetwork() {
(email?.collectEntries { [it.network.id, it] }) ?: [:]
}
static transients = ['emailsByNetwork']
}
域类
user.emailsByNetwork
现在Network
将是从Email
ID到<g:set var="emailsByNet" value="${userInstance.emailsByNetwork}" />
<g:each var="net"
in="${com.damascusgrp.dto.Network.findAll()}">
<div class="fieldcontain ${hasErrors(bean: emailsByNet[net.id], field: 'email', 'error')} required">
<label for="net_${net.id}_email">
${net.name}
<span class="required-indicator">*</span>
</label>
<g:field type="email" name="net_${net.id}_email" required="" value="${emailsByNet[net.id]?.email}"/>
</div>
</g:each>
的地图,在GSP中你可以说
params.net_1_email
在收到此表单帖子的控制器中,您必须相应地处理各种emailsByNetwork[n]
等,如果存在则更新现有userInstance.addToEmail(new Email(network:Network.load(n), email:value))
或如果不存在则更新{{1}}。