Rails包含验证



我正在努力进行以下包含验证,

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 String0将通过验证。

您必须使用数组(作为文字[]或单词%w())。如果您想使用I18n.available _ locales,请确保将它们转换为字符串

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

我无法重现您的错误,但:presence验证是无用的,因为:inclusion已经检查了列表中的值。

您应该向inclusion验证传递一个数组,而不是字符串。因此,在使用%(en fr es)的示例中,如果使用%w(en fr es),则效果良好。

最新更新