7

Is there a way to know if an attribute has a validation? Something like following:

Model.attribute.has_presence_validation?
Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
el_quick
  • 4,656
  • 11
  • 45
  • 53

3 Answers3

8

Well not sure about simplest solution but I achieved this functionality with quite complexity. Maybe someone come up with some simpler solution. Here is the code which worked perfectly for me.

I get all the validations on a model, chose presence validations(ActiveRecord::Validations::PresenceValidator) and then select all of their attributes and used include to check attribute(:your_attribute)presence in this array

Model.validators.collect{|validation| validation if validation.class==ActiveRecord::Validations::PresenceValidator}.compact.collect(&:attributes).flatten.include? :your_attribute

you can change compare statement

validation.class==ActiveRecord::Validations::PresenceValidator

to get all other types validation i.e uniqueness etc

Abubakar
  • 1,022
  • 10
  • 20
2

For me, the following code is working (it is basically checking if any validator for given field is an instance of the presence validator):

MyModel.validators_on(:my_attribute).any?{|validator| validator.kind_of?(ActiveModel::Validations::PresenceValidator)}
lacco
  • 882
  • 1
  • 10
  • 24
2

Combining some of the points in the other answers, I would have thought the following approach was most straightforward (Rails 4.2.7):

class Model < ActiveRecord::Base
  validates ... # Whatever your validation are

  def self.presence_required_attrs
    validators.select do |v|
      v.is_a?(ActiveRecord::Validations::PresenceValidator)
    end.map(&:attributes).flatten
  end
end

It's then as easy as:

Model.presence_required_attrs.include?(:my_attribute)

Edit:

More comprehensive solution I think is just having a helper or controller method:

def validated_attrs_for(model, validation)
    if validation.is_a?(String) || validation.is_a?(Symbol)
      klass = 'ActiveRecord::Validations::' \
              "#{validation.to_s.camelize}Validator"
      validation = klass.constantize
    end
    model.validators
         .select { |v| v.is_a?(validation) }
         .map(&:attributes)
         .flatten
end

Used:

validated_attrs_for(Model, :presence).include?(:my_attribute)

Just double check that the various validators (:presence, :uniqueness, etc.) correctly correspond to the appropriate Validator class -- I'm pretty sure they do, but haven't looked recently.

niborg
  • 390
  • 4
  • 16