1

我目前正在研究饮食跟踪应用程序。我有一个FoodEntry模型,其中每个实例都引用另一个表中的单个food,并且还从另一个表中引用measurement单元。验证Rails中的关联模型

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

这工作正常,但问题是,在measurements表中的每个条目设置(因为我使用外部数据)将具有一定food相关,即测量属于食品和食物有许多测量:

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

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

我的问题是,什么是验证我引用一个food_entry具体measurement也是其food.measurements的一个正确的方法是什么?

目前在我的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 

这个自定义的验证工作,但我不知道它是做最彻底的方法。

我试图做到这一点,而不是:

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

但是这给我打电话的轨道控制台FoodEntry.new(food_id: 1, measurement_id: 1)当错误(实际id s为无关):

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

在使用in: self.food.measurements验证没有区别。帮帮我?

回答

3

尝试:

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

validates是上的类中定义的方法,并且当一个类被声明被评估。通常,如果在程序启动之前已知包含值(并且是静态的),那么传递值就足够了 - 验证程序(在调用validates时创建)只保存传递的对象并在验证时使用。

在你的情况下,包含值在创建验证器的时候是未知的(它们也取决于验证对象)。因此,您需要传递一个lambda表达式,以便验证器可以在运行时使用它来获取包含值。

另请注意,该验证器对象附加到类,而不是特定的实例,所以lambda需要有记录参数。