5

我正在使用带有 mongodb 插件的 Grails 2.1.1。我在更改生成列表中的列顺序时遇到问题。正如grails 脚手架指南所说,您只需要在约束块中正确排序属性。

我的域名:

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[]))

知道如何更改它以获得我在约束中设置的工作顺序吗?

4

4 回答 4

3

应该填写一个 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>
<%  }   } %>
于 2012-12-27T21:37:47.717 回答
2

如果您在模板中注释下面的行并重新生成视图,则约束中的顺序将是脚手架中的顺序

//Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
于 2014-02-12T18:24:05.497 回答
0

如您所描述的,约束应该更新视图。尝试运行grails generate-all --stacktrace脚本可能在相应地更新视图之前终止。另一种策略是检查问题是否存在于以下陈述中,因此摆脱它们并检查视图是否相应更新可能会让您更接近解决问题。

static embedded = ['question']

List<Question> questions
static hasMany = [questions : Question]

希望这可以帮助!

于 2012-11-26T12:31:33.027 回答
0

经过一些测试,我确信只使用没有休眠插件的 mongodb 插件会导致禁用一些脚手架功能。例如,在生成视图期间省略了约束子句。要完成这项工作,您需要使用休眠。因此,如果您想拥有自动生成的代码并且仍然使用 mongodb,则有一个技巧:使用 hibernate 创建、生成和完成项目,然后在生产环境中卸载 hibernate 并安装 mongodb。

于 2012-12-05T12:06:27.617 回答