我目前正在研究饮食跟踪应用程序。我有一个FoodEntry模型,其中每个实例引用另一个表中的单个food
,并且还引用另一个表中的measurement
单位。
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
我的问题是,验证measurement
中我引用的特定food_entry
是否也是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 }
但是在rails控制台中调用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
没有任何区别。帮助
答案 0 :(得分:3)
尝试:
validates :measurement, inclusion: { in: ->(record) { record.food.measurements } }
validates
是在类上定义的方法,在声明类时进行评估。通常,当包含值在程序启动之前已知(并且是静态的)时,传递值就足够了 - 验证器(在调用validates
时创建)只是保存传递的对象并在验证时使用它。
在您的情况下,包含值在创建验证器时未知(并且它们还取决于验证对象)。因此,您需要传递一个lambda,因此验证器可以在运行时使用它来获取包含值。
另请注意,验证器对象附加到类,而不是特定实例,因此lambda需要具有记录参数。