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?
thanks in advance
-- Deb
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?
thanks in advance
-- Deb
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.
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.
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)
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
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
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):
# 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"]
If you only have two fields, this will get the job done:
validates :first_name, presence: true, if: :nick_name.blank?
validates :nick_name, presence: true, if: :first_name.blank?
This does not scale up well with more fields, but when you only have two, this is perhaps clearer than a custom validation method.
n.b. If they omit both, the error message will appear more restrictive than you intend. (e.g. First Name is required. Nick Name is required.
) ¯\(ツ)/¯