diff --git a/app/models/comment.rb b/app/models/comment.rb index 7beaef490..e455f1457 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -39,6 +39,14 @@ class Comment < ActiveRecord::Base self.post.touch end + after_create do + self.parent.update_comments_counter + end + + after_destroy do + self.parent.update_comments_counter + end + def diaspora_handle self.author.diaspora_handle end diff --git a/app/models/like.rb b/app/models/like.rb index d3f144988..21f9f6194 100644 --- a/app/models/like.rb +++ b/app/models/like.rb @@ -24,11 +24,11 @@ class Like < ActiveRecord::Base validates :target, :presence => true after_create do - self.target.update_likes_counter + self.parent.update_likes_counter end after_destroy do - self.target.update_likes_counter + self.parent.update_likes_counter end def diaspora_handle diff --git a/app/models/post.rb b/app/models/post.rb index 91f811241..b0e201314 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -126,5 +126,11 @@ class Post < ActiveRecord::Base def last_three_comments self.comments.order('created_at DESC').limit(3).includes(:author => :profile).reverse end + + # @return [Integer] + def update_comments_counter + self.class.where(:id => self.id). + update_all(:comments_count => self.comments.count) + end end diff --git a/db/migrate/20110911213207_counter_cache_on_post_comments.rb.rb b/db/migrate/20110911213207_counter_cache_on_post_comments.rb.rb new file mode 100644 index 000000000..3e6443fa9 --- /dev/null +++ b/db/migrate/20110911213207_counter_cache_on_post_comments.rb.rb @@ -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 < 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 diff --git a/db/schema.rb b/db/schema.rb index 7bc8c385d..96d8cda46 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # 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| t.integer "aspect_id", :null => false @@ -282,6 +282,7 @@ ActiveRecord::Schema.define(:version => 20110907205720) do t.string "root_guid", :limit => 30 t.string "status_message_guid" t.integer "likes_count", :default => 0 + t.integer "comments_count", :default => 0 end add_index "posts", ["author_id"], :name => "index_posts_on_person_id" diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index 1d4ffccb0..7d855360a 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -42,7 +42,6 @@ describe Comment do end end - describe 'User#comment' do it "should be able to comment on one's own status" do alice.comment("Yeah, it was great", :post => @status) @@ -53,6 +52,7 @@ describe Comment do bob.comment("sup dog", :post => @status) @status.reload.comments.first.text.should == "sup dog" end + it 'does not multi-post a comment' do lambda { alice.comment 'hello', :post => @status @@ -60,6 +60,16 @@ describe Comment do 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 before do @commenter = Factory.create(:user) @@ -69,19 +79,24 @@ describe Comment do @comment = @commenter.comment "Fool!", :post => @post @xml = @comment.to_xml.to_s end + it 'serializes the sender handle' do @xml.include?(@commenter.diaspora_handle).should be_true end + it 'serializes the post_guid' do @xml.should include(@post.guid) end + describe 'marshalling' do before do @marshalled_comment = Comment.from_xml(@xml) end + it 'marshals the author' do @marshalled_comment.author.should == @commenter.person end + it 'marshals the post' do @marshalled_comment.post.should == @post end