Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: Adding to errors[:base] does not make record invalid?

In my Purchase model, I have a method that calculates the tax:

def calculate_tax
  if self.shipping_address.state == State.new_york
    corresponding_tax = Tax.find_by(zip_code: self.shipping_address.zip_code, state_id: self.shipping_address.state_id)
    if corresponding_tax
      self.tax = corresponding_tax.rate * (self.subtotal + shipping)
    else
      #HERE !!!
      self.errors[:base] << "The zip code you have entered is invalid."
      puts "errors = #{self.errors.full_messages}" #<-- this prints out the error in my log, so I know it's being run
    end
  else
    self.tax = 0.00
  end
end

This method is being called within this method:

def update_all_fees!
  calculate_subtotal
  calculate_shipping
  calculate_tax #<-- being called here
  calculate_total
  save!
end

However, save! is saving the record successfully. Shouldn't it be throwing an exception? How would I make it so that save! fails when calculate_tax is in the second else block?

like image 915
bigpotato Avatar asked Oct 20 '22 07:10

bigpotato


2 Answers

You can add custom validation methods with the validate directive. Here's may take on the code you posted:

class Purchase < ActiveRecord::Base
  validate :new_york_needs_tax_record

  def update_all_fees!
    calculate_subtotal
    calculate_shipping
    calculate_tax
    calculate_total
    save!
  end

  private

  def calculate_tax
    if ships_to_new_york? && corresponding_tax
      self.tax = corresponding_tax.rate * (self.subtotal + shipping)
    elsif !ships_to_new_york?
      self.tax = 0.00
    else
      self.tax = nil
    end
  end

  def ships_to_new_york?
    self.shipping_address.state == State.new_york
  end

  def corresponding_tax
    Tax.find_by(zip_code: self.shipping_address.zip_code, state_id: self.shipping_address.state_id)
  end

  def new_york_need_tax_record
    if ships_to_new_york?  && !corresponding_tax
      self.errors[:base] << "The zip code you have entered is invalid."
    end
  end
end
like image 64
Arctodus Avatar answered Nov 03 '22 06:11

Arctodus


Edited for historical reasons. The first response didn't cover all scenarios.

But if you need to raise the error if there are any just do:

validate :taxes_scenario

def taxes_scenario
  [Add any clause here that makes your scenario invalid]
end

So you can validate the taxes scenario and made sure your error is added properly.

like image 20
Jorge de los Santos Avatar answered Nov 03 '22 07:11

Jorge de los Santos