Rails:如何要求至少一个字段不为空

我知道我可以通过向模型添加validates_presence_of :field来要求字段。 但是,如何要求至少一个字段是强制性的,而不需要任何特定字段?

提前致谢

– Deb

您可以使用:

 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_atupdated_at列,这可能不是您想要的。

在模型中添加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 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) 

我相信以下内容可能有用

 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 

进一步了解@ 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"]