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

时间:2010-05-13 00:02:19

标签: ruby-on-rails validation models

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

提前致谢

- Deb

5 个答案:

答案 0 :(得分:30)

您可以使用:

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

答案 1 :(得分:9)

这是一个可重复使用的版本:

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)

答案 2 :(得分:8)

为您的模型添加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

答案 3 :(得分:2)

我相信以下内容可能会起作用

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

答案 4 :(得分:1)

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