2011-08-18 27 views
6

如果我有一個ActiveRecord模型如下Ruby類評價,validates_inclusion_of與動態數據

class Foo < ActiveRecord::Base 
    validates_inclusion_of :value, :in => self.allowed_types 

    def self.allowed_types 
    # some code that returns an enumerable 
    end 
end 

因爲allowed_types方法尚未在其中的驗證評估時定義該不工作。我所能想到的所有修復基本上都是圍繞着驗證移動方法定義,以便在需要時可用。我認爲這可能是一個比任何代碼風格問題更多的東西(我希望我所有的驗證都在模型頂部和底部),但是我覺得應該有一些解決方案,涉及初始模型加載的懶惰評估?

是我想要做甚至可能的嗎?我應該只是在驗證上面定義方法,還是有更好的驗證解決方案來達到我想要的效果。

+0

@eightbitraptor ...嘗試':在=> Foo.allowed_types',而不是':在=> self.allowed_types' ...東陽我想'self'將被引用對象'Foo'而不是'Foo' – rubyprince

回答

10

您應該能夠使用lambda語法達到此目的。也許是這樣的:

class Foo < ActiveRecord::Base 
    validates_inclusion_of :value, :in => lambda { |foo| foo.allowed_types } 

    def allowed_types 
    # some code that returns an enumerable 
    end 
end 

這樣它會評估每個驗證的lambda塊並將Foo的實例傳遞給塊。然後它將從該實例中的allowed_types中返回值,以便可以動態驗證它。

另請注意,我從allowed_types方法聲明中刪除了self.,因爲那樣會創建一個類方法,而不是您想要的實例方法。

+0

非常感謝,那正是我想要去的地方,只是沒有意識到將一個對象傳遞給lambda會傳遞正在驗證的對象。 – eightbitraptor

+0

我希望我能投票兩次。 – patrickmcgraw

+1

您可以使用':in => lambda(&:allowed_types)'來獲得更簡潔的語法。 – radiospiel

0

validates_inclusion_of方法的in選項似乎不接受lambda或Proc。這裏的另一種方法:

validates_each :product_id do |record, attrib, value| 
    begin 
    Product.find(value) 
    rescue ActiveRecord::ActiveRecordError 
    record.errors.add attrib, 'must be selected from list.' 
    end 
end