在我的Schedule模型中,我想在:wdays字段中添加一些验证,这是一个int []。我只希望值0..6有效
有效
Schedule.wdays = [0,1,6]
无效
Schedule.wdays = [0,1,10]
我尝试使用
validates :wdays, inclusion: { in: [0, 1, 2, 3, 4, 5, 6] }
和
validates :wdays, inclusion: { in: 0..6 }
但不起作用
验证模型中数组中值的正确方法是什么?
答案 0 :(得分:26)
我不认为默认的Rails验证器会在这里做到这一点,你可以这样做:
validate :validate_wdays
def validate_wdays
if !wdays.is_a?(Array) || wdays.detect{|d| !(0..6).include?(d)}
errors.add(:wdays, :invalid)
end
end
答案 1 :(得分:5)
我不确定在现有的Rails验证结构中是否有更简单的方法来处理这个问题。你有一个奇怪的例子,验证器并没有真正构建来处理。您可能需要为此类内容编写自定义验证程序(假设现有的验证扩展gem不可用)。像这样:
class ArrayInRangeValidator < ActiveModel::EachValidator
def validate_each(record, attribute, valueArray)
valueArray.each do |value|
record.errors.add "#{attribute} - #{value}", (options[:message] || "is not in the acceptable range") unless (1..6).include?(value)
end
end
end
然后在你的模型中:
class Schedule < ActiveRecord::Base
include ActiveModel::Validations
validates :wdays, :presence => true, :array_in_range => true
... other model stuff
end
答案 2 :(得分:0)
我创建了这个gem: https://github.com/rafaelbiriba/active_model_validates_intersection_of
基本上,您可以使用:
class User < ActiveRecord::Base
DEFAULT_PERMISSION = ["read", "write", "share"]
validates_intersection_of :permission, in: DEFAULT_PERMISSION
end
如果你尝试:
user = User.new(permission: ["read", "share"])
user.valid? #true
user = User.new(permission: ["read", "admin"])
user.valid? #false
享受!欢迎提出评论,拉取请求和反馈。
答案 3 :(得分:0)
我认为接受的答案并没有真正正确地做到这一点。如果有人设置了wdays = 'meow'
,它将在没有警告的情况下将其设置为空数组wdays == []
。
正在使用此方法要求wdays
进行类型转换。如果无效,它已经将数据转换成数组。
wdays_before_type_cast
而不是wdays
。
validate :validate_wdays
def validate_wdays
errors.add(:wdays, :invalid) if wdays_changed? && !wdays_before_type_cast.is_a?(Array)
errors.add(:wdays, :invalid) if wdays.any? { |d| (0..6).exclude?(d) }
end