简体   繁体   English

验证Rails中的关联模型

[英]Validating associated models in Rails

I am currently working on a diet tracking app. 我目前正在研究饮食跟踪应用程序。 I have a FoodEntry model where each instance references a single food from another table, and also references a unit of measurement from yet another table. 我有一个FoodEntry模型,其中每个实例引用另一个表中的单个food ,并且还引用另一个表中的measurement单位。

class FoodEntry < ActiveRecord::Base
  belongs_to :food
  belongs_to :measurement
  validates :food, presence: { message: 'must exist' }
  ...
end

That works fine, but the thing is that each entry in the measurements table is set up (because I'm working with external data) to be associated with a certain food , ie a measurement belongs to a food, and a food has many measurements: 这很好,但问题是measurements表中的每个条目都已设置(因为我正在使用外部数据)与某种food相关联,即测量属于食物,食物有很多测量:

class Food < ActiveRecord::Base
  has_many :measurements
  ...
end

class Measurement < ActiveRecord::Base
  belongs_to :food
  ...
end

My question is, what is the correct way to validate that the specific measurement I'm referencing in a food_entry is also one of its food.measurements ? 我的问题是,验证我在food_entry引用的具体measurement也是其food.measurements measurement的正确方法是什么?

Currently in my FoodEntry model I'm doing this: 目前在我的FoodEntry模型中,我这样做:

validate :measurement_must_be_associated

def measurement_must_be_associated
  unless food.measurements.include? measure
    errors.add(:measurement, 'is not associated with that food')
  end
end

This custom validation works, but I'm not sure it's the cleanest way to do it. 这个自定义验证有效,但我不确定这是最干净的方法。

I attempted to do this instead: 我尝试这样做:

validates :measurement, inclusion: { in: food.measurements }

but this gives me an error when calling FoodEntry.new(food_id: 1, measurement_id: 1) in the rails console (actual id s are irrelevant): 但是当在rails控制台中调用FoodEntry.new(food_id: 1, measurement_id: 1)时,这会给我一个错误(实际id不相关):

NameError: undefined local variable or method `food' for FoodEntry (no database connection):Class

Using in: self.food.measurements in the validation made no difference. in: self.food.measurements在验证中没有区别。 Help? 救命?

Try: 尝试:

validates :measurement, inclusion: { in: ->(record) { record.food.measurements } }

validates is a method defined on a class, and is being evaluated when a class is declared. validates是在类上定义的方法,在声明类时进行评估。 Normally, when inclusion values are known before program starts (and are static), passing value is sufficient - validator (which is being created when validates is called) simply saves the passed object and uses it when validating. 通常,当包含值在程序启动之前已知(并且是静态的)时,传递值就足够了 - 验证器(在调用validates时创建)只是保存传递的对象并在验证时使用它。

In your case the inclusion values are unknown at the point when validator is created (and they also depends on the validating object). 在您的情况下,包含值在创建验证器时是未知的(并且它们还取决于验证对象)。 Hence, you need to pass a lambda, so validator can use it to get inclusion values during a runtime. 因此,您需要传递一个lambda,因此验证器可以使用它来在运行时获取包含值。

Note also, that validator object is attached to a class, not to a particular instance, so lambda needs to have record param. 另请注意,验证器对象附加到类,而不是特定实例,因此lambda需要具有记录参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM