Mike Wiesenhart Mike Wiesenhart - 28 days ago 6
Ruby Question

Rails Model Calculation Only If Condition Met

I have an

item
model and need to calculate the total profit less any fees. I am currently doing that right now in the model. However, I want to be able to have that calculation run only once the boolean is updated to sold. I've tried an if statement in the model, but that didn't work.

item.rb

class Item < ActiveRecord::Base
def profit_calc
sold_for - bought_for - fees - shipping rescue 0
end

def self.purchase_total
sum(:bought_for)
end

def self.fee_total
sum(:fees)
end

def self.shipping_total
sum(:shipping)
end

def self.sales_total
sum(:sold_for)
end

def self.profit_total
sum(:sold_for) - sum(:bought_for) - sum(:fees) - sum(:shipping)
end

scope :visible, -> { where(sold: false) }
scope :sold, -> { where(sold: true) }
end


schema.rb

create_table "items", force: :cascade do |t|
t.string "description"
t.float "bought_for"
t.float "sold_for"
t.float "fees"
t.float "shipping"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "sold", default: false
end


statistics.html.erb

<td><%= number_to_currency(@items.profit_total) %></td>

Answer

You can use sold scope in the calculation:

  def self.profit_total
    sold.sum(:sold_for) - sold.sum(:bought_for) - sold.sum(:fees) - sold.sum(:shipping)
  end

But each time you call Item.profit_total it will execute all the queries. You may want to cache the calculation if you need that frequently and expire the cache in after_save callback if that is sold.