recommendable 1.1.3 → 1.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +3 -3
- data/app/workers/recommendable/sidekiq_worker.rb +1 -1
- data/lib/generators/recommendable/templates/initializer.rb +15 -0
- data/lib/recommendable.rb +2 -0
- data/lib/recommendable/acts_as_recommendable.rb +24 -0
- data/lib/recommendable/acts_as_recommended_to.rb +5 -1
- data/lib/recommendable/version.rb +1 -1
- data/lib/sidekiq/middleware/client/unique_jobs.rb +37 -0
- data/lib/sidekiq/middleware/server/unique_jobs.rb +17 -0
- data/lib/tasks/recommendable_tasks.rake +1 -1
- data/spec/models/dislike_spec.rb +14 -0
- data/spec/models/like_spec.rb +14 -0
- metadata +5 -3
data/Gemfile.lock
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
recommendable (1.1.
|
4
|
+
recommendable (1.1.3)
|
5
5
|
hooks
|
6
6
|
rails (>= 3.0.0)
|
7
|
-
redis (
|
7
|
+
redis (>= 2.2.0)
|
8
8
|
|
9
9
|
GEM
|
10
10
|
remote: http://rubygems.org/
|
@@ -79,7 +79,7 @@ GEM
|
|
79
79
|
rake (0.9.2.2)
|
80
80
|
rdoc (3.12)
|
81
81
|
json (~> 1.4)
|
82
|
-
redis (
|
82
|
+
redis (3.0.1)
|
83
83
|
shoulda (3.0.1)
|
84
84
|
shoulda-context (~> 1.0.0)
|
85
85
|
shoulda-matchers (~> 1.0.0)
|
@@ -2,7 +2,7 @@ module Recommendable
|
|
2
2
|
if defined?(Sidekiq)
|
3
3
|
class SidekiqWorker
|
4
4
|
include ::Sidekiq::Worker
|
5
|
-
sidekiq_options :queue => :recommendable
|
5
|
+
sidekiq_options :queue => :recommendable, :unique => true
|
6
6
|
|
7
7
|
def perform(user_id)
|
8
8
|
user = Recommendable.user_class.find(user_id)
|
@@ -11,3 +11,18 @@ require "redis"
|
|
11
11
|
# Tell Redis which database to use (usually between 0 and 15). The default of 0
|
12
12
|
# is most likely okay unless you have another application using that database.
|
13
13
|
# Recommendable.redis.select "0"
|
14
|
+
|
15
|
+
# If using Sidekiq, uncomment the following or place it in config/initializers/sidekiq.rb:
|
16
|
+
# Sidekiq.configure_server do |config|
|
17
|
+
# require 'sidekiq/middleware/server/unique_jobs'
|
18
|
+
# config.server_middleware do |chain|
|
19
|
+
# chain.add Sidekiq::Middleware::Server::UniqueJobs
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# Sidekiq.configure_client do |config|
|
24
|
+
# require 'sidekiq/middleware/client/unique_jobs'
|
25
|
+
# config.client_middleware do |chain|
|
26
|
+
# chain.add Sidekiq::Middleware::Client::UniqueJobs
|
27
|
+
# end
|
28
|
+
# end
|
data/lib/recommendable.rb
CHANGED
@@ -6,6 +6,8 @@ require 'recommendable/exceptions'
|
|
6
6
|
require 'recommendable/railtie' if defined?(Rails)
|
7
7
|
require 'recommendable/version'
|
8
8
|
require 'hooks'
|
9
|
+
require 'sidekiq/middleware/client/unique_jobs' if defined?(Sidekiq)
|
10
|
+
require 'sidekiq/middleware/server/unique_jobs' if defined?(Sidekiq)
|
9
11
|
|
10
12
|
module Recommendable
|
11
13
|
mattr_accessor :redis, :user_class
|
@@ -121,8 +121,20 @@ module Recommendable
|
|
121
121
|
protected :redis_key
|
122
122
|
|
123
123
|
module LikeableMethods
|
124
|
+
# Retrieve the number of likes this object has received. Cached in Redis.
|
125
|
+
# @return [Fixnum] the number of times this object has been liked
|
126
|
+
def like_count
|
127
|
+
Recommendable.redis.get("#{redis_key}:like_count").to_i
|
128
|
+
end
|
129
|
+
|
124
130
|
private
|
125
131
|
|
132
|
+
# Updates the cache for how many times this object has been liked.
|
133
|
+
# @private
|
134
|
+
def update_like_count
|
135
|
+
Recommendable.redis.set "#{redis_key}:like_count", liked_by.count
|
136
|
+
end
|
137
|
+
|
126
138
|
# Used for setup purposes. Creates a set in redis containing users that
|
127
139
|
# have liked this object.
|
128
140
|
# @private
|
@@ -135,8 +147,20 @@ module Recommendable
|
|
135
147
|
end
|
136
148
|
|
137
149
|
module DislikeableMethods
|
150
|
+
# Retrieve the number of dislikes this object has received. Cached in Redis.
|
151
|
+
# @return [Fixnum] the number of times this object has been disliked
|
152
|
+
def dislike_count
|
153
|
+
Recommendable.redis.get("#{redis_key}:dislike_count").to_i
|
154
|
+
end
|
155
|
+
|
138
156
|
private
|
139
157
|
|
158
|
+
# Updates the cache for how many times this object has been disliked.
|
159
|
+
# @private
|
160
|
+
def update_dislike_count
|
161
|
+
Recommendable.redis.set "#{redis_key}:dislike_count", disliked_by.count
|
162
|
+
end
|
163
|
+
|
140
164
|
# Used for setup purposes. Creates a set in redis containing users that
|
141
165
|
# have disliked this object.
|
142
166
|
# @private
|
@@ -52,7 +52,11 @@ module Recommendable
|
|
52
52
|
end
|
53
53
|
|
54
54
|
%w(like unlike dislike undislike).each do |action|
|
55
|
-
send "after_#{action}", lambda { |obj|
|
55
|
+
send "after_#{action}", lambda { |obj|
|
56
|
+
obj.send(:update_score)
|
57
|
+
obj.send "update_#{action.gsub('un', '')}_count"
|
58
|
+
Recommendable.enqueue(self.id)
|
59
|
+
}
|
56
60
|
end
|
57
61
|
|
58
62
|
before_stash { |obj| unignore(obj) and unpredict(obj) }
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
if defined?(Sidekiq)
|
4
|
+
module Sidekiq
|
5
|
+
module Middleware
|
6
|
+
module Client
|
7
|
+
class UniqueJobs
|
8
|
+
HASH_KEY_EXPIRATION = 30 * 60
|
9
|
+
|
10
|
+
def call(worker_class, item, queue)
|
11
|
+
enabled = worker_class.get_sidekiq_options['unique']
|
12
|
+
if enabled
|
13
|
+
payload_hash = Digest::MD5.hexdigest(Sidekiq.dump_json(item))
|
14
|
+
unique = false
|
15
|
+
|
16
|
+
Sidekiq.redis do |conn|
|
17
|
+
conn.watch(payload_hash)
|
18
|
+
|
19
|
+
if conn.get(payload_hash)
|
20
|
+
conn.unwatch
|
21
|
+
else
|
22
|
+
unique = conn.multi do
|
23
|
+
conn.setex(payload_hash, HASH_KEY_EXPIRATION, 1)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
yield if unique
|
28
|
+
else
|
29
|
+
yield
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
if defined?(Sidekiq)
|
2
|
+
module Sidekiq
|
3
|
+
module Middleware
|
4
|
+
module Server
|
5
|
+
class UniqueJobs
|
6
|
+
def call(*args)
|
7
|
+
yield
|
8
|
+
ensure
|
9
|
+
json = Sidekiq.dump_json(args[1])
|
10
|
+
hash = Digest::MD5.hexdigest(json)
|
11
|
+
Sidekiq.redis {|conn| conn.del(hash) }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1 +1 @@
|
|
1
|
-
require 'resque/tasks'
|
1
|
+
require 'resque/tasks' if defined?(Resque)
|
data/spec/models/dislike_spec.rb
CHANGED
@@ -23,5 +23,19 @@ class DislikeSpec < MiniTest::Spec
|
|
23
23
|
@user.dislike(movie).must_be_nil
|
24
24
|
Recommendable::Dislike.count.must_equal 1
|
25
25
|
end
|
26
|
+
|
27
|
+
it "should cache the number of dislikes" do
|
28
|
+
movie = Movie.create(:title => "Star Wars: Episode I - The Phantom Menace", :year => 1999)
|
29
|
+
@user2 = User.create(:username => "frank")
|
30
|
+
|
31
|
+
@user.dislike(movie)
|
32
|
+
movie.dislike_count.must_equal 1
|
33
|
+
|
34
|
+
@user2.dislike(movie)
|
35
|
+
movie.dislike_count.must_equal 2
|
36
|
+
|
37
|
+
@user.undislike(movie)
|
38
|
+
movie.dislike_count.must_equal 1
|
39
|
+
end
|
26
40
|
end
|
27
41
|
end
|
data/spec/models/like_spec.rb
CHANGED
@@ -24,5 +24,19 @@ class LikeSpec < MiniTest::Spec
|
|
24
24
|
@user.like(movie).must_be_nil
|
25
25
|
Recommendable::Like.count.must_equal 1
|
26
26
|
end
|
27
|
+
|
28
|
+
it "should cache the number of likes" do
|
29
|
+
movie = Movie.create(:title => "2001: A Space Odyssey", :year => 1968)
|
30
|
+
@user2 = User.create(:username => "frank")
|
31
|
+
|
32
|
+
@user.like(movie)
|
33
|
+
movie.like_count.must_equal 1
|
34
|
+
|
35
|
+
@user2.like(movie)
|
36
|
+
movie.like_count.must_equal 2
|
37
|
+
|
38
|
+
@user.unlike(movie)
|
39
|
+
movie.like_count.must_equal 1
|
40
|
+
end
|
27
41
|
end
|
28
42
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: recommendable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sqlite3
|
@@ -195,6 +195,8 @@ files:
|
|
195
195
|
- lib/recommendable/helpers.rb
|
196
196
|
- lib/recommendable/railtie.rb
|
197
197
|
- lib/recommendable/version.rb
|
198
|
+
- lib/sidekiq/middleware/client/unique_jobs.rb
|
199
|
+
- lib/sidekiq/middleware/server/unique_jobs.rb
|
198
200
|
- lib/tasks/recommendable_tasks.rake
|
199
201
|
- recommendable.gemspec
|
200
202
|
- script/rails
|
@@ -276,7 +278,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
276
278
|
version: '0'
|
277
279
|
requirements: []
|
278
280
|
rubyforge_project:
|
279
|
-
rubygems_version: 1.8.
|
281
|
+
rubygems_version: 1.8.23
|
280
282
|
signing_key:
|
281
283
|
specification_version: 3
|
282
284
|
summary: Add like-based and/or dislike-based recommendations to your app.
|