Rails: как требовать, чтобы хотя бы одно поле не было пустым - PullRequest
28 голосов
/ 13 мая 2010

Я знаю, что мне может потребоваться поле, добавив validates_presence_of :field к модели. Однако, как мне требовать, чтобы хотя бы одно поле было обязательным, при этом не требуя какого-либо конкретного поля?

спасибо заранее

- Деб

Ответы [ 5 ]

30 голосов
/ 13 мая 2010

Вы можете использовать:

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, и это, вероятно, не то, что вам нужно.

9 голосов
/ 21 октября 2014

Вот многоразовая версия:

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)
8 голосов
/ 13 мая 2010

Добавьте метод 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
2 голосов
/ 13 мая 2010

Я верю, что что-то вроде следующего может работать

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
1 голос
/ 22 января 2013

Если продолжить с правильным ответом @ Votya, вот способ получить все столбцы, кроме create_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"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...