Topic: Is it possible to share validations between models?

Is it possible to share common validations between models? When I try I get a "method doesnt exist" error. I am assuming that because "validates_" methods are defined in active record.

Anyone know of a way to do this?

my code so far

require 'active_record'

module ContactValidations

  def self.included(base_class)
    base_class.extend(ContactValidations::ClassMethods)
  end
 
  module ClassMethods

    # model validations
    validates_presence_of(:name, :message => 'You must provide a company name.')
    validates_presence_of(:street, :message => 'You must provide a company street.')
    validates_presence_of(:city, :message => 'You must provide a company city.')
    validates_presence_of(:post_code, :message => 'You must provide a company post code.')
   
    validates_numericality_of(:telephone,
    :on => :create,
    :message => 'Telephone should be a number with no spaces.',
    :if => :telephone_given?)
   
    validates_numericality_of(:area_code,
    :on => :create,
    :message => 'Telephone area code should be a number with no spaces.',
    :if => :area_code_given?)
   
    validates_numericality_of(:fax,
    :on => :create,
    :message => 'Fax should be a number with no spaces.',
    :if => :fax_given?)
   
    validates_numericality_of(:fax_area_code,
    :on => :create,
    :message => 'Fax area code should be a number with no spaces.',
    :if => :fax_area_code_given?)
   
    validates_format_of(:web,
    :with => /^((http)?:\/\/)?(www\.)?([a-zA-Z0-9]+)(.[a-zA-Z0-9]{2,3})(\.[a-zA-Z0-9]{2,3})$/,
    :on => :create,
    :message => 'Web address is invalid. Example: http://www.domain or http://domain.',
    :if => :web_given?)
   
    validates_format_of(:email,
    :with => /^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/,
    :on => :create,
    :message => 'Th email address given is invalid.',
    :if => :email_given?)
   
    validates_uniqueness_of(:email, :message => 'This email is already given.')
 
    def telephone_given?
      !telephone.blank?
    end
    def fax_given?
      !fax.blank?
    end
    def web_given?
      !web.blank?
    end
    def email_given?
      !email.blank?
    end
    def area_code_given?
      !area_code.blank?
    end
    def fax_area_code_given?
      !fax_area_code.blank?
    end
   
  end
end

Re: Is it possible to share validations between models?

you could try this:

module ContactValidations

  def self.included(base_class)
    #include the new methods into this class
    base_class.extend(ClassMethods)

    base_class.class_eval do
      #run the new code in the context of the class it's included.
      validates_presence_of(:name, :message => 'You must provide a company name.')
      validates_presence_of(:street, :message => 'You must provide a company street.')
      validates_presence_of(:city, :message => 'You must provide a company city.')
      validates_presence_of(:post_code, :message => 'You must provide a company post code.')
   
      validates_numericality_of(:telephone,
      :on => :create,
      :message => 'Telephone should be a number with no spaces.',
      :if => :telephone_given?)
   
      validates_numericality_of(:area_code,
      :on => :create,
      :message => 'Telephone area code should be a number with no spaces.',
      :if => :area_code_given?)
   
      validates_numericality_of(:fax,
      :on => :create,
      :message => 'Fax should be a number with no spaces.',
      :if => :fax_given?)
   
      validates_numericality_of(:fax_area_code,
      :on => :create,
      :message => 'Fax area code should be a number with no spaces.',
      :if => :fax_area_code_given?)
     
      validates_format_of(:web,
      :with => /^((http)?:\/\/)?(www\.)?([a-zA-Z0-9]+)(.[a-zA-Z0-9]{2,3})(\.[a-zA-Z0-9]{2,3})$/,
      :on => :create,
      :message => 'Web address is invalid. Example: http://www.domain or http://domain.',
      :if => :web_given?)
   
      validates_format_of(:email,
      :with => /^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/,
      :on => :create,
      :message => 'Th email address given is invalid.',
      :if => :email_given?)
   
      validates_uniqueness_of(:email, :message => 'This email is already given.')
    end
  end
 
  module ClassMethods
 
    def telephone_given?
      !telephone.blank?
    end
    def fax_given?
      !fax.blank?
    end
    def web_given?
      !web.blank?
    end
    def email_given?
      !email.blank?
    end
    def area_code_given?
      !area_code.blank?
    end
    def fax_area_code_given?
      !fax_area_code.blank?
    end
   
  end
end


but i'm really not sure...

Re: Is it possible to share validations between models?

Basically what duplex said but you want to include your instance methods:

require 'active_record'

module ContactValidations

  def self.included(base_class)
    base_class.class_eval do
      include ContactValidations::InstanceMethods

      # model validations
      validates_presence_of(:name, :message => 'You must provide a company name.')
      validates_presence_of(:street, :message => 'You must provide a company street.')
      validates_presence_of(:city, :message => 'You must provide a company city.')
      validates_presence_of(:post_code, :message => 'You must provide a company post code.')
   
      validates_numericality_of(:telephone, :on => :create, :message => 'Telephone should be a number with no spaces.', :if => :telephone_given?)   
      validates_numericality_of(:area_code, :on => :create, :message => 'Telephone area code should be a number with no spaces.', :if => :area_code_given?)
   
      validates_numericality_of(:fax, :on => :create, :message => 'Fax should be a number with no spaces.', :if => :fax_given?)
   
      validates_numericality_of(:fax_area_code, :on => :create, :message => 'Fax area code should be a number with no spaces.', :if => :fax_area_code_given?)
   
      validates_format_of(:web, :with => /^((http)?:\/\/)?(www\.)?([a-zA-Z0-9]+)(.[a-zA-Z0-9]{2,3})(\.[a-zA-Z0-9]{2,3})$/, :on => :create, :message => 'Web address is invalid. Example: http://www.domain or http://domain.', :if => :web_given?)
   
      validates_format_of(:email, :with => /^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/, :on => :create, :message => 'Th email address given is invalid.', :if => :email_given?)
   
      validates_uniqueness_of(:email, :message => 'This email is already given.')
    end
  end
 
  module InstanceMethods

    def telephone_given?
      !telephone.blank?
    end
 
    def fax_given?
      !fax.blank?
    end

    def web_given?
      !web.blank?
    end

    def email_given?
      !email.blank?
    end

    def area_code_given?
      !area_code.blank?
    end

    def fax_area_code_given?
      !fax_area_code.blank?
    end
   
  end
end

Last edited by rob-twf (2008-07-25 13:58:05)

Rob Anderton
TheWebFellas