recommendable 0.1.8 → 0.2.1.1

Sign up to get free protection for your applications and to get access to all the features.
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