diff --git a/app/controllers/aspects_controller.rb b/app/controllers/aspects_controller.rb index d755a72685f6b4de2262336e652ab2187f0417af..ed2d1faa1f199827b5e678881d4ce8ad0f874d74 100644 --- a/app/controllers/aspects_controller.rb +++ b/app/controllers/aspects_controller.rb @@ -31,7 +31,7 @@ class AspectsController < ApplicationController @aspect_ids = @aspects.map{|a| a.id} @posts = StatusMessage.joins(:aspects).where(:pending => false, - :aspects => {:id => @aspect_ids}).includes(:comments, :photos).select('DISTINCT `posts`.*').paginate( + :aspects => {:id => @aspect_ids}).includes(:comments, :photos, :likes, :dislikes).select('DISTINCT `posts`.*').paginate( :page => params[:page], :per_page => 15, :order => sort_order + ' DESC') @fakes = PostsFake.new(@posts) diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 6e2ac8f5e4063f0a58e8e861e2aaa26d16cce77a..9f66f2b1524c5a924d704d7c10acae70bd864ca5 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -37,10 +37,10 @@ class CommentsController < ApplicationController format.mobile{ redirect_to status_message_path(@comment.post_id) } end else - render :nothing => true, :status => 406 + render :nothing => true, :status => 422 end else - render :nothing => true, :status => 406 + render :nothing => true, :status => 422 end end diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..6eef3bebb6d885c0c65723629e6d2fa9121c5550 --- /dev/null +++ b/app/controllers/likes_controller.rb @@ -0,0 +1,44 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +class LikesController < ApplicationController + include ApplicationHelper + before_filter :authenticate_user! + + respond_to :html, :mobile, :json + + def create + target = current_user.find_visible_post_by_id params[:post_id] + positive = (params[:positive] == 'true') ? true : false + if target + @like = current_user.build_like(positive, :on => target) + + if @like.save + Rails.logger.info("event=create type=like user=#{current_user.diaspora_handle} status=success like=#{@like.id} positive=#{positive}") + Postzord::Dispatch.new(current_user, @like).post + + respond_to do |format| + format.js { + json = { :post_id => @like.post_id, + :html => render_to_string( + :partial => 'likes/likes', + :locals => { + :likes => @like.post.likes, + :dislikes => @like.post.dislikes + } + ) + } + render(:json => json, :status => 201) + } + format.html { render :nothing => true, :status => 201 } + format.mobile { redirect_to status_message_path(@like.post_id) } + end + else + render :nothing => true, :status => 422 + end + else + render :nothing => true, :status => 422 + end + end +end diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 17ec166342684c66f71679b7e8e8051480899054..13fa0f488fc4b206a3c3232a5c2d9e9aa32fb442 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -111,10 +111,10 @@ class PhotosController < ApplicationController :status => 201} end else - render :nothing => true, :status => 406 + render :nothing => true, :status => 422 end else - render :nothing => true, :status => 406 + render :nothing => true, :status => 422 end end diff --git a/app/helpers/likes_helper.rb b/app/helpers/likes_helper.rb new file mode 100644 index 0000000000000000000000000000000000000000..fde7be672fa00c021f2648a9886ec0ffeceec499 --- /dev/null +++ b/app/helpers/likes_helper.rb @@ -0,0 +1,10 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +module LikesHelper + def likes_list likes + links = likes.collect { |like| link_to "#{h(like.author.name.titlecase)}", person_path(like.author) } + links.join(", ").html_safe + end +end diff --git a/app/helpers/sockets_helper.rb b/app/helpers/sockets_helper.rb index 8202ee9f3d43db5e6e690d4b9052b4de633efaf0..92b5fa11fc391b73347b9fb3b7f3c7f13b8d16bf 100644 --- a/app/helpers/sockets_helper.rb +++ b/app/helpers/sockets_helper.rb @@ -50,6 +50,9 @@ module SocketsHelper elsif object.is_a? Comment v = render_to_string(:partial => 'comments/comment', :locals => {:comment => object, :person => object.author}) + elsif object.is_a? Like + v = render_to_string(:partial => 'likes/likes', :locals => {:likes => object.post.likes, :dislikes => object.post.dislikes}) + elsif object.is_a? Notification v = render_to_string(:partial => 'notifications/popup', :locals => {:note => object, :person => opts[:actor]}) @@ -74,6 +77,10 @@ module SocketsHelper end + if object.is_a? Like + action_hash[:post_guid] = object.post.guid + end + action_hash[:mine?] = object.author && (object.author.owner_id == uid) if object.respond_to?(:author) I18n.locale = old_locale unless user.nil? diff --git a/app/models/like.rb b/app/models/like.rb new file mode 100644 index 0000000000000000000000000000000000000000..60ac461d9ad43065faa05c6ab8a5d3262666c73e --- /dev/null +++ b/app/models/like.rb @@ -0,0 +1,42 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +class Like < ActiveRecord::Base + require File.join(Rails.root, 'lib/diaspora/web_socket') + include ROXML + + include Diaspora::Webhooks + include Diaspora::Relayable + include Diaspora::Guid + + include Diaspora::Socketable + + xml_attr :positive + xml_attr :diaspora_handle + + belongs_to :post + belongs_to :author, :class_name => 'Person' + + validates_uniqueness_of :post_id, :scope => :author_id + + def diaspora_handle + self.author.diaspora_handle + end + + def diaspora_handle= nh + self.author = Webfinger.new(nh).fetch + end + + def parent_class + Post + end + + def parent + self.post + end + + def parent= parent + self.post = parent + end +end diff --git a/app/models/post.rb b/app/models/post.rb index dd103edc00728a5cfe899c5cc2845a13ec209301..627496a68885da5982ba768c252d883fa2d08c5a 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -14,6 +14,8 @@ class Post < ActiveRecord::Base xml_attr :created_at has_many :comments, :order => 'created_at ASC' + has_many :likes, :conditions => '`likes`.`positive` = 1' + has_many :dislikes, :conditions => '`likes`.`positive` = 0', :class_name => 'Like' has_many :post_visibilities has_many :aspects, :through => :post_visibilities has_many :mentions, :dependent => :destroy diff --git a/app/models/user.rb b/app/models/user.rb index cc9ec26095e5f61eade0f43f7cf6d19ce284ac84..ffcf0d2ce98f0d3f313dbdc46318449c4d7b7ef2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -176,6 +176,32 @@ class User < ActiveRecord::Base comment end + ######## Liking ######## + def build_like(positive, options = {}) + like = Like.new(:author_id => self.person.id, + :positive => positive, + :post => options[:on]) + like.set_guid + #sign like as liker + like.author_signature = like.sign_with_key(self.encryption_key) + + if !like.post_id.blank? && person.owns?(like.parent) + #sign like as post owner + like.parent_author_signature = like.sign_with_key(self.encryption_key) + end + + like + end + + def liked?(post) + [post.likes, post.dislikes].each do |likes| + likes.each do |like| + return true if like.author_id == self.person.id + end + end + return false + end + ######### Mailer ####################### def mail(job, *args) pref = job.to_s.gsub('Job::Mail', '').underscore diff --git a/app/views/likes/_likes.haml b/app/views/likes/_likes.haml new file mode 100644 index 0000000000000000000000000000000000000000..2c1ebe1e8520ed1d12e6aa683d5aa2cf6bbef674 --- /dev/null +++ b/app/views/likes/_likes.haml @@ -0,0 +1,17 @@ +-# Copyright (c) 2010, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + +- if likes.length > 0 + .likes + = image_tag('icons/happy_smiley.png') + = link_to t('.people_like_this', :count => likes.length), "#", :class => "expand_likes" + %span.hidden.likes_list + = likes_list(likes) + +- if dislikes.length > 0 + .dislikes + = image_tag('icons/sad_smiley.png') + = link_to t('.people_dislike_this', :count => dislikes.length), "#", :class => "expand_dislikes" + %span.hidden.dislikes_list + = likes_list(dislikes) diff --git a/app/views/photos/show.html.haml b/app/views/photos/show.html.haml index fc967e74fe52e39355dbd3fdf7bf484a9e405020..3aa7fb7378ba395f73eca7930504d1e4c30be338 100644 --- a/app/views/photos/show.html.haml +++ b/app/views/photos/show.html.haml @@ -66,5 +66,13 @@ = t('_comments') #photo_stream.stream.show + - if (defined?(current_user) && !current_user.liked?(@parent)) + %span.like_links + = link_to t('shared.stream_element.like'), {:controller => "likes", :action => "create", :positive => 'true', :post_id => @parent.id }, :class => "like_it", :remote => true + | + = link_to t('shared.stream_element.dislike'), {:controller => "likes", :action => "create", :positive => 'false', :post_id => @parent.id }, :class => "dislike_it", :remote => true + %div{:data=>{:guid=>@parent.id}} + .likes_container + = render "likes/likes", :post_id => @parent.id, :likes => @parent.likes, :dislikes => @parent.dislikes = render "comments/comments", :post_id => @parent.id, :comments => @parent.comments, :always_expanded => true diff --git a/app/views/shared/_stream_element.html.haml b/app/views/shared/_stream_element.html.haml index d65ac48e34262331391dfb493a2c5713912892e2..eca6529f4258ace5fc8bb6f1331dab4f665a1f28 100644 --- a/app/views/shared/_stream_element.html.haml +++ b/app/views/shared/_stream_element.html.haml @@ -32,6 +32,15 @@ = link_to(how_long_ago(post), status_message_path(post)) - unless (defined?(@commenting_disabled) && @commenting_disabled) - = link_to t('comments.new_comment.comment').downcase, '#', :class => 'focus_comment_textarea' + = link_to t('comments.new_comment.comment'), '#', :class => 'focus_comment_textarea' + - if (defined?(current_user) && !current_user.liked?(post)) + %span.like_links + | + = link_to t('.like'), {:controller => "likes", :action => "create", :positive => 'true', :post_id => post.id }, :class => "like_it", :remote => true + | + = link_to t('.dislike'), {:controller => "likes", :action => "create", :positive => 'false', :post_id => post.id }, :class => "dislike_it", :remote => true + + .likes_container + = render "likes/likes", :post_id => post.id, :likes => post.likes, :dislikes => post.dislikes, :current_user => current_user = render "comments/comments", :post_id => post.id, :comments => post.comments, :current_user => current_user, :condensed => true, :commenting_disabled => (defined?(@commenting_disabled) && @commenting_disabled) diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index 4dc2743b720e6aa4c5fa122643c1ff0365284a3c..dc5d9c6d50378425655c9a7bed0a1f14a4a64d27 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -157,7 +157,7 @@ en: many: "%{count} comments" other: "%{count} comments" new_comment: - comment: "Comment" + comment: "comment" commenting: "Commenting..." contacts: @@ -262,6 +262,22 @@ en: toggle: "toggle mobile site" public_feed: "Public Diaspora Feed for %{name}" + + likes: + likes: + people_like_this: + zero: "no people liked this" + one: "1 person liked this" + few: "%{count} people liked this" + many: "%{count} people liked this" + other: "%{count} people liked this" + people_dislike_this: + zero: "no people disliked this" + one: "1 person disliked this" + few: "%{count} people disliked this" + many: "%{count} people disliked this" + other: "%{count} people disliked this" + notifications: request_accepted: "accepted your share request." new_request: "offered to share with you." @@ -537,6 +553,9 @@ en: contact_list: all_contacts: "All contacts" cannot_remove: "Cannot remove person from last aspect. (If you want to disconnect from this person you must remove contact.)" + stream_element: + like: "I like this" + dislike: "I dislike this" status_messages: new: diff --git a/config/routes.rb b/config/routes.rb index ad70d3e2337c96d77d21b82f7a28378d549ac657..2cf65a096084873d350eda1cd46643da36376247 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,6 +6,8 @@ Diaspora::Application.routes.draw do resources :status_messages, :only => [:new, :create, :destroy, :show] resources :comments, :only => [:create] resources :requests, :only => [:destroy, :create] + match '/likes' => 'likes#create' + resources :likes, :only => [:create] match 'tags/:name' => 'tags#show' resources :tags, :only => [:show] diff --git a/db/migrate/201110319172136_add_likes.rb b/db/migrate/201110319172136_add_likes.rb new file mode 100644 index 0000000000000000000000000000000000000000..0cf481ae4f764ee9b02c57ac7cba7d8183949b27 --- /dev/null +++ b/db/migrate/201110319172136_add_likes.rb @@ -0,0 +1,21 @@ +class AddLikes < ActiveRecord::Migration + def self.up + create_table :likes do |t| + t.boolean :positive, :default => true + t.integer :post_id + t.integer :author_id + t.string :guid + t.text :author_signature + t.text :parent_author_signature + t.timestamps + end + add_index :likes, :guid, :unique => true + add_index :likes, :post_id + add_foreign_key(:likes, :posts, :dependant => :delete) + add_foreign_key(:likes, :people, :column => :author_id, :dependant => :delete) + end + + def self.down + drop_table :likes + end +end diff --git a/db/schema.rb b/db/schema.rb index a55b15a5c377b73f6fd52ed69334a3ee03ac6e31..ca201bb39e70a30552422b2ab776487422a8a617 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 => 20110319005509) do +ActiveRecord::Schema.define(:version => 201110319172136) do create_table "aspect_memberships", :force => true do |t| t.integer "aspect_id", :null => false @@ -105,6 +105,21 @@ ActiveRecord::Schema.define(:version => 20110319005509) do add_index "invitations", ["recipient_id"], :name => "index_invitations_on_recipient_id" add_index "invitations", ["sender_id"], :name => "index_invitations_on_sender_id" + create_table "likes", :force => true do |t| + t.boolean "positive", :default => true + t.integer "post_id" + t.integer "author_id" + t.string "guid" + t.text "author_signature" + t.text "parent_author_signature" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "likes", ["author_id"], :name => "likes_author_id_fk" + add_index "likes", ["guid"], :name => "index_likes_on_guid", :unique => true + add_index "likes", ["post_id"], :name => "index_likes_on_post_id" + create_table "mentions", :force => true do |t| t.integer "post_id", :null => false t.integer "person_id", :null => false @@ -342,6 +357,9 @@ ActiveRecord::Schema.define(:version => 20110319005509) do add_foreign_key "invitations", "users", :name => "invitations_recipient_id_fk", :column => "recipient_id", :dependent => :delete add_foreign_key "invitations", "users", :name => "invitations_sender_id_fk", :column => "sender_id", :dependent => :delete + add_foreign_key "likes", "people", :name => "likes_author_id_fk", :column => "author_id" + add_foreign_key "likes", "posts", :name => "likes_post_id_fk" + add_foreign_key "notification_actors", "notifications", :name => "notification_actors_notification_id_fk", :dependent => :delete add_foreign_key "posts", "people", :name => "posts_author_id_fk", :column => "author_id", :dependent => :delete diff --git a/public/images/icons/happy_smiley.png b/public/images/icons/happy_smiley.png new file mode 100644 index 0000000000000000000000000000000000000000..f9b44488d3b8e9f3cf70981f6d00f69386c03796 Binary files /dev/null and b/public/images/icons/happy_smiley.png differ diff --git a/public/images/icons/sad_smiley.png b/public/images/icons/sad_smiley.png new file mode 100644 index 0000000000000000000000000000000000000000..3e2de91c5b5a7694f27d276ba5073ba43f4773f5 Binary files /dev/null and b/public/images/icons/sad_smiley.png differ diff --git a/public/javascripts/stream.js b/public/javascripts/stream.js index b19c6f75c58f29955a12b9d39d2f2e2b42984e63..17e4eaba87f5ff713a370f7ad8ddbd12f06293e5 100644 --- a/public/javascripts/stream.js +++ b/public/javascripts/stream.js @@ -39,6 +39,32 @@ var Stream = { } }); + // like/dislike + $stream.delegate("a.expand_likes", "click", function(evt) { + evt.preventDefault(); + $(this).siblings('.likes_list').fadeToggle('fast'); + }); + + $stream.delegate("a.expand_dislikes", "click", function(evt) { + evt.preventDefault(); + $(this).siblings('.dislikes_list').fadeToggle('fast'); + }); + + $(".like_it, .dislike_it").live('ajax:loading', function(data, json, xhr) { + $(this).parent().fadeOut('fast'); + }); + + $(".like_it, .dislike_it").live('ajax:success', function(data, json, xhr) { + $(this).parent().detach(); + json = $.parseJSON(json); + WebSocketReceiver.processLike(json.post_id, json.html); + }); + + $('.like_it, .dislike_it').live('ajax:failure', function(data, html, xhr) { + Diaspora.widgets.alert.alert('Failed to like/dislike!'); + $(this).parent().fadeIn('fast'); + }); + // reshare button action $stream.delegate(".reshare_button", "click", function(evt) { evt.preventDefault(); diff --git a/public/javascripts/web-socket-receiver.js b/public/javascripts/web-socket-receiver.js index cb888f857ddd81882f88316a95c9328191cad209..4944198fc8b006ea01f0ca8cc3f3f5f954b16f2f 100644 --- a/public/javascripts/web-socket-receiver.js +++ b/public/javascripts/web-socket-receiver.js @@ -36,6 +36,9 @@ var WebSocketReceiver = { 'my_post?': obj['my_post?'] }); + } else if (obj['class']=="likes") { + WebSocketReceiver.processLike(obj.post_id, obj.html) + } else { WebSocketReceiver.processPost(obj['class'], obj.post_id, obj.html, obj.aspect_ids); } @@ -116,6 +119,11 @@ var WebSocketReceiver = { Diaspora.widgets.timeago.updateTimeAgo(); }, + processLike: function(postId, html) { + var post = $("*[data-guid='"+postId+"']"); + $(".likes_container", post).fadeOut('fast').html(html).fadeIn('fast'); + }, + processPost: function(className, postId, html, aspectIds) { if(WebSocketReceiver.onPageForAspects(aspectIds)) { WebSocketReceiver.addPostToStream(postId, html); diff --git a/public/stylesheets/sass/application.sass b/public/stylesheets/sass/application.sass index 9e801f8db4f0aff41e89965d3926d1796bd9c304..c993eca687a60db70057631d68914f2361318543 100644 --- a/public/stylesheets/sass/application.sass +++ b/public/stylesheets/sass/application.sass @@ -563,7 +563,9 @@ header :align right ul.comments, -ul.show_comments +ul.show_comments, +div.likes, +div.dislikes :margin 0 :top 0.5em :padding 0 @@ -2320,7 +2322,9 @@ h3,h4 :position relative :z-index 10 -ul.show_comments +ul.show_comments, +div.likes, +div.dislikes :margin :bottom -0.5em > li @@ -2852,3 +2856,16 @@ h1.tag .share_with :background :color rgb(245,245,245) + +.likes_container + .likes, + .dislikes + :border-bottom 1px solid white + a + :padding 1px + :vertical-align middle + :font-size smaller + img + :width 12px + :height 12px + :margin-left 0.5em diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb index 0f2b3897e6cd5cea8ac7828db7a9a1b2d7392bcf..9682b40e504925a00c8ae6f1755f25b3ed1d0f86 100644 --- a/spec/controllers/comments_controller_spec.rb +++ b/spec/controllers/comments_controller_spec.rb @@ -61,7 +61,7 @@ describe CommentsController do it 'posts no comment' do @user1.should_not_receive(:comment) post :create, comment_hash - response.code.should == '406' + response.code.should == '422' end end end diff --git a/spec/controllers/likes_controller_spec.rb b/spec/controllers/likes_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..afa2d8df92c1810fbed0f16c1337335431b39148 --- /dev/null +++ b/spec/controllers/likes_controller_spec.rb @@ -0,0 +1,68 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require 'spec_helper' + +describe LikesController do + render_views + + before do + @user1 = alice + @user2 = bob + + @aspect1 = @user1.aspects.first + @aspect2 = @user2.aspects.first + + sign_in :user, @user1 + end + + describe '#create' do + let(:like_hash) { + {:positive => 1, + :post_id => "#{@post.id}"} + } + let(:dislike_hash) { + {:positive => 0, + :post_id => "#{@post.id}"} + } + context "on my own post" do + before do + @post = @user1.post :status_message, :text => "AWESOME", :to => @aspect1.id + end + it 'responds to format js' do + post :create, like_hash.merge(:format => 'js') + response.code.should == '201' + end + end + + context "on a post from a contact" do + before do + @post = @user2.post :status_message, :text => "AWESOME", :to => @aspect2.id + end + it 'likes' do + post :create, like_hash + response.code.should == '201' + end + it 'dislikes' do + post :create, dislike_hash + response.code.should == '201' + end + it "doesn't post multiple times" do + @user1.like(1, :on => @post) + post :create, dislike_hash + response.code.should == '422' + end + end + context "on a post from a stranger" do + before do + @post = eve.post :status_message, :text => "AWESOME", :to => eve.aspects.first.id + end + it "doesn't post" do + @user1.should_not_receive(:like) + post :create, like_hash + response.code.should == '422' + end + end + end +end diff --git a/spec/controllers/photos_controller_spec.rb b/spec/controllers/photos_controller_spec.rb index bc795ad77c0cf302beae40329dda35269da68d3f..9b098b2dbd74bc08b43f450462b12667dac56ad4 100644 --- a/spec/controllers/photos_controller_spec.rb +++ b/spec/controllers/photos_controller_spec.rb @@ -162,9 +162,9 @@ describe PhotosController do response.code.should == "201" end - it 'should return a 406 on failure' do + it 'should return a 422 on failure' do get :make_profile_photo, :photo_id => @bobs_photo.id - response.code.should == "406" + response.code.should == "422" end end diff --git a/spec/models/like_spec.rb b/spec/models/like_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..9fea70324b5082f1ce25958c576fbc83f2d589a9 --- /dev/null +++ b/spec/models/like_spec.rb @@ -0,0 +1,80 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require 'spec_helper' +require File.join(Rails.root, "spec", "shared_behaviors", "relayable") + +describe Like do + before do + @alices_aspect = alice.aspects.first + @bobs_aspect = bob.aspects.first + + @bob = bob + @eve = eve + @status = alice.post(:status_message, :text => "hello", :to => @alices_aspect.id) + end + + describe 'User#like' do + it "should be able to like on one's own status" do + alice.like(1, :on => @status) + @status.reload.likes.first.positive.should == true + end + + it "should be able to like on a contact's status" do + bob.like(0, :on => @status) + @status.reload.dislikes.first.positive.should == false + end + + it "does not allow multiple likes" do + lambda { + alice.like(1, :on => @status) + alice.like(0, :on => @status) + }.should raise_error + end + end + + describe 'xml' do + before do + @liker = Factory.create(:user) + @liker_aspect = @liker.aspects.create(:name => "dummies") + connect_users(alice, @alices_aspect, @liker, @liker_aspect) + @post = alice.post :status_message, :text => "huhu", :to => @alices_aspect.id + @like = @liker.like 0, :on => @post + @xml = @like.to_xml.to_s + end + it 'serializes the sender handle' do + @xml.include?(@liker.diaspora_handle).should be_true + end + it' serializes the post_guid' do + @xml.should include(@post.guid) + end + describe 'marshalling' do + before do + @marshalled_like = Like.from_xml(@xml) + end + it 'marshals the author' do + @marshalled_like.author.should == @liker.person + end + it 'marshals the post' do + @marshalled_like.post.should == @post + end + end + end + + describe 'it is relayable' do + before do + @local_luke, @local_leia, @remote_raphael = set_up_friends + @remote_parent = Factory.create(:status_message, :author => @remote_raphael) + @local_parent = @local_luke.post :status_message, :text => "foobar", :to => @local_luke.aspects.first + + @object_by_parent_author = @local_luke.like(1, :on => @local_parent) + @object_by_recipient = @local_leia.build_like(1, :on => @local_parent) + @dup_object_by_parent_author = @object_by_parent_author.dup + + @object_on_remote_parent = @local_luke.like(0, :on => @remote_parent) + end + it_should_behave_like 'it is relayable' + end + +end diff --git a/spec/support/user_methods.rb b/spec/support/user_methods.rb index 975d7c5d9e3eaebca9dc820b787567f158fb9950..4382b752b355558a38b800e532bfc951d2db26f0 100644 --- a/spec/support/user_methods.rb +++ b/spec/support/user_methods.rb @@ -37,6 +37,16 @@ class User end end + def like(positive, options ={}) + fantasy_resque do + l = build_like(positive, options) + if l.save! + Postzord::Dispatch.new(self, l).post + end + l + end + end + def post_at_time(time) p = self.post(:status_message, :text => 'hi', :to => self.aspects.first) p.created_at = time