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

时间:2021-03-04 11:51:15

I know I can require a field by adding validates_presence_of :field to the model. However, how do I require at least one field to be mandatory, while not requiring any particular field?

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

thanks in advance

谢谢提前

-- Deb

——黛比

5 个解决方案

#1


27  

You can use:

您可以使用:

validate :any_present?

def any_present?
  if %w(field1 field2 field3).all?{|attr| self[attr].blank?}
    errors.add :base, "Error message"
  end
end

EDIT: updated from original answer for Rails 3+ as per comment.

编辑:根据注释更新Rails 3+的原始答案。

But you have to provide field names manually. You could get all content columns of a model with Model.content_columns.map(&:name), but it will include created_at and updated_at columns too, and that is probably not what you want.

但是您必须手动提供字段名。您可以使用model .content_columns.map(&:name)获取模型的所有内容列,但它也将包括created_at和updated_at列,这可能不是您想要的。

#2


8  

Add a validate method to your model:

向您的模型添加一个验证方法:

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


7  

Here's a reusable version:

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

class AnyPresenceValidator < ActiveModel::Validator
  def validate(record)
    unless options[:fields].any?{|attr| record[attr].present?}
      record.errors.add(:base, :blank)
    end
  end
end

You can use it in your model with:

您可以在您的模型中使用:

validates_with AnyPresenceValidator, fields: %w(field1 field2 field3)

#4


2  

I believe something like the following may work

我相信以下这样的方法可能有用

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

#5


1  

Going further with @Votya's correct answer, here is a way to retrieve all columns besides created_at and updated_at (and optionally, any others you want to throw out):

继续使用@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/}

For example:

例如:

 1.9.3p327 :012 > Client.content_columns.map(&:name).reject {|i| i =~ /(created|updated)_at/}
 => ["primary_email", "name"]

#1


27  

You can use:

您可以使用:

validate :any_present?

def any_present?
  if %w(field1 field2 field3).all?{|attr| self[attr].blank?}
    errors.add :base, "Error message"
  end
end

EDIT: updated from original answer for Rails 3+ as per comment.

编辑:根据注释更新Rails 3+的原始答案。

But you have to provide field names manually. You could get all content columns of a model with Model.content_columns.map(&:name), but it will include created_at and updated_at columns too, and that is probably not what you want.

但是您必须手动提供字段名。您可以使用model .content_columns.map(&:name)获取模型的所有内容列,但它也将包括created_at和updated_at列,这可能不是您想要的。

#2


8  

Add a validate method to your model:

向您的模型添加一个验证方法:

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


7  

Here's a reusable version:

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

class AnyPresenceValidator < ActiveModel::Validator
  def validate(record)
    unless options[:fields].any?{|attr| record[attr].present?}
      record.errors.add(:base, :blank)
    end
  end
end

You can use it in your model with:

您可以在您的模型中使用:

validates_with AnyPresenceValidator, fields: %w(field1 field2 field3)

#4


2  

I believe something like the following may work

我相信以下这样的方法可能有用

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

#5


1  

Going further with @Votya's correct answer, here is a way to retrieve all columns besides created_at and updated_at (and optionally, any others you want to throw out):

继续使用@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/}

For example:

例如:

 1.9.3p327 :012 > Client.content_columns.map(&:name).reject {|i| i =~ /(created|updated)_at/}
 => ["primary_email", "name"]