Starkers
Starkers

Reputation: 10541

Share validations across models with rails 4

There are other questions pertaining to this, but they all seems to be < Rails 4, and what's more, they're not too detailed!

They all talk about creating a module to share these common validations in:

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

But I for one have no idea where such a file should be saved. In the lib directory? All files in the lib directory are included, seems a bit wasteful for a module I only want to be included in a two or three models...

  1. Does Rails 4 have an inbuilt way to share validations?
  2. If not, where should I save my custom module?
  3. And just to be super clear, how should I require this module in the models that need to include these validations?

Upvotes: 2

Views: 1530

Answers (2)

Ju Liu
Ju Liu

Reputation: 3999

Create the module in app/models/concerns, then include them in your classes with:

include ContactValidations

In this way Rails will automatically load the shared modules and make them available for you to include.

Upvotes: 1

Related Questions