Skip to content

Instantly share code, notes, and snippets.

@thechrisoshow
Created March 29, 2012 11:56
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thechrisoshow/2236521 to your computer and use it in GitHub Desktop.
Save thechrisoshow/2236521 to your computer and use it in GitHub Desktop.
How to add validations to a specific instance of an active record object?
class Banana < ActiveRecord::Base; end
banana = Banana.new
banana.valid? #=> true
banana.singleton_class.validates_presence_of :name
banana.valid? #=> true - why did the validation not work?
banana.class.validates_presence_of :name
banana.valid? #=> false - as we'd expect...but now...
new_banana = Banana.new
new_banana.valid? #=> false - because the previous call soiled the Banana class with it's validation
# So how does one apply validations to the eigenclass of an ActiveRecord object?
# Or am I misunderstanding what .singleton_class is?
@kaligrafy
Copy link

I would like to do the exact same thing. Any news on this?

@nicosuria
Copy link

You may be better off just using #alias_method_chain

# Extending a User instance with this decorator will add a validation that the :old_password attribute is valid
class User
  module PasswordProtection

    def self.extended(user)
      class << user
        attr_writer :old_password
        alias_method_chain :valid?, :password_protection
      end
    end

    def valid_with_password_protection?
      valid_without_password_protection?
      validate_old_password
      errors.empty?
    end

    private

    def validate_old_password
      unless self.valid_password?(@old_password)
        errors.add :old_password, "is invalid"
      end
    end
  end
end

@bilus
Copy link

bilus commented Apr 16, 2014

Another solution would be using a Form Object and defining the validations depending on the context where they're used.

@divineforest
Copy link

class class User
  before_validation :add_instance_validations

  private

    def add_instance_validations
      singleton_class.class_eval { validates :name, presence: true }
    end
end

@DVG
Copy link

DVG commented Mar 5, 2015

I actually just blogged bout this, if anyone is still in need of a solution

http://dvg.github.io/2015/03/05/apply-activemodel-validations-by-policy.html

@equivalent
Copy link

wrote an article specially answering this topic: http://www.eq8.eu/blogs/22-different-ways-how-to-do-rails-validations :)

@trcarden
Copy link

A method that is directly built into Rails: https://github.com/rails/rails/blob/master/activemodel/lib/active_model/validations/with.rb#L115-L123

       class Person
         include ActiveModel::Validations

         validate :instance_validations, on: :create

         def instance_validations
           validates_with MyValidator, MyOtherValidator
         end
       end

@danielminsalesforce
Copy link

A method that is directly built into Rails: https://github.com/rails/rails/blob/master/activemodel/lib/active_model/validations/with.rb#L115-L123

       class Person
         include ActiveModel::Validations

         validate :instance_validations, on: :create

         def instance_validations
           validates_with MyValidator, MyOtherValidator
         end
       end

This solution is not corresponding with the initial subdmision. What the author need is to be able to "inject" as ad-hoc a validator without affecting to the Base class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment