我正在使用带有mongodb插件的Grails 2.1.1。我在生成列表中更改列的顺序时遇到问题。正如grails scaffolding guide所说,您只需要在约束块中正确排序属性。
我的域名:
class Section {
String idName
String visible
String required
String name
String bold
static embedded = ['question']
List<Question> questions
static hasMany = [questions : Question]
static constraints = {
idName (blank: false)
name (blank: false)
visible (blank: false)
required (blank: false)
bold (blank: false)
}
@Override
public String toString() {
name
}
}
但列仍按字母顺序排序。我正在使用静态脚手架,因此在更改约束后,我使用grails generate-all *
命令并覆盖所有文件。
是的,我尝试清理和编译代码,还清理并重启服务器(这与STS集成)并清理浏览器缓存。 mongo数据库有问题(hibernate插件是否已卸载)?
之后我还安装了grails模板。在list.gsp中有一行包含排序属性:
Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
我知道如何更改此项以获得我在约束中设置的工作顺序?
答案 0 :(得分:2)
应该填写一个jira问题。如果有人看 https://github.com/grails/grails-core/blob/master/grails-crud/src/main/groovy/org/codehaus/groovy/grails/scaffolding/DefaultGrailsTemplateGenerator.groovy
void generateView(GrailsDomainClass domainClass, String viewName, Writer out) {
def templateText = getTemplateText("${viewName}.gsp")
if (templateText) {
def t = engine.createTemplate(templateText)
def multiPart = domainClass.properties.find {it.type == ([] as Byte[]).class || it.type == ([] as byte[]).class}
boolean hasHibernate = pluginManager?.hasGrailsPlugin('hibernate')
def packageName = domainClass.packageName ? "<%@ page import=\"${domainClass.fullName}\" %>" : ""
def binding = [pluginManager: pluginManager,
packageName: packageName,
domainClass: domainClass,
multiPart: multiPart,
className: domainClass.shortName,
propertyName: getPropertyName(domainClass),
renderEditor: renderEditor,
comparator: hasHibernate ? DomainClassPropertyComparator : SimpleDomainClassPropertyComparator]
t.make(binding).writeTo(out)
}
}
很明显,调用生成视图决定使用SimpleDomainClassPropertyComparator。 Grails最初是为了依赖休眠而构建的。在过去几年中,世界一直在使用其他持久性机制。如果查看DomainClassPropertyComparator,则不依赖于hibernate。我觉得代码应该测试domainObject“hasConstraints”是否决定使用哪个比较器或默认使用DomainClassPropertyComparator。如果没有找到约束,它的行为是相同的。 DefaultGrailsTemplateGenerator不需要调用“hasHibernate”。
作为解决方法,您可以安装脚手架模板,编辑_form.gsp并将其使用的比较器更改为DomainClassPropertyComparator 例如我的_form.gsp
<%=packageName%>
<% import grails.persistence.Event %>
<% import org.codehaus.groovy.grails.scaffolding.DomainClassPropertyComparator %>
<% excludedProps = Event.allEvents.toList() << 'version' << 'dateCreated' << 'lastUpdated'
persistentPropNames = domainClass.persistentProperties*.name
boolean hasHibernate = pluginManager?.hasGrailsPlugin('hibernate')
if (hasHibernate && org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder.getMapping(domainClass)?.identity?.generator == 'assigned') {
persistentPropNames << domainClass.identifier.name
}
DomainClassPropertyComparator mattsComparator = new DomainClassPropertyComparator(domainClass)
comparator = mattsComparator
props = domainClass.properties.findAll { persistentPropNames.contains(it.name) && !excludedProps.contains(it.name) }
Collections.sort(props, comparator)
for (p in props) {
if (p.embedded) {
def embeddedPropNames = p.component.persistentProperties*.name
def embeddedProps = p.component.properties.findAll { embeddedPropNames.contains(it.name) && !excludedProps.contains(it.name) }
Collections.sort(embeddedProps, comparator)
%><fieldset class="embedded"><legend><g:message code="${domainClass.propertyName}.${p.name}.label" default="${p.naturalName}" /></legend><%
for (ep in p.component.properties) {
renderFieldForProperty(ep, p.component, "${p.name}.")
}
%></fieldset><%
} else {
renderFieldForProperty(p, domainClass)
}
}
private renderFieldForProperty(p, owningClass, prefix = "") {
boolean hasHibernate = pluginManager?.hasGrailsPlugin('hibernate')
boolean display = true
boolean required = false
if (hasHibernate) {
cp = owningClass.constrainedProperties[p.name]
display = (cp ? cp.display : true)
required = (cp ? !(cp.propertyType in [boolean, Boolean]) && !cp.nullable && (cp.propertyType != String || !cp.blank) : false)
}
if (display) { %>
<div class="fieldcontain \${hasErrors(bean: ${propertyName}, field: '${prefix}${p.name}', 'error')} ${required ? 'required' : ''}">
<label for="${prefix}${p.name}">
<g:message code="${domainClass.propertyName}.${prefix}${p.name}.label" default="${p.naturalName}" />
<% if (required) { %><span class="required-indicator">*</span><% } %>
</label>
${renderEditor(p)}
</div>
<% } } %>
答案 1 :(得分:2)
如果您在模板中注释下面的行并重新生成视图,则约束中的顺序将是脚手架中的顺序
//Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
答案 2 :(得分:0)
约束应该如您所述更新视图。尝试运行grails generate-all --stacktrace
在相应更新视图之前,脚本可能会终止。另一个策略是检查问题是否在下面的陈述中,因此删除它们并检查视图是否相应更新可能会使您更接近解决问题。
static embedded = ['question']
List<Question> questions
static hasMany = [questions : Question]
希望这有帮助!
答案 3 :(得分:0)
经过一些测试后,我确信只使用没有hibernate插件的mongodb插件会导致禁用一些脚手架功能。例如,在生成视图期间省略约束子句。要完成这项工作,您需要使用休眠。 因此,如果你想拥有自动生成的代码并仍然使用mongodb,那就有一个技巧: 使用hibernate创建,生成和完成项目,然后为生产卸载hibernate并安装mongodb。