Grails条件可空验证或具有可空选项的自定义验证程序

时间:2012-05-29 08:21:10

标签: grails grails-domain-class grails-2.0 grails-validation

我有一张表格可以创建一个地方。根据国家/地区,省(州,地区)字段是否需要。

当不需要时,我想要为空,而不是空字符串。我有代码,使所有空表单字段,null:

def newparams = [:]
        place = new Place()
        params.each() { k, v ->
            if (v instanceof String && place.hasProperty(k)) {
                if (!v.trim().length()) {
                    newparams[k] = null
                } else {
                    newparams[k] = v
                }
            }
        }

        place = new Place(newparams)
        place.validate()

现在,在地方域名中,我在该省有一个验证器:

province validator:  {val, obj -> if (obj.country in obj.requiresRegionCountries() && !obj.province) return [province.required]}

根据这条规则,即使是否需要,我也总是得到“省不能为空”。

我认为这是因为设置的可空验证器默认为false。

如果我添加nullable:true,那么即使省是必需的,也会跳过自定义验证器,并且可以使用空省保存(我认为这是因为它实例化为null)

现在,我需要以某种方式使用自定义验证器,并且还能够在我的验证器中指定可为空的内容,如下所示:

province validator:  {val, obj -> 
  if (obj.country in obj.requiresRegionCountries() && !obj.province) { 
    nullable: false
    return [province.required] }
  else {
    nullable: true
  }
}

如何在Grails 2.0.3中实现这一目标?

2 个答案:

答案 0 :(得分:12)

经过大量的研究和反馈,我发现了两种有效的解决方案。一个在控制器中。不要在模型中添加任何验证并从控制器动态添加它们:

class PlacesController {
  def create() {
  def place = new Place(params.address)
  if (place.country in placesThatRequiresProvinceArray) {
      place.constrains.province.nullable = false
  } else {
      place.constrains.province.nullable = true
  }

}

另一个解决方案是Tri在这个线程中提出的解决方案,但是将自定义验证器放在可以为空的约束之前(否则不会为空值调用自定义验证器):

static constraints = {
  province (validator: {val, obj ->
    if (obj.country == 'Canada' && !val)
      return ['province.required']
  }, nullable: true)
}

答案 1 :(得分:5)

我无法判断您粘贴的代码但是如果您的问题是默认验证不允许省为null,您是否尝试明确允许省为空?每个字段允许多个验证器。回到原始代码中,只需指定可空的验证器:

province nullable: true, validator:  {val, obj -> 
  if (obj != null && obj.country in obj.requiresRegionCountries() && !obj.province) 
    return [province.required]
}

编辑:  在自定义验证器中,可能还希望在if条件中防止obj为null。

EDIT2:演示项目,显示上述验证工作在grails 2.0.4

class Place {
String country
Province province

  static constraints = {
    province (nullable: true, validator: {val, obj ->
        if (obj.country == 'Canada' && !val) return ['province.required']
    })
  }
}

...控制器

 class MainController {
  def index() {
    def place = new Place(country: 'Canada')
    if (!place.validate()) {
        render "need province<br/>" + place.errors
    } else {
        render "cool"
    }

所以我的想法是我有一个虚拟控制器,我可以在其中调用索引操作,该操作是硬编码的,以创建类似于您的示例的Place域实例。请注意,我只定义了国家/地区字符串,因此我可以将其逻辑键入自定义验证。我在创建Place实例时没有定义省,所以它应该为null。在这种情况下,响应页面将打印以下内容......

输出摘录...

need province 
grails.validation.ValidationErrors: 1 .... does not pass custom validation]

如果我从Place中删除了nullable:true约束,那么错误就是预期的空值...

输出摘录...

need province
grails.validation.ValidationErrors: 1 .... cannot be null]