我正在努力进行以下包含验证,
class User < ActiveRecord::Base
attr_accessible :language
validates :language, :presence => true, :inclusion => { :in => I18n.available_locales.join(' ')}
end
如果我在控制台中运行这个,
u = User.new
u.valid?
然后在CCD_ 3的CCD_ 2方法中得到一个CCD_。
但是,如果我将验证行更改为
validates :language, :presence => true, :inclusion => { :in => %(en fr es)}
则验证工作如预期。如果语言为零或不是您所期望的列表中的一个条目,并且没有崩溃,那么它是无效的。
我已经仔细检查了代码,以验证它是否正确生成了包含列表。那么为什么它会崩溃呢?存在性验证不应该发现问题并阻止任何进一步的验证吗?为什么当我生成列表而不是硬编码值时它会崩溃?
我甚至尝试使用:in
的proc形式,看看这是否有什么不同,但没有。但后来我真的没想到这是必要的,因为我只想在应用程序加载时生成一次列表,因为I18n.available_locates在应用程序执行过程中永远不会改变。
更新:我有了一个想法,并测试了以下代码,
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(' ')
之间的差异有关。
第二个条件有效的原因是为String类定义了#include?
:
> "qwertyuiop".include? "tyu"
true
因此,如果您验证%(en fr es)
中的包含(确切地说是"en fr es"
),则值TypeError: can't convert nil into String
0将通过验证。
您必须使用数组(作为文字[]
或单词%w()
)。如果您想使用I18n.available _ locales,请确保将它们转换为字符串
validates :language, :inclusion => { :in => I18n.available_locales.map(&:to_s) }
我无法重现您的错误,但:presence
验证是无用的,因为:inclusion
已经检查了列表中的值。
您应该向inclusion
验证传递一个数组,而不是字符串。因此,在使用%(en fr es)
的示例中,如果使用%w(en fr es)
,则效果良好。