为什么Grails findOrSaveBy *动态查找器不接受创建的第二个参数?

时间:2012-09-25 22:46:12

标签: ruby-on-rails grails dynamic grails-2.0

来自Rails背景我很高兴看到Grails 2.0.x支持Model.findOrSaveBy*Model.findOrCreateBy*形式的动态查找器。但是,该功能极其人为限制 - 根据documentation,该方法接受 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 allows you to do this通过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)

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

1 个答案:

答案 0 :(得分:1)

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

class Car {
  String color = "red"
  String license

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

然后以下内容应该有效:

Car.findOrSaveByLicense("UVWXYZ")