Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Major refactoring of the Redis store. Everything now goes through pro…

…xy methods instead of so much code duplication.

BREAKING CHANGE: data format in Redis changed since last commit. This will break your app!
  • Loading branch information...
commit f4171adf0c61d8dbf0fcb747aeee53c2d5e5e07a 1 parent 4169f0c
@cmer authored
View
124 lib/socialization/stores/redis/base.rb
@@ -4,41 +4,121 @@ class Base
class << self
protected
- def generate_actor_key(actor, victim, type)
- keys = key_type_to_class_names(type)
- raise ArgumentError.new("`#{keys[1]}` needs to be an acts_as_#{keys[1]} objects, not a class.") if victim.class == Class
- unless actor.nil?
- "#{keys[0].pluralize.capitalize}:#{victim.class}:#{victim.id}:#{actor.class == Class ? actor : actor.class}"
+ def actors(victim, klass, options = {})
+ if options[:pluck]
+ Socialization.redis.smembers(generate_forward_key(victim)).inject([]) do |result, element|
+ result << element.match(/\:(\d+)$/)[1] if element.match(/^#{klass}\:/)
+ end
else
- "#{keys[0].pluralize.capitalize}:#{victim.class}:#{victim.id}"
+ actors_relation(victim, klass, options).all
end
end
- def generate_victim_key(actor, victim, type)
- keys = key_type_to_class_names(type)
- raise ArgumentError.new("`#{keys[0]}` needs to be an acts_as_#{keys[0]} objects, not a class.") if actor.class == Class
- unless victim.nil?
- "#{keys[1].pluralize.capitalize}:#{actor.class}:#{actor.id}:#{victim.class == Class ? victim : victim.class}"
+ def actors_relation(victim, klass, options = {})
+ ids = actors(victim, klass, :pluck => :id)
+ klass.where('id IN (?)', ids)
+ end
+
+ def victims_relation(actor, klass, options = {})
+ ids = victims(actor, klass, :pluck => :id)
+ klass.where('id IN (?)', ids)
+ end
+
+ def victims(actor, klass, options = {})
+ if options[:pluck]
+ Socialization.redis.smembers(generate_backward_key(actor)).inject([]) do |result, element|
+ result << element.match(/\:(\d+)$/)[1] if element.match(/^#{klass}\:/)
+ end
else
- "#{keys[1].pluralize.capitalize}:#{actor.class}:#{actor.id}"
+ victims_relation(actor, klass, options).all
+ end
+ end
+
+ def relation!(actor, victim, options = {})
+ unless options[:skip_check] || relation?(actor, victim)
+ Socialization.redis.sadd generate_forward_key(victim), generate_redis_value(actor)
+ Socialization.redis.sadd generate_backward_key(actor), generate_redis_value(victim)
+ call_after_create_hooks(actor, victim)
+ true
+ else
+ false
+ end
+ end
+
+ def unrelation!(actor, victim, options = {})
+ if options[:skip_check] || relation?(actor, victim)
+ Socialization.redis.srem generate_forward_key(victim), generate_redis_value(actor)
+ Socialization.redis.srem generate_backward_key(actor), generate_redis_value(victim)
+ call_after_destroy_hooks(actor, victim)
+ true
+ else
+ false
+ end
+ end
+
+ def relation?(actor, victim)
+ Socialization.redis.sismember generate_forward_key(victim), generate_redis_value(actor)
+ end
+
+ def remove_actor_relations(victim)
+ forward_key = generate_forward_key(victim)
+ actors = Socialization.redis.smembers forward_key
+ Socialization.redis.del forward_key
+ actors.each do |actor|
+ Socialization.redis.srem generate_backward_key(actor), generate_redis_value(victim)
end
+ true
end
+ def remove_victim_relations(actor)
+ backward_key = generate_backward_key(actor)
+ victims = Socialization.redis.smembers backward_key
+ Socialization.redis.del backward_key
+ victims.each do |victim|
+ Socialization.redis.srem generate_forward_key(victim), generate_redis_value(actor)
+ end
+ true
+ end
+
+
private
- def key_type_to_class_names(type)
- case type
- when :follow
+ def key_type_to_type_names(klass)
+ case klass.name
+ when "Socialization::RedisStores::Follow"
['follower', 'followable']
- when :like
+ when "Socialization::RedisStores::Like"
['liker', 'likeable']
- when :mention
+ when "Socialization::RedisStores::Mention"
['mentioner', 'mentionable']
else
- raise NotImplementedError
+ raise ArgumentError.new("Can't find matching type for #{klass}.")
+ end
+ end
+
+ def generate_forward_key(victim)
+ keys = key_type_to_type_names(self)
+ if victim.is_a?(String)
+ "#{keys[0].pluralize.capitalize}:#{victim}"
+ else
+ "#{keys[0].pluralize.capitalize}:#{victim.class}:#{victim.id}"
end
end
- end
- end
- end
-end
+ def generate_backward_key(actor)
+ keys = key_type_to_type_names(self)
+ if actor.is_a?(String)
+ "#{keys[1].pluralize.capitalize}:#{actor}"
+ else
+ "#{keys[1].pluralize.capitalize}:#{actor.class}:#{actor.id}"
+ end
+ end
+
+ def generate_redis_value(obj)
+ "#{obj.class.name}:#{obj.id}"
+ end
+
+ end # class << self
+
+ end # Base
+ end # RedisStores
+end # Socialization
View
83 lib/socialization/stores/redis/follow.rb
@@ -1,5 +1,3 @@
-# require File.expand_path(File.dirname(__FILE__)) + '/base'
-
module Socialization
module RedisStores
class Follow < Socialization::RedisStores::Base
@@ -8,77 +6,16 @@ class Follow < Socialization::RedisStores::Base
extend Socialization::RedisStores::Mixins::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_hooks(follower, followable)
- 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_hooks(follower, followable)
- 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
-
- private
- def generate_followers_key(follower, followable)
- generate_actor_key(follower, followable, :follow)
- end
-
- def generate_followables_key(follower, followable)
- generate_victim_key(follower, followable, :follow)
- end
- end # class << self
+ alias_method :follow!, :relation!; public :follow!
+ alias_method :unfollow!, :unrelation!; public :unfollow!
+ alias_method :follows?, :relation?; public :follows?
+ alias_method :followers_relation, :actors_relation; public :followers_relation
+ alias_method :followers, :actors; public :followers
+ alias_method :followables_relation, :victims_relation; public :followables_relation
+ alias_method :followables, :victims; public :followables
+ alias_method :remove_followers, :remove_actor_relations; public :remove_followers
+ alias_method :remove_followables, :remove_victim_relations; public :remove_followables
+ end
end
end
View
114 lib/socialization/stores/redis/like.rb
@@ -1,5 +1,3 @@
-# require File.expand_path(File.dirname(__FILE__)) + '/base'
-
module Socialization
module RedisStores
class Like < Socialization::RedisStores::Base
@@ -8,108 +6,16 @@ class Like < Socialization::RedisStores::Base
extend Socialization::RedisStores::Mixins::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_hooks(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_hooks(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_hooks(liker, likeable)
- self.send(@after_create_hook, liker, likeable) if @after_create_hook
- end
-
- def call_after_destroy_hooks(liker, likeable)
- self.send(@after_destroy_hook, liker, likeable) if @after_destroy_hook
- end
-
- def generate_likers_key(liker, likeable)
- generate_actor_key(liker, likeable, :like)
- end
-
- def generate_likeables_key(liker, likeable)
- generate_victim_key(liker, likeable, :like)
- end
- end # class << self
+ alias_method :like!, :relation!; public :like!
+ alias_method :unlike!, :unrelation!; public :unlike!
+ alias_method :likes?, :relation?; public :likes?
+ alias_method :likers_relation, :actors_relation; public :likers_relation
+ alias_method :likers, :actors; public :likers
+ alias_method :likeables_relation, :victims_relation; public :likeables_relation
+ alias_method :likeables, :victims; public :likeables
+ alias_method :remove_likers, :remove_actor_relations; public :remove_likers
+ alias_method :remove_likeables, :remove_victim_relations; public :remove_likeables
+ end
end
end
View
83 lib/socialization/stores/redis/mention.rb
@@ -1,5 +1,3 @@
-# require File.expand_path(File.dirname(__FILE__)) + '/base'
-
module Socialization
module RedisStores
class Mention < Socialization::RedisStores::Base
@@ -8,77 +6,16 @@ class Mention < Socialization::RedisStores::Base
extend Socialization::RedisStores::Mixins::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_hooks(mentioner, mentionable)
- 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_hooks(mentioner, mentionable)
- 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
-
- private
- def generate_mentioners_key(mentioner, mentionable)
- generate_actor_key(mentioner, mentionable, :mention)
- end
-
- def generate_mentionables_key(mentioner, mentionable)
- generate_victim_key(mentioner, mentionable, :mention)
- end
- end # class << self
+ alias_method :mention!, :relation!; public :mention!
+ alias_method :unmention!, :unrelation!; public :unmention!
+ alias_method :mentions?, :relation?; public :mentions?
+ alias_method :mentioners_relation, :actors_relation; public :mentioners_relation
+ alias_method :mentioners, :actors; public :mentioners
+ alias_method :mentionables_relation, :victims_relation; public :mentionables_relation
+ alias_method :mentionables, :victims; public :mentionables
+ alias_method :remove_mentioners, :remove_actor_relations; public :remove_mentioners
+ alias_method :remove_mentionables, :remove_victim_relations; public :remove_mentionables
+ end
end
end
View
203 test/stores/redis/base_test.rb
@@ -0,0 +1,203 @@
+require File.expand_path(File.dirname(__FILE__))+'/../../test_helper'
+
+class RedisBaseStoreTest < Test::Unit::TestCase
+ # Testing through RedisStores::Follow for easy testing
+ context "RedisStores::Base through RedisStores::Follow" do
+ setup do
+ use_redis_store
+ @klass = Socialization::RedisStores::Follow
+ @klass.touch nil
+ @klass.after_follow nil
+ @klass.after_unfollow nil
+ @follower1 = ImAFollower.create
+ @follower2 = ImAFollower.create
+ @followable1 = ImAFollowable.create
+ @followable2 = ImAFollowable.create
+ end
+
+ context "Stores" do
+ should "inherit Socialization::RedisStores::Follow" do
+ assert_equal Socialization::RedisStores::Follow, Socialization.follow_model
+ end
+ end
+
+ context "#follow!" do
+ should "create follow records" do
+ @klass.follow!(@follower1, @followable1)
+ assert_array_similarity ["#{@follower1.class}:#{@follower1.id}"], Socialization.redis.smembers(forward_key(@followable1))
+ assert_array_similarity ["#{@followable1.class}:#{@followable1.id}"], Socialization.redis.smembers(backward_key(@follower1))
+
+ @klass.follow!(@follower2, @followable1)
+ assert_array_similarity ["#{@follower1.class}:#{@follower1.id}", "#{@follower2.class}:#{@follower2.id}"], Socialization.redis.smembers(forward_key(@followable1))
+ assert_array_similarity ["#{@followable1.class}:#{@followable1.id}"], Socialization.redis.smembers(backward_key(@follower1))
+ assert_array_similarity ["#{@followable1.class}:#{@followable1.id}"], Socialization.redis.smembers(backward_key(@follower2))
+ end
+
+ should "touch follower when instructed" do
+ @klass.touch :follower
+ @follower1.expects(:touch).once
+ @followable1.expects(:touch).never
+ @klass.follow!(@follower1, @followable1)
+ end
+
+ should "touch followable when instructed" do
+ @klass.touch :followable
+ @follower1.expects(:touch).never
+ @followable1.expects(:touch).once
+ @klass.follow!(@follower1, @followable1)
+ end
+
+ should "touch all when instructed" do
+ @klass.touch :all
+ @follower1.expects(:touch).once
+ @followable1.expects(:touch).once
+ @klass.follow!(@follower1, @followable1)
+ end
+
+ should "call after follow hook" do
+ @klass.after_follow :after_follow
+ @klass.expects(:after_follow).once
+ @klass.follow!(@follower1, @followable1)
+ end
+
+ should "call after unfollow hook" do
+ @klass.after_follow :after_unfollow
+ @klass.expects(:after_unfollow).once
+ @klass.follow!(@follower1, @followable1)
+ end
+ end
+
+ context "#unfollow!" do
+ setup do
+ @klass.follow!(@follower1, @followable1)
+ end
+
+ should "remove follow records" do
+ @klass.unfollow!(@follower1, @followable1)
+ assert_empty Socialization.redis.smembers forward_key(@followable1)
+ assert_empty Socialization.redis.smembers backward_key(@follower1)
+ end
+ end
+
+ context "#follows?" do
+ should "return true when follow exists" do
+ @klass.follow!(@follower1, @followable1)
+ assert_true @klass.follows?(@follower1, @followable1)
+ end
+
+ should "return false when follow doesn't exist" do
+ assert_false @klass.follows?(@follower1, @followable1)
+ end
+ end
+
+ context "#followers" do
+ should "return an array of followers" do
+ follower1 = ImAFollower.create
+ follower2 = ImAFollower.create
+ follower1.follow!(@followable1)
+ follower2.follow!(@followable1)
+ assert_array_similarity [follower1, follower2], @klass.followers(@followable1, follower1.class)
+ end
+
+ should "return an array of follower ids when plucking" do
+ follower1 = ImAFollower.create
+ follower2 = ImAFollower.create
+ follower1.follow!(@followable1)
+ follower2.follow!(@followable1)
+ assert_array_similarity ["#{follower1.id}", "#{follower2.id}"], @klass.followers(@followable1, follower1.class, :pluck => :id)
+ end
+ end
+
+ context "#followables" do
+ should "return an array of followables" do
+ followable1 = ImAFollowable.create
+ followable2 = ImAFollowable.create
+ @follower1.follow!(followable1)
+ @follower1.follow!(followable2)
+
+ assert_array_similarity [followable1, followable2], @klass.followables(@follower1, followable1.class)
+ end
+
+ should "return an array of followables ids when plucking" do
+ followable1 = ImAFollowable.create
+ followable2 = ImAFollowable.create
+ @follower1.follow!(followable1)
+ @follower1.follow!(followable2)
+ assert_array_similarity ["#{followable1.id}", "#{followable2.id}"], @klass.followables(@follower1, followable1.class, :pluck => :id)
+ end
+ end
+
+ context "#generate_forward_key" do
+ should "return valid key when passed an object" do
+ assert_equal "Followers:#{@followable1.class.name}:#{@followable1.id}", forward_key(@followable1)
+ end
+
+ should "return valid key when passed a String" do
+ assert_equal "Followers:Followable:1", forward_key("Followable:1")
+ end
+ end
+
+ context "#generate_backward_key" do
+ should "return valid key when passed an object" do
+ assert_equal "Followables:#{@follower1.class.name}:#{@follower1.id}", backward_key(@follower1)
+ end
+
+ should "return valid key when passed a String" do
+ assert_equal "Followables:Follower:1", backward_key("Follower:1")
+ end
+ end
+
+ context "#remove_followers" do
+ should "delete all followers relationships for a followable" do
+ @follower1.follow!(@followable1)
+ @follower2.follow!(@followable1)
+ assert_equal 2, @followable1.followers(@follower1.class).count
+
+ @klass.remove_followers(@followable1)
+ assert_equal 0, @followable1.followers(@follower1.class).count
+ assert_empty Socialization.redis.smembers forward_key(@followable1)
+ assert_empty Socialization.redis.smembers backward_key(@follower1)
+ assert_empty Socialization.redis.smembers backward_key(@follower2)
+ end
+ end
+
+ context "#remove_followables" do
+ should "delete all followables relationships for a follower" do
+ @follower1.follow!(@followable1)
+ @follower1.follow!(@followable2)
+ assert_equal 2, @follower1.followables(@followable1.class).count
+
+ @klass.remove_followables(@follower1)
+ assert_equal 0, @follower1.followables(@followable1.class).count
+ assert_empty Socialization.redis.smembers backward_key(@followable1)
+ assert_empty Socialization.redis.smembers backward_key(@follower2)
+ assert_empty Socialization.redis.smembers forward_key(@follower1)
+ end
+ end
+
+ context "#key_type_to_type_names" do
+ should "return the proper arrays" do
+ assert_equal ['follower', 'followable'], @klass.send(:key_type_to_type_names, Socialization::RedisStores::Follow)
+ assert_equal ['mentioner', 'mentionable'], @klass.send(:key_type_to_type_names, Socialization::RedisStores::Mention)
+ assert_equal ['liker', 'likeable'], @klass.send(:key_type_to_type_names, Socialization::RedisStores::Like)
+ 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 forward_key(followable)
+ Socialization::RedisStores::Follow.send(:generate_forward_key, followable)
+ end
+
+ def backward_key(follower)
+ Socialization::RedisStores::Follow.send(:generate_backward_key, follower)
+ end
+end
View
161 test/stores/redis/follow_store_test.rb
@@ -1,156 +1,27 @@
require File.expand_path(File.dirname(__FILE__))+'/../../test_helper'
class RedisFollowStoreTest < Test::Unit::TestCase
- context "RedisStores::FollowStoreTest" do
+ context "RedisStores::Follow" do
setup do
use_redis_store
@klass = Socialization::RedisStores::Follow
- @klass.touch nil
- @klass.after_follow nil
- @klass.after_unfollow nil
- @follower = ImAFollower.create
- @followable = ImAFollowable.create
+ @base = Socialization::RedisStores::Base
end
- context "Stores" do
- should "inherit Socialization::RedisStores::Follow" do
- assert_equal Socialization::RedisStores::Follow, Socialization.follow_model
+ context "method aliases" do
+ should "be set properly and made public" do
+ # TODO: Can't figure out how to test method aliases properly. The following doesn't work:
+ # assert @klass.method(:follow!) == @base.method(:relation!)
+ assert_method_public @klass, :follow!
+ assert_method_public @klass, :unfollow!
+ assert_method_public @klass, :follows?
+ assert_method_public @klass, :followers_relation
+ assert_method_public @klass, :followers
+ assert_method_public @klass, :followables_relation
+ assert_method_public @klass, :followables
+ assert_method_public @klass, :remove_followers
+ assert_method_public @klass, :remove_followables
end
end
-
- context "#follow!" do
- should "create a Follow record" do
- @klass.follow!(@follower, @followable)
- assert_equal ["#{@follower.id}"], Socialization.redis.smembers(followers_key(@follower, @followable))
- assert_equal ["#{@followable.id}"], Socialization.redis.smembers(followables_key(@follower, @followable))
- 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, @followable), @follower.id
- Socialization.redis.sadd followables_key(@follower, @followable), @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
-
- should "return valid key when follower is nil" do
- assert_equal "Followers:ImAFollowable:#{@followable.id}", followers_key(nil, @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
-
- should "return valid key when followable is nil" do
- assert_equal "Followables:ImAFollower:#{@follower.id}", followables_key(@follower, nil)
- 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)
- @klass.send(:generate_followers_key, follower, followable)
- end
-
- def followables_key(follower = nil, followable = nil)
- @klass.send(:generate_followables_key, follower, followable)
end
-end
+end
View
160 test/stores/redis/like_store_test.rb
@@ -1,157 +1,25 @@
require File.expand_path(File.dirname(__FILE__))+'/../../test_helper'
class RedisLikeStoreTest < Test::Unit::TestCase
- context "RedisStores::LikeStoreTest" do
+ context "RedisStores::Like" do
setup do
use_redis_store
@klass = Socialization::RedisStores::Like
- @klass.touch nil
- @klass.after_like nil
- @klass.after_unlike nil
- @liker = ImALiker.create
- @likeable = ImALikeable.create
+ @base = Socialization::RedisStores::Base
end
- context "Stores" do
- should "inherit Socialization::RedisStores::Like" do
- assert_equal Socialization::RedisStores::Like, Socialization.like_model
+ context "method aliases" do
+ should "be set properly and made public" do
+ assert_method_public @klass, :like!
+ assert_method_public @klass, :unlike!
+ assert_method_public @klass, :likes?
+ assert_method_public @klass, :likers_relation
+ assert_method_public @klass, :likers
+ assert_method_public @klass, :likeables_relation
+ assert_method_public @klass, :likeables
+ assert_method_public @klass, :remove_likers
+ assert_method_public @klass, :remove_likeables
end
end
-
- context "#like!" do
- should "create a Like record" do
- @klass.like!(@liker, @likeable)
- assert_equal ["#{@liker.id}"], Socialization.redis.smembers(likers_key(@liker, @likeable))
- assert_equal ["#{@likeable.id}"], Socialization.redis.smembers(likeables_key(@liker, @likeable))
- 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, @likeable), @liker.id
- Socialization.redis.sadd likeables_key(@liker, @likeable), @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
-
- should "return valid key when liker is nil" do
- assert_equal "Likers:ImALikeable:#{@likeable.id}", likers_key(nil, @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
-
- should "return valid key when likeable is nil" do
- assert_equal "Likeables:ImALiker:#{@liker.id}", likeables_key(@liker, nil)
- 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)
- @klass.send(:generate_likers_key, liker, likeable)
- end
-
- def likeables_key(liker = nil, likeable = nil)
- @klass.send(:generate_likeables_key, liker, likeable)
end
-end
+end
View
160 test/stores/redis/mention_store_test.rb
@@ -1,157 +1,25 @@
require File.expand_path(File.dirname(__FILE__))+'/../../test_helper'
class RedisMentionStoreTest < Test::Unit::TestCase
- context "RedisStores::MentionStoreTest" do
+ context "RedisStores::Mention" do
setup do
use_redis_store
@klass = Socialization::RedisStores::Mention
- @klass.touch nil
- @klass.after_mention nil
- @klass.after_unmention nil
- @mentioner = ImAMentioner.create
- @mentionable = ImAMentionable.create
+ @base = Socialization::RedisStores::Base
end
- context "Stores" do
- should "inherit Socialization::RedisStores::Mention" do
- assert_equal Socialization::RedisStores::Mention, Socialization.mention_model
+ context "method aliases" do
+ should "be set properly and made public" do
+ assert_method_public @klass, :mention!
+ assert_method_public @klass, :unmention!
+ assert_method_public @klass, :mentions?
+ assert_method_public @klass, :mentioners_relation
+ assert_method_public @klass, :mentioners
+ assert_method_public @klass, :mentionables_relation
+ assert_method_public @klass, :mentionables
+ assert_method_public @klass, :remove_mentioners
+ assert_method_public @klass, :remove_mentionables
end
end
-
- context "#mention!" do
- should "create a Mention record" do
- @klass.mention!(@mentioner, @mentionable)
- assert_equal ["#{@mentioner.id}"], Socialization.redis.smembers(mentioners_key(@mentioner, @mentionable))
- assert_equal ["#{@mentionable.id}"], Socialization.redis.smembers(mentionables_key(@mentioner, @mentionable))
- 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, @mentionable), @mentioner.id
- Socialization.redis.sadd mentionables_key(@mentioner, @mentionable), @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
-
- should "return valid key when mentioner is nil" do
- assert_equal "Mentioners:ImAMentionable:#{@mentionable.id}", mentioners_key(nil, @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
-
- should "return valid key when mentionable is nil" do
- assert_equal "Mentionables:ImAMentioner:#{@mentioner.id}", mentionables_key(@mentioner, nil)
- 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)
- @klass.send(:generate_mentioners_key, mentioner, mentionable)
- end
-
- def mentionables_key(mentioner = nil, mentionable = nil)
- @klass.send(:generate_mentionables_key, mentioner, mentionable)
end
-end
+end
View
18 test/test_helper.rb
@@ -8,6 +8,7 @@
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
+# require 'pry'
$:.push File.expand_path("../lib", __FILE__)
require "socialization"
@@ -29,6 +30,23 @@ 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
+
+ def assert_empty(obj, msg = nil)
+ msg = "Expected #{obj.inspect} to be empty" unless msg
+ assert_respond_to obj, :empty?
+ assert obj.empty?, msg
+ end
+
+ def assert_method_public(obj, method, msg = nil)
+ msg = "Expected method #{obj}.#{method} to be public."
+ method = if RUBY_VERSION.match(/^1\.8/)
+ method.to_s
+ else
+ method.to_s.to_sym
+ end
+
+ assert obj.public_methods.include?(method), msg
+ end
end
class Test::Unit::TestCase
Please sign in to comment.
Something went wrong with that request. Please try again.