From 02a3c3f88b4bd3cae3954ae2f4740e32af568898 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Manuel=20Sch=C3=B6lling?= <manuel.schoelling@gmx.de>
Date: Thu, 25 Aug 2011 20:26:36 +0200
Subject: [PATCH] Introduced Shareable

---
 ...er.rb => share_visibilities_controller.rb} | 11 ++--
 app/helpers/aspect_global_helper.rb           |  2 +-
 app/models/aspect.rb                          |  2 +-
 app/models/aspect_visibility.rb               |  4 +-
 app/models/contact.rb                         |  6 +--
 app/models/notification.rb                    |  8 +--
 app/models/post.rb                            | 12 ++---
 app/models/post_visibility.rb                 | 27 ----------
 app/models/share_visibility.rb                | 26 ++++++++++
 app/models/status_message.rb                  |  4 +-
 app/views/posts/show.mobile.haml              |  1 +
 .../update.js.erb                             |  0
 app/views/shared/_stream_element.html.haml    |  8 +--
 config/routes.rb                              |  2 +-
 db/migrate/20110824190037_share_anything.rb   | 41 +++++++++++++++
 db/schema.rb                                  | 51 +++++++++----------
 lib/diaspora/shareable.rb                     | 17 +++++++
 lib/diaspora/user/connecting.rb               |  8 +--
 lib/diaspora/user/querying.rb                 |  6 +--
 lib/postzord/receiver/local_batch.rb          |  6 +--
 ... => share_visibilities_controller_spec.rb} | 10 ++--
 spec/integration/receiving_spec.rb            | 18 +++----
 .../lib/postzord/receiver/local_batch_spec.rb | 14 ++---
 spec/models/jobs/receive_local_batch_spec.rb  |  2 +-
 spec/models/notification_spec.rb              |  2 +-
 ...ility_spec.rb => share_visibility_spec.rb} | 10 ++--
 spec/models/user/connecting_spec.rb           | 10 ++--
 spec/models/user/querying_spec.rb             |  2 +-
 28 files changed, 181 insertions(+), 129 deletions(-)
 rename app/controllers/{post_visibilities_controller.rb => share_visibilities_controller.rb} (67%)
 delete mode 100644 app/models/post_visibility.rb
 create mode 100644 app/models/share_visibility.rb
 rename app/views/{post_visibilities => share_visibilities}/update.js.erb (100%)
 create mode 100644 db/migrate/20110824190037_share_anything.rb
 create mode 100644 lib/diaspora/shareable.rb
 rename spec/controllers/{post_visibilities_controller_spec.rb => share_visibilities_controller_spec.rb} (93%)
 rename spec/models/{post_visibility_spec.rb => share_visibility_spec.rb} (61%)

diff --git a/app/controllers/post_visibilities_controller.rb b/app/controllers/share_visibilities_controller.rb
similarity index 67%
rename from app/controllers/post_visibilities_controller.rb
rename to app/controllers/share_visibilities_controller.rb
index eb0c46855e..b7fca13860 100644
--- a/app/controllers/post_visibilities_controller.rb
+++ b/app/controllers/share_visibilities_controller.rb
@@ -3,18 +3,21 @@
 #   the COPYRIGHT file.
 #
 
-class PostVisibilitiesController < ApplicationController
+class ShareVisibilitiesController < ApplicationController
   before_filter :authenticate_user!
 
   def update
     #note :id references a postvisibility
+    params[:shareable_id] ||= params[:post_id]
+    params[:shareable_type] ||= 'Post'
 
     @post = accessible_post
     @contact = current_user.contact_for(@post.author)
 
-    if @contact && @vis = PostVisibility.where(:contact_id => @contact.id,
-                                               :post_id => params[:post_id]).first
-      @vis.hidden = !@vis.hidden 
+    if @contact && @vis = ShareVisibility.where(:contact_id => @contact.id,
+                                                :shareable_id => params[:shareable_id],
+                                                :shareable_type => params[:shareable_type]).first
+      @vis.hidden = !@vis.hidden
       if @vis.save
         update_cache(@vis)
         render 'update'
diff --git a/app/helpers/aspect_global_helper.rb b/app/helpers/aspect_global_helper.rb
index 276f3591b5..98d5a21afc 100644
--- a/app/helpers/aspect_global_helper.rb
+++ b/app/helpers/aspect_global_helper.rb
@@ -5,7 +5,7 @@
 module AspectGlobalHelper
   def aspects_with_post(aspects, post)
     aspects.select do |aspect|
-      AspectVisibility.exists?(:aspect_id => aspect.id, :post_id => post.id)
+      AspectVisibility.exists?(:aspect_id => aspect.id, :shareable_id => post.id, :shareable_type => 'Post')
     end
   end
 
diff --git a/app/models/aspect.rb b/app/models/aspect.rb
index 55dd2dccb0..056bb102f5 100644
--- a/app/models/aspect.rb
+++ b/app/models/aspect.rb
@@ -9,7 +9,7 @@ class Aspect < ActiveRecord::Base
   has_many :contacts, :through => :aspect_memberships
 
   has_many :aspect_visibilities
-  has_many :posts, :through => :aspect_visibilities
+  has_many :posts, :through => :aspect_visibilities, :source => :shareable, :source_type => 'Post'
   
   validates :name, :presence => true, :length => { :maximum => 20 }
 
diff --git a/app/models/aspect_visibility.rb b/app/models/aspect_visibility.rb
index 42f560eade..a5593b8340 100644
--- a/app/models/aspect_visibility.rb
+++ b/app/models/aspect_visibility.rb
@@ -7,7 +7,7 @@ class AspectVisibility < ActiveRecord::Base
   belongs_to :aspect
   validates :aspect, :presence => true
 
-  belongs_to :post
-  validates :post, :presence => true
+  belongs_to :shareable, :polymorphic => true
+  validates :shareable, :presence => true
 
 end
diff --git a/app/models/contact.rb b/app/models/contact.rb
index fa3094b3e9..bbd27edd33 100644
--- a/app/models/contact.rb
+++ b/app/models/contact.rb
@@ -12,8 +12,8 @@ class Contact < ActiveRecord::Base
   has_many :aspect_memberships
   has_many :aspects, :through => :aspect_memberships
 
-  has_many :post_visibilities
-  has_many :posts, :through => :post_visibilities
+  has_many :share_visibilities, :source => :shareable, :source_type => 'Post'
+  has_many :posts, :through => :share_visibilities, :source => :shareable, :source_type => 'Post'
 
   validate :not_contact_for_self
 
@@ -55,7 +55,7 @@ class Contact < ActiveRecord::Base
   end
 
   def receive_post(post)
-    PostVisibility.create!(:post_id => post.id, :contact_id => self.id)
+    ShareVisibility.create!(:shareable_id => post.id, :shareable_type => 'Post', :contact_id => self.id)
     post.socket_to_user(self.user, :aspect_ids => self.aspect_ids) if post.respond_to? :socket_to_user
   end
 
diff --git a/app/models/notification.rb b/app/models/notification.rb
index 1a1bbb6c11..40711786aa 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -47,7 +47,7 @@ class Notification < ActiveRecord::Base
 
 private
   def self.concatenate_or_create(recipient, target, actor, notification_type)
-    return nil if post_visiblity_is_hidden?(recipient, target)
+    return nil if share_visiblity_is_hidden?(recipient, target)
     if n = notification_type.where(:target_id => target.id,
                                    :target_type => target.class.base_class,
                                    :recipient_id => recipient.id,
@@ -68,7 +68,7 @@ private
 
 
   def self.make_notification(recipient, target, actor, notification_type)
-    return nil if post_visiblity_is_hidden?(recipient, target)
+    return nil if share_visiblity_is_hidden?(recipient, target)
     n = notification_type.new(:target => target,
                                :recipient_id => recipient.id)
     n.actors = n.actors | [actor]
@@ -78,12 +78,12 @@ private
   end
 
   #horrible hack that should not be here!
-  def self.post_visiblity_is_hidden?(recipient, post)
+  def self.share_visiblity_is_hidden?(recipient, post)
     return false unless post.is_a?(Post)
 
     contact = recipient.contact_for(post.author)
     return false unless contact && recipient && post
-    pv = PostVisibility.where(:contact_id => contact.id, :post_id => post.id).first
+    pv = ShareVisibility.where(:contact_id => contact.id, :shareable_id => post.id, :shareable_type => post.class.base_class.to_s).first
     pv.present? ? pv.hidden? : false
   end
 end
diff --git a/app/models/post.rb b/app/models/post.rb
index 39b662504e..3fddb9abc2 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -11,17 +11,13 @@ class Post < ActiveRecord::Base
 
   include Diaspora::Likeable
   include Diaspora::Commentable
+  include Diaspora::Shareable
 
   xml_attr :diaspora_handle
   xml_attr :provider_display_name
   xml_attr :public
   xml_attr :created_at
 
-  has_many :aspect_visibilities
-  has_many :aspects, :through => :aspect_visibilities
-
-  has_many :post_visibilities
-  has_many :contacts, :through => :post_visibilities
   has_many :mentions, :dependent => :destroy
 
   has_many :reshares, :class_name => "Reshare", :foreign_key => :root_guid, :primary_key => :guid
@@ -56,10 +52,10 @@ class Post < ActiveRecord::Base
   end
 
   def user_refs
-    if AspectVisibility.exists?(:post_id => self.id)
-      self.post_visibilities.count + 1
+    if AspectVisibility.exists?(:shareable_id => self.id, :shareable_type => 'Post')
+      self.share_visibilities.count + 1
     else
-      self.post_visibilities.count
+      self.share_visibilities.count
     end
   end
 
diff --git a/app/models/post_visibility.rb b/app/models/post_visibility.rb
deleted file mode 100644
index 6b41c8d3b8..0000000000
--- a/app/models/post_visibility.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-#   Copyright (c) 2010-2011, Diaspora Inc.  This file is
-#   licensed under the Affero General Public License version 3 or later.  See
-#   the COPYRIGHT file.
-
-class PostVisibility < ActiveRecord::Base
-
-  belongs_to :contact
-  belongs_to :post
-
-  # Perform a batch import, given a set of contacts and a post
-  # @note performs a bulk insert in mySQL; performs linear insertions in postgres
-  # @param contacts [Array<Contact>] Recipients
-  # @param post [Post]
-  # @return [void]
-  def self.batch_import(contact_ids, post)
-    if postgres?
-      contact_ids.each do |contact_id|
-        PostVisibility.find_or_create_by_contact_id_and_post_id(contact_id, post.id)
-      end
-    else
-       new_post_visibilities_data = contact_ids.map do |contact_id|
-        [contact_id, post.id]
-      end
-      PostVisibility.import([:contact_id, :post_id], new_post_visibilities_data)
-    end
-  end
-end
diff --git a/app/models/share_visibility.rb b/app/models/share_visibility.rb
new file mode 100644
index 0000000000..cfadc0047d
--- /dev/null
+++ b/app/models/share_visibility.rb
@@ -0,0 +1,26 @@
+#   Copyright (c) 2010-2011, Diaspora Inc.  This file is
+#   licensed under the Affero General Public License version 3 or later.  See
+#   the COPYRIGHT file.
+
+class ShareVisibility < ActiveRecord::Base
+  belongs_to :contact
+  belongs_to :shareable, :polymorphic => :true
+
+  # Perform a batch import, given a set of contacts and a shareable
+  # @note performs a bulk insert in mySQL; performs linear insertions in postgres
+  # @param contacts [Array<Contact>] Recipients
+  # @param share [Shareable]
+  # @return [void]
+  def self.batch_import(contact_ids, share)
+    if postgres?
+      contact_ids.each do |contact_id|
+        ShareVisibility.find_or_create_by_contact_id_and_shareable_id_and_shareable_type(contact_id, share.id, share.type)
+      end
+    else
+       new_share_visibilities_data = contact_ids.map do |contact_id|
+        [contact_id, share.id, share.class.base_class.to_s]
+      end
+      ShareVisibility.import([:contact_id, :shareable_id, :shareable_type], new_share_visibilities_data)
+    end
+  end
+end
diff --git a/app/models/status_message.rb b/app/models/status_message.rb
index 9cc74a7114..df0b2e34c1 100644
--- a/app/models/status_message.rb
+++ b/app/models/status_message.rb
@@ -33,8 +33,8 @@ class StatusMessage < Post
   scope :where_person_is_mentioned, lambda{|person| joins(:mentions).where(:mentions => {:person_id => person.id})}
 
   def self.owned_or_visible_by_user(user)
-    joins("LEFT OUTER JOIN post_visibilities ON post_visibilities.post_id = posts.id").
-    joins("LEFT OUTER JOIN contacts ON contacts.id = post_visibilities.contact_id").
+    joins("LEFT OUTER JOIN share_visibilities ON share_visibilities.shareable_id = posts.id AND share_visibilities.shareable_type = 'Post'").
+    joins("LEFT OUTER JOIN contacts ON contacts.id = share_visibilities.contact_id").
     where(Contact.arel_table[:user_id].eq(user.id).or(
       StatusMessage.arel_table[:public].eq(true).or(
         StatusMessage.arel_table[:author_id].eq(user.person.id)
diff --git a/app/views/posts/show.mobile.haml b/app/views/posts/show.mobile.haml
index 84d886908f..63bf093765 100644
--- a/app/views/posts/show.mobile.haml
+++ b/app/views/posts/show.mobile.haml
@@ -5,3 +5,4 @@
 .stream
   = render :partial => 'shared/stream_element',
     :locals => {:post => @post, :commenting_disabled => commenting_disabled?(@post), :expanded_info => true}
+
diff --git a/app/views/post_visibilities/update.js.erb b/app/views/share_visibilities/update.js.erb
similarity index 100%
rename from app/views/post_visibilities/update.js.erb
rename to app/views/share_visibilities/update.js.erb
diff --git a/app/views/shared/_stream_element.html.haml b/app/views/shared/_stream_element.html.haml
index e2f3dcb1cc..f66f3099ac 100644
--- a/app/views/shared/_stream_element.html.haml
+++ b/app/views/shared/_stream_element.html.haml
@@ -8,15 +8,15 @@
     - if current_user && post.author.owner_id == current_user.id
       = link_to image_tag('deletelabel.png'), post_path(post), :confirm => t('are_you_sure'), :method => :delete, :remote => true, :class => "delete stream_element_delete", :title => t('delete')
     - else
-      = link_to image_tag('deletelabel.png'), post_visibility_path(:id => "42", :post_id => post.id), :method => :put, :remote => true, :class => "delete stream_element_delete vis_hide", :title => t('.hide_and_mute')
+      = link_to image_tag('deletelabel.png'), share_visibility_path(:id => "42", :post_id => post.id), :method => :put, :remote => true, :class => "delete stream_element_delete vis_hide", :title => t('.hide_and_mute')
     = image_tag 'ajax-loader.gif', :class => "hide_loader hidden"
 
   .undo_text.hidden
     %p
-      = t('post_visibilites.update.post_hidden_and_muted', :name => person_link(post.author)).html_safe
+      = t('share_visibilites.update.post_hidden_and_muted', :name => person_link(post.author)).html_safe
     %p
-      = t('post_visibilites.update.see_it_on_their_profile', :name => person_link(post.author)).html_safe
-    = link_to t('undo'), post_visibility_path(:id => "42", :post_id => post.id), :method => :put, :remote => true
+      = t('share_visibilites.update.see_it_on_their_profile', :name => person_link(post.author)).html_safe
+    = link_to t('undo'), share_visibility_path(:id => "42", :post_id => post.id), :method => :put, :remote => true
 
   .sm_body
     = person_image_link(post.author, :size => :thumb_small)
diff --git a/config/routes.rb b/config/routes.rb
index 0c3e44237a..6154daa2d6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -107,7 +107,7 @@ Diaspora::Application.routes.draw do
     get :sharing, :on => :collection
   end
   resources :aspect_memberships, :only   => [:destroy, :create, :update]
-  resources :post_visibilities,  :only   => [:update]
+  resources :share_visibilities,  :only   => [:update]
 
   get 'featured' => 'featured_users#index', :as => 'featured'
 
diff --git a/db/migrate/20110824190037_share_anything.rb b/db/migrate/20110824190037_share_anything.rb
new file mode 100644
index 0000000000..f9bdf3d050
--- /dev/null
+++ b/db/migrate/20110824190037_share_anything.rb
@@ -0,0 +1,41 @@
+class ShareAnything < ActiveRecord::Migration
+  def self.up
+    remove_foreign_key :aspect_visibilities, :posts
+    remove_index :aspect_visibilities, :post_id_and_aspect_id
+    remove_index :aspect_visibilities, :post_id
+
+    change_table :aspect_visibilities do |t|
+      t.rename :post_id, :shareable_id
+      t.string :shareable_type, :default => 'Post', :null => false
+    end
+
+
+    remove_foreign_key :post_visibilities, :posts
+    remove_index :post_visibilities, :contact_id_and_post_id
+    remove_index :post_visibilities, :post_id_and_hidden_and_contact_id
+
+    change_table :post_visibilities do |t|
+      t.rename :post_id, :shareable_id
+      t.string :shareable_type, :default => 'Post', :null => false
+    end
+    rename_table :post_visibilities, :share_visibilities 
+  end
+
+
+
+  def self.down
+    rename_column :aspect_visibilities, :shareable_id, :post_id
+    add_foreign_key :aspect_visibilities, :posts
+    add_index :aspect_visibilities, :post_id
+    remove_column :aspect_visibilities, :shareable_type
+
+    rename_table :share_visibilities, :post_visibilities 
+    rename_column :post_visibilities, :shareable_id, :post_id
+    add_foreign_key :post_visibilities, :posts
+    add_index :post_visibilities, :post_id_and_post_id
+    add_index :post_visibilities, [:contact_id, :post_id]
+    add_index :post_visibilities, [:post_id, :hidden, :contact_id]
+    add_index :post_visibilities, :post_id
+    remove_column :post_visibilities, :shareable_type
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 547f8cf097..0eda270e4b 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -24,15 +24,14 @@ ActiveRecord::Schema.define(:version => 20111011193702) do
   add_index "aspect_memberships", ["contact_id"], :name => "index_aspect_memberships_on_contact_id"
 
   create_table "aspect_visibilities", :force => true do |t|
-    t.integer  "post_id",    :null => false
-    t.integer  "aspect_id",  :null => false
+    t.integer  "shareable_id",                       :null => false
+    t.integer  "aspect_id",                          :null => false
     t.datetime "created_at"
     t.datetime "updated_at"
+    t.string   "shareable_type", :default => "Post", :null => false
   end
 
   add_index "aspect_visibilities", ["aspect_id"], :name => "index_aspect_visibilities_on_aspect_id"
-  add_index "aspect_visibilities", ["post_id", "aspect_id"], :name => "index_aspect_visibilities_on_post_id_and_aspect_id", :unique => true
-  add_index "aspect_visibilities", ["post_id"], :name => "index_aspect_visibilities_on_post_id"
 
   create_table "aspects", :force => true do |t|
     t.string   "name",                               :null => false
@@ -47,21 +46,21 @@ ActiveRecord::Schema.define(:version => 20111011193702) do
   add_index "aspects", ["user_id"], :name => "index_aspects_on_user_id"
 
   create_table "comments", :force => true do |t|
-    t.text     "text",                                   :null => false
-    t.integer  "post_id",                                :null => false
-    t.integer  "author_id",                              :null => false
-    t.string   "guid",                                   :null => false
+    t.text     "text",                                        :null => false
+    t.integer  "commentable_id",                              :null => false
+    t.integer  "author_id",                                   :null => false
+    t.string   "guid",                                        :null => false
     t.text     "author_signature"
     t.text     "parent_author_signature"
     t.text     "youtube_titles"
     t.datetime "created_at"
     t.datetime "updated_at"
-    t.integer  "likes_count",             :default => 0, :null => false
+    t.integer  "likes_count",             :default => 0,      :null => false
+    t.string   "commentable_type",        :default => "Post", :null => false
   end
 
   add_index "comments", ["author_id"], :name => "index_comments_on_person_id"
   add_index "comments", ["guid"], :name => "index_comments_on_guid", :unique => true
-  add_index "comments", ["post_id"], :name => "index_comments_on_post_id"
 
   create_table "contacts", :force => true do |t|
     t.integer  "user_id",                       :null => false
@@ -250,19 +249,6 @@ ActiveRecord::Schema.define(:version => 20111011193702) do
     t.datetime "updated_at"
   end
 
-  create_table "post_visibilities", :force => true do |t|
-    t.integer  "post_id",                       :null => false
-    t.datetime "created_at"
-    t.datetime "updated_at"
-    t.boolean  "hidden",     :default => false, :null => false
-    t.integer  "contact_id",                    :null => false
-  end
-
-  add_index "post_visibilities", ["contact_id", "post_id"], :name => "index_post_visibilities_on_contact_id_and_post_id", :unique => true
-  add_index "post_visibilities", ["contact_id"], :name => "index_post_visibilities_on_contact_id"
-  add_index "post_visibilities", ["post_id", "hidden", "contact_id"], :name => "index_post_visibilities_on_post_id_and_hidden_and_contact_id", :unique => true
-  add_index "post_visibilities", ["post_id"], :name => "index_post_visibilities_on_post_id"
-
   create_table "posts", :force => true do |t|
     t.integer  "author_id",                                              :null => false
     t.boolean  "public",                              :default => false, :null => false
@@ -354,6 +340,18 @@ ActiveRecord::Schema.define(:version => 20111011193702) do
   add_index "services", ["type", "uid"], :name => "index_services_on_type_and_uid"
   add_index "services", ["user_id"], :name => "index_services_on_user_id"
 
+  create_table "share_visibilities", :force => true do |t|
+    t.integer  "shareable_id",                       :null => false
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.boolean  "hidden",         :default => false,  :null => false
+    t.integer  "contact_id",                         :null => false
+    t.string   "shareable_type", :default => "Post", :null => false
+  end
+
+  add_index "share_visibilities", ["contact_id"], :name => "index_post_visibilities_on_contact_id"
+  add_index "share_visibilities", ["shareable_id"], :name => "index_post_visibilities_on_post_id"
+
   create_table "tag_followings", :force => true do |t|
     t.integer  "tag_id",     :null => false
     t.integer  "user_id",    :null => false
@@ -431,10 +429,8 @@ ActiveRecord::Schema.define(:version => 20111011193702) do
   add_foreign_key "aspect_memberships", "contacts", :name => "aspect_memberships_contact_id_fk", :dependent => :delete
 
   add_foreign_key "aspect_visibilities", "aspects", :name => "aspect_visibilities_aspect_id_fk", :dependent => :delete
-  add_foreign_key "aspect_visibilities", "posts", :name => "aspect_visibilities_post_id_fk", :dependent => :delete
 
   add_foreign_key "comments", "people", :name => "comments_author_id_fk", :column => "author_id", :dependent => :delete
-  add_foreign_key "comments", "posts", :name => "comments_post_id_fk", :dependent => :delete
 
   add_foreign_key "contacts", "people", :name => "contacts_person_id_fk", :dependent => :delete
 
@@ -453,13 +449,12 @@ ActiveRecord::Schema.define(:version => 20111011193702) do
 
   add_foreign_key "notification_actors", "notifications", :name => "notification_actors_notification_id_fk", :dependent => :delete
 
-  add_foreign_key "post_visibilities", "contacts", :name => "post_visibilities_contact_id_fk", :dependent => :delete
-  add_foreign_key "post_visibilities", "posts", :name => "post_visibilities_post_id_fk", :dependent => :delete
-
   add_foreign_key "posts", "people", :name => "posts_author_id_fk", :column => "author_id", :dependent => :delete
 
   add_foreign_key "profiles", "people", :name => "profiles_person_id_fk", :dependent => :delete
 
   add_foreign_key "services", "users", :name => "services_user_id_fk", :dependent => :delete
 
+  add_foreign_key "share_visibilities", "contacts", :name => "post_visibilities_contact_id_fk", :dependent => :delete
+
 end
diff --git a/lib/diaspora/shareable.rb b/lib/diaspora/shareable.rb
new file mode 100644
index 0000000000..688d511ec9
--- /dev/null
+++ b/lib/diaspora/shareable.rb
@@ -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.
+
+module Diaspora
+  module Shareable
+    def self.included(model)
+      model.instance_eval do
+        has_many :aspect_visibilities, :as => :shareable
+        has_many :aspects, :through => :aspect_visibilities
+
+        has_many :share_visibilities, :as => :shareable
+        has_many :contacts, :through => :share_visibilities
+      end
+    end
+  end
+end
diff --git a/lib/diaspora/user/connecting.rb b/lib/diaspora/user/connecting.rb
index a1fc290be2..bcaf168a75 100644
--- a/lib/diaspora/user/connecting.rb
+++ b/lib/diaspora/user/connecting.rb
@@ -23,20 +23,20 @@ module Diaspora
           notification.update_attributes(:unread=>false)
         end
 
-        register_post_visibilities(contact)
+        register_share_visibilities(contact)
         contact
       end
 
       # This puts the last 100 public posts by the passed in contact into the user's stream.
       # @param [Contact] contact
       # @return [void]
-      def register_post_visibilities(contact)
+      def register_share_visibilities(contact)
         #should have select here, but proven hard to test
         posts = Post.where(:author_id => contact.person_id, :public => true).limit(100)
         p = posts.map do |post|
-          PostVisibility.new(:contact_id => contact.id, :post_id => post.id)
+          ShareVisibility.new(:contact_id => contact.id, :shareable_id => post.id, :shareable_type => 'Post')
         end
-        PostVisibility.import(p) unless posts.empty?
+        ShareVisibility.import(p) unless posts.empty?
         nil
       end
 
diff --git a/lib/diaspora/user/querying.rb b/lib/diaspora/user/querying.rb
index cc838d9fb7..437e864a9e 100644
--- a/lib/diaspora/user/querying.rb
+++ b/lib/diaspora/user/querying.rb
@@ -48,7 +48,7 @@ module Diaspora
         opts = prep_opts(opts)
         select_clause ='DISTINCT posts.id, posts.updated_at AS updated_at, posts.created_at AS created_at'
 
-        posts_from_others = Post.joins(:contacts).where( :pending => false, :type => opts[:type], :post_visibilities => {:hidden => opts[:hidden]}, :contacts => {:user_id => self.id})
+        posts_from_others = Post.joins(:contacts).where( :pending => false, :type => opts[:type], :share_visibilities => {:hidden => opts[:hidden]}, :contacts => {:user_id => self.id})
         posts_from_self = self.person.posts.where(:pending => false, :type => opts[:type])
 
         if opts[:by_members_of]
@@ -68,7 +68,7 @@ module Diaspora
         contact_for_person_id(person.id)
       end
       def aspects_with_post(post_id)
-        self.aspects.joins(:aspect_visibilities).where(:aspect_visibilities => {:post_id => post_id})
+        self.aspects.joins(:aspect_visibilities).where(:aspect_visibilities => {:shareable_id => post_id, :shareable_type => 'Post'})
       end
 
       def contact_for_person_id(person_id)
@@ -111,7 +111,7 @@ module Diaspora
         post_ids = []
         if contact = self.contact_for(person)
           post_ids = Post.connection.select_values(
-            contact.post_visibilities.where(:hidden => false).select('post_visibilities.post_id').to_sql
+            contact.share_visibilities.where(:hidden => false, :shareable_type => 'Post').select('share_visibilities.shareable_id').to_sql
           )
         end
         post_ids += Post.connection.select_values(
diff --git a/lib/postzord/receiver/local_batch.rb b/lib/postzord/receiver/local_batch.rb
index 2cc6942319..be91e2c936 100644
--- a/lib/postzord/receiver/local_batch.rb
+++ b/lib/postzord/receiver/local_batch.rb
@@ -16,7 +16,7 @@ class Postzord::Receiver::LocalBatch < Postzord::Receiver
     if @object.respond_to?(:relayable?)
       receive_relayable
     else
-      create_post_visibilities
+      create_share_visibilities
     end
     notify_mentioned_users if @object.respond_to?(:mentions)
 
@@ -51,9 +51,9 @@ class Postzord::Receiver::LocalBatch < Postzord::Receiver
   # Batch import post visibilities for the recipients of the given @object
   # @note performs a bulk insert into mySQL
   # @return [void]
-  def create_post_visibilities
+  def create_share_visibilities
     contacts_ids = Contact.connection.select_values(Contact.where(:user_id => @recipient_user_ids, :person_id => @object.author_id).select("id").to_sql)
-    PostVisibility.batch_import(contacts_ids, object)
+    ShareVisibility.batch_import(contacts_ids, object)
   end
 
   # Notify any mentioned users within the @object's text
diff --git a/spec/controllers/post_visibilities_controller_spec.rb b/spec/controllers/share_visibilities_controller_spec.rb
similarity index 93%
rename from spec/controllers/post_visibilities_controller_spec.rb
rename to spec/controllers/share_visibilities_controller_spec.rb
index cf2ae329d0..a7634c37a8 100644
--- a/spec/controllers/post_visibilities_controller_spec.rb
+++ b/spec/controllers/share_visibilities_controller_spec.rb
@@ -4,10 +4,10 @@
 
 require 'spec_helper'
 
-describe PostVisibilitiesController do
+describe ShareVisibilitiesController do
   before do
     @status = alice.post(:status_message, :text => "hello", :to => alice.aspects.first)
-    @vis = @status.post_visibilities.first
+    @vis = @status.share_visibilities.first
     sign_in :user, bob
   end
 
@@ -23,7 +23,7 @@ describe PostVisibilitiesController do
       end
 
       it 'calls #update_cache' do
-        @controller.should_receive(:update_cache).with(an_instance_of(PostVisibility))
+        @controller.should_receive(:update_cache).with(an_instance_of(ShareVisibility))
         put :update, :format => :js, :id => 42, :post_id => @status.id
       end
 
@@ -74,13 +74,13 @@ describe PostVisibilitiesController do
 
     it 'removes the post from the cache if visibility is marked as hidden' do
       @vis.hidden = true
-      @cache.should_receive(:remove).with(@vis.post_id)
+      @cache.should_receive(:remove).with(@vis.shareable_id)
       @controller.send(:update_cache, @vis)
     end
 
     it 'adds the post from the cache if visibility is marked as hidden' do
       @vis.hidden = false
-      @cache.should_receive(:add).with(@status.created_at.to_i, @vis.post_id)
+      @cache.should_receive(:add).with(@status.created_at.to_i, @vis.shareable_id)
       @controller.send(:update_cache, @vis)
     end
   end
diff --git a/spec/integration/receiving_spec.rb b/spec/integration/receiving_spec.rb
index 2e18f2c875..25a3653c4a 100644
--- a/spec/integration/receiving_spec.rb
+++ b/spec/integration/receiving_spec.rb
@@ -169,12 +169,12 @@ describe 'a user receives a post' do
         alice.contacts.create(:person => @person, :aspects => [@alices_aspect])
 
         @post = Factory.create(:status_message, :author => @person)
-        @post.post_visibilities.should be_empty
+        @post.share_visibilities.should be_empty
         receive_with_zord(alice, @person, @post.to_diaspora_xml)
         @contact = alice.contact_for(@person)
-        @contact.post_visibilities.reset
+        @contact.share_visibilities.reset
         @contact.posts(true).should include(@post)
-        @post.post_visibilities.reset
+        @post.share_visibilities.reset
       end
 
       it 'deletes a post if the no one links to it' do
@@ -183,10 +183,10 @@ describe 'a user receives a post' do
         }.should change(Post, :count).by(-1)
       end
 
-      it 'deletes post_visibilities on disconnected by' do
+      it 'deletes share_visibilities on disconnected by' do
         lambda {
           alice.disconnected_by(@person)
-        }.should change{@post.post_visibilities(true).count}.by(-1)
+        }.should change{@post.share_visibilities(true).count}.by(-1)
       end
     end
 
@@ -198,13 +198,13 @@ describe 'a user receives a post' do
       alice.remove_contact(@contact, :force => true)
       @status_message.reload
       @status_message.contacts(true).should_not include(@contact)
-      @status_message.post_visibilities.reset
+      @status_message.share_visibilities.reset
       @status_message.user_refs.should == 2
     end
 
     it 'should not override userrefs on receive by another person' do
       new_user = Factory(:user_with_aspect)
-      @status_message.post_visibilities.reset
+      @status_message.share_visibilities.reset
       @status_message.user_refs.should == 3
 
       new_user.contacts.create(:person => bob.person, :aspects => [new_user.aspects.first])
@@ -212,11 +212,11 @@ describe 'a user receives a post' do
 
       receive_with_zord(new_user, bob.person, xml)
 
-      @status_message.post_visibilities.reset
+      @status_message.share_visibilities.reset
       @status_message.user_refs.should == 4
 
       alice.remove_contact(@contact, :force => true)
-      @status_message.post_visibilities.reset
+      @status_message.share_visibilities.reset
       @status_message.user_refs.should == 3
     end
   end
diff --git a/spec/lib/postzord/receiver/local_batch_spec.rb b/spec/lib/postzord/receiver/local_batch_spec.rb
index 2663d2954d..1a2cec007c 100644
--- a/spec/lib/postzord/receiver/local_batch_spec.rb
+++ b/spec/lib/postzord/receiver/local_batch_spec.rb
@@ -18,8 +18,8 @@ describe Postzord::Receiver::LocalBatch do
   end
 
   describe '#receive!' do
-    it 'calls .create_post_visibilities' do
-      receiver.should_receive(:create_post_visibilities)
+    it 'calls .create_share_visibilities' do
+      receiver.should_receive(:create_share_visibilities)
       receiver.receive!
     end
 
@@ -40,10 +40,10 @@ describe Postzord::Receiver::LocalBatch do
     end
   end
 
-  describe '#create_post_visibilities' do
-    it 'calls Postvisibility.batch_import with hashes' do
-      PostVisibility.should_receive(:batch_import).with(instance_of(Array), @object)
-      receiver.create_post_visibilities
+  describe '#create_share_visibilities' do
+    it 'calls sharevisibility.batch_import with hashes' do
+      ShareVisibility.should_receive(:batch_import).with(instance_of(Array), @object)
+      receiver.create_share_visibilities
     end
   end
 
@@ -107,7 +107,7 @@ describe Postzord::Receiver::LocalBatch do
     end
     it 'does not call create_visibilities and notify_mentioned_users' do
       receiver.should_not_receive(:notify_mentioned_users)
-      receiver.should_not_receive(:create_post_visibilities)
+      receiver.should_not_receive(:create_share_visibilities)
       receiver.perform!
     end
   end
diff --git a/spec/models/jobs/receive_local_batch_spec.rb b/spec/models/jobs/receive_local_batch_spec.rb
index 6fb4fde46a..9117720bae 100644
--- a/spec/models/jobs/receive_local_batch_spec.rb
+++ b/spec/models/jobs/receive_local_batch_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
 describe Jobs::ReceiveLocalBatch do
   #takes author id, post id and array of receiving user ids
   #for each recipient, it gets the aspects that the author is in
-  #Gets all the aspect ids, and inserts into post_visibilities for each aspect
+  #Gets all the aspect ids, and inserts into share_visibilities for each aspect
   #Then it sockets to those users
   #And notifies mentioned people
   before do
diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb
index 85e0202cf9..393203b428 100644
--- a/spec/models/notification_spec.rb
+++ b/spec/models/notification_spec.rb
@@ -56,7 +56,7 @@ describe Notification do
     end
 
     it 'does not create a notification if the post visibility is hidden' do
-      Notification.stub(:post_visiblity_is_hidden).and_return(true)
+      Notification.stub(:share_visiblity_is_hidden).and_return(true)
       expect{
         Notification.notify(@user, @sm, @person)
       }.to change(Notification, :count).by(0)
diff --git a/spec/models/post_visibility_spec.rb b/spec/models/share_visibility_spec.rb
similarity index 61%
rename from spec/models/post_visibility_spec.rb
rename to spec/models/share_visibility_spec.rb
index e35470e672..805c1bbdb3 100644
--- a/spec/models/post_visibility_spec.rb
+++ b/spec/models/share_visibility_spec.rb
@@ -4,7 +4,7 @@
 
 require 'spec_helper'
 
-describe PostVisibility do
+describe ShareVisibility do
   describe '.batch_import' do
     before do
       @post = Factory(:status_message, :author => alice.person)
@@ -13,16 +13,16 @@ describe PostVisibility do
 
     it 'creates a visibility for each user' do
       lambda {
-        PostVisibility.batch_import([@contact.id], @post)
+        ShareVisibility.batch_import([@contact.id], @post)
       }.should change {
-        PostVisibility.exists?(:contact_id => @contact.id, :post_id => @post.id)
+        ShareVisibility.exists?(:contact_id => @contact.id, :shareable_id => @post.id, :shareable_type => 'Post')
       }.from(false).to(true)
     end
 
     it 'does not raise if a visibility already exists' do
-      PostVisibility.create!(:contact_id => @contact.id, :post_id => @post.id)
+      ShareVisibility.create!(:contact_id => @contact.id, :shareable_id => @post.id, :shareable_type => 'Post')
       lambda {
-        PostVisibility.batch_import([@contact.id], @post)
+        ShareVisibility.batch_import([@contact.id], @post)
       }.should_not raise_error
     end
   end
diff --git a/spec/models/user/connecting_spec.rb b/spec/models/user/connecting_spec.rb
index 3109132338..c5cf3da1af 100644
--- a/spec/models/user/connecting_spec.rb
+++ b/spec/models/user/connecting_spec.rb
@@ -76,13 +76,13 @@ describe Diaspora::UserModules::Connecting do
     end
   end
 
-  describe '#register_post_visibilities' do
+  describe '#register_share_visibilities' do
     it 'creates post visibilites for up to 100 posts' do
       Post.stub_chain(:where, :limit).and_return([Factory(:status_message, :public => true)])
       c = Contact.create!(:user_id => alice.id, :person_id => eve.person.id)
       expect{
-        alice.register_post_visibilities(c)
-      }.to change(PostVisibility, :count).by(1)
+        alice.register_share_visibilities(c)
+      }.to change(ShareVisibility, :count).by(1)
     end
   end
 
@@ -114,8 +114,8 @@ describe Diaspora::UserModules::Connecting do
       }.should change(contact.aspects, :count).by(1)
     end
 
-    it 'calls #register_post_visibilities with a contact' do
-      eve.should_receive(:register_post_visibilities)
+    it 'calls #register_share_visibilities with a contact' do
+      eve.should_receive(:register_share_visibilities)
       eve.share_with(alice.person, eve.aspects.first)
     end
 
diff --git a/spec/models/user/querying_spec.rb b/spec/models/user/querying_spec.rb
index befff05390..c0c847dbb4 100644
--- a/spec/models/user/querying_spec.rb
+++ b/spec/models/user/querying_spec.rb
@@ -72,7 +72,7 @@ describe User do
       before do
         aspect_to_post = bob.aspects.where(:name => "generic").first
         @status = bob.post(:status_message, :text=> "hello", :to => aspect_to_post)
-        @vis = @status.post_visibilities.first
+        @vis = @status.share_visibilities.first
       end
 
       it "pulls back non hidden posts" do
-- 
GitLab