(快速参考)

约束用法

约束为 Grails 提供了用于定义验证规则、模式生成和 CRUD 生成元数据的声明性 DSL。例如,考虑以下约束

class User {
    ...

    static constraints = {
        login size: 5..15, blank: false, unique: true
        password size: 5..15, blank: false
        email email: true, blank: false
        age min: 18
    }
}

有关详细信息,请参阅有关约束的用户指南主题。

全局约束

你可以在 grails-app/conf/runtime.groovy 中全局应用约束,如下所示

grails.gorm.default.constraints = {
    '*'(nullable: true, size: 1..20)
}

通配符表示约束适用于所有属性。你还可以定义共享约束

grails.gorm.default.constraints = {
    myShared(nullable: true, size: 1..20)
}

可以在你的类中重用

class User {
    ...

    static constraints = {
        login(shared: "myShared")
    }
}

共享约束

全局约束是共享不同类(例如,域类和命令对象)之间约束的一种方法。这不再是唯一的方法。Grails 2 为 constraints 块引入了新语法,允许你直接从另一个类重用约束。

假设你有一个这样的域类

class User {
    String firstName
    String lastName
    String passwordHash

    static constraints = {
        firstName blank: false, nullable: false
        lastName blank: false, nullable: false
        passwordHash blank: false, nullable: false
    }
}

然后,你希望创建一个命令对象 UserCommand,它共享域类的部分属性和相应的约束。你可以使用 importFrom() 方法实现

class UserCommand {
    String firstName
    String lastName
    String password
    String confirmPassword

    static constraints = {
        importFrom User

        password blank: false, nullable: false
        confirmPassword blank: false, nullable: false
    }
}

这会从 User 域类中导入所有约束并将它们应用于 UserCommand。导入将忽略源类 (User) 中任何在导入类 (UserCommand) 中没有对应属性的约束。在上述情况下,只有 'firstName' 和 'lastName' 约束将导入到 UserCommand 中。

如果希望对导入哪些约束有更多控制,请使用 includeexclude 命名参数。这两个参数都接受一个列表,该列表包含在源约束中的属性名称匹配的简单字符串或正则表达式字符串。因此,例如,如果你只想导入 'lastName' 约束,则可以使用

...
static constraints = {
    importFrom User, include: ["lastName"]
    ...
}

或者,如果你想导入以 'Name' 结尾的所有约束

...
static constraints = {
    importFrom User, include: [/.*Name/]
    ...
}

当然,exclude 执行相反的操作,指定了不应导入的约束。

快速参考

约束 描述 示例

blank

验证一个字符串值不是空白的

login(blank:false)

creditCard

验证一个字符串值是不是一个有效的信用卡号

cardNumber(creditCard: true)

email

验证一个字符串值是不是一个有效的电子邮件地址。

homeEmail(email: true)

inList

验证一个值在一个范围或受约束值的集合中。

name(inList: ["Joe", "Fred", "Bob"])

matches

验证一个字符串值是不是与一个给定的正则表达式匹配。

login(matches: "[a-zA-Z]+")

max

验证一个值不超过给出的最大值。

age(max: new Date()) price(max: 999F)

maxSize

验证一个值的尺寸不超过给出的最大值。

children(maxSize: 25)

min

验证一个值不低于给出的最小值。

age(min: new Date()) price(min: 0F)

minSize

验证一个值的尺寸不低于给出的最小值。

children(minSize: 25)

notEqual

验证一个属性不等于指定的值

login(notEqual: "Bob")

nullable

允许一个属性设置为 null - 默认值为 false

age(nullable: true)

range

使用一个 Groovy 范围来确保一个属性的值发生在一个范围内

age(range: 18..65)

scale

设置为浮点数字的期望尺度(即,小数点右边的数字个数)。

salary(scale: 2)

size

使用一个 Groovy 范围来限制一个集合的尺寸或数字或一个字符串的长度。

children(size: 5..15)

unique

在数据库层将一个属性约束为唯一的

login(unique: true)

url

验证一个字符串值是不是一个有效的 URL 。

homePage(url: true)

validator

给一个字段加入自定义的验证。

参见文档

Scaffolding

一些约束在持久化方面没有影响,但是会对 scaffolding 进行自定义。在你的域中包含 UI 信息通常不是一个好习惯,不过如果你广泛使用了 Grails' scaffolding,它会带来很大的方便。

约束 描述

display

布尔值,决定一个属性是否在 scaffolding 视图中显示。如果为 true (默认值),则会显示该属性。

editable

布尔值,决定一个属性是否可以从 scaffolding 视图中编辑。如果为 false ,则关联的表单字段会以只读模式显示。

format

为可以接受一个值的类型(例如,日期)指定一个显示格式。例如, 'yyyy-MM-dd'。

password

布尔值,指示这个属性是不是应该用一个密码字段显示。只适用于那些通常使用一个文本字段显示的字段。

widget

控制使用什么小部件来显示该属性。例如,“textarea”将强制脚手架使用 <textArea> 标签。

以编程方式访问

你可以通过访问某个领域类别的 constrainedProperties 静态属性,在其他上下文中以编程方式访问一个领域的约束。该属性是 Map<String, ConstrainedProperty> 的一个实例。

class User {
    String firstName
    String middleName

    static constraints = {
        firstName blank: false, nullable: false
        middleName blank: true, nullable: true
    }
}

在上面的示例中,访问 User.constrainedProperties.firstName.blank 将得到 false,而 User.constrainedProperties.middleName.blank 将得到 true

指令对象

访问指令对象上的约束在某种程度上有所不同。你可以通过访问实现 Validateable 的类别的 constraintsMap 静态属性,在其他上下文中以编程方式访问一个指令对象的约束。该属性是 Map<String, ConstrainedProperty> 的一个实例。

class User implements Validateable {
    String firstName
    String middleName

    static constraints = {
        firstName blank: false, nullable: false
        middleName blank: true, nullable: true
    }
}

在上面的示例中,访问 User.constraintsMap.firstName.blank 将得到 false,而 User.constraintsMap.middleName.blank 将得到 true