Customizable Validations on Rails Models

Customizable Validations on Rails Models

In this example let’s use factory_girl gem and rspec rails gem for test suite:

First our tests:

We need the next two factories:

factories/invoice.rb


FactoryGirl.define do
 factory :invoice do
 association :admin
 folio 222
 signature "xx94108"
 total 3400.09
 subtotal 500.50
 tipo_comprobante 'Factura'
 end
end

factories/admin.rb


FactoryGirl.define do
 factory :admin do
 stamp = Time.now.to_i
 email = "user+#{stamp}@email.com"
 password "12345679"
 password_confirmation "12345679"
 email email
 nombre "Jose heriberto"
 apellidos "Perez Maga"
 razon_social "Mi Compu S.A. de C.V."
 rfc 'PEMH87022ES3'
 fecha_vencimiento_suscripcion Time.now - 1.day
 numero_folios_validos 20
 end
end

spec/models/invoice_spec.rb

require 'spec_helper'

describe Invoice do

  describe '#validate_unique_folio_number' do
    let(:admin_user) { FactoryGirl.create :admin, id: 1234}

    context 'when the user input a unique folio number' do

      subject { FactoryGirl.create(:invoice, :admin => admin_user, folio: 333) }

      specify do
        subject.should have(0).error_on(:folio)
      end
    end

    context 'when the user input a not unique folio number' do
      let(:invoice_2) { FactoryGirl.create(:invoice, :admin => admin_user, folio: 333) }
      before do
        FactoryGirl.create(:invoice, :admin => admin_user, folio: 333)
      end

      specify do
         #the next two lines do the same, you can select whatever you want
# if we use expect(invoice_2).should it doesn't execute lambda for that reason we use {} instead ()
         expect { invoice_2.should raise_error(ActiveRecord::RecordInvalid) }
         lambda {
           invoice_2
         }.should raise_error(ActiveRecord::RecordInvalid)
      end
    end
  end
end

Our model: app/models.invoce.rb


class Invoice < ActiveRecord::Base

attr_accessible :folio

belongs_to :admin
   validate :validate_unique_folio_number, :on => :create

   def validate_unique_folio_number
     user = Admin.find(self.admin_id)
     record_found = Invoice.where("admin_id = ? AND folio = ?", user.id, folio)
     errors.add(:folio, "add different folio number") unless record_found.empty?
   end
end

No Comments

Post A Comment