LearningRoR
LearningRoR

Reputation: 27202

How to get sum of parent association?

In my Rails 3.2.8 application, I'm trying to calculate all of the users products and tax amount in total. It should get the total of the Products and then the Tax on each product.

class Product
  attr_accessible :amount, :location_id, :tax_id
  belongs_to :tax
  belongs_to :location
  belongs_to :user
  belongs_to :tax, :class_name => "Tax"

  def self.total
    self.sum(:amount) + self.tax.sum(:amount)
  end
end

Tax.rb

class Tax < ActiveRecord::Base
  attr_accessible :amount, :date, :location_id
  belongs_to :user
  belongs_to :location
  has_many :products
end

So when I try a scope like this:

<%= number_to_currency(current_user.products.total) %>

This of course gives me an error:

undefined method `tax' for #<Class:0x57f5298>

How can I write this to make it work?

Thank you.

Upvotes: 0

Views: 326

Answers (3)

megas
megas

Reputation: 21791

From this line

<%= number_to_currency(current_user.products.total) %>

I understood that for current user you need the sum from his products and taxes. What you have done before is not related to the current user but to the whole table of products instead, and of course some product in this table can be not related to the current user.

So here's what I think how it might be.

#Instance method for current user
class User < ...
  def product_tax_total
    products.joins(:tax).select('SUM(products.amount + taxes.amount) AS sum').sum
  end
end

And use it like this:

<%= number_to_currency(current_user.product_tax_total) %>

Update:

You can use scope to chain the queries:

class Product
  scope :today, lambda { where(:date => Date.today) }
end

And then chain it

class User < ...
  def product_tax_total
    products.today.joins(:tax).select('SUM(products.amount + taxes.amount) AS sum').sum
  end
end

Upvotes: 1

Baylor Rae&#39;
Baylor Rae&#39;

Reputation: 4010

I'm not great with ActiveRecord's newer query methods. I guest I'm a little old fashioned and have a tendency to lean more towards SQL, but this should "efficiently" get what you want.

  def self.total
    self.select('sum(products.amount + taxes.amount) AS sum').joins(:tax).try(:sum, 0)
  end

Upvotes: 1

sumskyi
sumskyi

Reputation: 1835

tax is a Product's instance method, not of class Product

try the following (weak performance):

class Product
  belongs_to :tax

  def self.total
    self.sum(:amount) + all.map(&:tax).map(&:amount).sum
  end
end

Upvotes: 3

Related Questions