recommendable 2.0.0 → 2.0.0.20121011

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,6 +45,7 @@ module Recommendable
45
45
  relevant_user_ids = Recommendable.config.ratable_classes.inject([]) do |memo, klass|
46
46
  liked_set = Recommendable::Helpers::RedisKeyMapper.liked_set_for(klass, user_id)
47
47
  disliked_set = Recommendable::Helpers::RedisKeyMapper.disliked_set_for(klass, user_id)
48
+
48
49
  item_ids = Recommendable.redis.sunion(liked_set, disliked_set)
49
50
 
50
51
  unless item_ids.empty?
@@ -76,18 +77,37 @@ module Recommendable
76
77
  def update_recommendations_for(user_id)
77
78
  nearest_neighbors = Recommendable.config.nearest_neighbors || Recommendable.config.user_class.count
78
79
  Recommendable.config.ratable_classes.each do |klass|
79
- similarity_set = Recommendable::Helpers::RedisKeyMapper.similarity_set_for(user_id)
80
+ rated_sets = [
81
+ Recommendable::Helpers::RedisKeyMapper.liked_set_for(klass, user_id),
82
+ Recommendable::Helpers::RedisKeyMapper.disliked_set_for(klass, user_id),
83
+ Recommendable::Helpers::RedisKeyMapper.hidden_set_for(klass, user_id),
84
+ Recommendable::Helpers::RedisKeyMapper.bookmarked_set_for(klass, user_id)
85
+ ]
86
+ temp_set = Recommendable::Helpers::RedisKeyMapper.temp_set_for(Recommendable.config.user_class, user_id)
87
+ similarity_set = Recommendable::Helpers::RedisKeyMapper.similarity_set_for(user_id)
80
88
  recommended_set = Recommendable::Helpers::RedisKeyMapper.recommended_set_for(klass, user_id)
81
- similar_user_ids = Recommendable.redis.zrevrange(similarity_set, 0, nearest_neighbors - 1)
89
+ most_similar_user_ids = Recommendable.redis.zrevrange(similarity_set, 0, nearest_neighbors - 1)
90
+ least_similar_user_ids = Recommendable.redis.zrange(similarity_set, 0, nearest_neighbors - 1)
82
91
 
83
- sets_to_union = similar_user_ids.inject([]) do |sets, id|
92
+ # Get likes from the most similar users
93
+ sets_to_union = most_similar_user_ids.inject([]) do |sets, id|
84
94
  sets << Recommendable::Helpers::RedisKeyMapper.liked_set_for(klass, id)
85
95
  end
86
96
 
87
- next if sets_to_union.empty?
88
- scores = Recommendable.redis.sunion(sets_to_union).map { |id| [predict_for(user_id, klass, id), id] }
89
- next if scores.empty?
90
- Recommendable.redis.zadd(recommended_set, scores)
97
+ # Get dislikes from the least similar users
98
+ least_similar_user_ids.inject(sets_to_union) do |sets, id|
99
+ sets << Recommendable::Helpers::RedisKeyMapper.disliked_set_for(klass, id)
100
+ end
101
+
102
+ return if sets_to_union.empty?
103
+
104
+ # SDIFF rated items so they aren't recommended
105
+ Recommendable.redis.sunionstore(temp_set, sets_to_union)
106
+ item_ids = Recommendable.redis.sdiff(temp_set, rated_sets)
107
+ scores = item_ids.map { |id| [predict_for(user_id, klass, id), id] }
108
+ scores.each do |s|
109
+ Recommendable.redis.zadd(recommended_set, s[0], s[1])
110
+ end
91
111
  end
92
112
 
93
113
  true
@@ -13,16 +13,20 @@ module Recommendable
13
13
  end
14
14
 
15
15
  def liked_by_set_for(klass, id)
16
- [Recommendable.config.redis_namespace, klass.to_s.tableize, id, "liked_by"].compact.join(':')
16
+ [Recommendable.config.redis_namespace, klass.to_s.tableize, id, 'liked_by'].compact.join(':')
17
17
  end
18
18
 
19
19
  def disliked_by_set_for(klass, id)
20
- [Recommendable.config.redis_namespace, klass.to_s.tableize, id, "disliked_by"].compact.join(':')
20
+ [Recommendable.config.redis_namespace, klass.to_s.tableize, id, 'disliked_by'].compact.join(':')
21
21
  end
22
22
 
23
23
  def score_set_for(klass)
24
24
  [Recommendable.config.redis_namespace, klass.to_s.tableize, 'scores'].join(':')
25
25
  end
26
+
27
+ def temp_set_for(klass, id)
28
+ [Recommendable.config.redis_namespace, klass.to_s.tableize, id, 'temp'].compact.join(':')
29
+ end
26
30
  end
27
31
  end
28
32
  end
@@ -2,7 +2,7 @@ module Recommendable
2
2
  MAJOR = 2
3
3
  MINOR = 0
4
4
  PATCH = 0
5
- PRE = nil
5
+ PRE = 20121011
6
6
 
7
7
  VERSION = [MAJOR, MINOR, PATCH, PRE].compact.join '.'
8
8
  end
@@ -1,8 +1,10 @@
1
1
  module Recommendable
2
2
  module Workers
3
3
  class Sidekiq
4
- include ::Sidekiq::Worker
5
- sidekiq_options :unique => true, :queue => :recommendable
4
+ if defined?(::Sidekiq)
5
+ include ::Sidekiq::Worker
6
+ sidekiq_options :unique => true, :queue => :recommendable
7
+ end
6
8
 
7
9
  def perform(user_id)
8
10
  Recommendable::Helpers::Calculations.update_similarities_for(user_id)
data/lib/recommendable.rb CHANGED
@@ -7,6 +7,11 @@ require 'recommendable/helpers'
7
7
  require 'recommendable/rater'
8
8
  require 'recommendable/ratable'
9
9
 
10
+ require 'recommendable/workers/sidekiq'
11
+ require 'recommendable/workers/resque'
12
+ require 'recommendable/workers/delayed_job'
13
+ require 'recommendable/workers/rails'
14
+
10
15
  module Recommendable
11
16
  class << self
12
17
  def redis() config.redis end
@@ -21,18 +26,14 @@ module Recommendable
21
26
  user_id = user_id.id if user_id.is_a?(Recommendable.config.user_class)
22
27
 
23
28
  if defined?(::Sidekiq)
24
- require 'recommendable/workers/sidekiq'
25
29
  Recommendable::Workers::Sidekiq.perform_async(user_id)
26
30
  elsif defined?(::Resque)
27
- require 'recommendable/workers/resque'
28
31
  Resque.enqueue(Recommendable::Workers::Resque, user_id)
29
32
  elsif defined?(::Delayed::Job)
30
- require 'recommendable/workers/delayed_job'
31
33
  Delayed::Job.enqueue(Recommendable::Workers::DelayedJob.new(user_id))
32
34
  elsif defined?(::Rails::Queueing)
33
- require 'recommendable/workers/rails'
34
35
  unless Rails.queue.any? { |w| w.user_id == user_id }
35
- Rails.queue.push(Recommendable::Workers::Rails.new(user_idid))
36
+ Rails.queue.push(Recommendable::Workers::Rails.new(user_id))
36
37
  Rails.application.queue_consumer.start
37
38
  end
38
39
  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: 2.0.0
4
+ version: 2.0.0.20121011
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-10-09 00:00:00.000000000 Z
12
+ date: 2012-10-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -213,4 +213,3 @@ signing_key:
213
213
  specification_version: 3
214
214
  summary: A Like/Dislike recommendation engine for Ruby apps using Redis
215
215
  test_files: []
216
- has_rdoc: yard