likeable 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -7,7 +7,7 @@ source 'http://rubygems.org'
7
7
  group :development, :test do
8
8
  gem 'activerecord', '~>3.0.4' ## not needed if you're just using KeyBuilder
9
9
  gem 'rake', '~>0.8.7'
10
- gem 'jeweler', '~>1.5.2'
10
+ gem 'jeweler'
11
11
  gem "autotest-standalone"
12
12
  gem "autotest-growl"
13
13
  end
data/README.md CHANGED
@@ -1,16 +1,152 @@
1
- # Likeable Has Moved!!
1
+ Use Redis to Make your Ruby objects Likeable!
2
+ ======
2
3
 
3
- You can see the most up-to-date version here: https://github.com/schneems/likeable
4
+ I no longer use this gem in production (it was written for Gowalla), if you do and want to help me maintain it, let me know [@schneems](http://twitter.com/schneems).
4
5
 
5
- # What is it?
6
+ You like this
7
+ -------------
8
+ Likeable will allow your models to be liked by users, just drop a few lines of code into your model and you're good to go.
6
9
 
7
- Use Redis to make any Ruby objects Likeable!
10
+ ```ruby
8
11
 
12
+ class Comment
13
+ include Likeable
9
14
 
10
- # Why
15
+ # ...
16
+ end
11
17
 
12
- We chose Redis because it is screaming fast, and very simple to work with. By using Redis for likeable we take load off of our relational database and speed up individual calls to retrieve information about the "liked" state of an object. If you're not using Redis in production, and don't want to, there are many other great liking/voting libraries out there such as [thumbs up](https://github.com/brady8/thumbs_up).
18
+ class User
19
+ include Likeable::UserMethods
13
20
 
21
+ # ...
22
+ end
23
+
24
+ Likeable.setup do |likeable|
25
+ likeable.redis = Redis.new
26
+ end
27
+
28
+ comment = Comment.find(15)
29
+ comment.like_count # => 0
30
+ current_user.like!(comment) # => #<Likeable::Like ... >
31
+ comment.like_count # => 1
32
+ comment.likes # => [#<Likeable::Like ... >]
33
+ comment.likes.last.user # => #<User ... >
34
+ comment.likes.last.created_at # => Wed Jul 27 19:34:32 -0500 2011
35
+
36
+ comment.liked_by?(current_user) # => true
37
+
38
+ current_user.all_liked(Comment) # => [#<Comment ...>, ...]
39
+
40
+ liked_comment = Likeable.find_by_resource_id("Comment", 15)
41
+ liked_comment == comment # => true
42
+
43
+ ```
44
+
45
+ This library doesn't do dislikes, if you want something with more flexibility check out [opinions](https://github.com/leehambley/opinions).
46
+
47
+ ## Screencast
48
+
49
+ You can view a [screencast of likeable in action on youtube](http://youtu.be/iJoMXUQ33Jw?hd=1). There is also an example [Likeable rails application](https://github.com/schneems/likeable_example) that you can use to follow along.
50
+
51
+
52
+
53
+ Setup
54
+ =======
55
+ Gemfile:
56
+
57
+ gem 'likeable'
58
+
59
+ Next set up your Redis connection in initializers/likeable.rb:
60
+
61
+ ```ruby
62
+
63
+ Likeable.setup do |likeable|
64
+ likeable.redis = Redis.new
65
+ end
66
+ ```
67
+
68
+ Then add the `Likeable::UserMethods` module to models/user.rb:
69
+
70
+ ```ruby
71
+
72
+ class User
73
+ include Likeable::UserMethods
74
+ end
75
+ ```
76
+
77
+ Finally add `Likeable` module to any model you want to be liked:
78
+
79
+ ```ruby
80
+
81
+ class Comment
82
+ include Likeable
83
+ end
84
+ ```
85
+
86
+ ## Rails Info
87
+ If you're using Likeable in Rails this should help you get started
88
+
89
+ controllers/likes_controller.rb
90
+
91
+ ```ruby
92
+
93
+ class LikesController < ApplicationController
94
+
95
+ def create
96
+ target = Likeable.find_by_resource_id(params[:resource_name], params[:resource_id])
97
+ current_user.like!(target)
98
+ redirect_to :back, :notice => 'success'
99
+ end
100
+
101
+ def destroy
102
+ target = Likeable.find_by_resource_id(params[:resource_name], params[:resource_id])
103
+ current_user.unlike!(target)
104
+ redirect_to :back, :notice => 'success'
105
+ end
106
+ end
107
+
108
+ ```
109
+
110
+ config/routes.rb
111
+
112
+ ```ruby
113
+
114
+ delete 'likes/:resource_name/:resource_id' => "likes#destroy", :as => 'like'
115
+ post 'likes/:resource_name/:resource_id' => "likes#create", :as => 'like'
116
+
117
+ ```
118
+
119
+ helpers/like_helper.rb
120
+
121
+ ```ruby
122
+
123
+ def like_link_for(target)
124
+ link_to "like it!!", like_path(:resource_name => target .class, :resource_id => target.id), :method => :post
125
+ end
126
+
127
+ def unlike_link_for(target)
128
+ link_to "unlike it!!", like_path(:resource_name => target.class, :resource_id => target.id), :method => :delete
129
+ end
130
+
131
+ ```
132
+
133
+ Then in any view you can simply call the helper methods to give your user a link
134
+
135
+ ```ruby
136
+
137
+ <%- if @user.likes? @comment -%>
138
+ <%= unlike_link_for @comment %>
139
+ <%- else -%>
140
+ <%= like_link_for @comment %>
141
+ <%- end -%>
142
+
143
+
144
+ ```
145
+
146
+ Why
147
+ ===
148
+
149
+ We chose Redis because it is screaming fast, and very simple to work with. By using redis for likeable we take load off of our relational database and speed up individual calls retrieve information about the "liked" state of an object. If you're not using redis in production, and don't want to, there are many other great liking/voting libraries out there such as [thumbs up](https://github.com/brady8/thumbs_up).
14
150
 
15
151
 
16
152
  RedisRed RedisRedi
@@ -40,3 +176,13 @@ Authors
40
176
  =======
41
177
  [Richard Schneeman](http://schneems.com) for [Gowalla](http://gowalla.com) <3
42
178
 
179
+
180
+ Contribution
181
+ ============
182
+
183
+ Fork away. If you want to chat about a feature idea, or a question you can find me on the twitters [@schneems](http://twitter.com/schneems). Put any major changes into feature branches. Make sure all tests stay green, and make sure your changes are covered.
184
+
185
+
186
+ licensed under MIT License
187
+ Copyright (c) 2011 Schneems. See LICENSE.txt for
188
+ further details.
data/Rakefile CHANGED
@@ -27,3 +27,5 @@ Jeweler::RubygemsDotOrgTasks.new
27
27
 
28
28
  require 'rspec/core/rake_task'
29
29
  RSpec::Core::RakeTask.new(:spec)
30
+
31
+ task :default => [:spec]
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
@@ -1,7 +1,6 @@
1
1
  require 'active_support/concern'
2
2
  require 'keytar'
3
3
 
4
-
5
4
  module Likeable
6
5
  extend ActiveSupport::Concern
7
6
 
@@ -44,9 +43,16 @@ module Likeable
44
43
 
45
44
  # removes a like
46
45
  def remove_like_from(user)
47
- Likeable.redis.hdel(like_key, user.id)
48
- Likeable.redis.hdel(user.like_key(self.class.to_s.downcase), self.id)
49
- clear_memoized_methods(:like_count, :like_user_ids, :liked_user_ids, :liked_users)
46
+ if Likeable.redis.hexists(like_key, user.id)
47
+ Likeable.redis.hdel(like_key, user.id)
48
+ Likeable.redis.hdel(user.like_key(self.class.to_s.downcase), self.id)
49
+ after_unlike(user)
50
+ clear_memoized_methods(:like_count, :like_user_ids, :liked_user_ids, :liked_users)
51
+ end
52
+ end
53
+
54
+ def after_unlike(user)
55
+ Likeable.after_unlike.call(user)
50
56
  end
51
57
 
52
58
  def like_count
@@ -55,11 +61,11 @@ module Likeable
55
61
 
56
62
  # get all user ids that have liked a target object
57
63
  def like_user_ids
58
- @like_user_ids ||= (Likeable.redis.hkeys(like_key)||[]).map(&:to_i)
64
+ @like_user_ids ||= (Likeable.redis.hkeys(like_key)||[]).map {|id| Likeable.cast_id(id)}
59
65
  end
60
66
 
61
67
  def liked_users(limit = nil)
62
- @liked_users ||= Likeable.user_class.where(:id => like_user_ids)
68
+ @liked_users ||= Likeable.find_many(Likeable.user_class, like_user_ids)
63
69
  end
64
70
 
65
71
  def likes
@@ -73,8 +79,8 @@ module Likeable
73
79
  # did given user like the object
74
80
  def liked_by?(user)
75
81
  return false unless user
76
- liked_by = @like_user_ids.include?(user.id) if @like_user_ids
77
- liked_by ||= Likeable.redis.hexists(like_key, user.id)
82
+ liked_by = @like_user_ids.include?(Likeable.cast_id(user.id)) if @like_user_ids
83
+ liked_by ||= true & Likeable.redis.hexists(like_key, user.id)
78
84
  end
79
85
 
80
86
 
@@ -87,16 +93,18 @@ module Likeable
87
93
  # ----------------- #
88
94
  # allows us to setup callbacks when creating likes
89
95
  # after_like :notify_users
96
+ # allows us to setup callbacks when destroying likes
97
+ # after_unlike :notify_users
90
98
  module ClassMethods
91
99
 
92
100
  def all_liked_ids_by(user)
93
101
  key = user.like_key(self.to_s.downcase)
94
- ids = (Likeable.redis.hkeys(key)||[]).map(&:to_i)
102
+ ids = (Likeable.redis.hkeys(key)||[]).map {|id| Likeable.cast_id(id)}
95
103
  end
96
104
 
97
105
  def all_liked_by(user)
98
106
  ids = all_liked_ids_by(user)
99
- self.where(:id => ids)
107
+ Likeable.find_many(self, ids)
100
108
  end
101
109
 
102
110
  def after_like(*methods)
@@ -106,7 +114,19 @@ module Likeable
106
114
  end
107
115
  end
108
116
  end
117
+
118
+ def after_unlike(*methods)
119
+ define_method(:after_unlike) do |user|
120
+ methods.each do |method|
121
+ eval("#{method}(user)")
122
+ end
123
+ end
124
+ end
109
125
  end
126
+
127
+ autoload :DefaultAdapter , "likeable/adapters/default_adapter"
128
+ autoload :MongoidAdapter , "likeable/adapters/mongoid_adapter"
129
+ autoload :OhmAdapter , "likeable/adapters/ohm_adapter"
110
130
  end
111
131
 
112
132
  require 'likeable/like'
@@ -0,0 +1,19 @@
1
+ module Likeable
2
+ module DefaultAdapter
3
+ def self.cast_id
4
+ lambda { |id| id.to_i }
5
+ end
6
+
7
+ def self.find_one
8
+ lambda { |klass, id|
9
+ klass.where(:id => id).first
10
+ }
11
+ end
12
+
13
+ def self.find_many
14
+ lambda { |klass, ids|
15
+ klass.where(:id => ids)
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Likeable
2
+ module MongoidAdapter
3
+ def self.cast_id
4
+ lambda { |id| id.to_s }
5
+ end
6
+
7
+ def self.find_one
8
+ lambda { |klass, id|
9
+ klass.find id
10
+ }
11
+ end
12
+
13
+ def self.find_many
14
+ lambda { |klass, ids|
15
+ klass.find ids
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ module Likeable
2
+ module OhmAdapter
3
+ def self.find_one
4
+ lambda { |klass, id|
5
+ klass[id]
6
+ }
7
+ end
8
+
9
+ def self.find_many
10
+ lambda { |klass, ids|
11
+ Array(ids).collect do |id|
12
+ klass[id]
13
+ end.compact
14
+ }
15
+ end
16
+ end
17
+ end
@@ -16,7 +16,7 @@ class Likeable::Like
16
16
 
17
17
  def user
18
18
  @user ||= like_user
19
- @user ||= Likeable.find_one(User, user_id)
19
+ @user ||= Likeable.find_one(Likeable.user_class, user_id)
20
20
  @user
21
21
  end
22
22
 
@@ -28,4 +28,4 @@ class Likeable::Like
28
28
  :user => user.to_hash(type)
29
29
  }
30
30
  end
31
- end
31
+ end
@@ -8,6 +8,8 @@ module Likeable
8
8
  ### Module Methods ###
9
9
  # ------------------ #
10
10
  class << self
11
+ attr_writer :cast_id, :find_one, :find_many
12
+
11
13
  def classes
12
14
  (@classes||[]).flatten
13
15
  end
@@ -64,25 +66,37 @@ module Likeable
64
66
  @after_like
65
67
  end
66
68
 
67
- def find_many=(find_many)
68
- @find_many = find_many
69
+ def after_unlike(&block)
70
+ @after_unlike = block if block.present?
71
+ @after_unlike ||= lambda {|like|}
72
+ @after_unlike
73
+ end
74
+
75
+ def adapter=(adapter)
76
+ self.find_one = adapter.find_one
77
+ self.find_many = adapter.find_many
78
+ @adapter = adapter
79
+ end
80
+
81
+ def cast_id(id)
82
+ @cast_id ||= if @adapter && @adapter.respond_to?(:cast_id)
83
+ @adapter.cast_id
84
+ else
85
+ DefaultAdapter.cast_id
86
+ end
87
+ @cast_id.call(id)
69
88
  end
70
89
 
71
90
  def find_many(klass, ids)
72
- @find_many ||= lambda {|klass, ids| klass.where(:id => ids)}
91
+ @find_many ||= DefaultAdapter.find_many
73
92
  @find_many.call(klass, ids)
74
93
  end
75
94
 
76
-
77
95
  def find_one(klass, id)
78
- @find_one ||= lambda {|klass, id| klass.where(:id => id).first}
96
+ @find_one ||= DefaultAdapter.find_one
79
97
  @find_one.call(klass, id)
80
98
  end
81
99
 
82
- def find_one=(find_one)
83
- @find_one = find_one
84
- end
85
-
86
100
  def user_class
87
101
  begin
88
102
  @user_class ||= ::User
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "likeable"
8
- s.version = "0.1.1"
8
+ s.version = "0.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Schneems"]
12
- s.date = "2011-12-17"
12
+ s.date = "2012-05-24"
13
13
  s.description = "\n Likeable allows you to make your models...well...likeable using redis.\n "
14
14
  s.email = "richard.schneeman@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -24,12 +24,17 @@ Gem::Specification.new do |s|
24
24
  "VERSION",
25
25
  "autotest/discover.rb",
26
26
  "lib/likeable.rb",
27
+ "lib/likeable/adapters/default_adapter.rb",
28
+ "lib/likeable/adapters/mongoid_adapter.rb",
29
+ "lib/likeable/adapters/ohm_adapter.rb",
27
30
  "lib/likeable/facepile.rb",
28
31
  "lib/likeable/like.rb",
29
32
  "lib/likeable/module_methods.rb",
30
33
  "lib/likeable/user_methods.rb",
31
34
  "license.txt",
32
35
  "likeable.gemspec",
36
+ "spec/likeable/adapters/mongoid_adapter_spec.rb",
37
+ "spec/likeable/adapters/ohm_adapter_spec.rb",
33
38
  "spec/likeable/facepile_spec.rb",
34
39
  "spec/likeable/like_spec.rb",
35
40
  "spec/likeable/module_methods_spec.rb",
@@ -43,15 +48,6 @@ Gem::Specification.new do |s|
43
48
  s.require_paths = ["lib"]
44
49
  s.rubygems_version = "1.8.10"
45
50
  s.summary = "Like ruby objects backed by redis"
46
- s.test_files = [
47
- "spec/likeable/facepile_spec.rb",
48
- "spec/likeable/like_spec.rb",
49
- "spec/likeable/module_methods_spec.rb",
50
- "spec/likeable/setup_spec.rb",
51
- "spec/likeable/user_methods_spec.rb",
52
- "spec/likeable_spec.rb",
53
- "spec/spec_helper.rb"
54
- ]
55
51
 
56
52
  if s.respond_to? :specification_version then
57
53
  s.specification_version = 3
@@ -62,7 +58,7 @@ Gem::Specification.new do |s|
62
58
  s.add_runtime_dependency(%q<redis>, [">= 0"])
63
59
  s.add_development_dependency(%q<activerecord>, ["~> 3.0.4"])
64
60
  s.add_development_dependency(%q<rake>, ["~> 0.8.7"])
65
- s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
61
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
66
62
  s.add_development_dependency(%q<autotest-standalone>, [">= 0"])
67
63
  s.add_development_dependency(%q<autotest-growl>, [">= 0"])
68
64
  s.add_development_dependency(%q<rspec>, [">= 0"])
@@ -72,7 +68,7 @@ Gem::Specification.new do |s|
72
68
  s.add_dependency(%q<redis>, [">= 0"])
73
69
  s.add_dependency(%q<activerecord>, ["~> 3.0.4"])
74
70
  s.add_dependency(%q<rake>, ["~> 0.8.7"])
75
- s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
71
+ s.add_dependency(%q<jeweler>, [">= 0"])
76
72
  s.add_dependency(%q<autotest-standalone>, [">= 0"])
77
73
  s.add_dependency(%q<autotest-growl>, [">= 0"])
78
74
  s.add_dependency(%q<rspec>, [">= 0"])
@@ -83,7 +79,7 @@ Gem::Specification.new do |s|
83
79
  s.add_dependency(%q<redis>, [">= 0"])
84
80
  s.add_dependency(%q<activerecord>, ["~> 3.0.4"])
85
81
  s.add_dependency(%q<rake>, ["~> 0.8.7"])
86
- s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
82
+ s.add_dependency(%q<jeweler>, [">= 0"])
87
83
  s.add_dependency(%q<autotest-standalone>, [">= 0"])
88
84
  s.add_dependency(%q<autotest-growl>, [">= 0"])
89
85
  s.add_dependency(%q<rspec>, [">= 0"])
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Likeable::MongoidAdapter do
4
+ let(:klass) { Class.new }
5
+
6
+ before do
7
+ Likeable.adapter = Likeable::MongoidAdapter
8
+ end
9
+
10
+ after do
11
+ default_adapter!
12
+ end
13
+
14
+ it "finds one by passing the id to find" do
15
+ klass.should_receive(:find).with(42)
16
+ Likeable.find_one(klass, 42)
17
+ end
18
+
19
+ it "finds many by passing the ids array find" do
20
+ klass.should_receive(:find).with([1, 42])
21
+ Likeable.find_many(klass, [1, 42])
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Likeable::OhmAdapter do
4
+ let(:klass) { Class.new }
5
+
6
+ before do
7
+ Likeable.adapter = Likeable::OhmAdapter
8
+ end
9
+
10
+ after do
11
+ default_adapter!
12
+ end
13
+
14
+ it "finds one by passing the id to find" do
15
+ klass.should_receive(:[]).with(42)
16
+ Likeable.find_one(klass, 42)
17
+ end
18
+
19
+ it "finds many by passing the ids array find" do
20
+ klass.should_receive(:[]).with(1).ordered
21
+ klass.should_receive(:[]).with(42).ordered
22
+ Likeable.find_many(klass, [1, 42])
23
+ end
24
+ end
@@ -2,6 +2,7 @@ require 'spec_helper'
2
2
  describe Likeable::Like do
3
3
  before do
4
4
  @time = Time.now
5
+ @user = User.new
5
6
  end
6
7
  describe 'attributes' do
7
8
  it 'stores target, user, and created_at' do
@@ -17,4 +18,17 @@ describe Likeable::Like do
17
18
  like.created_at.should be_within(1).of(@time)
18
19
  end
19
20
  end
21
+ describe "#user" do
22
+ it "returns like_user if available" do
23
+ like = Likeable::Like.new(:target => @target, :user => @user, :time => @time)
24
+ like.user.should == @user
25
+ end
26
+ it "finds the user in the Likeable::user_model if the like was initialized without a user" do
27
+ like = Likeable::Like.new(:target => @target, :user => nil, :user_id => 100, :time => @time)
28
+ Account = stub()
29
+ Likeable.stub(:user_class).and_return(Account)
30
+ Likeable.should_receive(:find_one).with(Account, 100)
31
+ like.user
32
+ end
33
+ end
20
34
  end
@@ -1,26 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
 
4
- class LikeableIncludedInSetup
5
-
6
- end
7
-
8
- class SetupCleanTestClassForLikeable
9
- include Likeable
10
- def like_key
11
- "like_key"
12
- end
13
-
14
- def to_hash(*args); {} end
15
-
16
- def foo
17
- end
18
-
19
- def id
20
- @id ||= rand(100)
21
- end
22
- end
23
-
24
4
  describe Likeable do
25
5
  describe "setup" do
26
6
  context "when the User class is defined" do
@@ -28,7 +8,7 @@ describe Likeable do
28
8
  reload_user!
29
9
  Likeable.user_class = User
30
10
  @user = User.new
31
- @target = SetupCleanTestClassForLikeable.new
11
+ @target = CleanTestClassForLikeable.new
32
12
  end
33
13
 
34
14
  it "" do
@@ -1,37 +1,22 @@
1
1
  require 'spec_helper'
2
- class CleanTestClassForLikeable
3
- include Likeable
4
- def like_key
5
- "like_key"
6
- end
7
-
8
- def to_hash(*args); {} end
9
2
 
10
- def foo
11
- end
3
+ describe Likeable do
12
4
 
13
- def id
14
- @id ||= rand(100)
5
+ before(:all) do
6
+ Likeable.setup do |like|
7
+ like.find_one = lambda { |klass, id| klass.where(:id => id) }
8
+ end
15
9
  end
16
- end
17
-
18
-
19
-
20
-
21
- Likeable.setup do |like|
22
- like.find_one = lambda {|klass, id| klass.where(:id => id)}
23
- end
24
-
25
-
26
- describe Likeable do
27
10
 
28
11
  before(:each) do
29
12
  @user = User.new
30
13
  @target = CleanTestClassForLikeable.new
31
14
  end
15
+
32
16
  describe 'instance methods' do
33
17
 
34
18
  describe "#add_like_from" do
19
+
35
20
  it "creates a like" do
36
21
  target_class = @target.class.to_s.downcase
37
22
  user_like_key = "users:like:#{@user.id}:#{target_class}"
@@ -41,71 +26,135 @@ describe Likeable do
41
26
  Likeable.redis.should_receive(:hset).with(user_like_key, @target.id, time).once
42
27
  @target.add_like_from(@user, time)
43
28
  end
29
+
44
30
  end
45
31
 
46
32
  describe "#remove_like_from" do
33
+
47
34
  it "removes a like" do
48
35
  target_class = @target.class.to_s.downcase
49
36
  user_like_key = "users:like:#{@user.id}:#{target_class}"
37
+ Likeable.redis.should_receive(:hexists).with("like_key", @user.id).and_return(true)
50
38
  @user.should_receive(:like_key).with(target_class).and_return(user_like_key)
51
39
  Likeable.redis.should_receive(:hdel).with("like_key", @user.id).once
52
40
  Likeable.redis.should_receive(:hdel).with(user_like_key, @target.id)
53
41
  @target.remove_like_from(@user)
54
42
  end
43
+
44
+ it "doesn't call after_unlike if like didn't exist" do
45
+ CleanTestClassForLikeable.after_unlike(:foo)
46
+ Likeable.redis.should_receive(:hexists).with("like_key", @user.id).and_return(false)
47
+ @target = CleanTestClassForLikeable.new
48
+ @target.should_not_receive(:foo)
49
+ @target.remove_like_from(@user)
50
+ end
51
+
55
52
  end
56
53
 
57
54
  describe "#liked_users" do
58
- it "finds the users that like it" do
59
- @target.should_receive(:like_user_ids).and_return([1,2])
60
- User.should_receive(:where).with(:id => [1,2])
61
- @target.liked_users(@user)
55
+
56
+ it "finds the users that like it", :integration do
57
+ user1 = User.new :name => "user1"
58
+ user2 = User.new :name => "user2"
59
+ user1.like! @target
60
+ user2.like! @target
61
+ User.should_receive(:where).with(:id => [user1.id, user2.id]).and_return([user1, user2])
62
+ @target.liked_users.should =~ [user1, user2]
62
63
  end
64
+
65
+ it "supports user id models where the id is a hash string", :integration do
66
+ Likeable.cast_id = lambda { |id| id.to_s }
67
+ user_id = "ce7961bd9ca9de6753b6e04754c1c615"
68
+ @user.should_receive(:id).at_least(:once).and_return(user_id)
69
+ @user.like! @target
70
+ User.should_receive(:where).with(:id => [user_id]).and_return([@user])
71
+ @target.liked_users.should =~ [@user]
72
+ end
73
+
63
74
  end
64
75
 
65
76
  describe "#likes" do
77
+
66
78
  it "returns set of likes" do
67
79
  Likeable.redis.should_receive(:hkeys).with("like_key").once
68
80
  @target.like_user_ids
69
81
  end
82
+
70
83
  end
71
84
 
72
85
  describe "#liked_by?" do
73
- it "will answer if current user likes target" do
74
- Likeable.redis.should_receive(:hexists).with("like_key", @user.id).once
75
- @target.liked_by?(@user)
86
+
87
+ it "will answer if current user likes target", :integration do
88
+ @target.should_not be_liked_by(@user)
89
+ @user.like! @target
90
+ @target.should be_liked_by(@user)
76
91
  end
92
+
93
+ it "works with hash string based user ids", :integration do
94
+ user_id = "fa7961bd9ca9de6753b6e04754c1c615"
95
+ @user.should_receive(:id).at_least(:once).and_return(user_id)
96
+ @target.should_not be_liked_by(@user)
97
+ @user.like! @target
98
+ @target.should be_liked_by(@user)
99
+ end
100
+
77
101
  end
78
102
 
79
103
  describe "#liked_friend_ids" do
104
+
80
105
  it "will return all friend ids of user who like target" do
81
106
  common_value = 3
82
107
  @target.should_receive(:like_user_ids).and_return([1,2, common_value])
83
108
  @user.should_receive(:friend_ids).and_return([common_value])
84
109
  @target.liked_friend_ids(@user).should == [common_value]
85
110
  end
111
+
86
112
  end
87
113
 
88
114
  describe "#liked_friends" do
115
+
89
116
  it "will return all friends who like object" do
90
117
  values = [1]
91
118
  @target.should_receive(:liked_friend_ids).with(@user).and_return(values)
92
119
  User.should_receive(:where).with(:id => values)
93
120
  @target.liked_friends(@user)
94
121
  end
122
+
95
123
  end
124
+
96
125
  end
97
126
 
98
127
  describe "class methods" do
128
+
99
129
  describe 'after_like' do
130
+
100
131
  it 'should be a class method when included' do
101
132
  CleanTestClassForLikeable.respond_to?(:after_like).should be_true
102
133
  end
134
+
103
135
  it 'is called after a like is created' do
104
136
  CleanTestClassForLikeable.after_like(:foo)
105
137
  @target.should_receive(:foo)
106
138
  @target.add_like_from(@user)
107
139
  end
140
+
108
141
  end
142
+
143
+ describe 'after_unlike' do
144
+
145
+ it 'should be a class method when included' do
146
+ CleanTestClassForLikeable.respond_to?(:after_unlike).should be_true
147
+ end
148
+
149
+ it 'is called after a like is destroyed' do
150
+ CleanTestClassForLikeable.after_unlike(:foo)
151
+ Likeable.redis.should_receive(:hexists).and_return(true)
152
+ @target.should_receive(:foo)
153
+ @target.remove_like_from(@user)
154
+ end
155
+
156
+ end
157
+
109
158
  end
110
159
 
111
160
  end
@@ -1,47 +1,150 @@
1
1
  require 'rubygems'
2
2
  require 'active_record'
3
-
3
+ require 'singleton'
4
+ require 'tempfile'
4
5
 
5
6
  $LOAD_PATH.unshift(File.dirname(__FILE__))
6
7
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '../..', 'lib'))
7
8
 
8
-
9
9
  require 'likeable'
10
10
 
11
+ module UserHelperMethods
11
12
 
12
- def build_user!
13
- eval %Q{
14
- class User
15
- include Likeable::UserMethods
16
- def id
17
- @time ||= Time.now.to_f.to_s
18
- end
13
+ def build_user!
14
+ eval %Q{
15
+ class ::User
16
+ include Likeable::UserMethods
17
+ def id
18
+ @time ||= Time.now.to_f.to_s.tr('.', '').to_i
19
+ end
19
20
 
20
- def self.where(*args)
21
- end
21
+ def self.where(*args)
22
+ end
22
23
 
23
- def friends_ids
24
- []
25
- end
24
+ def friends_ids
25
+ []
26
+ end
26
27
 
27
- def self.after_destroy
28
+ def self.after_destroy
29
+ end
28
30
  end
29
- end
30
- }
31
+ }
32
+ end
33
+
34
+ def unload_user!
35
+ Object.instance_eval{ remove_const :User }
36
+ end
37
+
38
+ def reload_user!
39
+ unload_user!
40
+ build_user!
41
+ end
42
+
43
+ def default_adapter!
44
+ Likeable.adapter = Likeable::DefaultAdapter
45
+ end
46
+
31
47
  end
32
48
 
33
- def unload_user!
34
- Object.instance_eval{ remove_const :User }
49
+ RSpec.configure do |c|
50
+
51
+ c.include UserHelperMethods
52
+
53
+ c.treat_symbols_as_metadata_keys_with_true_values = true
54
+
55
+ c.before :suite do
56
+ Likeable.redis = NullRedis.new
57
+ end
58
+
59
+ c.before :each do
60
+ build_user!
61
+ end
62
+
63
+ c.around :each, :integration do |example|
64
+ IntegrationTestRedis.instance.start
65
+ Likeable.redis = IntegrationTestRedis.instance.client
66
+ Likeable.redis.flushdb
67
+ example.run
68
+ IntegrationTestRedis.instance.stop
69
+ Likeable.redis = NullRedis.new
70
+ end
71
+
35
72
  end
36
73
 
37
- def reload_user!
38
- unload_user!
39
- build_user!
74
+ class NullRedis
75
+
76
+ def method_missing(*args)
77
+ self
78
+ end
79
+
80
+ def to_s
81
+ "Null Redis"
82
+ end
83
+
84
+ end
85
+
86
+ class IntegrationTestRedis
87
+
88
+ include ::Singleton
89
+
90
+ PORT = 9737
91
+ PIDFILE = Tempfile.new('likeable-integration-test-redis-pid')
92
+
93
+ def start
94
+ install_at_exit_handler
95
+ system("echo '#{options}' | redis-server -")
96
+ end
97
+
98
+ def stop
99
+ system("if [ -e #{PIDFILE.path} ]; then kill -QUIT $(cat #{PIDFILE.path}) 2>/dev/null; fi")
100
+ end
101
+
102
+ def client
103
+ return Redis.new(:port => PORT, :db => 15)
104
+ end
105
+
106
+ private
107
+
108
+ def options
109
+ {
110
+ 'daemonize' => 'yes',
111
+ 'pidfile' => PIDFILE.path,
112
+ 'bind' => '127.0.0.1',
113
+ 'port' => PORT,
114
+ 'timeout' => 300,
115
+ 'dir' => '/tmp',
116
+ 'loglevel' => 'debug',
117
+ 'logfile' => 'stdout',
118
+ 'databases' => 16
119
+ }.map { |k, v| "#{k} #{v}" }.join("\n")
120
+ end
121
+
122
+ def install_at_exit_handler
123
+ at_exit {
124
+ IntegrationTestRedis.instance.stop
125
+ }
126
+ end
127
+
40
128
  end
41
129
 
42
- build_user!
130
+ class CleanTestClassForLikeable
43
131
 
132
+ include Likeable
44
133
 
45
- require 'rspec'
46
- require 'rspec/autorun'
134
+ def like_key
135
+ "like_key"
136
+ end
47
137
 
138
+ def to_hash(*args);
139
+ Hash.new
140
+ end
141
+
142
+ def foo
143
+ nil
144
+ end
145
+
146
+ def id
147
+ @id ||= rand(100)
148
+ end
149
+
150
+ end
metadata CHANGED
@@ -1,165 +1,123 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: likeable
3
- version: !ruby/object:Gem::Version
4
- hash: 25
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 1
9
- - 1
10
- version: 0.1.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Schneems
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-12-17 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- version_requirements: &id001 !ruby/object:Gem::Requirement
22
- none: false
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- hash: 3
27
- segments:
28
- - 0
29
- version: "0"
12
+ date: 2012-05-24 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
30
15
  name: activesupport
31
- prerelease: false
16
+ requirement: &70203026878580 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
32
22
  type: :runtime
33
- requirement: *id001
34
- - !ruby/object:Gem::Dependency
35
- version_requirements: &id002 !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ version_requirements: *70203026878580
25
+ - !ruby/object:Gem::Dependency
26
+ name: keytar
27
+ requirement: &70203026877840 !ruby/object:Gem::Requirement
36
28
  none: false
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- hash: 7
41
- segments:
42
- - 1
43
- - 5
44
- - 2
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
45
32
  version: 1.5.2
46
- name: keytar
47
- prerelease: false
48
33
  type: :runtime
49
- requirement: *id002
50
- - !ruby/object:Gem::Dependency
51
- version_requirements: &id003 !ruby/object:Gem::Requirement
52
- none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- hash: 3
57
- segments:
58
- - 0
59
- version: "0"
60
- name: redis
61
34
  prerelease: false
35
+ version_requirements: *70203026877840
36
+ - !ruby/object:Gem::Dependency
37
+ name: redis
38
+ requirement: &70203026877180 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
62
44
  type: :runtime
63
- requirement: *id003
64
- - !ruby/object:Gem::Dependency
65
- version_requirements: &id004 !ruby/object:Gem::Requirement
45
+ prerelease: false
46
+ version_requirements: *70203026877180
47
+ - !ruby/object:Gem::Dependency
48
+ name: activerecord
49
+ requirement: &70203026876300 !ruby/object:Gem::Requirement
66
50
  none: false
67
- requirements:
51
+ requirements:
68
52
  - - ~>
69
- - !ruby/object:Gem::Version
70
- hash: 15
71
- segments:
72
- - 3
73
- - 0
74
- - 4
53
+ - !ruby/object:Gem::Version
75
54
  version: 3.0.4
76
- name: activerecord
77
- prerelease: false
78
55
  type: :development
79
- requirement: *id004
80
- - !ruby/object:Gem::Dependency
81
- version_requirements: &id005 !ruby/object:Gem::Requirement
56
+ prerelease: false
57
+ version_requirements: *70203026876300
58
+ - !ruby/object:Gem::Dependency
59
+ name: rake
60
+ requirement: &70203026875160 !ruby/object:Gem::Requirement
82
61
  none: false
83
- requirements:
62
+ requirements:
84
63
  - - ~>
85
- - !ruby/object:Gem::Version
86
- hash: 49
87
- segments:
88
- - 0
89
- - 8
90
- - 7
64
+ - !ruby/object:Gem::Version
91
65
  version: 0.8.7
92
- name: rake
93
- prerelease: false
94
66
  type: :development
95
- requirement: *id005
96
- - !ruby/object:Gem::Dependency
97
- version_requirements: &id006 !ruby/object:Gem::Requirement
98
- none: false
99
- requirements:
100
- - - ~>
101
- - !ruby/object:Gem::Version
102
- hash: 7
103
- segments:
104
- - 1
105
- - 5
106
- - 2
107
- version: 1.5.2
108
- name: jeweler
109
67
  prerelease: false
110
- type: :development
111
- requirement: *id006
112
- - !ruby/object:Gem::Dependency
113
- version_requirements: &id007 !ruby/object:Gem::Requirement
68
+ version_requirements: *70203026875160
69
+ - !ruby/object:Gem::Dependency
70
+ name: jeweler
71
+ requirement: &70203026874460 !ruby/object:Gem::Requirement
114
72
  none: false
115
- requirements:
116
- - - ">="
117
- - !ruby/object:Gem::Version
118
- hash: 3
119
- segments:
120
- - 0
121
- version: "0"
122
- name: autotest-standalone
123
- prerelease: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
124
77
  type: :development
125
- requirement: *id007
126
- - !ruby/object:Gem::Dependency
127
- version_requirements: &id008 !ruby/object:Gem::Requirement
128
- none: false
129
- requirements:
130
- - - ">="
131
- - !ruby/object:Gem::Version
132
- hash: 3
133
- segments:
134
- - 0
135
- version: "0"
136
- name: autotest-growl
137
78
  prerelease: false
79
+ version_requirements: *70203026874460
80
+ - !ruby/object:Gem::Dependency
81
+ name: autotest-standalone
82
+ requirement: &70203026873560 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
138
88
  type: :development
139
- requirement: *id008
140
- - !ruby/object:Gem::Dependency
141
- version_requirements: &id009 !ruby/object:Gem::Requirement
89
+ prerelease: false
90
+ version_requirements: *70203026873560
91
+ - !ruby/object:Gem::Dependency
92
+ name: autotest-growl
93
+ requirement: &70203026872580 !ruby/object:Gem::Requirement
142
94
  none: false
143
- requirements:
144
- - - ">="
145
- - !ruby/object:Gem::Version
146
- hash: 3
147
- segments:
148
- - 0
149
- version: "0"
150
- name: rspec
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
151
100
  prerelease: false
101
+ version_requirements: *70203026872580
102
+ - !ruby/object:Gem::Dependency
103
+ name: rspec
104
+ requirement: &70203026871040 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
152
110
  type: :development
153
- requirement: *id009
154
- description: "\n Likeable allows you to make your models...well...likeable using redis.\n "
111
+ prerelease: false
112
+ version_requirements: *70203026871040
113
+ description: ! "\n Likeable allows you to make your models...well...likeable using
114
+ redis.\n "
155
115
  email: richard.schneeman@gmail.com
156
116
  executables: []
157
-
158
117
  extensions: []
159
-
160
- extra_rdoc_files:
118
+ extra_rdoc_files:
161
119
  - README.md
162
- files:
120
+ files:
163
121
  - .autotest
164
122
  - .rspec
165
123
  - Gemfile
@@ -168,12 +126,17 @@ files:
168
126
  - VERSION
169
127
  - autotest/discover.rb
170
128
  - lib/likeable.rb
129
+ - lib/likeable/adapters/default_adapter.rb
130
+ - lib/likeable/adapters/mongoid_adapter.rb
131
+ - lib/likeable/adapters/ohm_adapter.rb
171
132
  - lib/likeable/facepile.rb
172
133
  - lib/likeable/like.rb
173
134
  - lib/likeable/module_methods.rb
174
135
  - lib/likeable/user_methods.rb
175
136
  - license.txt
176
137
  - likeable.gemspec
138
+ - spec/likeable/adapters/mongoid_adapter_spec.rb
139
+ - spec/likeable/adapters/ohm_adapter_spec.rb
177
140
  - spec/likeable/facepile_spec.rb
178
141
  - spec/likeable/like_spec.rb
179
142
  - spec/likeable/module_methods_spec.rb
@@ -182,43 +145,31 @@ files:
182
145
  - spec/likeable_spec.rb
183
146
  - spec/spec_helper.rb
184
147
  homepage: https://github.com/schneems/Likeable
185
- licenses:
148
+ licenses:
186
149
  - MIT
187
150
  post_install_message:
188
151
  rdoc_options: []
189
-
190
- require_paths:
152
+ require_paths:
191
153
  - lib
192
- required_ruby_version: !ruby/object:Gem::Requirement
154
+ required_ruby_version: !ruby/object:Gem::Requirement
193
155
  none: false
194
- requirements:
195
- - - ">="
196
- - !ruby/object:Gem::Version
197
- hash: 3
198
- segments:
156
+ requirements:
157
+ - - ! '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ segments:
199
161
  - 0
200
- version: "0"
201
- required_rubygems_version: !ruby/object:Gem::Requirement
162
+ hash: -187478466153155606
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
202
164
  none: false
203
- requirements:
204
- - - ">="
205
- - !ruby/object:Gem::Version
206
- hash: 3
207
- segments:
208
- - 0
209
- version: "0"
165
+ requirements:
166
+ - - ! '>='
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
210
169
  requirements: []
211
-
212
170
  rubyforge_project:
213
171
  rubygems_version: 1.8.10
214
172
  signing_key:
215
173
  specification_version: 3
216
174
  summary: Like ruby objects backed by redis
217
- test_files:
218
- - spec/likeable/facepile_spec.rb
219
- - spec/likeable/like_spec.rb
220
- - spec/likeable/module_methods_spec.rb
221
- - spec/likeable/setup_spec.rb
222
- - spec/likeable/user_methods_spec.rb
223
- - spec/likeable_spec.rb
224
- - spec/spec_helper.rb
175
+ test_files: []