Topic: counter_cache help

I've added a counter cache to my models, and it seems to be working correctly, except for the fact that the counter is not being updated to the db

Here are the two relevant models:

[code =ruby]
class FinishedLineItem < ActiveRecord::Base
  belongs_to :order, :class_name => "Order", :foreign_key => "order_id", :counter_cache => true
  belongs_to :finished_item, :class_name => "FinishedItem", :foreign_key => "finished_item_id"
end

class Order < ActiveRecord::Base
  has_many :finished_line_items, :class_name => "FinishedLineItem"
end
[/code]

My orders table has a column called finished_line_items_count which defaults to zero, but it never updates

I am not sure how the count is correctly maintained if the column never updates the count! Can any help explain how this works?

thanks!

Re: counter_cache help

If you follow Rails naming conventions (which it looks like you are) you don't need to manually specify the class name/foriegn key:

class FinishedLineItem < ActiveRecord::Base
  belongs_to :order, :counter_cache => true
  belongs_to :finished_item
end

class Order < ActiveRecord::Base
  has_many :finished_line_items
end


As for what's wrong, I don't know. How are you checking if the column gets updated? You may need to call reload on the order model first for it to update.

Railscasts - Free Ruby on Rails Screencasts

Re: counter_cache help

I'm checking to see if the db gets updated with CocoaMySQL. I've made a few changes to the code and I am completely baffled  as to why it isn't working.

class FinishedLineItem < ActiveRecord::Base
  belongs_to :order, :class_name => "Order", :counter_cache => true
  belongs_to :finished_item, :class_name => "FinishedItem"
 
  after_create :increment

  def increment
    self.order.increment
  end
end

class Order < ActiveRecord::Base
  has_many :finished_line_items, :class_name => "FinishedLineItem"
 
  def increment
    self.finished_line_items_counter += 1
    self.update
  end
end


The after_create callback functions, and order.increment run properly. For some reason the db will not update when the self.update is called (or self.save). I can't change any of the other attributes in order either. I can't really make any sense out of this one. I also cannot reference order.size, it tells me It is an undefined method.

For some reason though. order.finished_line_items_count returns the proper amount, even though the DB value always remains zero, even after saving or updating the db!

Thanks for your help.

Re: counter_cache help

Just to ask the obvious, are you viewing the correct database and record? Is everything else updating properly?

Last edited by ryanb (2006-11-15 15:03:02)

Railscasts - Free Ruby on Rails Screencasts

Re: counter_cache help

This is what the table looks like, if you look at order 20 it is in progress at the moment.

http://optimal-vision.com/images/table.png

AFter a line item is created, the following code executes in the following models.

class FinishedLineItem < ActiveRecord::Base
  belongs_to :order, :class_name => "Order", :counter_cache => true
  belongs_to :finished_item, :class_name => "FinishedItem"
 
  after_create :increment

  def increment
    self.order.increment
  end

######
class Order < ActiveRecord::Base
  has_many :finished_line_items, :class_name => "FinishedLineItem"
 
  def increment
    self.is_sale = 1
    self.finished_line_items_count += 1
    self.update
  end


and the result is that the table stays exactly the same. I am totally baffled.

Last edited by dahuk (2006-11-15 15:30:17)

Re: counter_cache help

You may want to check the mysql database directly to rule out the software being the problem:

In the terminal:

mysql -u root -p
USE my_app_development;
SELECT * FROM orders;

Are all the values zero in there?

Railscasts - Free Ruby on Rails Screencasts

Re: counter_cache help

I've tried this and the result is the same. I'll take another crack at it tomorrow with some fresh eyes. Thanks!

Re: counter_cache help

Found the problem, I had a stray @order.save in my controller, and it must have been overwriting the values with the old ones.

Re: counter_cache help

I have some more detailed information in case it might be useful to someone in the future.

this link might be useful to you too.

In my controller I had

def new
    @order = find_order
    @order.save

This would retrieve the order from the session or create a new one.

This would then take you to the order page. From the order page you go to the add line items page, which would redirect you back to 'new' after it added the line items. @order.save would then be run again, writing a zero back to the DB.

I changed that my controller code to:

def new
    @order = find_order
    #@order.save
    @order.update_attributes(:finished_line_items_count => @order.finished_line_items_count(:refresh))

And things are working as expected.