Q:

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.
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, i.e. a measurement belongs to a food, and a food has many measurements:
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?
Currently in my FoodEntry model I'm doing this:
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 ids are irrelevant):
NameError: undefined local variable or method `food' for FoodEntry (no database connection):Class

Using in: self.food.measurements in the validation made no difference. Help?

A:

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. 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.
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.
Note also, that validator object is attached to a class, not to a particular instance, so lambda needs to have record param.

