验证Rails中的关联模型

时间:2014-02-08 23:44:10

标签: ruby-on-rails validation activerecord ruby-on-rails-4 associations

我目前正在研究饮食跟踪应用程序。我有一个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没有任何区别。帮助

1 个答案:

答案 0 :(得分:3)

尝试:

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

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

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

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