diff --git a/app/helpers/reshares_helper.rb b/app/helpers/reshares_helper.rb index f5131814ffb1c4076475f3a8ca887e3056e50563..eccb757116ca60f5390b74d0592c0bfba109df6d 100644 --- a/app/helpers/reshares_helper.rb +++ b/app/helpers/reshares_helper.rb @@ -25,8 +25,7 @@ module ResharesHelper :remote => true, :confirm => t('reshares.reshare.reshare_confirmation', :author => post.root.author.name) else - link_to t("reshares.reshare.reshare", - :count => post.reshares.size), + link_to t('shared.reshare.reshare'), reshares_path(:root_guid => post.guid), :method => :post, :remote => true, diff --git a/app/models/post.rb b/app/models/post.rb index e161f8fca34ddcbc552cd0f13381814bef3bcc75..109943797a7abc2b3dd9cad4c31d46b40388f19c 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -53,10 +53,6 @@ class Post < ActiveRecord::Base new_post end - def reshare_count - @reshare_count ||= Post.where(:root_guid => self.guid).count - end - # @return Returns true if this Post will accept updates (i.e. updates to the caption of a photo). def mutable? false diff --git a/app/models/reshare.rb b/app/models/reshare.rb index cfb17a6466042101a3c1bde2fb51fa7aba234734..7d945ff6278eda252680b9fe6936f91674a9e6eb 100644 --- a/app/models/reshare.rb +++ b/app/models/reshare.rb @@ -17,6 +17,14 @@ class Reshare < Post self.public = true end + after_create do + self.root.update_reshares_counter + end + + after_destroy do + self.root.update_reshares_counter + end + def root_diaspora_id self.root.author.diaspora_handle end @@ -36,7 +44,7 @@ class Reshare < Post def notification_type(user, person) Notifications::Reshared if root.author == user.person end - + private def after_parse @@ -46,7 +54,7 @@ class Reshare < Post return if Post.exists?(:guid => self.root_guid) fetched_post = self.class.fetch_post(root_author, self.root_guid) - + if fetched_post #Why are we checking for this? if root_author.diaspora_handle != fetched_post.diaspora_handle @@ -71,7 +79,7 @@ class Reshare < Post def root_must_be_public if self.root && !self.root.public - errors[:base] << "you must reshare public posts" + errors[:base] << "Only posts which are public may be reshared." return false end end diff --git a/app/views/reshares/_reshare.haml b/app/views/reshares/_reshare.haml index 4ccee89f1ddfcabf09351593e4793114bc75794e..c6194850282c06192f15873a3045207d43488baf 100644 --- a/app/views/reshares/_reshare.haml +++ b/app/views/reshares/_reshare.haml @@ -16,7 +16,7 @@ %span.timeago = link_to(how_long_ago(post), post_path(post)) – - = t("reshares.reshare.reshare", :count => post.reshare_count) + = t("reshares.reshare.reshare", :count => post.reshares_count) - if post.activity_streams? = link_to image_tag(post.image_url, 'data-small-photo' => post.image_url, 'data-full-photo' => post.image_url, :class => 'stream-photo'), post.object_url, :class => "stream-photo-link" diff --git a/app/views/shared/_stream_element.html.haml b/app/views/shared/_stream_element.html.haml index 6f9467bb3380c085804169cae05642eb234dd9bc..8bbc8c6279cfa8d65bd58b50388e2c9e27d269cd 100644 --- a/app/views/shared/_stream_element.html.haml +++ b/app/views/shared/_stream_element.html.haml @@ -32,6 +32,10 @@ – %span.timeago = link_to(how_long_ago(post), post_path(post)) + - if post.reshares_count > 0 + – + %span.num_reshares + = t("reshares.reshare.reshare", :count => post.reshares.size) .post-content = nsfw_sheild(post) diff --git a/db/migrate/20111111025358_counter_cache_on_post_reshares.rb b/db/migrate/20111111025358_counter_cache_on_post_reshares.rb new file mode 100644 index 0000000000000000000000000000000000000000..ffeed45665489b5b8406c7ea7f9e7e5bff750e9e --- /dev/null +++ b/db/migrate/20111111025358_counter_cache_on_post_reshares.rb @@ -0,0 +1,35 @@ +class CounterCacheOnPostReshares < ActiveRecord::Migration + class Post < ActiveRecord::Base; end + + def self.up + add_column :posts, :reshares_count, :integer, :default => 0 + + if postgres? + execute %{ + UPDATE posts + SET reshares_count = ( + SELECT COUNT(*) + FROM posts p2 + WHERE + p2.type = 'Reshare' + AND p2.root_guid = posts.guid + ) + } + else # mysql + execute "CREATE TEMPORARY TABLE posts_reshared SELECT * FROM posts WHERE type = 'Reshare'" + execute %{ + UPDATE posts p1 + SET reshares_count = ( + SELECT COUNT(*) + FROM posts_reshared p2 + WHERE p2.root_guid = p1.guid + ) + } + end + + end + + def self.down + remove_column :posts, :reshares_count + end +end diff --git a/db/schema.rb b/db/schema.rb index 26a9bacf3ab85da7e4724bd3d5db41b8ce10efb8..d224545e85442dfbd9bfdb9542ec406686de34cc 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -314,6 +314,7 @@ ActiveRecord::Schema.define(:version => 20111217042006) do t.integer "likes_count", :default => 0 t.integer "comments_count", :default => 0 t.integer "o_embed_cache_id" + t.integer "reshares_count", :default => 0 t.integer "photos_count", :default => 0 end diff --git a/lib/diaspora/shareable.rb b/lib/diaspora/shareable.rb index 1ba5746ef8e770f4ce79e50519ddc2d8aecc04ad..541cc882c6b1ab211091a30da771174fa75f9ec1 100644 --- a/lib/diaspora/shareable.rb +++ b/lib/diaspora/shareable.rb @@ -107,6 +107,11 @@ module Diaspora end end + # @return [Integer] + def update_reshares_counter + self.class.where(:id => self.id). + update_all(:reshares_count => self.reshares.count) + end protected diff --git a/spec/helpers/reshares_helper_spec.rb b/spec/helpers/reshares_helper_spec.rb index af5bac1e13e06ef8fc8f421a242acd507236567c..5907fcca4b024f0a30c9c9683bfb9ecae12ae6c7 100644 --- a/spec/helpers/reshares_helper_spec.rb +++ b/spec/helpers/reshares_helper_spec.rb @@ -1,15 +1,5 @@ require 'spec_helper' -# Specs in this file have access to a helper object that includes -# the ResharesHelper. For example: -# -# describe ResharesHelper do -# describe "string concat" do -# it "concats two strings with spaces" do -# helper.concat_strings("this","that").should == "this that" -# end -# end -# end describe ResharesHelper do include StreamHelper @@ -20,5 +10,41 @@ describe ResharesHelper do reshare_link(reshare) }.should_not raise_error end + + describe 'for a typical post' do + before :each do + aspect = alice.aspects.first + @post = alice.build_post :status_message, :text => "ohai", :to => aspect.id, :public => true + @post.save! + alice.add_to_streams(@post, [aspect]) + alice.dispatch_post @post, :to => aspect.id + end + + describe 'which has not been reshared' do + before :each do + @post.reshares_count.should == 0 + end + + it 'has "Reshare" as the English text' do + reshare_link(@post).should =~ %r{>Reshare</a>} + end + end + + describe 'which has been reshared' do + before :each do + @reshare = Factory.create(:reshare, :root => @post) + @post.reload + @post.reshares_count.should == 1 + end + + it 'has "Reshare" as the English text' do + reshare_link(@post).should =~ %r{>Reshare</a>} + end + + it 'its reshare has "Reshare original" as the English text' do + reshare_link(@reshare).should =~ %r{>Reshare original</a>} + end + end + end end end diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index fa546987ed17650b221aec7d78f0093ee196d986..aaf881e1d166867ee6b5e8df751382ea22d37c8b 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -24,7 +24,7 @@ describe Post do StatusMessage.owned_or_visible_by_user(@you).should include(@post_from_contact) end - it 'returns your posts' do + it 'returns your posts' do StatusMessage.owned_or_visible_by_user(@you).should include(@your_post) end @@ -378,4 +378,45 @@ describe Post do end end end + + describe '#reshares_count' do + before :each do + @post = @user.post :status_message, :text => "hello", :to => @aspect.id, :public => true + @post.reshares.size.should == 0 + end + + describe 'when post has not been reshared' do + it 'returns zero' do + @post.reshares_count.should == 0 + end + end + + describe 'when post has been reshared exactly 1 time' do + before :each do + @post.reshares.size.should == 0 + @reshare = Factory.create(:reshare, :root => @post) + @post.reload + @post.reshares.size.should == 1 + end + + it 'returns 1' do + @post.reshares_count.should == 1 + end + end + + describe 'when post has been reshared more than once' do + before :each do + @post.reshares.size.should == 0 + Factory.create(:reshare, :root => @post) + Factory.create(:reshare, :root => @post) + Factory.create(:reshare, :root => @post) + @post.reload + @post.reshares.size.should == 3 + end + + it 'returns the number of reshares' do + @post.reshares_count.should == 3 + end + end + end end diff --git a/spec/models/reshare_spec.rb b/spec/models/reshare_spec.rb index 51687a2a12c8c3c8a656f2f53bbcfd06134ba8ae..5795fc9eba54ac64b9497968989b3a8457d5575a 100644 --- a/spec/models/reshare_spec.rb +++ b/spec/models/reshare_spec.rb @@ -18,7 +18,9 @@ describe Reshare do end it 'require public root' do - Factory.build(:reshare, :root => Factory.build(:status_message, :public => false)).should_not be_valid + reshare = Factory.build(:reshare, :root => Factory.build(:status_message, :public => false)) + reshare.should_not be_valid + reshare.errors[:base].should include('Only posts which are public may be reshared.') end it 'forces public' do