recommendable 0.1.8 → 0.2.1.1

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.
data/CHANGELOG.markdown CHANGED
@@ -1,8 +1,34 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
- 0.1.6 (current version)
4
+ 0.2.0 (current version)
5
5
  -----------------------
6
+ * NOTE: This release is NOT backwards compatible. Please migrate your databases:
7
+
8
+ ```
9
+ rename_column :recommendable_ignores, :ignoreable_id, :ignorable_id
10
+ rename_column :recommendable_ignores, :ignoreable_type, :ignorable_type
11
+ rename_table :recommendable_stashed_items, :recommendable_stashes
12
+ ```
13
+
14
+ * Fix an issue with recommendable models implemented via STI
15
+ * Fix a library-wide typo of "ignoreable" to "ignorable"
16
+
17
+ 0.1.9
18
+ -----
19
+ * Yanked due to breaking bug
20
+
21
+ 0.1.8
22
+ -----
23
+ * Revert changes made in 0.1.7 due to licensing
24
+
25
+ 0.1.7
26
+ -----
27
+ * Yanked and no longer available.
28
+ * Attempted switch from Resque to Sidekiq
29
+
30
+ 0.1.6
31
+ -----
6
32
  * Dynamic finders for your User class:
7
33
 
8
34
  `current_user.liked_movies`
data/Gemfile.lock CHANGED
@@ -30,8 +30,6 @@ GEM
30
30
  multi_json (~> 1.0)
31
31
  arel (3.0.0)
32
32
  builder (3.0.0)
33
- celluloid (0.10.0)
34
- connection_pool (0.9.1)
35
33
  erubis (2.7.0)
36
34
  hike (1.2.1)
37
35
  i18n (0.6.0)
@@ -50,6 +48,8 @@ GEM
50
48
  rack (1.4.0)
51
49
  rack-cache (1.1)
52
50
  rack (>= 0.4)
51
+ rack-protection (1.2.0)
52
+ rack
53
53
  rack-ssl (1.3.2)
54
54
  rack
55
55
  rack-test (0.6.1)
@@ -73,15 +73,20 @@ GEM
73
73
  rdoc (3.12)
74
74
  json (~> 1.4)
75
75
  redis (2.2.2)
76
- redis-namespace (1.1.0)
76
+ redis-namespace (1.0.3)
77
77
  redis (< 3.0.0)
78
+ resque (1.19.0)
79
+ multi_json (~> 1.0)
80
+ redis-namespace (~> 1.0.2)
81
+ sinatra (>= 0.9.2)
82
+ vegas (~> 0.1.2)
83
+ resque-loner (1.2.0)
84
+ resque (~> 1.0)
78
85
  shoulda (2.11.3)
79
- sidekiq (1.0.0)
80
- celluloid (~> 0.10.0)
81
- connection_pool (~> 0.9.0)
82
- multi_json
83
- redis
84
- redis-namespace
86
+ sinatra (1.3.2)
87
+ rack (~> 1.3, >= 1.3.6)
88
+ rack-protection (~> 1.2)
89
+ tilt (~> 1.3, >= 1.3.3)
85
90
  sprockets (2.1.2)
86
91
  hike (~> 1.2)
87
92
  rack (~> 1.0)
@@ -93,6 +98,8 @@ GEM
93
98
  polyglot
94
99
  polyglot (>= 0.3.1)
95
100
  tzinfo (0.3.31)
101
+ vegas (0.1.11)
102
+ rack (>= 1.0.0)
96
103
  yard (0.6.8)
97
104
 
98
105
  PLATFORMS
@@ -104,7 +111,8 @@ DEPENDENCIES
104
111
  minitest
105
112
  rails (>= 3.1.0)
106
113
  redis (~> 2.2.0)
114
+ resque (~> 1.19.0)
115
+ resque-loner (~> 1.2.0)
107
116
  shoulda
108
- sidekiq
109
117
  sqlite3
110
118
  yard (~> 0.6.0)
@@ -8,5 +8,9 @@ module Recommendable
8
8
 
9
9
  validates :user_id, :uniqueness => { :scope => [:dislikeable_id, :dislikeable_type],
10
10
  :message => "has already disliked this item" }
11
+
12
+ def dislikeable_type=(sType)
13
+ super sType.to_s.classify.constantize.base_class.to_s
14
+ end
11
15
  end
12
16
  end
@@ -1,12 +1,15 @@
1
1
  module Recommendable
2
2
  class Ignore < ActiveRecord::Base
3
3
  self.table_name = 'recommendable_ignores'
4
- attr_accessible :user_id, :ignoreable_id, :ignoreable_type
4
+ attr_accessible :user_id, :ignorable_id, :ignorable_type
5
5
 
6
6
  belongs_to :user, :class_name => Recommendable.user_class.to_s, :foreign_key => :user_id
7
- belongs_to :ignoreable, :polymorphic => true
7
+ belongs_to :ignorable, :polymorphic => true
8
8
 
9
- validates :user_id, :uniqueness => { :scope => [:ignoreable_id, :ignoreable_type],
9
+ validates :user_id, :uniqueness => { :scope => [:ignorable_id, :ignorable_type],
10
10
  :message => "has already ignored this item" }
11
+ def ignorable_type=(sType)
12
+ super sType.to_s.classify.constantize.base_class.to_s
13
+ end
11
14
  end
12
15
  end
@@ -8,5 +8,9 @@ module Recommendable
8
8
 
9
9
  validates :user_id, :uniqueness => { :scope => [:likeable_id, :likeable_type],
10
10
  :message => "has already liked this item" }
11
+
12
+ def likeable_type=(sType)
13
+ super sType.to_s.classify.constantize.base_class.to_s
14
+ end
11
15
  end
12
16
  end
@@ -1,6 +1,6 @@
1
1
  module Recommendable
2
- class StashedItem < ActiveRecord::Base
3
- self.table_name = 'recommendable_stashed_items'
2
+ class Stash < ActiveRecord::Base
3
+ self.table_name = 'recommendable_stashes'
4
4
  attr_accessible :user_id, :stashable_id, :stashable_type
5
5
 
6
6
  belongs_to :user, :class_name => Recommendable.user_class.to_s, :foreign_key => :user_id
@@ -8,5 +8,8 @@ module Recommendable
8
8
 
9
9
  validates :user_id, :uniqueness => { :scope => [:stashable_id, :stashable_type],
10
10
  :message => "has already stashed this item" }
11
+ def stashable_type=(sType)
12
+ super sType.to_s.classify.constantize.base_class.to_s
13
+ end
11
14
  end
12
15
  end
@@ -2,13 +2,13 @@ class CreateIgnores < ActiveRecord::Migration
2
2
  def up
3
3
  create_table :recommendable_ignores do |t|
4
4
  t.references :user
5
- t.references :ignoreable, :polymorphic => true
5
+ t.references :ignorable, :polymorphic => true
6
6
  t.timestamps
7
7
  end
8
8
 
9
- add_index :recommendable_ignores, :ignoreable_id
10
- add_index :recommendable_ignores, :ignoreable_type
11
- add_index :recommendable_ignores, [:user_id, :ignoreable_id, :ignoreable_type], :unique => true, :name => "user_ignore_constraint"
9
+ add_index :recommendable_ignores, :ignorable_id
10
+ add_index :recommendable_ignores, :ignorable_type
11
+ add_index :recommendable_ignores, [:user_id, :ignorable_id, :ignorable_type], :unique => true, :name => "user_ignore_constraint"
12
12
  end
13
13
 
14
14
  def down
@@ -0,0 +1,17 @@
1
+ class CreateStashes < ActiveRecord::Migration
2
+ def up
3
+ create_table :recommendable_stashes do |t|
4
+ t.references :user
5
+ t.references :stashable, :polymorphic => true
6
+ t.timestamps
7
+ end
8
+
9
+ add_index :recommendable_stashes, :stashable_id
10
+ add_index :recommendable_stashes, :stashable_type
11
+ add_index :recommendable_stashes, [:user_id, :stashable_id, :stashable_type], :unique => true, :name => "user_stashed_constraint"
12
+ end
13
+
14
+ def down
15
+ drop_table :recommendable_stashes
16
+ end
17
+ end
data/lib/recommendable.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'recommendable/engine'
2
+ require 'recommendable/helpers'
2
3
  require 'recommendable/acts_as_recommended_to'
3
4
  require 'recommendable/acts_as_recommendable'
4
5
  require 'recommendable/exceptions'
@@ -12,4 +13,8 @@ module Recommendable
12
13
  def self.recommendable_classes
13
14
  @@recommendable_classes ||= []
14
15
  end
16
+
17
+ def self.enqueue(user_id)
18
+ Resque.enqueue RecommendationRefresher, user_id
19
+ end
15
20
  end
@@ -7,12 +7,19 @@ module Recommendable
7
7
  class_eval do
8
8
  Recommendable.recommendable_classes << self
9
9
 
10
- has_many :likes, :as => :likeable, :dependent => :destroy, :class_name => "Recommendable::Like"
11
- has_many :dislikes, :as => :dislikeable, :dependent => :destroy, :class_name => "Recommendable::Dislike"
12
- has_many :ignores, :as => :ignoreable, :dependent => :destroy, :class_name => "Recommendable::Ignore"
13
- has_many :stashes, :as => :stashable, :dependent => :destroy, :class_name => "Recommendable::StashedItem"
14
- has_many :liked_by, :through => :likes, :source => :user, :foreign_key => :user_id, :class_name => Recommendable.user_class.to_s
15
- has_many :disliked_by, :through => :dislikes, :source => :user, :foreign_key => :user_id, :class_name => Recommendable.user_class.to_s
10
+ has_many :likes, :as => :likeable, :dependent => :destroy,
11
+ :class_name => "Recommendable::Like"
12
+ has_many :dislikes, :as => :dislikeable, :dependent => :destroy,
13
+ :class_name => "Recommendable::Dislike"
14
+ has_many :ignores, :as => :ignorable, :dependent => :destroy,
15
+ :class_name => "Recommendable::Ignore"
16
+ has_many :stashes, :as => :stashable, :dependent => :destroy,
17
+ :class_name => "Recommendable::Stash"
18
+
19
+ has_many :liked_by, :through => :likes, :source => :user, :foreign_key => :user_id,
20
+ :class_name => Recommendable.user_class.to_s
21
+ has_many :disliked_by, :through => :dislikes, :source => :user, :foreign_key => :user_id,
22
+ :class_name => Recommendable.user_class.to_s
16
23
 
17
24
  include LikeableMethods
18
25
  include DislikeableMethods
@@ -72,8 +79,8 @@ module Recommendable
72
79
  # {#create_recommendable_sets}
73
80
  # @private
74
81
  def destroy_recommendable_sets
75
- Recommendable.redis.del "#{self.class}:#{id}:liked_by"
76
- Recommendable.redis.del "#{self.class}:#{id}:disliked_by"
82
+ Recommendable.redis.del "#{self.class.base_class}:#{id}:liked_by"
83
+ Recommendable.redis.del "#{self.class.base_class}:#{id}:disliked_by"
77
84
  end
78
85
 
79
86
  # Returns an array of IDs of users that have liked or disliked this item.
@@ -92,12 +99,16 @@ module Recommendable
92
99
  end
93
100
 
94
101
  def acts_as_recommendable?() false end
102
+
103
+ def sti?() self.base_class != self end
104
+
105
+ private
95
106
  end
96
107
 
97
108
  # Instance methods.
98
109
  def recommendable?() self.class.acts_as_recommendable? end
99
110
 
100
- def redis_key() "#{self.class}:#{id}" end
111
+ def redis_key() "#{self.class.base_class}:#{id}" end
101
112
 
102
113
  protected :redis_key
103
114
 
@@ -2,6 +2,7 @@ require 'active_support/concern'
2
2
 
3
3
  module Recommendable
4
4
  module ActsAsRecommendedTo
5
+ include Recommendable::Helpers
5
6
  extend ActiveSupport::Concern
6
7
 
7
8
  module ClassMethods
@@ -17,7 +18,7 @@ module Recommendable
17
18
  has_many :likes, :class_name => "Recommendable::Like", :dependent => :destroy, :foreign_key => :user_id
18
19
  has_many :dislikes, :class_name => "Recommendable::Dislike", :dependent => :destroy, :foreign_key => :user_id
19
20
  has_many :ignores, :class_name => "Recommendable::Ignore", :dependent => :destroy, :foreign_key => :user_id
20
- has_many :stashed_items, :class_name => "Recommendable::StashedItem", :dependent => :destroy, :foreign_key => :user_id
21
+ has_many :stashed_items, :class_name => "Recommendable::Stash", :dependent => :destroy, :foreign_key => :user_id
21
22
 
22
23
  include LikeMethods
23
24
  include DislikeMethods
@@ -81,9 +82,9 @@ module Recommendable
81
82
  raise RecordNotRecommendableError unless object.recommendable?
82
83
  return if likes? object
83
84
  completely_unrecommend object
84
- likes.create! :likeable_id => object.id, :likeable_type => object.class.to_s
85
+ likes.create! :likeable_id => object.id, :likeable_type => object.class
85
86
  object.send :update_score
86
- Resque.enqueue RecommendationRefresher, self.id
87
+ Recommendable.enqueue self.id
87
88
  true
88
89
  end
89
90
 
@@ -92,7 +93,7 @@ module Recommendable
92
93
  # @param [Object] object the object you want to check
93
94
  # @return true if self likes object, false if not
94
95
  def likes? object
95
- likes.exists? :likeable_id => object.id, :likeable_type => object.class.to_s
96
+ likes.exists? :likeable_id => object.id, :likeable_type => object.class.base_class.to_s
96
97
  end
97
98
 
98
99
  # Destroys a Recommendable::Like currently associating self with object
@@ -100,9 +101,9 @@ module Recommendable
100
101
  # @param [Object] object the object you want to remove from self's likes
101
102
  # @return true if object is unliked, nil if nothing happened
102
103
  def unlike object
103
- if likes.where(:likeable_id => object.id, :likeable_type => object.class.to_s).first.try(:destroy)
104
+ if likes.where(:likeable_id => object.id, :likeable_type => object.class.base_class.to_s).first.try(:destroy)
104
105
  object.send :update_score
105
- Resque.enqueue RecommendationRefresher, self.id
106
+ Recommendable.enqueue self.id
106
107
  true
107
108
  end
108
109
  end
@@ -122,7 +123,13 @@ module Recommendable
122
123
  # @param [Class, String, Symbol] klass the class of records. Can be the class constant, or a String/Symbol representation of the class name.
123
124
  # @return [Array] an array of ActiveRecord objects that self has liked belonging to klass
124
125
  def liked_for klass
125
- likes.where(:likeable_type => klass).includes(:likeable).map(&:likeable)
126
+ liked = if klass.sti?
127
+ likes.joins manual_join(klass, 'like')
128
+ else
129
+ likes.where(:likeable_type => klass.to_s).includes(:likeable)
130
+ end
131
+
132
+ liked.map(&:likeable)
126
133
  end
127
134
 
128
135
  # Get a list of Recommendable::Likes with a `#likeable_type` of the passed
@@ -132,7 +139,11 @@ module Recommendable
132
139
  # @note You should not need to use this method. (see {#liked_for})
133
140
  # @private
134
141
  def likes_for klass
135
- likes.where :likeable_type => klass.to_s.classify
142
+ if klass.sti?
143
+ likes.joins manual_join(klass, 'like')
144
+ else
145
+ likes.where(:likeable_type => klass.to_s)
146
+ end
136
147
  end
137
148
  end
138
149
 
@@ -149,9 +160,9 @@ module Recommendable
149
160
  raise RecordNotRecommendableError unless object.recommendable?
150
161
  return if dislikes? object
151
162
  completely_unrecommend object
152
- dislikes.create! :dislikeable_id => object.id, :dislikeable_type => object.class.to_s
163
+ dislikes.create! :dislikeable_id => object.id, :dislikeable_type => object.class
153
164
  object.send :update_score
154
- Resque.enqueue RecommendationRefresher, self.id
165
+ Recommendable.enqueue self.id
155
166
  true
156
167
  end
157
168
 
@@ -160,7 +171,7 @@ module Recommendable
160
171
  # @param [Object] object the object you want to check
161
172
  # @return true if self dislikes object, false if not
162
173
  def dislikes? object
163
- dislikes.exists? :dislikeable_id => object.id, :dislikeable_type => object.class.to_s
174
+ dislikes.exists? :dislikeable_id => object.id, :dislikeable_type => object.class.base_class.to_s
164
175
  end
165
176
 
166
177
  # Destroys a Recommendable::Dislike currently associating self with object
@@ -168,9 +179,9 @@ module Recommendable
168
179
  # @param [Object] object the object you want to remove from self's dislikes
169
180
  # @return true if object is removed from self's dislikes, nil if nothing happened
170
181
  def undislike object
171
- if dislikes.where(:dislikeable_id => object.id, :dislikeable_type => object.class.to_s).first.try(:destroy)
182
+ if dislikes.where(:dislikeable_id => object.id, :dislikeable_type => object.class.base_class.to_s).first.try(:destroy)
172
183
  object.send :update_score
173
- Resque.enqueue RecommendationRefresher, self.id
184
+ Recommendable.enqueue self.id
174
185
  true
175
186
  end
176
187
  end
@@ -190,7 +201,13 @@ module Recommendable
190
201
  # @param [Class, String, Symbol] klass the class of records. Can be the class constant, or a String/Symbol representation of the class name.
191
202
  # @return [Array] an array of ActiveRecord objects that self has disliked belonging to klass
192
203
  def disliked_for klass
193
- dislikes.where(:dislikeable_type => klass).includes(:dislikeable).map(&:dislikeable)
204
+ disliked = if klass.sti?
205
+ dislikes.joins manual_join(klass, 'dislike')
206
+ else
207
+ dislikes.where(:dislikeable_type => klass.to_s).includes(:dislikeable)
208
+ end
209
+
210
+ disliked.map(&:dislikeable)
194
211
  end
195
212
 
196
213
  # Get a list of Recommendable::Dislikes with a `#dislikeable_type` of the
@@ -200,12 +217,16 @@ module Recommendable
200
217
  # @note You should not need to use this method. (see {#disliked_for})
201
218
  # @private
202
219
  def dislikes_for klass
203
- dislikes.where :dislikeable_type => klass.to_s.classify
220
+ if klass.sti?
221
+ dislikes.joins manual_join(klass, 'dislike')
222
+ else
223
+ dislikes.where(:dislikeable_type => klass.to_s)
224
+ end
204
225
  end
205
226
  end
206
227
 
207
228
  module StashMethods
208
- # Creates a Recommendable::StashedItem to associate self to a passed object.
229
+ # Creates a Recommendable::Stash to associate self to a passed object.
209
230
  # This will remove the item from this user's recommendations.
210
231
  # If self is currently found to have liked or disliked the object, nothing
211
232
  # will happen. It will, however, be unignored.
@@ -218,7 +239,7 @@ module Recommendable
218
239
  return if rated?(object) || stashed?(object)
219
240
  unignore object
220
241
  unpredict object
221
- stashed_items.create! :stashable_id => object.id, :stashable_type => object.class.to_s
242
+ stashed_items.create! :stashable_id => object.id, :stashable_type => object.class
222
243
  true
223
244
  end
224
245
 
@@ -227,15 +248,15 @@ module Recommendable
227
248
  # @param [Object] object the object you want to check
228
249
  # @return true if self has stashed object, false if not
229
250
  def stashed? object
230
- stashed_items.exists? :stashable_id => object.id, :stashable_type => object.class.to_s
251
+ stashed_items.exists? :stashable_id => object.id, :stashable_type => object.class.base_class.to_s
231
252
  end
232
253
 
233
- # Destroys a Recommendable::StashedItem currently associating self with object
254
+ # Destroys a Recommendable::Stash currently associating self with object
234
255
  #
235
256
  # @param [Object] object the object you want to remove from self's stash
236
257
  # @return true if object is stashed, nil if nothing happened
237
258
  def unstash object
238
- true if stashed_items.where(:stashable_id => object.id, :stashable_type => object.class.to_s).first.try(:destroy)
259
+ true if stashed_items.where(:stashable_id => object.id, :stashable_type => object.class.base_class.to_s).first.try(:destroy)
239
260
  end
240
261
 
241
262
  # Get a list of records that self has currently stashed for later
@@ -253,7 +274,13 @@ module Recommendable
253
274
  # @param [Class, String, Symbol] klass the class of records. Can be the class constant, or a String/Symbol representation of the class name.
254
275
  # @return [Array] an array of ActiveRecord objects that self has stashed belonging to klass
255
276
  def stashed_for klass
256
- stashed_items.where(:stashable_type => klass).includes(:stashable).map(&:stashable)
277
+ stashed = if klass.sti?
278
+ stashed_items.joins manual_join(klass, 'stash')
279
+ else
280
+ stashed_items.where(:stashable_type => klass.to_s).includes(:stashable)
281
+ end
282
+
283
+ stashed.map(&:stashable)
257
284
  end
258
285
  end
259
286
 
@@ -270,7 +297,7 @@ module Recommendable
270
297
  raise RecordNotRecommendableError unless object.recommendable?
271
298
  return if ignored? object
272
299
  completely_unrecommend object
273
- ignores.create! :ignoreable_id => object.id, :ignoreable_type => object.class.to_s
300
+ ignores.create! :ignorable_id => object.id, :ignorable_type => object.class
274
301
  true
275
302
  end
276
303
 
@@ -279,7 +306,7 @@ module Recommendable
279
306
  # @param [Object] object the object you want to check
280
307
  # @return true if self has ignored object, false if not
281
308
  def ignored? object
282
- ignores.exists? :ignoreable_id => object.id, :ignoreable_type => object.class.to_s
309
+ ignores.exists? :ignorable_id => object.id, :ignorable_type => object.class.base_class.to_s
283
310
  end
284
311
 
285
312
  # Destroys a Recommendable::Ignore currently associating self with object
@@ -287,7 +314,7 @@ module Recommendable
287
314
  # @param [Object] object the object you want to remove from self's ignores
288
315
  # @return true if object is removed from self's ignores, nil if nothing happened
289
316
  def unignore object
290
- true if ignores.where(:ignoreable_id => object.id, :ignoreable_type => object.class.to_s).first.try(:destroy)
317
+ true if ignores.where(:ignorable_id => object.id, :ignorable_type => object.class.base_class.to_s).first.try(:destroy)
291
318
  end
292
319
 
293
320
  # Get a list of records that self is currently ignoring
@@ -305,7 +332,13 @@ module Recommendable
305
332
  # @param [Class, String, Symbol] klass the class of records. Can be the class constant, or a String/Symbol representation of the class name.
306
333
  # @return [Array] an array of ActiveRecord objects that self has ignored belonging to klass
307
334
  def ignored_for klass
308
- ignores.where(:ignoreable_type => klass).includes(:ignoreable).map(&:ignoreable)
335
+ ignored = if klass.sti?
336
+ ignores.joins manual_join(klass, 'ignore')
337
+ else
338
+ ignores.where(:ignorable_type => klass.to_s).includes(:ignorable)
339
+ end
340
+
341
+ ignored.map(&:ignorable)
309
342
  end
310
343
  end
311
344
 
@@ -397,7 +430,8 @@ module Recommendable
397
430
  # @param [Class, String, Symbol] klass the class to receive recommendations for. Can be the class constant, or a String/Symbol representation of the class name.
398
431
  # @return [Array] an array of ActiveRecord objects that are recommendable
399
432
  def recommended_for klass
400
- return [] if likes_for(klass).count + dislikes_for(klass).count == 0 || Recommendable.redis.zcard(predictions_set_for(klass)) == 0
433
+ return [] if likes_for(klass.base_class).count + dislikes_for(klass.base_class).count == 0 || \
434
+ Recommendable.redis.zcard(predictions_set_for(klass)) == 0
401
435
 
402
436
  recommendations = []
403
437
  i = 0
@@ -0,0 +1,8 @@
1
+ module Recommendable
2
+ module Helpers
3
+ def manual_join(klass, action)
4
+ table = klass.base_class.table_name
5
+ "JOIN #{table} ON recommendable_#{action.pluralize}.#{action}able_id = #{table}.id AND #{table}.type = '#{klass}'"
6
+ end
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module Recommendable
2
- VERSION = '0.1.8'
2
+ VERSION = '0.2.1.1'
3
3
  end
@@ -3,13 +3,13 @@ class CreateIgnores < ActiveRecord::Migration
3
3
  def up
4
4
  create_table :recommendable_ignores, :force => true do |t|
5
5
  t.references :user
6
- t.references :ignoreable, :polymorphic => true
6
+ t.references :ignorable, :polymorphic => true
7
7
  t.timestamps
8
8
  end
9
9
 
10
- add_index :recommendable_ignores, :ignoreable_id
11
- add_index :recommendable_ignores, :ignoreable_type
12
- add_index :recommendable_ignores, [:user_id, :ignoreable_id, :ignoreable_type], :unique => true, :name => "user_ignore_constraint"
10
+ add_index :recommendable_ignores, :ignorable_id
11
+ add_index :recommendable_ignores, :ignorable_type
12
+ add_index :recommendable_ignores, [:user_id, :ignorable_id, :ignorable_type], :unique => true, :name => "user_ignore_constraint"
13
13
  end
14
14
 
15
15
  def down
@@ -0,0 +1,19 @@
1
+ # This migration comes from recommendable (originally 20120131173909)
2
+ class CreateStashes < ActiveRecord::Migration
3
+ def up
4
+ create_table :recommendable_stashes do |t|
5
+ t.references :user
6
+ t.references :stashable, :polymorphic => true
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :recommendable_stashes, :stashable_id
11
+ add_index :recommendable_stashes, :stashable_type
12
+ add_index :recommendable_stashes, [:user_id, :stashable_id, :stashable_type], :unique => true, :name => "user_stashed_constraint"
13
+ end
14
+
15
+ def down
16
+ drop_table :recommendable_stashes
17
+ end
18
+ end
19
+
@@ -46,15 +46,15 @@ ActiveRecord::Schema.define(:version => 20120131195416) do
46
46
 
47
47
  create_table "recommendable_ignores", :force => true do |t|
48
48
  t.integer "user_id"
49
- t.integer "ignoreable_id"
50
- t.string "ignoreable_type"
51
- t.datetime "created_at", :null => false
52
- t.datetime "updated_at", :null => false
49
+ t.integer "ignorable_id"
50
+ t.string "ignorable_type"
51
+ t.datetime "created_at", :null => false
52
+ t.datetime "updated_at", :null => false
53
53
  end
54
54
 
55
- add_index "recommendable_ignores", ["ignoreable_id"], :name => "index_recommendable_ignores_on_ignoreable_id"
56
- add_index "recommendable_ignores", ["ignoreable_type"], :name => "index_recommendable_ignores_on_ignoreable_type"
57
- add_index "recommendable_ignores", ["user_id", "ignoreable_id", "ignoreable_type"], :name => "user_ignore_constraint", :unique => true
55
+ add_index "recommendable_ignores", ["ignorable_id"], :name => "index_recommendable_ignores_on_ignorable_id"
56
+ add_index "recommendable_ignores", ["ignorable_type"], :name => "index_recommendable_ignores_on_ignorable_type"
57
+ add_index "recommendable_ignores", ["user_id", "ignorable_id", "ignorable_type"], :name => "user_ignore_constraint", :unique => true
58
58
 
59
59
  create_table "recommendable_likes", :force => true do |t|
60
60
  t.integer "user_id"
@@ -68,7 +68,7 @@ ActiveRecord::Schema.define(:version => 20120131195416) do
68
68
  add_index "recommendable_likes", ["likeable_type"], :name => "index_recommendable_likes_on_likeable_type"
69
69
  add_index "recommendable_likes", ["user_id", "likeable_id", "likeable_type"], :name => "user_like_constraint", :unique => true
70
70
 
71
- create_table "recommendable_stashed_items", :force => true do |t|
71
+ create_table "recommendable_stashes", :force => true do |t|
72
72
  t.integer "user_id"
73
73
  t.integer "stashable_id"
74
74
  t.string "stashable_type"
@@ -76,9 +76,9 @@ ActiveRecord::Schema.define(:version => 20120131195416) do
76
76
  t.datetime "updated_at", :null => false
77
77
  end
78
78
 
79
- add_index "recommendable_stashed_items", ["stashable_id"], :name => "index_recommendable_stashed_items_on_stashable_id"
80
- add_index "recommendable_stashed_items", ["stashable_type"], :name => "index_recommendable_stashed_items_on_stashable_type"
81
- add_index "recommendable_stashed_items", ["user_id", "stashable_id", "stashable_type"], :name => "user_stashed_constraint", :unique => true
79
+ add_index "recommendable_stashes", ["stashable_id"], :name => "index_recommendable_stashes_on_stashable_id"
80
+ add_index "recommendable_stashes", ["stashable_type"], :name => "index_recommendable_stashes_on_stashable_type"
81
+ add_index "recommendable_stashes", ["user_id", "stashable_id", "stashable_type"], :name => "user_stashed_constraint", :unique => true
82
82
 
83
83
  create_table "users", :force => true do |t|
84
84
  t.string "username"
Binary file
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
- class StashedItemSpec < MiniTest::Spec
4
- describe Recommendable::StashedItem do
3
+ class StashSpec < MiniTest::Spec
4
+ describe Recommendable::Stash do
5
5
  before :each do
6
6
  @user = User.create(:username => "dave")
7
7
  end
@@ -21,7 +21,7 @@ class StashedItemSpec < MiniTest::Spec
21
21
 
22
22
  @user.stash(movie).must_equal true
23
23
  @user.stash(movie).must_be_nil
24
- Recommendable::StashedItem.count.must_equal 1
24
+ Recommendable::Stash.count.must_equal 1
25
25
  end
26
26
  end
27
27
  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: 0.1.8
4
+ version: 0.2.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-11 00:00:00.000000000 Z
12
+ date: 2012-05-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sqlite3
16
- requirement: &70124007208240 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70124007208240
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: minitest
27
- requirement: &70124007206840 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70124007206840
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: shoulda
38
- requirement: &70124007205260 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70124007205260
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: yard
49
- requirement: &70124007203840 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ~>
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: 0.6.0
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *70124007203840
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.6.0
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: bundler
60
- requirement: &70124007201400 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ~>
@@ -65,10 +85,15 @@ dependencies:
65
85
  version: 1.0.0
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *70124007201400
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 1.0.0
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: jeweler
71
- requirement: &70124007200440 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
72
97
  none: false
73
98
  requirements:
74
99
  - - ~>
@@ -76,10 +101,15 @@ dependencies:
76
101
  version: 1.6.4
77
102
  type: :development
78
103
  prerelease: false
79
- version_requirements: *70124007200440
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 1.6.4
80
110
  - !ruby/object:Gem::Dependency
81
111
  name: rcov
82
- requirement: &70124007199640 !ruby/object:Gem::Requirement
112
+ requirement: !ruby/object:Gem::Requirement
83
113
  none: false
84
114
  requirements:
85
115
  - - ! '>='
@@ -87,10 +117,15 @@ dependencies:
87
117
  version: '0'
88
118
  type: :development
89
119
  prerelease: false
90
- version_requirements: *70124007199640
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
91
126
  - !ruby/object:Gem::Dependency
92
127
  name: rails
93
- requirement: &70124007198320 !ruby/object:Gem::Requirement
128
+ requirement: !ruby/object:Gem::Requirement
94
129
  none: false
95
130
  requirements:
96
131
  - - ! '>='
@@ -98,10 +133,15 @@ dependencies:
98
133
  version: 3.0.0
99
134
  type: :runtime
100
135
  prerelease: false
101
- version_requirements: *70124007198320
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: 3.0.0
102
142
  - !ruby/object:Gem::Dependency
103
143
  name: redis
104
- requirement: &70124007196840 !ruby/object:Gem::Requirement
144
+ requirement: !ruby/object:Gem::Requirement
105
145
  none: false
106
146
  requirements:
107
147
  - - ~>
@@ -109,10 +149,15 @@ dependencies:
109
149
  version: 2.2.0
110
150
  type: :runtime
111
151
  prerelease: false
112
- version_requirements: *70124007196840
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ~>
156
+ - !ruby/object:Gem::Version
157
+ version: 2.2.0
113
158
  - !ruby/object:Gem::Dependency
114
159
  name: resque
115
- requirement: &70124007195680 !ruby/object:Gem::Requirement
160
+ requirement: !ruby/object:Gem::Requirement
116
161
  none: false
117
162
  requirements:
118
163
  - - ! '>='
@@ -120,10 +165,15 @@ dependencies:
120
165
  version: 1.19.0
121
166
  type: :runtime
122
167
  prerelease: false
123
- version_requirements: *70124007195680
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: 1.19.0
124
174
  - !ruby/object:Gem::Dependency
125
175
  name: resque-loner
126
- requirement: &70124007194380 !ruby/object:Gem::Requirement
176
+ requirement: !ruby/object:Gem::Requirement
127
177
  none: false
128
178
  requirements:
129
179
  - - ~>
@@ -131,7 +181,12 @@ dependencies:
131
181
  version: 1.2.0
132
182
  type: :runtime
133
183
  prerelease: false
134
- version_requirements: *70124007194380
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ~>
188
+ - !ruby/object:Gem::Version
189
+ version: 1.2.0
135
190
  description: Allow a model (typically User) to Like and/or Dislike models in your
136
191
  app. Generate recommendations quickly using redis.
137
192
  email: david@davidcelis.com
@@ -151,13 +206,13 @@ files:
151
206
  - app/models/recommendable/dislike.rb
152
207
  - app/models/recommendable/ignore.rb
153
208
  - app/models/recommendable/like.rb
154
- - app/models/recommendable/stashed_item.rb
209
+ - app/models/recommendable/stash.rb
155
210
  - app/workers/recommendable/recommendation_refresher.rb
156
211
  - config/routes.rb
157
212
  - db/migrate/20120124193723_create_likes.rb
158
213
  - db/migrate/20120124193728_create_dislikes.rb
159
214
  - db/migrate/20120127092558_create_ignores.rb
160
- - db/migrate/20120131173909_create_stashed_items.rb
215
+ - db/migrate/20120131173909_create_stashes.rb
161
216
  - lib/generators/recommendable/USAGE
162
217
  - lib/generators/recommendable/install_generator.rb
163
218
  - lib/generators/recommendable/templates/initializer.rb
@@ -166,6 +221,7 @@ files:
166
221
  - lib/recommendable/acts_as_recommended_to.rb
167
222
  - lib/recommendable/engine.rb
168
223
  - lib/recommendable/exceptions.rb
224
+ - lib/recommendable/helpers.rb
169
225
  - lib/recommendable/railtie.rb
170
226
  - lib/recommendable/version.rb
171
227
  - lib/tasks/recommendable_tasks.rake
@@ -209,7 +265,7 @@ files:
209
265
  - spec/dummy/db/migrate/20120128020413_create_movies.rb
210
266
  - spec/dummy/db/migrate/20120128024632_create_php_frameworks.rb
211
267
  - spec/dummy/db/migrate/20120128024804_create_bullies.rb
212
- - spec/dummy/db/migrate/20120131195416_create_stashed_items.recommendable.rb
268
+ - spec/dummy/db/migrate/20120131195416_create_stashes.recommendable.rb
213
269
  - spec/dummy/db/schema.rb
214
270
  - spec/dummy/lib/assets/.gitkeep
215
271
  - spec/dummy/log/.gitkeep
@@ -225,7 +281,7 @@ files:
225
281
  - spec/models/ignore_spec.rb
226
282
  - spec/models/like_spec.rb
227
283
  - spec/models/movie_spec.rb
228
- - spec/models/stashed_item_spec.rb
284
+ - spec/models/stash_spec.rb
229
285
  - spec/models/user_benchmark_spec.rb
230
286
  - spec/models/user_spec.rb
231
287
  - spec/spec_helper.rb
@@ -249,7 +305,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
249
305
  version: '0'
250
306
  requirements: []
251
307
  rubyforge_project:
252
- rubygems_version: 1.8.11
308
+ rubygems_version: 1.8.22
253
309
  signing_key:
254
310
  specification_version: 3
255
311
  summary: Add like-based and/or dislike-based recommendations to your app.
@@ -1,17 +0,0 @@
1
- class CreateStashedItems < ActiveRecord::Migration
2
- def up
3
- create_table :recommendable_stashed_items do |t|
4
- t.references :user
5
- t.references :stashable, :polymorphic => true
6
- t.timestamps
7
- end
8
-
9
- add_index :recommendable_stashed_items, :stashable_id
10
- add_index :recommendable_stashed_items, :stashable_type
11
- add_index :recommendable_stashed_items, [:user_id, :stashable_id, :stashable_type], :unique => true, :name => "user_stashed_constraint"
12
- end
13
-
14
- def down
15
- drop_table :recommendable_stashed_items
16
- end
17
- end
@@ -1,18 +0,0 @@
1
- # This migration comes from recommendable (originally 20120131173909)
2
- class CreateStashedItems < ActiveRecord::Migration
3
- def up
4
- create_table :recommendable_stashed_items do |t|
5
- t.references :user
6
- t.references :stashable, :polymorphic => true
7
- t.timestamps
8
- end
9
-
10
- add_index :recommendable_stashed_items, :stashable_id
11
- add_index :recommendable_stashed_items, :stashable_type
12
- add_index :recommendable_stashed_items, [:user_id, :stashable_id, :stashable_type], :unique => true, :name => "user_stashed_constraint"
13
- end
14
-
15
- def down
16
- drop_table :recommendable_stashed_items
17
- end
18
- end