Permalink
Browse files

Added Redis store and refactored further to make this possible

  • Loading branch information...
1 parent 280f940 commit 2794f65b7651bc2ecd3fd1a3252127cd23e926b9 @cmer committed Jun 6, 2012
Showing with 1,152 additions and 133 deletions.
  1. +1 −1 lib/generators/socialization/socialization_generator.rb
  2. +1 −0 lib/socialization.rb
  3. +4 −4 lib/socialization/actors/follower.rb
  4. +4 −4 lib/socialization/actors/liker.rb
  5. +4 −4 lib/socialization/actors/mentioner.rb
  6. +45 −0 lib/socialization/config.rb
  7. +4 −0 lib/socialization/helpers/string.rb
  8. +3 −3 lib/socialization/stores/active_record/follow_store.rb
  9. +3 −3 lib/socialization/stores/active_record/like_store.rb
  10. +3 −3 lib/socialization/stores/active_record/mention_store.rb
  11. +8 −0 lib/socialization/stores/redis/base.rb
  12. +11 −0 lib/socialization/stores/redis/config.rb
  13. +126 −0 lib/socialization/stores/redis/follow_store.rb
  14. +126 −0 lib/socialization/stores/redis/like_store.rb
  15. +126 −0 lib/socialization/stores/redis/mention_store.rb
  16. +2 −2 lib/socialization/victims/followable.rb
  17. +2 −2 lib/socialization/victims/likeable.rb
  18. +2 −2 lib/socialization/victims/mentionable.rb
  19. +1 −0 socialization.gemspec
  20. +8 −8 test/actors/follower_test.rb
  21. +8 −8 test/actors/liker_test.rb
  22. +8 −8 test/actors/mentioner_test.rb
  23. +6 −0 test/stores/active_record/follow_store_test.rb
  24. +6 −0 test/stores/active_record/like_store_test.rb
  25. +6 −0 test/stores/active_record/mention_store_test.rb
  26. +30 −0 test/stores/redis/config_test.rb
  27. +153 −0 test/stores/redis/follow_store_test.rb
  28. +153 −0 test/stores/redis/like_store_test.rb
  29. +153 −0 test/stores/redis/mention_store_test.rb
  30. +52 −3 test/test_helper.rb
  31. +4 −4 test/victims/followable_test.rb
  32. +4 −4 test/victims/likeable_test.rb
  33. +4 −4 test/victims/mentionable_test.rb
  34. +81 −66 test/world_test.rb
View
2 lib/generators/socialization/socialization_generator.rb
@@ -1,7 +1,7 @@
require 'rails/generators'
require 'rails/generators/migration'
-STORES = %w(active_record)
+STORES = %w(active_record redis)
class SocializationGenerator < Rails::Generators::Base
include Rails::Generators::Migration
View
1 lib/socialization.rb
@@ -1,3 +1,4 @@
+require 'socialization/config'
require 'socialization/acts_as_helpers'
ActiveRecord::Base.send :include, Socialization::ActsAsHelpers
View
8 lib/socialization/actors/follower.rb
@@ -24,7 +24,7 @@ def is_follower?
# @return [Boolean]
def follow!(followable)
raise ArgumentError, "#{followable} is not followable!" unless followable.respond_to?(:is_followable?) && followable.is_followable?
- Follow.follow!(self, followable)
+ Socialization.follow_model.follow!(self, followable)
end
# Delete a {FollowStores follow} relationship.
@@ -33,7 +33,7 @@ def follow!(followable)
# @return [Boolean]
def unfollow!(followable)
raise ArgumentError, "#{followable} is not followable!" unless followable.respond_to?(:is_followable?) && followable.is_followable?
- Follow.unfollow!(self, followable)
+ Socialization.follow_model.unfollow!(self, followable)
end
# Toggles a {FollowStores follow} relationship.
@@ -57,7 +57,7 @@ def toggle_follow!(followable)
# @return [Boolean]
def follows?(followable)
raise ArgumentError, "#{followable} is not followable!" unless followable.respond_to?(:is_followable?) && followable.is_followable?
- Follow.follows?(self, followable)
+ Socialization.follow_model.follows?(self, followable)
end
# Returns all the followables of a certain type that are followed by self
@@ -66,7 +66,7 @@ def follows?(followable)
# @params [Hash] opts a hash of options
# @return [Array<Followable, Numeric>] An array of Followable objects or IDs
def followables(klass, opts = {})
- Follow.followables(self, klass, opts)
+ Socialization.follow_model.followables(self, klass, opts)
end
end
View
8 lib/socialization/actors/liker.rb
@@ -24,7 +24,7 @@ def is_liker?
# @return [Boolean]
def like!(likeable)
raise ArgumentError, "#{likeable} is not likeable!" unless likeable.respond_to?(:is_likeable?) && likeable.is_likeable?
- Like.like!(self, likeable)
+ Socialization.like_model.like!(self, likeable)
end
# Delete a {LikeStores like} relationship.
@@ -33,7 +33,7 @@ def like!(likeable)
# @return [Boolean]
def unlike!(likeable)
raise ArgumentError, "#{likeable} is not likeable!" unless likeable.respond_to?(:is_likeable?) && likeable.is_likeable?
- Like.unlike!(self, likeable)
+ Socialization.like_model.unlike!(self, likeable)
end
# Toggles a {LikeStores like} relationship.
@@ -57,7 +57,7 @@ def toggle_like!(likeable)
# @return [Boolean]
def likes?(likeable)
raise ArgumentError, "#{likeable} is not likeable!" unless likeable.respond_to?(:is_likeable?) && likeable.is_likeable?
- Like.likes?(self, likeable)
+ Socialization.like_model.likes?(self, likeable)
end
# Returns all the likeables of a certain type that are liked by self
@@ -66,7 +66,7 @@ def likes?(likeable)
# @params [Hash] opts a hash of options
# @return [Array<Likeable, Numeric>] An array of Likeable objects or IDs
def likeables(klass, opts = {})
- Like.likeables(self, klass, opts)
+ Socialization.like_model.likeables(self, klass, opts)
end
end
View
8 lib/socialization/actors/mentioner.rb
@@ -24,7 +24,7 @@ def is_mentioner?
# @return [Boolean]
def mention!(mentionable)
raise ArgumentError, "#{mentionable} is not mentionable!" unless mentionable.respond_to?(:is_mentionable?) && mentionable.is_mentionable?
- Mention.mention!(self, mentionable)
+ Socialization.mention_model.mention!(self, mentionable)
end
# Delete a {MentionStores mention} relationship.
@@ -33,7 +33,7 @@ def mention!(mentionable)
# @return [Boolean]
def unmention!(mentionable)
raise ArgumentError, "#{mentionable} is not mentionable!" unless mentionable.respond_to?(:is_mentionable?) && mentionable.is_mentionable?
- Mention.unmention!(self, mentionable)
+ Socialization.mention_model.unmention!(self, mentionable)
end
# Toggles a {MentionStores mention} relationship.
@@ -57,7 +57,7 @@ def toggle_mention!(mentionable)
# @return [Boolean]
def mentions?(mentionable)
raise ArgumentError, "#{mentionable} is not mentionable!" unless mentionable.respond_to?(:is_mentionable?) && mentionable.is_mentionable?
- Mention.mentions?(self, mentionable)
+ Socialization.mention_model.mentions?(self, mentionable)
end
# Returns all the mentionables of a certain type that are mentioned by self
@@ -66,7 +66,7 @@ def mentions?(mentionable)
# @params [Hash] opts a hash of options
# @return [Array<Mentionable, Numeric>] An array of Mentionable objects or IDs
def mentionables(klass, opts = {})
- Mention.mentionables(self, klass, opts)
+ Socialization.mention_model.mentionables(self, klass, opts)
end
end
View
45 lib/socialization/config.rb
@@ -0,0 +1,45 @@
+module Socialization
+ class << self
+ def follow_model
+ if @follow_model
+ @follow_model
+ elsif defined?(::Follow)
+ ::Follow
+ else
+ raise RuntimeError.new("No Follow model has been defined.")
+ end
+ end
+
+ def follow_model=(klass)
+ @follow_model = klass
+ end
+
+ def like_model
+ if @like_model
+ @like_model
+ elsif defined?(::Like)
+ ::Like
+ else
+ raise RuntimeError.new("No Like model has been defined.")
+ end
+ end
+
+ def like_model=(klass)
+ @like_model = klass
+ end
+
+ def mention_model
+ if @mention_model
+ @mention_model
+ elsif defined?(::Mention)
+ ::Mention
+ else
+ raise RuntimeError.new("No Mention model has been defined.")
+ end
+ end
+
+ def mention_model=(klass)
+ @mention_model = klass
+ end
+ end
+end
View
4 lib/socialization/helpers/string.rb
@@ -10,4 +10,8 @@ def deep_const_get
result
end
+ def is_integer?
+ self.to_i.to_s == self
+ end
+
end
View
6 lib/socialization/stores/active_record/follow_store.rb
@@ -24,7 +24,7 @@ def table_name
def follow!(follower, followable)
unless follows?(follower, followable)
- Follow.create! do |follow|
+ self.create! do |follow|
follow.follower = follower
follow.followable = followable
end
@@ -56,7 +56,7 @@ def follows?(follower, followable)
# Returns an ActiveRecord::Relation of all the followers of a certain type that are following followable
def followers_relation(followable, klass, opts = {})
rel = klass.where(:id =>
- Follow.select(:follower_id).
+ self.select(:follower_id).
where(:follower_type => klass.table_name.classify).
where(:followable_type => followable.class.to_s).
where(:followable_id => followable.id)
@@ -82,7 +82,7 @@ def followers(followable, klass, opts = {})
# Returns an ActiveRecord::Relation of all the followables of a certain type that are followed by follower
def followables_relation(follower, klass, opts = {})
rel = klass.where(:id =>
- Follow.select(:followable_id).
+ self.select(:followable_id).
where(:followable_type => klass.table_name.classify).
where(:follower_type => follower.class.to_s).
where(:follower_id => follower.id)
View
6 lib/socialization/stores/active_record/like_store.rb
@@ -24,7 +24,7 @@ def table_name
def like!(liker, likeable)
unless likes?(liker, likeable)
- Like.create! do |like|
+ self.create! do |like|
like.liker = liker
like.likeable = likeable
end
@@ -56,7 +56,7 @@ def likes?(liker, likeable)
# Returns an ActiveRecord::Relation of all the likers of a certain type that are liking likeable
def likers_relation(likeable, klass, opts = {})
rel = klass.where(:id =>
- Like.select(:liker_id).
+ self.select(:liker_id).
where(:liker_type => klass.table_name.classify).
where(:likeable_type => likeable.class.to_s).
where(:likeable_id => likeable.id)
@@ -82,7 +82,7 @@ def likers(likeable, klass, opts = {})
# Returns an ActiveRecord::Relation of all the likeables of a certain type that are liked by liker
def likeables_relation(liker, klass, opts = {})
rel = klass.where(:id =>
- Like.select(:likeable_id).
+ self.select(:likeable_id).
where(:likeable_type => klass.table_name.classify).
where(:liker_type => liker.class.to_s).
where(:liker_id => liker.id)
View
6 lib/socialization/stores/active_record/mention_store.rb
@@ -24,7 +24,7 @@ def table_name
def mention!(mentioner, mentionable)
unless mentions?(mentioner, mentionable)
- Mention.create! do |mention|
+ self.create! do |mention|
mention.mentioner = mentioner
mention.mentionable = mentionable
end
@@ -56,7 +56,7 @@ def mentions?(mentioner, mentionable)
# Returns an ActiveRecord::Relation of all the mentioners of a certain type that are mentioning mentionable
def mentioners_relation(mentionable, klass, opts = {})
rel = klass.where(:id =>
- Mention.select(:mentioner_id).
+ self.select(:mentioner_id).
where(:mentioner_type => klass.table_name.classify).
where(:mentionable_type => mentionable.class.to_s).
where(:mentionable_id => mentionable.id)
@@ -82,7 +82,7 @@ def mentioners(mentionable, klass, opts = {})
# Returns an ActiveRecord::Relation of all the mentionables of a certain type that are mentioned by mentioner
def mentionables_relation(mentioner, klass, opts = {})
rel = klass.where(:id =>
- Mention.select(:mentionable_id).
+ self.select(:mentionable_id).
where(:mentionable_type => klass.table_name.classify).
where(:mentioner_type => mentioner.class.to_s).
where(:mentioner_id => mentioner.id)
View
8 lib/socialization/stores/redis/base.rb
@@ -0,0 +1,8 @@
+module Socialization
+ module RedisStores
+ class Base
+ @@after_create_hook = nil
+ @@after_destroy_hook = nil
+ end
+ end
+end
View
11 lib/socialization/stores/redis/config.rb
@@ -0,0 +1,11 @@
+module Socialization
+ class << self
+ def redis
+ @redis ||= Redis.new
+ end
+
+ def redis=(redis)
+ @redis = redis
+ end
+ end
+end
View
126 lib/socialization/stores/redis/follow_store.rb
@@ -0,0 +1,126 @@
+require File.expand_path(File.dirname(__FILE__)) + '/base'
+
+module Socialization
+ module RedisStores
+ class FollowStore < Socialization::RedisStores::Base
+ class << self
+ def follow!(follower, followable)
+ unless follows?(follower, followable)
+ Socialization.redis.sadd generate_followers_key(follower, followable), follower.id
+ Socialization.redis.sadd generate_followables_key(follower, followable), followable.id
+
+ call_after_create_hook(follower, followable)
+ follower.touch if [:all, :follower].include?(touch) && follower.respond_to?(:touch)
+ followable.touch if [:all, :followable].include?(touch) && followable.respond_to?(:touch)
+ true
+ else
+ false
+ end
+ end
+
+ def unfollow!(follower, followable)
+ if follows?(follower, followable)
+ Socialization.redis.srem generate_followers_key(follower, followable), follower.id
+ Socialization.redis.srem generate_followables_key(follower, followable), followable.id
+
+ call_after_destroy_hook(follower, followable)
+ follower.touch if [:all, :follower].include?(touch) && follower.respond_to?(:touch)
+ followable.touch if [:all, :followable].include?(touch) && followable.respond_to?(:touch)
+ true
+ else
+ false
+ end
+ end
+
+ def follows?(follower, followable)
+ Socialization.redis.sismember generate_followers_key(follower, followable), follower.id
+ end
+
+ # Returns an ActiveRecord::Relation of all the followers of a certain type that are following followable
+ def followers_relation(followable, klass, opts = {})
+ ids = followers(followable, klass, :pluck => :id)
+ klass.where('id IN (?)', ids)
+ end
+
+ # Returns all the followers of a certain type that are following followable
+ def followers(followable, klass, opts = {})
+ if opts[:pluck]
+ Socialization.redis.smembers(generate_followers_key(klass, followable)).map { |id|
+ id.to_i if id.is_integer?
+ }
+ else
+ followers_relation(followable, klass, opts).all
+ end
+ end
+
+ # Returns an ActiveRecord::Relation of all the followables of a certain type that are followed by follower
+ def followables_relation(follower, klass, opts = {})
+ ids = followables(follower, klass, :pluck => :id)
+ klass.where('id IN (?)', ids)
+ end
+
+ # Returns all the followables of a certain type that are followed by follower
+ def followables(follower, klass, opts = {})
+ if opts[:pluck]
+ Socialization.redis.smembers(generate_followables_key(follower, klass)).map { |id|
+ id.to_i if id.is_integer?
+ }
+ else
+ followables_relation(follower, klass, opts).all
+ end
+ end
+
+ def touch(what = nil)
+ if what.nil?
+ @touch || false
+ else
+ raise ArgumentError unless [:all, :follower, :followable, false, nil].include?(what)
+ @touch = what
+ end
+ end
+
+ def after_follow(method)
+ raise ArgumentError unless method.is_a?(Symbol) || method.nil?
+ @after_create_hook = method
+ end
+
+ def after_unfollow(method)
+ raise ArgumentError unless method.is_a?(Symbol) || method.nil?
+ @after_destroy_hook = method
+ end
+
+ private
+ def call_after_create_hook(follower, followable)
+ self.send(@after_create_hook, follower, followable) if @after_create_hook
+ end
+
+ def call_after_destroy_hook(follower, followable)
+ self.send(@after_destroy_hook, follower, followable) if @after_destroy_hook
+ end
+
+ def generate_followers_key(follower, followable)
+ raise ArgumentError.new("`followable` needs to be an acts_as_followable objecs, not a class.") if followable.class == Class
+ follower_class = if follower.class == Class
+ follower
+ else
+ follower.class
+ end
+
+ "Followers:#{followable.class}:#{followable.id}:#{follower_class}"
+ end
+
+ def generate_followables_key(follower, followable)
+ raise ArgumentError.new("`follower` needs to be an acts_as_follower object, not a class.") if follower.class == Class
+ followable_class = if followable.class == Class
+ followable
+ else
+ followable.class
+ end
+
+ "Followables:#{follower.class}:#{follower.id}:#{followable_class}"
+ end
+ end # class << self
+
+ end
+ end
+end
View
126 lib/socialization/stores/redis/like_store.rb
@@ -0,0 +1,126 @@
+require File.expand_path(File.dirname(__FILE__)) + '/base'
+
+module Socialization
+ module RedisStores
+ class LikeStore < Socialization::RedisStores::Base
+ class << self
+ def like!(liker, likeable)
+ unless likes?(liker, likeable)
+ Socialization.redis.sadd generate_likers_key(liker, likeable), liker.id
+ Socialization.redis.sadd generate_likeables_key(liker, likeable), likeable.id
+
+ call_after_create_hook(liker, likeable)
+ liker.touch if [:all, :liker].include?(touch) && liker.respond_to?(:touch)
+ likeable.touch if [:all, :likeable].include?(touch) && likeable.respond_to?(:touch)
+ true
+ else
+ false
+ end
+ end
+
+ def unlike!(liker, likeable)
+ if likes?(liker, likeable)
+ Socialization.redis.srem generate_likers_key(liker, likeable), liker.id
+ Socialization.redis.srem generate_likeables_key(liker, likeable), likeable.id
+
+ call_after_destroy_hook(liker, likeable)
+ liker.touch if [:all, :liker].include?(touch) && liker.respond_to?(:touch)
+ likeable.touch if [:all, :likeable].include?(touch) && likeable.respond_to?(:touch)
+ true
+ else
+ false
+ end
+ end
+
+ def likes?(liker, likeable)
+ Socialization.redis.sismember generate_likers_key(liker, likeable), liker.id
+ end
+
+ # Returns an ActiveRecord::Relation of all the likers of a certain type that are likeing likeable
+ def likers_relation(likeable, klass, opts = {})
+ ids = likers(likeable, klass, :pluck => :id)
+ klass.where('id IN (?)', ids)
+ end
+
+ # Returns all the likers of a certain type that are likeing likeable
+ def likers(likeable, klass, opts = {})
+ if opts[:pluck]
+ Socialization.redis.smembers(generate_likers_key(klass, likeable)).map { |id|
+ id.to_i if id.is_integer?
+ }
+ else
+ likers_relation(likeable, klass, opts).all
+ end
+ end
+
+ # Returns an ActiveRecord::Relation of all the likeables of a certain type that are liked by liker
+ def likeables_relation(liker, klass, opts = {})
+ ids = likeables(liker, klass, :pluck => :id)
+ klass.where('id IN (?)', ids)
+ end
+
+ # Returns all the likeables of a certain type that are liked by liker
+ def likeables(liker, klass, opts = {})
+ if opts[:pluck]
+ Socialization.redis.smembers(generate_likeables_key(liker, klass)).map { |id|
+ id.to_i if id.is_integer?
+ }
+ else
+ likeables_relation(liker, klass, opts).all
+ end
+ end
+
+ def touch(what = nil)
+ if what.nil?
+ @touch || false
+ else
+ raise ArgumentError unless [:all, :liker, :likeable, false, nil].include?(what)
+ @touch = what
+ end
+ end
+
+ def after_like(method)
+ raise ArgumentError unless method.is_a?(Symbol) || method.nil?
+ @after_create_hook = method
+ end
+
+ def after_unlike(method)
+ raise ArgumentError unless method.is_a?(Symbol) || method.nil?
+ @after_destroy_hook = method
+ end
+
+ private
+ def call_after_create_hook(liker, likeable)
+ self.send(@after_create_hook, liker, likeable) if @after_create_hook
+ end
+
+ def call_after_destroy_hook(liker, likeable)
+ self.send(@after_destroy_hook, liker, likeable) if @after_destroy_hook
+ end
+
+ def generate_likers_key(liker, likeable)
+ raise ArgumentError.new("`likeable` needs to be an acts_as_likeable objecs, not a class.") if likeable.class == Class
+ liker_class = if liker.class == Class
+ liker
+ else
+ liker.class
+ end
+
+ "Likers:#{likeable.class}:#{likeable.id}:#{liker_class}"
+ end
+
+ def generate_likeables_key(liker, likeable)
+ raise ArgumentError.new("`liker` needs to be an acts_as_liker object, not a class.") if liker.class == Class
+ likeable_class = if likeable.class == Class
+ likeable
+ else
+ likeable.class
+ end
+
+ "Likeables:#{liker.class}:#{liker.id}:#{likeable_class}"
+ end
+ end # class << self
+
+ end
+ end
+end
View
126 lib/socialization/stores/redis/mention_store.rb
@@ -0,0 +1,126 @@
+require File.expand_path(File.dirname(__FILE__)) + '/base'
+
+module Socialization
+ module RedisStores
+ class MentionStore < Socialization::RedisStores::Base
+ class << self
+ def mention!(mentioner, mentionable)
+ unless mentions?(mentioner, mentionable)
+ Socialization.redis.sadd generate_mentioners_key(mentioner, mentionable), mentioner.id
+ Socialization.redis.sadd generate_mentionables_key(mentioner, mentionable), mentionable.id
+
+ call_after_create_hook(mentioner, mentionable)
+ mentioner.touch if [:all, :mentioner].include?(touch) && mentioner.respond_to?(:touch)
+ mentionable.touch if [:all, :mentionable].include?(touch) && mentionable.respond_to?(:touch)
+ true
+ else
+ false
+ end
+ end
+
+ def unmention!(mentioner, mentionable)
+ if mentions?(mentioner, mentionable)
+ Socialization.redis.srem generate_mentioners_key(mentioner, mentionable), mentioner.id
+ Socialization.redis.srem generate_mentionables_key(mentioner, mentionable), mentionable.id
+
+ call_after_destroy_hook(mentioner, mentionable)
+ mentioner.touch if [:all, :mentioner].include?(touch) && mentioner.respond_to?(:touch)
+ mentionable.touch if [:all, :mentionable].include?(touch) && mentionable.respond_to?(:touch)
+ true
+ else
+ false
+ end
+ end
+
+ def mentions?(mentioner, mentionable)
+ Socialization.redis.sismember generate_mentioners_key(mentioner, mentionable), mentioner.id
+ end
+
+ # Returns an ActiveRecord::Relation of all the mentioners of a certain type that are mentioning mentionable
+ def mentioners_relation(mentionable, klass, opts = {})
+ ids = mentioners(mentionable, klass, :pluck => :id)
+ klass.where('id IN (?)', ids)
+ end
+
+ # Returns all the mentioners of a certain type that are mentioning mentionable
+ def mentioners(mentionable, klass, opts = {})
+ if opts[:pluck]
+ Socialization.redis.smembers(generate_mentioners_key(klass, mentionable)).map { |id|
+ id.to_i if id.is_integer?
+ }
+ else
+ mentioners_relation(mentionable, klass, opts).all
+ end
+ end
+
+ # Returns an ActiveRecord::Relation of all the mentionables of a certain type that are mentioned by mentioner
+ def mentionables_relation(mentioner, klass, opts = {})
+ ids = mentionables(mentioner, klass, :pluck => :id)
+ klass.where('id IN (?)', ids)
+ end
+
+ # Returns all the mentionables of a certain type that are mentioned by mentioner
+ def mentionables(mentioner, klass, opts = {})
+ if opts[:pluck]
+ Socialization.redis.smembers(generate_mentionables_key(mentioner, klass)).map { |id|
+ id.to_i if id.is_integer?
+ }
+ else
+ mentionables_relation(mentioner, klass, opts).all
+ end
+ end
+
+ def touch(what = nil)
+ if what.nil?
+ @touch || false
+ else
+ raise ArgumentError unless [:all, :mentioner, :mentionable, false, nil].include?(what)
+ @touch = what
+ end
+ end
+
+ def after_mention(method)
+ raise ArgumentError unless method.is_a?(Symbol) || method.nil?
+ @after_create_hook = method
+ end
+
+ def after_unmention(method)
+ raise ArgumentError unless method.is_a?(Symbol) || method.nil?
+ @after_destroy_hook = method
+ end
+
+ private
+ def call_after_create_hook(mentioner, mentionable)
+ self.send(@after_create_hook, mentioner, mentionable) if @after_create_hook
+ end
+
+ def call_after_destroy_hook(mentioner, mentionable)
+ self.send(@after_destroy_hook, mentioner, mentionable) if @after_destroy_hook
+ end
+
+ def generate_mentioners_key(mentioner, mentionable)
+ raise ArgumentError.new("`mentionable` needs to be an acts_as_mentionable objecs, not a class.") if mentionable.class == Class
+ mentioner_class = if mentioner.class == Class
+ mentioner
+ else
+ mentioner.class
+ end
+
+ "Mentioners:#{mentionable.class}:#{mentionable.id}:#{mentioner_class}"
+ end
+
+ def generate_mentionables_key(mentioner, mentionable)
+ raise ArgumentError.new("`mentioner` needs to be an acts_as_mentioner object, not a class.") if mentioner.class == Class
+ mentionable_class = if mentionable.class == Class
+ mentionable
+ else
+ mentionable.class
+ end
+
+ "Mentionables:#{mentioner.class}:#{mentioner.id}:#{mentionable_class}"
+ end
+ end # class << self
+
+ end
+ end
+end
View
4 lib/socialization/victims/followable.rb
@@ -23,15 +23,15 @@ def is_followable?
# @return [Boolean]
def followed_by?(follower)
raise ArgumentError, "#{follower} is not follower!" unless follower.respond_to?(:is_follower?) && follower.is_follower?
- Follow.follows?(follower, self)
+ Socialization.follow_model.follows?(follower, self)
end
# Returns a scope of the {Follower}s following self.
#
# @param [Class] klass the {Follower} class to be included in the scope. e.g. `User`
# @return [Array<Follower, Numeric>] An array of Follower objects or IDs
def followers(klass, opts = {})
- Follow.followers(self, klass, opts)
+ Socialization.follow_model.followers(self, klass, opts)
end
end
end
View
4 lib/socialization/victims/likeable.rb
@@ -23,15 +23,15 @@ def is_likeable?
# @return [Boolean]
def liked_by?(liker)
raise ArgumentError, "#{liker} is not liker!" unless liker.respond_to?(:is_liker?) && liker.is_liker?
- Like.likes?(liker, self)
+ Socialization.like_model.likes?(liker, self)
end
# Returns a scope of the {Liker}s likeing self.
#
# @param [Class] klass the {Liker} class to be included in the scope. e.g. `User`.
# @return [Array<Liker, Numeric>] An array of Liker objects or IDs
def likers(klass, opts = {})
- Like.likers(self, klass, opts)
+ Socialization.like_model.likers(self, klass, opts)
end
end
end
View
4 lib/socialization/victims/mentionable.rb
@@ -23,15 +23,15 @@ def is_mentionable?
# @return [Boolean]
def mentioned_by?(mentioner)
raise ArgumentError, "#{mentioner} is not mentioner!" unless mentioner.respond_to?(:is_mentioner?) && mentioner.is_mentioner?
- Mention.mentions?(mentioner, self)
+ Socialization.mention_model.mentions?(mentioner, self)
end
# Returns a scope of the {Mentioner}s mentioning self.
#
# @param [Class] klass the {Mentioner} class to be included in the scope. e.g. `User`.
# @return [Array<Mentioner, Numeric>] An array of Mentioner objects or IDs
def mentioners(klass, opts = {})
- Mention.mentioners(self, klass, opts)
+ Socialization.mention_model.mentioners(self, klass, opts)
end
end
end
View
1 socialization.gemspec
@@ -26,4 +26,5 @@ Gem::Specification.new do |s|
s.add_development_dependency "shoulda"
s.add_development_dependency "sqlite3"
s.add_development_dependency "yard"
+ s.add_development_dependency "mock_redis"
end
View
16 test/actors/follower_test.rb
@@ -18,8 +18,8 @@ class FollowerTest < Test::Unit::TestCase
assert_raise(ArgumentError) { @follower.follow!(:foo) }
end
- should "call Follow.follow!" do
- Follow.expects(:follow!).with(@follower, @followable).once
+ should "call $Follow.follow!" do
+ $Follow.expects(:follow!).with(@follower, @followable).once
@follower.follow!(@followable)
end
end
@@ -29,8 +29,8 @@ class FollowerTest < Test::Unit::TestCase
assert_raise(ArgumentError) { @follower.unfollow!(:foo) }
end
- should "call Follow.follow!" do
- Follow.expects(:unfollow!).with(@follower, @followable).once
+ should "call $Follow.follow!" do
+ $Follow.expects(:unfollow!).with(@follower, @followable).once
@follower.unfollow!(@followable)
end
end
@@ -58,15 +58,15 @@ class FollowerTest < Test::Unit::TestCase
assert_raise(ArgumentError) { @follower.unfollow!(:foo) }
end
- should "call Follow.follows?" do
- Follow.expects(:follows?).with(@follower, @followable).once
+ should "call $Follow.follows?" do
+ $Follow.expects(:follows?).with(@follower, @followable).once
@follower.follows?(@followable)
end
end
context "#followables" do
- should "call Follow.followables" do
- Follow.expects(:followables).with(@follower, @followable.class, { :foo => :bar })
+ should "call $Follow.followables" do
+ $Follow.expects(:followables).with(@follower, @followable.class, { :foo => :bar })
@follower.followables(@followable.class, { :foo => :bar })
end
end
View
16 test/actors/liker_test.rb
@@ -18,8 +18,8 @@ class LikerTest < Test::Unit::TestCase
assert_raise(ArgumentError) { @liker.like!(:foo) }
end
- should "call Like.like!" do
- Like.expects(:like!).with(@liker, @likeable).once
+ should "call $Like.like!" do
+ $Like.expects(:like!).with(@liker, @likeable).once
@liker.like!(@likeable)
end
end
@@ -29,8 +29,8 @@ class LikerTest < Test::Unit::TestCase
assert_raise(ArgumentError) { @liker.unlike!(:foo) }
end
- should "call Like.like!" do
- Like.expects(:unlike!).with(@liker, @likeable).once
+ should "call $Like.like!" do
+ $Like.expects(:unlike!).with(@liker, @likeable).once
@liker.unlike!(@likeable)
end
end
@@ -58,15 +58,15 @@ class LikerTest < Test::Unit::TestCase
assert_raise(ArgumentError) { @liker.unlike!(:foo) }
end
- should "call Like.likes?" do
- Like.expects(:likes?).with(@liker, @likeable).once
+ should "call $Like.likes?" do
+ $Like.expects(:likes?).with(@liker, @likeable).once
@liker.likes?(@likeable)
end
end
context "#likeables" do
- should "call Like.likeables" do
- Like.expects(:likeables).with(@liker, @likeable.class, { :foo => :bar })
+ should "call $Like.likeables" do
+ $Like.expects(:likeables).with(@liker, @likeable.class, { :foo => :bar })
@liker.likeables(@likeable.class, { :foo => :bar })
end
end
View
16 test/actors/mentioner_test.rb
@@ -18,8 +18,8 @@ class MentionerTest < Test::Unit::TestCase
assert_raise(ArgumentError) { @mentioner.mention!(:foo) }
end
- should "call Mention.mention!" do
- Mention.expects(:mention!).with(@mentioner, @mentionable).once
+ should "call $Mention.mention!" do
+ $Mention.expects(:mention!).with(@mentioner, @mentionable).once
@mentioner.mention!(@mentionable)
end
end
@@ -29,8 +29,8 @@ class MentionerTest < Test::Unit::TestCase
assert_raise(ArgumentError) { @mentioner.unmention!(:foo) }
end
- should "call Mention.mention!" do
- Mention.expects(:unmention!).with(@mentioner, @mentionable).once
+ should "call $Mention.mention!" do
+ $Mention.expects(:unmention!).with(@mentioner, @mentionable).once
@mentioner.unmention!(@mentionable)
end
end
@@ -58,15 +58,15 @@ class MentionerTest < Test::Unit::TestCase
assert_raise(ArgumentError) { @mentioner.unmention!(:foo) }
end
- should "call Mention.mentions?" do
- Mention.expects(:mentions?).with(@mentioner, @mentionable).once
+ should "call $Mention.mentions?" do
+ $Mention.expects(:mentions?).with(@mentioner, @mentionable).once
@mentioner.mentions?(@mentionable)
end
end
context "#mentionables" do
- should "call Mention.mentionables" do
- Mention.expects(:mentionables).with(@mentioner, @mentionable.class, { :foo => :bar })
+ should "call $Mention.mentionables" do
+ $Mention.expects(:mentionables).with(@mentioner, @mentionable.class, { :foo => :bar })
@mentioner.mentionables(@mentionable.class, { :foo => :bar })
end
end
View
6 test/stores/active_record/follow_store_test.rb
@@ -11,6 +11,12 @@ class ActiveRecordFollowStoreTest < Test::Unit::TestCase
@followable = ImAFollowable.create
end
+ context "data store" do
+ should "inherit Socialization::ActiveRecordStores::FollowStore" do
+ assert_equal Socialization::ActiveRecordStores::FollowStore, Socialization.follow_model
+ end
+ end
+
context "#follow!" do
should "create a Follow record" do
@klass.follow!(@follower, @followable)
View
6 test/stores/active_record/like_store_test.rb
@@ -11,6 +11,12 @@ class ActiveRecordLikeStoreTest < Test::Unit::TestCase
@likeable = ImALikeable.create
end
+ context "data store" do
+ should "inherit Socialization::ActiveRecordStores::LikeStore" do
+ assert_equal Socialization::ActiveRecordStores::LikeStore, Socialization.like_model
+ end
+ end
+
context "#like!" do
should "create a Like record" do
@klass.like!(@liker, @likeable)
View
6 test/stores/active_record/mention_store_test.rb
@@ -11,6 +11,12 @@ class ActiveRecordMentionStoreTest < Test::Unit::TestCase
@mentionable = ImAMentionable.create
end
+ context "data store" do
+ should "inherit Socialization::ActiveRecordStores::MentionStore" do
+ assert_equal Socialization::ActiveRecordStores::MentionStore, Socialization.mention_model
+ end
+ end
+
context "#mention!" do
should "create a Mention record" do
@klass.mention!(@mentioner, @mentionable)
View
30 test/stores/redis/config_test.rb
@@ -0,0 +1,30 @@
+require File.expand_path(File.dirname(__FILE__))+'/../../test_helper'
+
+class RedisStoreConfigTest < Test::Unit::TestCase
+ context "redis" do
+ setup do
+ Socialization.instance_eval { @redis = nil }
+ end
+
+ should "return a new Redis object when none were specified" do
+ assert_instance_of Redis, Socialization.redis
+ end
+
+ should "always return the same Redis object when none were specified" do
+ redis = Socialization.redis
+ assert_same redis, Socialization.redis
+ end
+
+ should "be able to set and get a redis instance" do
+ redis = Redis.new
+ Socialization.redis = redis
+ assert_same redis, Socialization.redis
+ end
+
+ should "always return the same Redis object when it was specified" do
+ redis = Redis.new
+ Socialization.redis = redis
+ assert_same redis, Socialization.redis
+ end
+ end
+end
View
153 test/stores/redis/follow_store_test.rb
@@ -0,0 +1,153 @@
+require File.expand_path(File.dirname(__FILE__))+'/../../test_helper'
+
+class RedisFollowStoreTest < Test::Unit::TestCase
+ context "RedisStores::FollowStoreTest" do
+ setup do
+ use_redis_store
+ @klass = Socialization::RedisStores::FollowStore
+ @klass.touch nil
+ @klass.after_follow nil
+ @klass.after_unfollow nil
+ @follower = ImAFollower.create
+ @followable = ImAFollowable.create
+ end
+
+ context "Stores" do
+ should "inherit Socialization::RedisStores::FollowStore" do
+ assert_equal Socialization::RedisStores::FollowStore, Socialization.follow_model
+ end
+ end
+
+ context "#follow!" do
+ should "create a Follow record" do
+ @klass.follow!(@follower, @followable)
+ assert_equal ["#{@follower.id}"], Socialization.redis.smembers(followers_key)
+ assert_equal ["#{@followable.id}"], Socialization.redis.smembers(followables_key)
+ end
+
+ should "touch follower when instructed" do
+ @klass.touch :follower
+ @follower.expects(:touch).once
+ @followable.expects(:touch).never
+ @klass.follow!(@follower, @followable)
+ end
+
+ should "touch followable when instructed" do
+ @klass.touch :followable
+ @follower.expects(:touch).never
+ @followable.expects(:touch).once
+ @klass.follow!(@follower, @followable)
+ end
+
+ should "touch all when instructed" do
+ @klass.touch :all
+ @follower.expects(:touch).once
+ @followable.expects(:touch).once
+ @klass.follow!(@follower, @followable)
+ end
+
+ should "call after follow hook" do
+ @klass.after_follow :after_follow
+ @klass.expects(:after_follow).once
+ @klass.follow!(@follower, @followable)
+ end
+
+ should "call after unfollow hook" do
+ @klass.after_follow :after_unfollow
+ @klass.expects(:after_unfollow).once
+ @klass.follow!(@follower, @followable)
+ end
+ end
+
+ context "#follows?" do
+ should "return true when follow exists" do
+ Socialization.redis.sadd followers_key, @follower.id
+ Socialization.redis.sadd followables_key, @followable.id
+ assert_true @klass.follows?(@follower, @followable)
+ end
+
+ should "return false when follow doesn't exist" do
+ assert_false @klass.follows?(@follower, @followable)
+ end
+ end
+
+ context "#followers" do
+ should "return an array of followers" do
+ follower1 = ImAFollower.create
+ follower2 = ImAFollower.create
+ follower1.follow!(@followable)
+ follower2.follow!(@followable)
+ assert_array_similarity [follower1, follower2], @klass.followers(@followable, follower1.class)
+ end
+
+ should "return an array of follower ids when plucking" do
+ follower1 = ImAFollower.create
+ follower2 = ImAFollower.create
+ follower1.follow!(@followable)
+ follower2.follow!(@followable)
+ assert_array_similarity [follower1.id, follower2.id], @klass.followers(@followable, follower1.class, :pluck => :id)
+ end
+ end
+
+ context "#followables" do
+ should "return an array of followables" do
+ followable1 = ImAFollowable.create
+ followable2 = ImAFollowable.create
+ @follower.follow!(followable1)
+ @follower.follow!(followable2)
+
+ assert_array_similarity [followable1, followable2], @klass.followables(@follower, followable1.class)
+ end
+
+ should "return an array of followables ids when plucking" do
+ followable1 = ImAFollowable.create
+ followable2 = ImAFollowable.create
+ @follower.follow!(followable1)
+ @follower.follow!(followable2)
+ assert_array_similarity [followable1.id, followable2.id], @klass.followables(@follower, followable1.class, :pluck => :id)
+ end
+ end
+
+ context "#generate_followers_key" do
+ should "return valid key when passed objects" do
+ assert_equal "Followers:ImAFollowable:#{@followable.id}:ImAFollower", followers_key(@follower, @followable)
+ end
+
+ should "return valid key when follower is a class" do
+ assert_equal "Followers:ImAFollowable:#{@followable.id}:ImAFollower", followers_key(@follower.class, @followable)
+ end
+ end
+
+ context "#generate_followables_key" do
+ should "return valid key when passed objects" do
+ assert_equal "Followables:ImAFollower:#{@follower.id}:ImAFollowable", followables_key(@follower, @followable)
+ end
+
+ should "return valid key when followable is a class" do
+ assert_equal "Followables:ImAFollower:#{@follower.id}:ImAFollowable", followables_key(@follower, @followable.class)
+ end
+ end
+
+ end
+
+ # Helpers
+ def assert_match_follower(follow_record, follower)
+ assert follow_record.follower_type == follower.class.to_s && follow_record.follower_id == follower.id
+ end
+
+ def assert_match_followable(follow_record, followable)
+ assert follow_record.followable_type == followable.class.to_s && follow_record.followable_id == followable.id
+ end
+
+ def followers_key(follower = nil, followable = nil)
+ follower ||= @follower
+ followable ||= @followable
+ @klass.send(:generate_followers_key, follower, followable)
+ end
+
+ def followables_key(follower = nil, followable = nil)
+ follower ||= @follower
+ followable ||= @followable
+ @klass.send(:generate_followables_key, follower, followable)
+ end
+end
View
153 test/stores/redis/like_store_test.rb
@@ -0,0 +1,153 @@
+require File.expand_path(File.dirname(__FILE__))+'/../../test_helper'
+
+class RedisLikeStoreTest < Test::Unit::TestCase
+ context "RedisStores::LikeStoreTest" do
+ setup do
+ use_redis_store
+ @klass = Socialization::RedisStores::LikeStore
+ @klass.touch nil
+ @klass.after_like nil
+ @klass.after_unlike nil
+ @liker = ImALiker.create
+ @likeable = ImALikeable.create
+ end
+
+ context "Stores" do
+ should "inherit Socialization::RedisStores::LikeStore" do
+ assert_equal Socialization::RedisStores::LikeStore, Socialization.like_model
+ end
+ end
+
+ context "#like!" do
+ should "create a Like record" do
+ @klass.like!(@liker, @likeable)
+ assert_equal ["#{@liker.id}"], Socialization.redis.smembers(likers_key)
+ assert_equal ["#{@likeable.id}"], Socialization.redis.smembers(likeables_key)
+ end
+
+ should "touch liker when instructed" do
+ @klass.touch :liker
+ @liker.expects(:touch).once
+ @likeable.expects(:touch).never
+ @klass.like!(@liker, @likeable)
+ end
+
+ should "touch likeable when instructed" do
+ @klass.touch :likeable
+ @liker.expects(:touch).never
+ @likeable.expects(:touch).once
+ @klass.like!(@liker, @likeable)
+ end
+
+ should "touch all when instructed" do
+ @klass.touch :all
+ @liker.expects(:touch).once
+ @likeable.expects(:touch).once
+ @klass.like!(@liker, @likeable)
+ end
+
+ should "call after like hook" do
+ @klass.after_like :after_like
+ @klass.expects(:after_like).once
+ @klass.like!(@liker, @likeable)
+ end
+
+ should "call after unlike hook" do
+ @klass.after_like :after_unlike
+ @klass.expects(:after_unlike).once
+ @klass.like!(@liker, @likeable)
+ end
+ end
+
+ context "#likes?" do
+ should "return true when like exists" do
+ Socialization.redis.sadd likers_key, @liker.id
+ Socialization.redis.sadd likeables_key, @likeable.id
+ assert_true @klass.likes?(@liker, @likeable)
+ end
+
+ should "return false when like doesn't exist" do
+ assert_false @klass.likes?(@liker, @likeable)
+ end
+ end
+
+ context "#likers" do
+ should "return an array of likers" do
+ liker1 = ImALiker.create
+ liker2 = ImALiker.create
+ liker1.like!(@likeable)
+ liker2.like!(@likeable)
+ assert_array_similarity [liker1, liker2], @klass.likers(@likeable, liker1.class)
+ end
+
+ should "return an array of liker ids when plucking" do
+ liker1 = ImALiker.create
+ liker2 = ImALiker.create
+ liker1.like!(@likeable)
+ liker2.like!(@likeable)
+ assert_array_similarity [liker1.id, liker2.id], @klass.likers(@likeable, liker1.class, :pluck => :id)
+ end
+ end
+
+ context "#likeables" do
+ should "return an array of likeables" do
+ likeable1 = ImALikeable.create
+ likeable2 = ImALikeable.create
+ @liker.like!(likeable1)
+ @liker.like!(likeable2)
+
+ assert_array_similarity [likeable1, likeable2], @klass.likeables(@liker, likeable1.class)
+ end
+
+ should "return an array of likeables ids when plucking" do
+ likeable1 = ImALikeable.create
+ likeable2 = ImALikeable.create
+ @liker.like!(likeable1)
+ @liker.like!(likeable2)
+ assert_array_similarity [likeable1.id, likeable2.id], @klass.likeables(@liker, likeable1.class, :pluck => :id)
+ end
+ end
+
+ context "#generate_likers_key" do
+ should "return valid key when passed objects" do
+ assert_equal "Likers:ImALikeable:#{@likeable.id}:ImALiker", likers_key(@liker, @likeable)
+ end
+
+ should "return valid key when liker is a class" do
+ assert_equal "Likers:ImALikeable:#{@likeable.id}:ImALiker", likers_key(@liker.class, @likeable)
+ end
+ end
+
+ context "#generate_likeables_key" do
+ should "return valid key when passed objects" do
+ assert_equal "Likeables:ImALiker:#{@liker.id}:ImALikeable", likeables_key(@liker, @likeable)
+ end
+
+ should "return valid key when likeable is a class" do
+ assert_equal "Likeables:ImALiker:#{@liker.id}:ImALikeable", likeables_key(@liker, @likeable.class)
+ end
+ end
+
+ end
+
+ # Helpers
+ def assert_match_liker(like_record, liker)
+ assert like_record.liker_type == liker.class.to_s && like_record.liker_id == liker.id
+ end
+
+ def assert_match_likeable(like_record, likeable)
+ assert like_record.likeable_type == likeable.class.to_s && like_record.likeable_id == likeable.id
+ end
+
+ def likers_key(liker = nil, likeable = nil)
+ liker ||= @liker
+ likeable ||= @likeable
+ @klass.send(:generate_likers_key, liker, likeable)
+ end
+
+ def likeables_key(liker = nil, likeable = nil)
+ liker ||= @liker
+ likeable ||= @likeable
+ @klass.send(:generate_likeables_key, liker, likeable)
+ end
+end
View
153 test/stores/redis/mention_store_test.rb
@@ -0,0 +1,153 @@
+require File.expand_path(File.dirname(__FILE__))+'/../../test_helper'
+
+class RedisMentionStoreTest < Test::Unit::TestCase
+ context "RedisStores::MentionStoreTest" do
+ setup do
+ use_redis_store
+ @klass = Socialization::RedisStores::MentionStore
+ @klass.touch nil
+ @klass.after_mention nil
+ @klass.after_unmention nil
+ @mentioner = ImAMentioner.create
+ @mentionable = ImAMentionable.create
+ end
+
+ context "Stores" do
+ should "inherit Socialization::RedisStores::MentionStore" do
+ assert_equal Socialization::RedisStores::MentionStore, Socialization.mention_model
+ end
+ end
+
+ context "#mention!" do
+ should "create a Mention record" do
+ @klass.mention!(@mentioner, @mentionable)
+ assert_equal ["#{@mentioner.id}"], Socialization.redis.smembers(mentioners_key)
+ assert_equal ["#{@mentionable.id}"], Socialization.redis.smembers(mentionables_key)
+ end
+
+ should "touch mentioner when instructed" do
+ @klass.touch :mentioner
+ @mentioner.expects(:touch).once
+ @mentionable.expects(:touch).never
+ @klass.mention!(@mentioner, @mentionable)
+ end
+
+ should "touch mentionable when instructed" do
+ @klass.touch :mentionable
+ @mentioner.expects(:touch).never
+ @mentionable.expects(:touch).once
+ @klass.mention!(@mentioner, @mentionable)
+ end
+
+ should "touch all when instructed" do
+ @klass.touch :all
+ @mentioner.expects(:touch).once
+ @mentionable.expects(:touch).once
+ @klass.mention!(@mentioner, @mentionable)
+ end
+
+ should "call after mention hook" do
+ @klass.after_mention :after_mention
+ @klass.expects(:after_mention).once
+ @klass.mention!(@mentioner, @mentionable)
+ end
+
+ should "call after unmention hook" do
+ @klass.after_mention :after_unmention
+ @klass.expects(:after_unmention).once
+ @klass.mention!(@mentioner, @mentionable)
+ end
+ end
+
+ context "#mentions?" do
+ should "return true when mention exists" do
+ Socialization.redis.sadd mentioners_key, @mentioner.id
+ Socialization.redis.sadd mentionables_key, @mentionable.id
+ assert_true @klass.mentions?(@mentioner, @mentionable)
+ end
+
+ should "return false when mention doesn't exist" do
+ assert_false @klass.mentions?(@mentioner, @mentionable)
+ end
+ end
+
+ context "#mentioners" do
+ should "return an array of mentioners" do
+ mentioner1 = ImAMentioner.create
+ mentioner2 = ImAMentioner.create
+ mentioner1.mention!(@mentionable)
+ mentioner2.mention!(@mentionable)
+ assert_array_similarity [mentioner1, mentioner2], @klass.mentioners(@mentionable, mentioner1.class)
+ end
+
+ should "return an array of mentioner ids when plucking" do
+ mentioner1 = ImAMentioner.create
+ mentioner2 = ImAMentioner.create
+ mentioner1.mention!(@mentionable)
+ mentioner2.mention!(@mentionable)
+ assert_array_similarity [mentioner1.id, mentioner2.id], @klass.mentioners(@mentionable, mentioner1.class, :pluck => :id)
+ end
+ end
+
+ context "#mentionables" do
+ should "return an array of mentionables" do
+ mentionable1 = ImAMentionable.create
+ mentionable2 = ImAMentionable.create
+ @mentioner.mention!(mentionable1)
+ @mentioner.mention!(mentionable2)
+
+ assert_array_similarity [mentionable1, mentionable2], @klass.mentionables(@mentioner, mentionable1.class)
+ end
+
+ should "return an array of mentionables ids when plucking" do
+ mentionable1 = ImAMentionable.create
+ mentionable2 = ImAMentionable.create
+ @mentioner.mention!(mentionable1)
+ @mentioner.mention!(mentionable2)
+ assert_array_similarity [mentionable1.id, mentionable2.id], @klass.mentionables(@mentioner, mentionable1.class, :pluck => :id)
+ end
+ end
+
+ context "#generate_mentioners_key" do
+ should "return valid key when passed objects" do
+ assert_equal "Mentioners:ImAMentionable:#{@mentionable.id}:ImAMentioner", mentioners_key(@mentioner, @mentionable)
+ end
+
+ should "return valid key when mentioner is a class" do
+ assert_equal "Mentioners:ImAMentionable:#{@mentionable.id}:ImAMentioner", mentioners_key(@mentioner.class, @mentionable)
+ end
+ end
+
+ context "#generate_mentionables_key" do
+ should "return valid key when passed objects" do
+ assert_equal "Mentionables:ImAMentioner:#{@mentioner.id}:ImAMentionable", mentionables_key(@mentioner, @mentionable)
+ end
+
+ should "return valid key when mentionable is a class" do
+ assert_equal "Mentionables:ImAMentioner:#{@mentioner.id}:ImAMentionable", mentionables_key(@mentioner, @mentionable.class)
+ end
+ end
+
+ end
+
+ # Helpers
+ def assert_match_mentioner(mention_record, mentioner)
+ assert mention_record.mentioner_type == mentioner.class.to_s && mention_record.mentioner_id == mentioner.id
+ end
+
+ def assert_match_mentionable(mention_record, mentionable)
+ assert mention_record.mentionable_type == mentionable.class.to_s && mention_record.mentionable_id == mentionable.id
+ end
+
+ def mentioners_key(mentioner = nil, mentionable = nil)
+ mentioner ||= @mentioner
+ mentionable ||= @mentionable
+ @klass.send(:generate_mentioners_key, mentioner, mentionable)
+ end
+
+ def mentionables_key(mentioner = nil, mentionable = nil)
+ mentioner ||= @mentioner
+ mentionable ||= @mentionable
+ @klass.send(:generate_mentionables_key, mentioner, mentionable)
+ end
+end
View
55 test/test_helper.rb
@@ -1,13 +1,21 @@
+$MOCK_REDIS = true
+
require 'rubygems'
require 'active_record'
require 'shoulda'
require 'test/unit'
require 'logger'
+require 'mock_redis' if $MOCK_REDIS
+require 'redis' unless $MOCK_REDIS
require 'mocha' # mocha always needs to be loaded last! http://stackoverflow.com/questions/3118866/mocha-mock-carries-to-another-test/4375296#4375296
$:.push File.expand_path("../lib", __FILE__)
require "socialization"
+silence_warnings do
+ Redis = MockRedis if $MOCK_REDIS # Magic!
+end
+
module Test::Unit::Assertions
def assert_true(object, message="")
assert_equal(true, object, message)
@@ -16,6 +24,47 @@ def assert_true(object, message="")
def assert_false(object, message="")
assert_equal(false, object, message)
end
+
+ def assert_array_similarity(expected, actual, message=nil)
+ full_message = build_message(message, "<?> expected but was\n<?>.\n", expected, actual)
+ assert_block(full_message) { (expected.size == actual.size) && (expected - actual == []) }
+ end
+end
+
+class Test::Unit::TestCase
+ def setup
+ use_ar_store
+ end
+
+ def teardown
+ clear_redis
+ end
+end
+
+def use_redis_store
+ Socialization.follow_model = Socialization::RedisStores::FollowStore
+ Socialization.mention_model = Socialization::RedisStores::MentionStore
+ Socialization.like_model = Socialization::RedisStores::LikeStore
+ setup_model_shortcuts
+end
+
+def use_ar_store
+ Socialization.follow_model = Socialization::ActiveRecordStores::FollowStore
+ Socialization.mention_model = Socialization::ActiveRecordStores::MentionStore
+ Socialization.like_model = Socialization::ActiveRecordStores::LikeStore
+ setup_model_shortcuts
+end
+
+def setup_model_shortcuts
+ $Follow = Socialization.follow_model
+ $Mention = Socialization.mention_model
+ $Like = Socialization.like_model
+end
+
+def clear_redis
+ Socialization.redis.keys(nil).each do |k|
+ Socialization.redis.del k
+ end
end
ActiveRecord::Base.configurations = {'sqlite3' => {:adapter => 'sqlite3', :database => ':memory:'}}
@@ -127,9 +176,9 @@ class Movie < ActiveRecord::Base
has_many :comments
end
-class Follow < Socialization::ActiveRecordStores::FollowStore; end
-class Like < Socialization::ActiveRecordStores::LikeStore; end
-class Mention < Socialization::ActiveRecordStores::MentionStore; end
+# class Follow < Socialization::ActiveRecordStores::FollowStore; end
+# class Like < Socialization::ActiveRecordStores::LikeStore; end
+# class Mention < Socialization::ActiveRecordStores::MentionStore; end
class ImAFollower < ActiveRecord::Base
acts_as_follower
View
8 test/victims/followable_test.rb
@@ -18,15 +18,15 @@ class FollowableTest < Test::Unit::TestCase
assert_raise(ArgumentError) { @followable.followed_by?(:foo) }
end
- should "call Follow.follows?" do
- Follow.expects(:follows?).with(@follower, @followable).once
+ should "call $Follow.follows?" do
+ $Follow.expects(:follows?).with(@follower, @followable).once
@followable.followed_by?(@follower)
end
end
context "#followers" do
- should "call Follow.followers" do
- Follow.expects(:followers).with(@followable, @follower.class, { :foo => :bar })
+ should "call $Follow.followers" do
+ $Follow.expects(:followers).with(@followable, @follower.class, { :foo => :bar })
@followable.followers(@follower.class, { :foo => :bar })
end
end
View
8 test/victims/likeable_test.rb
@@ -18,15 +18,15 @@ class LikeableTest < Test::Unit::TestCase
assert_raise(ArgumentError) { @likeable.liked_by?(:foo) }
end
- should "call Like.likes?" do
- Like.expects(:likes?).with(@liker, @likeable).once
+ should "call $Like.likes?" do
+ $Like.expects(:likes?).with(@liker, @likeable).once
@likeable.liked_by?(@liker)
end
end
context "#likers" do
- should "call Like.likers" do
- Like.expects(:likers).with(@likeable, @liker.class, { :foo => :bar })
+ should "call $Like.likers" do
+ $Like.expects(:likers).with(@likeable, @liker.class, { :foo => :bar })
@likeable.likers(@liker.class, { :foo => :bar })
end
end
View
8 test/victims/mentionable_test.rb
@@ -18,15 +18,15 @@ class MentionableTest < Test::Unit::TestCase
assert_raise(ArgumentError) { @mentionable.mentioned_by?(:foo) }
end
- should "call Mention.mentions?" do
- Mention.expects(:mentions?).with(@mentioner, @mentionable).once
+ should "call $Mention.mentions?" do
+ $Mention.expects(:mentions?).with(@mentioner, @mentionable).once
@mentionable.mentioned_by?(@mentioner)
end
end
context "#mentioners" do
- should "call Mention.mentioners" do
- Mention.expects(:mentioners).with(@mentionable, @mentioner.class, { :foo => :bar })
+ should "call $Mentionmentioners" do
+ $Mention.expects(:mentioners).with(@mentionable, @mentioner.class, { :foo => :bar })
@mentionable.mentioners(@mentioner.class, { :foo => :bar })
end
end
View
147 test/world_test.rb
@@ -2,95 +2,110 @@
# Test Socialization as it would be used in a "real world" scenario
class WorldTest < Test::Unit::TestCase
- attr_reader :users, :movies, :celebs, :comments
+ cattr_reader :users, :movies, :celebs, :comments
context "The World" do
setup do
seed
end
- should "be social" do
- john.like!(pulp)
- john.follow!(jane)
- john.follow!(travolta)
+ context "ActiveRecord store" do
+ setup { use_ar_store }
+ should "be social" do
+ test_the_world
+ end
+ end
+
+ context "Redis store" do
+ setup { use_redis_store }
+ should "be social" do
+ test_the_world
+ end
+ end
+ end
- assert john.likes?(pulp)
- assert john.follows?(jane)
- assert john.follows?(travolta)
+ def test_the_world
+ john.like!(pulp)
+ john.follow!(jane)
+ john.follow!(travolta)
- assert pulp.liked_by?(john)
- assert travolta.followed_by?(john)
+ assert john.likes?(pulp)
+ assert john.follows?(jane)
+ assert john.follows?(travolta)
- carl.like!(pulp)
- camilo.like!(pulp)
- assert_equal 3, pulp.likers(User).size
+ assert pulp.liked_by?(john)
+ assert travolta.followed_by?(john)
- assert pulp.likers(User).include?(carl)
- assert pulp.likers(User).include?(john)
- assert pulp.likers(User).include?(camilo)
- assert !pulp.likers(User).include?(mat)
+ carl.like!(pulp)
+ camilo.like!(pulp)
+ assert_equal 3, pulp.likers(User).size
- carl.follow!(mat)
- mat.follow!(carl)
- camilo.follow!(carl)
+ assert pulp.likers(User).include?(carl)
+ assert pulp.likers(User).include?(john)
+ assert pulp.likers(User).include?(camilo)
+ assert !pulp.likers(User).include?(mat)
- assert carl.follows?(mat)
- assert mat.followed_by?(carl)
- assert mat.follows?(carl)
- assert carl.followed_by?(mat)
- assert camilo.follows?(carl)
- assert !carl.follows?(camilo)
+ carl.follow!(mat)
+ mat.follow!(carl)
+ camilo.follow!(carl)
- assert_raise ArgumentError do
- john.like!(travolta) # Can't like a Celeb
- end
+ assert carl.follows?(mat)
+ assert mat.followed_by?(carl)
+ assert mat.follows?(carl)
+ assert carl.followed_by?(mat)
+ assert camilo.follows?(carl)
+ assert !carl.follows?(camilo)
- assert_raise ArgumentError do
- john.follow!(kill_bill) # Can't follow a movie
- end
+ assert_raise ArgumentError do
+ john.like!(travolta) # Can't like a Celeb
+ end
- # You can even follow or like yourself if your ego is that big.
- assert john.follow!(john)
- assert john.like!(john)
-
- comment = john.comments.create(:body => "I think Tami and Carl would like this movie!", :movie_id => pulp.id)
- comment.mention!(tami)
- comment.mention!(carl)
- assert comment.mentions?(carl)
- assert carl.mentioned_by?(comment)
- assert comment.mentions?(tami)
- assert tami.mentioned_by?(comment)
+ assert_raise ArgumentError do
+ john.follow!(kill_bill) # Can't follow a movie
end
+
+ # You can even follow or like yourself if your ego is that big.
+ assert john.follow!(john)
+ assert john.like!(john)
+
+ comment = john.comments.create(:body => "I think Tami and Carl would like this movie!", :movie_id => pulp.id)
+ comment.mention!(tami)
+ comment.mention!(carl)
+ assert comment.mentions?(carl)
+ assert carl.mentioned_by?(comment)
+ assert comment.mentions?(tami)
+ assert tami.mentioned_by?(comment)
end
def seed
- @users = {}
- @celebs = {}
- @movies = {}
- @comments = {}
-
- @users[:john] = User.create :name => 'John Doe'
- @users[:jane] = User.create :name => 'Jane Doe'
- @users[:mat] = User.create :name => 'Mat'
- @users[:carl] = User.create :name => 'Carl'
- @users[:camilo] = User.create :name => 'Camilo'
- @users[:tami] = User.create :name => 'Tami'
-
- @movies[:pulp] = Movie.create :name => 'Pulp Fiction'
- @movies[:reservoir] = Movie.create :name => 'Reservoir Dogs'
- @movies[:kill_bill] = Movie.create :name => 'Kill Bill'
-
- @celebs[:willis] = Celebrity.create :name => 'Bruce Willis'
- @celebs[:travolta] = Celebrity.create :name => 'John Travolta'
- @celebs[:jackson] = Celebrity.create :name => 'Samuel L. Jackson'
+ @@users = {}
+ @@celebs = {}
+ @@movies = {}
+ @@comments = {}
+
+ @@users[:john] = User.create :name => 'John Doe'
+ @@users[:jane] = User.create :name => 'Jane Doe'
+ @@users[:mat] = User.create :name => 'Mat'
+ @@users[:carl] = User.create :name => 'Carl'
+ @@users[:camilo] = User.create :name => 'Camilo'
+ @@users[:tami] = User.create :name => 'Tami'
+
+ @@movies[:pulp] = Movie.create :name => 'Pulp Fiction'
+ @@movies[:reservoir] = Movie.create :name => 'Reservoir Dogs'
+ @@movies[:kill_bill] = Movie.create :name => 'Kill Bill'
+
+ @@celebs[:willis] = Celebrity.create :name => 'Bruce Willis'
+ @@celebs[:travolta] = Celebrity.create :name => 'John Travolta'
+ @@celebs[:jackson] = Celebrity.create :name => 'Samuel L. Jackson'
end
def method_missing(meth, *args, &block)
sym = meth.to_sym
- return users[sym] if users[sym]
- return celebs[sym] if celebs[sym]
- return movies[sym] if movies[sym]
- return comments[sym] if comments[sym]
+ return users[sym] if users && users[sym]
+ return celebs[sym] if celebs && celebs[sym]
+ return movies[sym] if movies && movies[sym]
+ return comments[sym] if comments && comments[sym]
+ require 'pry'; binding.pry
super
end

0 comments on commit 2794f65

Please sign in to comment.