Add counter cache for comments on posts

This commit is contained in:
danielgrippi 2011-09-11 14:51:08 -07:00
parent 37787605aa
commit 1d0bec11f7
6 changed files with 48 additions and 4 deletions

View file

@ -39,6 +39,14 @@ class Comment < ActiveRecord::Base
self.post.touch self.post.touch
end end
after_create do
self.parent.update_comments_counter
end
after_destroy do
self.parent.update_comments_counter
end
def diaspora_handle def diaspora_handle
self.author.diaspora_handle self.author.diaspora_handle
end end

View file

@ -24,11 +24,11 @@ class Like < ActiveRecord::Base
validates :target, :presence => true validates :target, :presence => true
after_create do after_create do
self.target.update_likes_counter self.parent.update_likes_counter
end end
after_destroy do after_destroy do
self.target.update_likes_counter self.parent.update_likes_counter
end end
def diaspora_handle def diaspora_handle

View file

@ -126,5 +126,11 @@ class Post < ActiveRecord::Base
def last_three_comments def last_three_comments
self.comments.order('created_at DESC').limit(3).includes(:author => :profile).reverse self.comments.order('created_at DESC').limit(3).includes(:author => :profile).reverse
end end
# @return [Integer]
def update_comments_counter
self.class.where(:id => self.id).
update_all(:comments_count => self.comments.count)
end
end end

View file

@ -0,0 +1,14 @@
class CounterCacheOnPostComments < ActiveRecord::Migration
class Post < ActiveRecord::Base; end
def self.up
add_column :posts, :comments_count, :integer, :default => 0
execute <<SQL if Post.count > 0
UPDATE posts
SET posts.comments_count = (SELECT COUNT(*) FROM comments WHERE comments.post_id = posts.id)
SQL
end
def self.down
remove_column :posts, :comments_count
end
end

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20110907205720) do ActiveRecord::Schema.define(:version => 20110911213207) do
create_table "aspect_memberships", :force => true do |t| create_table "aspect_memberships", :force => true do |t|
t.integer "aspect_id", :null => false t.integer "aspect_id", :null => false
@ -282,6 +282,7 @@ ActiveRecord::Schema.define(:version => 20110907205720) do
t.string "root_guid", :limit => 30 t.string "root_guid", :limit => 30
t.string "status_message_guid" t.string "status_message_guid"
t.integer "likes_count", :default => 0 t.integer "likes_count", :default => 0
t.integer "comments_count", :default => 0
end end
add_index "posts", ["author_id"], :name => "index_posts_on_person_id" add_index "posts", ["author_id"], :name => "index_posts_on_person_id"

View file

@ -42,7 +42,6 @@ describe Comment do
end end
end end
describe 'User#comment' do describe 'User#comment' do
it "should be able to comment on one's own status" do it "should be able to comment on one's own status" do
alice.comment("Yeah, it was great", :post => @status) alice.comment("Yeah, it was great", :post => @status)
@ -53,6 +52,7 @@ describe Comment do
bob.comment("sup dog", :post => @status) bob.comment("sup dog", :post => @status)
@status.reload.comments.first.text.should == "sup dog" @status.reload.comments.first.text.should == "sup dog"
end end
it 'does not multi-post a comment' do it 'does not multi-post a comment' do
lambda { lambda {
alice.comment 'hello', :post => @status alice.comment 'hello', :post => @status
@ -60,6 +60,16 @@ describe Comment do
end end
end end
describe 'counter cache' do
it 'increments the counter cache on its post' do
lambda {
alice.comment("oh yeah", :post => @status)
}.should change{
@status.reload.comments_count
}.by(1)
end
end
describe 'xml' do describe 'xml' do
before do before do
@commenter = Factory.create(:user) @commenter = Factory.create(:user)
@ -69,19 +79,24 @@ describe Comment do
@comment = @commenter.comment "Fool!", :post => @post @comment = @commenter.comment "Fool!", :post => @post
@xml = @comment.to_xml.to_s @xml = @comment.to_xml.to_s
end end
it 'serializes the sender handle' do it 'serializes the sender handle' do
@xml.include?(@commenter.diaspora_handle).should be_true @xml.include?(@commenter.diaspora_handle).should be_true
end end
it 'serializes the post_guid' do it 'serializes the post_guid' do
@xml.should include(@post.guid) @xml.should include(@post.guid)
end end
describe 'marshalling' do describe 'marshalling' do
before do before do
@marshalled_comment = Comment.from_xml(@xml) @marshalled_comment = Comment.from_xml(@xml)
end end
it 'marshals the author' do it 'marshals the author' do
@marshalled_comment.author.should == @commenter.person @marshalled_comment.author.should == @commenter.person
end end
it 'marshals the post' do it 'marshals the post' do
@marshalled_comment.post.should == @post @marshalled_comment.post.should == @post
end end