SitePoint Sponsor

User Tag List

Results 1 to 2 of 2

Hybrid View

  1. #1
    SitePoint Member
    Join Date
    Oct 2003
    Location
    York, UK
    Posts
    23
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Rails: counter_cache problems

    I'm having trouble getting a counter_cache to update when associated data is removed from the database... Here's my schema:

    Code:
    ActiveRecord::Schema.define(:version => 4) do
      create_table "comments", :force => true do |t|
        t.string   "content"
        t.integer  "post_id", :null => false
        t.integer  "user_id", :null => false
        t.datetime "created_at"
        t.datetime "updated_at"
      end
    
      create_table "posts", :force => true do |t|
        t.string   "content"
        t.string   "permalink"
        t.integer  "comments_count", :default => 0
        t.datetime "created_at"
        t.datetime "updated_at"
      end
    
      create_table "users", :force => true do |t|
        t.string   "username"
        t.integer  "comments_count", :default => 0
        t.datetime "created_at"
        t.datetime "updated_at"
      end
    end
    Here's the comment model:

    Code:
    class Comment < ActiveRecord::Base
      belongs_to :user, :counter_cache => true
      belongs_to :post, :counter_cache => true
    end
    The post model:

    Code:
    class Post < ActiveRecord::Base
      belongs_to :user
      has_many :comments, :dependent => :delete_all
    end
    And the user model:

    Code:
    class User < ActiveRecord::Base
      has_many :comments, :dependent => :delete_all
      has_many :posts, :through => :comments
    end
    Both users and posts have a comments_count column, which are both counter caches. Upon creating a new comment, the counter_cache columns for the both tables update fine. Also, deleting a comment will update, and therefore decrement the counter_caches for both users and posts.

    Here's my problem. If I delete a user, I want to delete all the comments they've left on any post. That means I also need the counter cache to update to reflect the new number of comments on any posts that have had comments removed from them.

    Right now, deleting a user removes any comments they've made from the database, but fails to update the counter_caches in the posts table...

    Any way to get this doing what I want it to do? It's driving me nuts!

    Anyone who can help out will get to be awesome for the day... My treat

    Thanks!

  2. #2
    SitePoint Member
    Join Date
    Oct 2003
    Location
    York, UK
    Posts
    23
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Never mind... Got it

    Use :dependent => :destroy otherwise the callbacks (which include the counter cacher) won't get called.

    :delete_all simply performs a single delete query, where as destroy will call each objects destroy method.
    To fix the problem in my case I edited the User model to this (altered code in bold):

    Code:
    class User < ActiveRecord::Base
      has_many :comments, :dependent => :destroy
      has_many :posts, :through => :comments
    end
    Using :dependent => :delete_all, deleting a user simply looks at the comments, and drops them where the user ID matches the one you're removing. :dependent => :destroy on the other hand will go through each comment as it removes them, and will perform a separate removal call, which in this case will update, and decrement, the counter_cache in the posts table.

    Very clever stuff... I wonder how long it would have taken me to code up something similar in PHP... Too long, no doubt

    The full thread is here in case anyone else runs into this problem


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •