2012-09-30 28 views
3

我與以下納入驗證掙扎,Rails的包容驗證

class User < ActiveRecord::Base 
    attr_accessible :language 

    validates :language, :presence => true, :inclusion => { :in => I18n.available_locales.join(' ')} 
end 

如果我在控制檯運行此,

u = User.new 
u.valid? 

然後我在active_model/validations/inclusion.rbinclude?方法得到TypeError: can't convert nil into String

不過,如果我更改驗證線,

validates :language, :presence => true, :inclusion => { :in => %(en fr es)} 

然後驗證按預期工作。如果語言無論是否爲列表中的條目之一,並且沒有崩潰,則這是無效的。

我已經通過代碼來驗證它是否生成包含列表好吧,它是。那爲什麼它會崩潰?不應該存在驗證挑起問題並阻止任何進一步驗證?爲什麼當我生成列表而不是硬編碼值時會崩潰?

我甚至嘗試使用:in的proc形式來查看是否有任何區別,哪些沒有。但後來我並沒有真正期望這是需要的,因爲我只想在應用程序加載時只生成一次列表,因爲I18n.available_locales在應用程序執行過程中永遠不會改變。

更新: 我有一個想法,並測試了下面的代碼,

class User < ActiveRecord::Base 
    attr_accessible :language 

    validates :language, :presence => true, :inclusion => { :in => ['en','fr','es'].join(' ') } 
end 

此代碼也產生了同樣的錯誤,所以這個問題是不是與i18n或者類似的東西。它與%(en fr es)['en','fr','es'].join(' ')之間的差異有關。

回答

11

你的第二個條件的工作的原因是#include?是String類中定義:

> "qwertyuiop".include? "tyu" 
true 

因此,如果您驗證列入%(en fr es)(這正是"en fr es")的值"n f"將通過驗證。

您必須使用該數組(或者作爲文字[]或單詞%w())。如果你想使用I18n.available_locales務必將它們轉換爲字符串

validates :language, :inclusion => { :in => I18n.available_locales.map(&:to_s) } 

我無法重現你的錯誤,但是:presence驗證是沒用的,因爲:inclusion已檢查的值是列表。

4

您應該將數組傳遞給inclusion驗證,而不是字符串。所以在你的例子中%(en fr es)如果你使用%w(en fr es)它可以正常工作。