【发布时间】:2011-02-18 21:35:11
【问题描述】:
我知道我可以通过在模型中添加 validates_presence_of :field 来要求一个字段。但是,我如何要求至少一个字段是必填字段,而不需要任何特定字段?
提前致谢
-- 德布
【问题讨论】:
-
我相信你必须自己写验证
标签: ruby-on-rails validation models
我知道我可以通过在模型中添加 validates_presence_of :field 来要求一个字段。但是,我如何要求至少一个字段是必填字段,而不需要任何特定字段?
提前致谢
-- 德布
【问题讨论】:
标签: ruby-on-rails validation models
为您的模型添加一个validate 方法:
def validate
if field1.blank? and field2.blank? and field3.blank? # ...
errors.add_to_base("You must fill in at least one field")
end
end
【讨论】:
我相信像下面这样的东西可能会起作用
class MyModel < ActiveRecord::Base
validate do |my_model|
my_model.my_validation
end
def my_validation
errors.add_to_base("Your error message") if self.blank?
#or self.attributes.blank? - not sure
end
end
【讨论】:
你可以使用:
validate :any_present?
def any_present?
if %w(field1 field2 field3).all?{|attr| self[attr].blank?}
errors.add :base, "Error message"
end
end
编辑:根据评论从 Rails 3+ 的原始答案更新。
但您必须手动提供字段名称。
您可以使用Model.content_columns.map(&:name) 获取模型的所有内容列,但它也将包括created_at 和updated_at 列,这可能不是您想要的。
【讨论】:
errors.add :base, "Error Message",因为 add_to_base 已弃用
进一步了解@Votya 的正确答案,这是一种检索除 created_at 和 updated_at 之外的所有列(以及您想要丢弃的任何其他列)的方法:
# Get all column names as an array and reject the ones we don't want
Model.content_columns.map(&:name).reject {|i| i =~ /(created|updated)_at/}
例如:
1.9.3p327 :012 > Client.content_columns.map(&:name).reject {|i| i =~ /(created|updated)_at/}
=> ["primary_email", "name"]
【讨论】:
这是一个可重复使用的版本:
class AnyPresenceValidator < ActiveModel::Validator
def validate(record)
unless options[:fields].any?{|attr| record[attr].present?}
record.errors.add(:base, :blank)
end
end
end
你可以在你的模型中使用它:
validates_with AnyPresenceValidator, fields: %w(field1 field2 field3)
【讨论】:
all? 与blank? 配对,您还可以将any? 与present? 配对,以便代码本身遵循验证器名称的语义