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需要有記錄參數。