2

来自 Rails 背景,我很高兴看到 Grails 2.0.x 支持表单的动态查找器Model.findOrSaveBy*Model.findOrCreateBy*. 但是,该功能受到极大的人为限制——根据文档,该方法接受n 个参数,其中n是方法调用中列出的属性的确切数量。例如:

class Car {
  String color
  String license

  static constraints = {
    license blank: false, unique: true
    color blank: false, inList: ["red", "black"]
  }
}

/* If there exists a Car(color: red, license: "ABCDEF") */

// WORKS
Car.findOrSaveByColor("red")  // will find the car
Car.findOrSaveByLicense("ABCDEF")  // will find the car
Car.findOrSaveByLicenseAndColor("UVWXYZ", "black")  // will persist a new car

// DOES NOT WORK
Car.findOrSaveByLicense("UVWXYZ")  // will fail because the color is not provided
Car.findOrSaveByLicense("UVWXYZ", color: "black")  // will fail due to an extra parameter
Car.findOrSaveByLicenseAndColor("ABCDEF", "black")  // will fail due to persisting a new instance because the color does not match, which then has a unique collision

我只关心通过唯一license值定位,但如果对象不存在,我需要用所有必需的属性填充它。Rails 允许您通过Hash参数来执行此操作,如下所示:

// Using findOrSaveBy* because Grails:"save"::Rails:"create" and "create" does not persist in Grails
Car.findOrSaveByLicense("ABCDEF", color: "red")  // will find a car with that license plate regardless of color or persist a new entry with the license and color "red"

这个功能没有在 Grails 中实现是有原因的吗?在我看来,这极大地限制了这些动态查找器的有用性。我想我可以methodMissing在域类中添加一个拦截调用并委托给类似的东西:

def car = Car.findByLicense("UVWXYZ") ?: new Car(license: "UVWXYZ", color: "red").save(flush: true)

但它似乎非常重复。有什么建议么?谢谢。

4

1 回答 1

1

根据您的示例,一个简单的解决方案是在您的域类中为颜色提供默认值:

class Car {
  String color = "red"
  String license

  static constraints = {
    license blank: false, unique: true
    color blank: false, inList: ["red", "black"]
  }
}

然后以下应该工作:

Car.findOrSaveByLicense("UVWXYZ")
于 2012-10-04T20:30:51.563 回答