LearningRoR
LearningRoR

Reputation: 27232

Method gives ActiveRecord::Relation error?

I have 3 models called Price, UnitPrice and Purchase. The Price and UnitPrice models have an attribute called amount that I'm trying to scope to and get the total sum of both combined. I created two scopes, one for the total sum of both models. The other scope is to get the date attribute of both model's date fields.

I'm trying to do this:

<%= number_to_currency(current_user.purchases.today.total)

But get the error:

NoMethodError in pages#home

undefined method `today' for #<ActiveRecord::Relation:0x77f94c0>

My Code:

class Purchase < ActiveRecord::Base
  belongs_to :user
  belongs_to :price
  belongs_to :unit_price

  def total
    self.price.sum(:amount) + self.unit_price.sum(:amount)
  end

  def today
    self.price.where(:date => Date.today) && self.unit_price.where(:date=> Date.today)
  end
end

class Price < ActiveRecord::Base
  attr_accessible :amount, :date
  belongs_to :user
  has_many :purchases
end

class UnitPrice < ActiveRecord::Base
  attr_accessible :amount, :date
  belongs_to :user
  has_many :purchases
end

What should I do?

Upvotes: 0

Views: 1546

Answers (2)

Piotr Jakubowski
Piotr Jakubowski

Reputation: 1750

The methods total and today are defined on a model object. When you call current_user.purchases you associate to a relation which is has_many which means that in the end it's the Array. Therefore you can't call Purchase methods on it. You can do it this way:

  class Purchase < ActiveRecord::Base
    # ...
    scope :today, lambda { joins(:unit_price, :price).
                             where(:price => {:date => Date.today}, 
                                   :unit_price => { :date => Date.today }) }
    def total
        self.price.sum(:amount) + self.unit_price.sum(:amount)
    end
  end

And then call it like this:

   <%= number_to_currency(current_user.purchases.today.inject{ |sum, p| sum + p.total }) %>

Scope can be called on a relation.

You need to call inject since again total is Purchase method and the relation is Array so you need to aggregate the array. In order to keep the code clean you may want to define a today_purchases_total method on User so then you can call it like:

   <%= number_to_currency(current_user.today_purchases_total) %>

For more info about this you may refer to http://guides.rubyonrails.org/active_record_querying.html#scopes and all RoR guides in general.

Upvotes: 1

Peter Brown
Peter Brown

Reputation: 51717

I think your problem may be that you're using class methods instead of instance methods. In your Purchase class, remove the self. before the method definitions:

class Purchase < ActiveRecord::Base
  def total
    self.price.sum(:amount) + self.unit_price.sum(:amount)
  end

  def today
    self.price.where(:date => Date.today) && self.unit_price.where(:date=> Date.today)
  end
end

Upvotes: 2

Related Questions