recommendable 1.1.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/lib/recommendable.rb +38 -26
  2. data/lib/recommendable/configuration.rb +47 -0
  3. data/lib/recommendable/helpers.rb +3 -9
  4. data/lib/recommendable/helpers/calculations.rb +150 -0
  5. data/lib/recommendable/helpers/queriers.rb +23 -0
  6. data/lib/recommendable/helpers/redis_key_mapper.rb +29 -0
  7. data/lib/recommendable/orm/active_record.rb +6 -0
  8. data/lib/recommendable/orm/data_mapper.rb +7 -0
  9. data/lib/recommendable/orm/mongo_mapper.rb +8 -0
  10. data/lib/recommendable/orm/mongoid.rb +7 -0
  11. data/lib/recommendable/ratable.rb +83 -0
  12. data/lib/recommendable/ratable/dislikable.rb +26 -0
  13. data/lib/recommendable/ratable/likable.rb +26 -0
  14. data/lib/recommendable/rater.rb +109 -0
  15. data/lib/recommendable/rater/bookmarker.rb +120 -0
  16. data/lib/recommendable/rater/disliker.rb +122 -0
  17. data/lib/recommendable/rater/hider.rb +120 -0
  18. data/lib/recommendable/rater/liker.rb +122 -0
  19. data/lib/recommendable/rater/recommender.rb +68 -0
  20. data/lib/recommendable/version.rb +5 -4
  21. data/lib/recommendable/workers/delayed_job.rb +16 -0
  22. data/lib/recommendable/workers/rails.rb +16 -0
  23. data/lib/recommendable/workers/resque.rb +13 -0
  24. data/lib/recommendable/workers/sidekiq.rb +13 -0
  25. metadata +62 -131
  26. data/.gitignore +0 -57
  27. data/.travis.yml +0 -3
  28. data/CHANGELOG.markdown +0 -159
  29. data/Gemfile +0 -3
  30. data/Gemfile.lock +0 -112
  31. data/LICENSE.txt +0 -22
  32. data/README.markdown +0 -135
  33. data/Rakefile +0 -26
  34. data/TODO +0 -7
  35. data/app/models/recommendable/dislike.rb +0 -19
  36. data/app/models/recommendable/ignore.rb +0 -19
  37. data/app/models/recommendable/like.rb +0 -19
  38. data/app/models/recommendable/stash.rb +0 -19
  39. data/app/workers/recommendable/delayed_job_worker.rb +0 -17
  40. data/app/workers/recommendable/rails_worker.rb +0 -17
  41. data/app/workers/recommendable/resque_worker.rb +0 -14
  42. data/app/workers/recommendable/sidekiq_worker.rb +0 -14
  43. data/config/routes.rb +0 -3
  44. data/db/migrate/20120124193723_create_likes.rb +0 -17
  45. data/db/migrate/20120124193728_create_dislikes.rb +0 -17
  46. data/db/migrate/20120127092558_create_ignores.rb +0 -17
  47. data/db/migrate/20120131173909_create_stashes.rb +0 -17
  48. data/lib/generators/recommendable/USAGE +0 -8
  49. data/lib/generators/recommendable/install_generator.rb +0 -40
  50. data/lib/generators/recommendable/templates/initializer.rb +0 -28
  51. data/lib/recommendable/acts_as_recommendable.rb +0 -176
  52. data/lib/recommendable/acts_as_recommended_to.rb +0 -774
  53. data/lib/recommendable/engine.rb +0 -14
  54. data/lib/recommendable/exceptions.rb +0 -4
  55. data/lib/recommendable/railtie.rb +0 -6
  56. data/lib/sidekiq/middleware/client/unique_jobs.rb +0 -37
  57. data/lib/sidekiq/middleware/server/unique_jobs.rb +0 -17
  58. data/lib/tasks/recommendable_tasks.rake +0 -1
  59. data/recommendable.gemspec +0 -30
  60. data/script/rails +0 -8
  61. data/spec/configuration_spec.rb +0 -9
  62. data/spec/dummy/README.rdoc +0 -261
  63. data/spec/dummy/Rakefile +0 -7
  64. data/spec/dummy/app/assets/javascripts/application.js +0 -15
  65. data/spec/dummy/app/assets/stylesheets/application.css +0 -13
  66. data/spec/dummy/app/controllers/application_controller.rb +0 -3
  67. data/spec/dummy/app/helpers/application_helper.rb +0 -2
  68. data/spec/dummy/app/mailers/.gitkeep +0 -0
  69. data/spec/dummy/app/models/.gitkeep +0 -0
  70. data/spec/dummy/app/models/bully.rb +0 -2
  71. data/spec/dummy/app/models/movie.rb +0 -2
  72. data/spec/dummy/app/models/php_framework.rb +0 -2
  73. data/spec/dummy/app/models/user.rb +0 -3
  74. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  75. data/spec/dummy/config.ru +0 -4
  76. data/spec/dummy/config/application.rb +0 -56
  77. data/spec/dummy/config/boot.rb +0 -10
  78. data/spec/dummy/config/database.yml +0 -25
  79. data/spec/dummy/config/environment.rb +0 -5
  80. data/spec/dummy/config/environments/development.rb +0 -37
  81. data/spec/dummy/config/environments/production.rb +0 -67
  82. data/spec/dummy/config/environments/test.rb +0 -37
  83. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  84. data/spec/dummy/config/initializers/inflections.rb +0 -15
  85. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  86. data/spec/dummy/config/initializers/recommendable.rb +0 -14
  87. data/spec/dummy/config/initializers/secret_token.rb +0 -7
  88. data/spec/dummy/config/initializers/session_store.rb +0 -8
  89. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  90. data/spec/dummy/config/locales/en.yml +0 -5
  91. data/spec/dummy/config/routes.rb +0 -4
  92. data/spec/dummy/db/migrate/20120128005553_create_likes.recommendable.rb +0 -18
  93. data/spec/dummy/db/migrate/20120128005554_create_dislikes.recommendable.rb +0 -18
  94. data/spec/dummy/db/migrate/20120128005555_create_ignores.recommendable.rb +0 -18
  95. data/spec/dummy/db/migrate/20120128020228_create_users.rb +0 -9
  96. data/spec/dummy/db/migrate/20120128020413_create_movies.rb +0 -10
  97. data/spec/dummy/db/migrate/20120128024632_create_php_frameworks.rb +0 -9
  98. data/spec/dummy/db/migrate/20120128024804_create_bullies.rb +0 -9
  99. data/spec/dummy/db/migrate/20120131195416_create_stashes.recommendable.rb +0 -19
  100. data/spec/dummy/db/schema.rb +0 -89
  101. data/spec/dummy/lib/assets/.gitkeep +0 -0
  102. data/spec/dummy/log/.gitkeep +0 -0
  103. data/spec/dummy/public/404.html +0 -26
  104. data/spec/dummy/public/422.html +0 -26
  105. data/spec/dummy/public/500.html +0 -25
  106. data/spec/dummy/public/favicon.ico +0 -0
  107. data/spec/dummy/recommendable_dummy_development +0 -0
  108. data/spec/dummy/recommendable_dummy_test +0 -0
  109. data/spec/dummy/script/rails +0 -6
  110. data/spec/factories.rb +0 -16
  111. data/spec/models/dislike_spec.rb +0 -41
  112. data/spec/models/ignore_spec.rb +0 -27
  113. data/spec/models/like_spec.rb +0 -42
  114. data/spec/models/movie_spec.rb +0 -82
  115. data/spec/models/stash_spec.rb +0 -27
  116. data/spec/models/user_benchmark_spec.rb +0 -49
  117. data/spec/models/user_spec.rb +0 -443
  118. data/spec/spec_helper.rb +0 -28
@@ -1,27 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class StashSpec < MiniTest::Spec
4
- describe Recommendable::Stash do
5
- before :each do
6
- @user = User.create(:username => "dave")
7
- end
8
-
9
- it "should not be created for an object that does not act_as_recommendedable" do
10
- web2py = PhpFramework.create(:name => "web2py")
11
- proc { @user.stash(web2py) }.must_raise Recommendable::UnrecommendableError
12
- end
13
-
14
- it "should be created for an object that does act_as_recommendable" do
15
- movie = Movie.create(:title => "Star Wars: Episode I - The Phantom Menace", :year => 1999)
16
- @user.stash(movie).must_equal true
17
- end
18
-
19
- it "should not be created twice for the same user-object pair" do
20
- movie = Movie.create(:title => "Star Wars: Episode I - The Phantom Menace", :year => 1999)
21
-
22
- @user.stash(movie).must_equal true
23
- @user.stash(movie).must_be_nil
24
- Recommendable::Stash.count.must_equal 1
25
- end
26
- end
27
- end
@@ -1,49 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class UserBenchmarkSpec < MiniTest::Unit::TestCase
4
- def test_update_recommendations
5
- if ENV["BENCH"] then
6
- Recommendable.redis.flushdb
7
- @actions = [:like, :dislike]
8
-
9
- puts "\n"
10
-
11
- assert_performance_exponential do |n|
12
- @user = Factory(:user)
13
- @users = []
14
- @movies = []
15
-
16
- # Make n users, 5n movies
17
- n.times do
18
- @users << Factory(:user)
19
- @movies << Factory(:movie)
20
- @movies << Factory(:movie)
21
- @movies << Factory(:movie)
22
- @movies << Factory(:movie)
23
- @movies << Factory(:movie)
24
- end
25
-
26
- # Main user randomly likes/dislikes 1/4 of the movies
27
- @movies.sample(n/4).each do |m|
28
- @user.send(@actions.sample, m)
29
- end
30
-
31
- # Other users randomly like/dislike some movies
32
- @movies.sample(n/2).each do |m|
33
- @users.sample.send(@actions.sample, m)
34
- @users.sample.send(@actions.sample, m)
35
- @users.sample.send(@actions.sample, m)
36
- end
37
-
38
- @user.send :update_similarities
39
- @user.send :update_recommendations
40
- Recommendable.redis.flushdb
41
-
42
- User.delete_all
43
- Movie.delete_all
44
- Recommendable::Like.delete_all
45
- Recommendable::Dislike.delete_all
46
- end
47
- end
48
- end
49
- end
@@ -1,443 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class UserSpec < MiniTest::Spec
4
- # User and Bully are skeleton classes defined in the dummy application for
5
- # the sole purpose of running these tests. They're in spec/dummy/models/ but
6
- # really, there's nothing there of note.
7
-
8
- describe User do
9
- describe "before_destroy filters" do
10
- before :each do
11
- Recommendable.redis.flushdb
12
- @user1 = Factory(:user)
13
- @user2 = Factory(:user)
14
- @movie1 = Factory(:movie)
15
- @movie2 = Factory(:movie)
16
- end
17
-
18
- it "should no longer be involved in similarities or predictions" do
19
- @user1.like @movie1
20
- @user1.like @movie2
21
- @user2.like @movie1
22
-
23
- @user1.send :update_similarities
24
- @user2.send :update_similarities
25
- @user2.send :update_recommendations
26
-
27
- similarity_set = @user2.send :similarity_set
28
- predictions_set = @user2.send :predictions_set_for, Movie
29
- @user2.destroy
30
-
31
- @user1.similar_raters.wont_include @user2
32
- Recommendable.redis.get(similarity_set).must_be_nil
33
- Recommendable.redis.get(predictions_set).must_be_nil
34
- end
35
- end
36
-
37
- describe "that does not act_as_recommended_to" do
38
- before :each do
39
- @user = Factory(:bully)
40
- @movie = Factory(:movie)
41
- end
42
-
43
- it "should not be able to rate, ignore, or stash an item, and trying should not be enough to get Redis keys" do
44
- proc { @user.like(@movie) }.must_raise NoMethodError
45
- proc { @user.dislike(@movie) }.must_raise NoMethodError
46
- proc { @user.ignore(@movie) }.must_raise NoMethodError
47
- proc { @user.stash(@movie) }.must_raise NoMethodError
48
-
49
- @movie.liked_by.must_be_empty
50
- @movie.disliked_by.must_be_empty
51
-
52
- proc { @user.create_recommended_to_sets }.must_raise NoMethodError
53
-
54
- proc { @user.likes_set_for(Movie) }.must_raise NoMethodError
55
- proc { @user.dislikes_set_for(Movie) }.must_raise NoMethodError
56
-
57
- Recommendable.redis.smembers("Bully:#{@user.id}:likes:Movie").must_be_empty
58
- Recommendable.redis.smembers("Bully:#{@user.id}:dislikes:Movie").must_be_empty
59
- Recommendable.redis.smembers("Bully:#{@user.id}:similarities").must_be_empty
60
- Recommendable.redis.smembers("Bully:#{@user.id}:predictions:Movie").must_be_empty
61
- end
62
- end
63
-
64
- describe "that does act_as_recommendable" do
65
- before :each do
66
- @user = Factory(:user)
67
- @movie = Factory(:movie)
68
- end
69
-
70
- after :each do
71
- Recommendable.redis.flushdb
72
- end
73
-
74
- it "should be able to like a recommendable item" do
75
- @user.like(@movie).must_equal true
76
- @user.send(:create_recommended_to_sets)
77
- Recommendable.redis.smembers("User:#{@user.id}:likes:Movie").must_include @movie.id.to_s
78
- @user.send(:destroy_recommended_to_sets)
79
- end
80
-
81
- it "should not dislike an item after liking it" do
82
- @user.dislike(@movie)
83
- @user.like(@movie).must_equal true
84
- @user.dislikes?(@movie).must_equal false
85
- @user.likes?(@movie).must_equal true
86
-
87
- @user.send(:create_recommended_to_sets)
88
- Recommendable.redis.smembers("User:#{@user.id}:dislikes:Movie").wont_include @movie.id.to_s
89
- @user.send(:destroy_recommended_to_sets)
90
- end
91
-
92
- it "should not be ignoring an item after liking it" do
93
- @user.ignore(@movie)
94
- @user.like(@movie).must_equal true
95
- @user.ignored?(@movie).must_equal false
96
- @user.likes?(@movie).must_equal true
97
- end
98
-
99
- it "should not have an item stashed after liking it" do
100
- @user.stash(@movie)
101
- @user.like(@movie).must_equal true
102
- @user.stashed?(@movie).must_equal false
103
- @user.likes?(@movie).must_equal true
104
- end
105
-
106
- it "should be able to dislike a recommendable item" do
107
- @user.dislike(@movie).must_equal true
108
- @user.send(:create_recommended_to_sets)
109
- Recommendable.redis.smembers("User:#{@user.id}:dislikes:Movie").must_include @movie.id.to_s
110
- @user.send(:destroy_recommended_to_sets)
111
- end
112
-
113
- it "should not like an item after disliking it" do
114
- @user.like(@movie)
115
- @user.dislike(@movie).must_equal true
116
- @user.likes?(@movie).must_equal false
117
- @user.dislikes?(@movie).must_equal true
118
-
119
- @user.send(:create_recommended_to_sets)
120
- Recommendable.redis.smembers("User:#{@user.id}:dislikes:Movie").must_include @movie.id.to_s
121
- Recommendable.redis.smembers("User:#{@user.id}:likes:Movie").wont_include @movie.id.to_s
122
- @user.send(:destroy_recommended_to_sets)
123
- end
124
-
125
- it "should not be ignoring an item after disliking it" do
126
- @user.ignore(@movie)
127
- @user.dislike(@movie).must_equal true
128
- @user.ignored?(@movie).must_equal false
129
- @user.dislikes?(@movie).must_equal true
130
- end
131
-
132
- it "should not have an item stashed after disliking it" do
133
- @user.stash(@movie)
134
- @user.dislike(@movie).must_equal true
135
- @user.stashed?(@movie).must_equal false
136
- @user.dislikes?(@movie).must_equal true
137
- end
138
-
139
- it "should be able to ignore a recommendable item" do
140
- @user.ignore(@movie).must_equal true
141
- end
142
-
143
- it "should not like an item after ignoring it" do
144
- @user.like(@movie)
145
- @user.ignore(@movie).must_equal true
146
- @user.likes?(@movie).must_equal false
147
- @user.ignored?(@movie).must_equal true
148
- end
149
-
150
- it "should not dislike an item after ignoring it" do
151
- @user.dislike(@movie)
152
- @user.ignore(@movie).must_equal true
153
- @user.dislikes?(@movie).must_equal false
154
- @user.ignored?(@movie).must_equal true
155
- end
156
-
157
- it "should not have an item stashed after ignoring it" do
158
- @user.stash(@movie)
159
- @user.ignore(@movie).must_equal true
160
- @user.stashed?(@movie).must_equal false
161
- @user.ignored?(@movie).must_equal true
162
- end
163
-
164
- it "should be able to stash a recommendable item" do
165
- @user.stash(@movie).must_equal true
166
- end
167
-
168
- it "should not stash a liked item" do
169
- @user.like(@movie)
170
- @user.stash(@movie).must_be_nil
171
- @user.likes?(@movie).must_equal true
172
- @user.stashed?(@movie).must_equal false
173
- end
174
-
175
- it "should not stash a disliked item" do
176
- @user.dislike(@movie)
177
- @user.stash(@movie).must_be_nil
178
- @user.dislikes?(@movie).must_equal true
179
- @user.stashed?(@movie).must_equal false
180
- end
181
-
182
- it "should not have an item ignored after stashing it" do
183
- @user.ignore(@movie)
184
- @user.stash(@movie).must_equal true
185
- @user.ignored?(@movie).must_equal false
186
- @user.stashed?(@movie).must_equal true
187
- end
188
-
189
- it "should not be able to rate or ignore an item that is not recommendable." do
190
- @cakephp = Factory(:php_framework)
191
-
192
- proc { @user.like(@cakephp) }.must_raise Recommendable::UnrecommendableError
193
- proc { @user.dislike(@cakephp) }.must_raise Recommendable::UnrecommendableError
194
- proc { @user.ignore(@cakephp) }.must_raise Recommendable::UnrecommendableError
195
- proc { @user.stash(@cakephp) }.must_raise Recommendable::UnrecommendableError
196
-
197
- proc { @cakephp.liked_by }.must_raise NoMethodError
198
- proc { @cakephp.disliked_by }.must_raise NoMethodError
199
-
200
- @user.send(:create_recommended_to_sets)
201
-
202
- Recommendable.redis.smembers("User:#{@user.id}:likes:PhpFramework").must_be_empty
203
- Recommendable.redis.smembers("User:#{@user.id}:dislikes:PhpFramework").must_be_empty
204
- Recommendable.redis.smembers("User:#{@user.id}:similarities").must_be_empty
205
- Recommendable.redis.smembers("User:#{@user.id}:predictions:Movie").must_be_empty
206
-
207
- @user.send(:destroy_recommended_to_sets)
208
- end
209
-
210
- it "should not freak out when re-rating, re-ignoring, or re-stashing items" do
211
- @user.like(@movie)
212
- @user.like(@movie).must_be_nil
213
-
214
- @user.dislike(@movie)
215
- @user.dislike(@movie).must_be_nil
216
-
217
- @user.ignore(@movie)
218
- @user.ignore(@movie).must_be_nil
219
-
220
- @user.stash(@movie)
221
- @user.stash(@movie).must_be_nil
222
- end
223
-
224
- it "should be able to unrate, unignore or unstash items" do
225
- @user.like(@movie)
226
- @user.unlike(@movie).must_equal true
227
-
228
- @user.dislike(@movie)
229
- @user.undislike(@movie).must_equal true
230
-
231
- @user.ignore(@movie)
232
- @user.unignore(@movie).must_equal true
233
-
234
- @user.stash(@movie)
235
- @user.unstash(@movie).must_equal true
236
- end
237
- end
238
-
239
- describe "while using finders" do
240
- it "should return ActiveRecord::Relations" do
241
- @user = Factory(:user)
242
- @movie1 = Factory(:movie)
243
- @movie2 = Factory(:movie)
244
- @movie3 = Factory(:movie)
245
- @movie4 = Factory(:movie)
246
- @movie5 = Factory(:movie)
247
-
248
- @user.like @movie1
249
- @user.like @movie2
250
- @user.dislike @movie3
251
-
252
- @user.liked_movies.must_be_instance_of ActiveRecord::Relation
253
- @user.liked_movies.where(:title => @movie1.title).must_include @movie1
254
- @user.liked_movies.where(:title => @movie2.title).wont_include @movie1
255
- @user.liked_movies.limit(1).size.must_equal 1
256
- @user.disliked_movies.where(:title => @movie5.title).must_be_empty
257
- end
258
- end
259
-
260
- describe "while getting recommendations" do
261
- before :each do
262
- @dave = Factory(:user)
263
- @frank = Factory(:user)
264
- @hal = Factory(:user)
265
- @movie1 = Factory(:movie)
266
- @movie2 = Factory(:movie)
267
- @movie3 = Factory(:movie)
268
- @movie4 = Factory(:movie)
269
- @movie5 = Factory(:movie)
270
- end
271
-
272
- after :each do
273
- Recommendable.redis.del "User:#{@dave.id}:similarities"
274
- Recommendable.redis.del "User:#{@dave.id}:predictions:Movie"
275
- Recommendable.redis.del "User:#{@frank.id}:similarities"
276
- Recommendable.redis.del "User:#{@frank.id}:predictions:Movie"
277
- end
278
-
279
- it "should respect passed counts" do
280
- @dave.like @movie1
281
- @frank.like @movie1
282
- @frank.like @movie2
283
- @frank.like @movie3
284
- @frank.like @movie4
285
- @frank.like @movie5
286
-
287
- @dave.send :update_similarities and @dave.send :update_recommendations
288
-
289
- @dave.recommendations.size.must_equal 4
290
- @dave.recommendations(2).size.must_equal 2
291
- end
292
-
293
- it "should return an ActiveRecord::Relation when using the dynamic finder" do
294
- @dave.like @movie1
295
- @frank.like @movie1
296
- @frank.like @movie2
297
- @frank.like @movie3
298
- @frank.like @movie4
299
- @frank.like @movie5
300
-
301
- @dave.send :update_similarities and @dave.send :update_recommendations
302
-
303
- @dave.recommended_movies.limit(2).size.must_equal 2
304
- @dave.recommended_movies.where(:title => @movie3.title).must_include @movie3
305
- @dave.recommended_movies.where(:title => @movie3.title).wont_include @movie2
306
- @dave.recommended_movies.where(:title => @movie3.title).wont_include @movie4
307
- @dave.recommended_movies.where(:title => @movie3.title).wont_include @movie5
308
- end
309
-
310
- it "should have common likes with a friend" do
311
- @dave.like @movie1
312
- @dave.like @movie2
313
- @dave.like @movie4
314
-
315
- @frank.like @movie2
316
- @frank.like @movie3
317
- @frank.like @movie4
318
-
319
- @dave.liked_movies_in_common_with(@frank).must_include @movie2
320
- @dave.liked_movies_in_common_with(@frank).must_include @movie4
321
- @dave.liked_movies_in_common_with(@frank).wont_include @movie1
322
- @dave.liked_movies_in_common_with(@frank).wont_include @movie3
323
- end
324
-
325
- it "should have common dislikes with a friend" do
326
- @dave.dislike @movie1
327
- @dave.dislike @movie3
328
- @dave.like @movie4
329
-
330
- @frank.dislike @movie2
331
- @frank.dislike @movie3
332
- @frank.dislike @movie4
333
-
334
- @dave.disliked_movies_in_common_with(@frank).wont_include @movie2
335
- @dave.disliked_movies_in_common_with(@frank).wont_include @movie4
336
- @dave.disliked_movies_in_common_with(@frank).wont_include @movie1
337
- @dave.disliked_movies_in_common_with(@frank).must_include @movie3
338
- end
339
-
340
- it "should get populated sorted sets for similarities and recommendations" do
341
- @dave.like(@movie1)
342
- @frank.like(@movie1)
343
- @frank.like(@movie2)
344
- @dave.send :update_similarities
345
- @dave.send :update_recommendations
346
-
347
- @dave.similar_raters.must_include @frank
348
- @dave.recommended_movies.must_include @movie2
349
- end
350
-
351
- it "should return only the number of specified recommendations" do
352
- @dave.like(@movie1)
353
- @frank.like(@movie1)
354
- @frank.like(@movie2)
355
- @frank.like(@movie3)
356
- @frank.like(@movie4)
357
- @dave.send :update_similarities
358
- @dave.send :update_recommendations
359
-
360
- @dave.recommendations(2).size.must_equal 2
361
- @dave.recommended_movies(1).size.must_equal 1
362
- end
363
-
364
- it "should order similar users by similarity" do
365
- @dave.like(@movie1)
366
- @dave.like(@movie2)
367
- @frank.like(@movie1)
368
- @frank.dislike(@movie2)
369
- @hal.like(@movie1)
370
- @hal.like(@movie2)
371
-
372
- # hal should be more similar to dave than frank
373
- @dave.send :update_similarities
374
- @dave.send :update_recommendations
375
-
376
- @dave.similar_raters.must_equal [@hal, @frank]
377
- end
378
-
379
- it "should correctly recommend an awesome movie or two. In the correct order, of course." do
380
- @dave.like(@movie1)
381
- @dave.like(@movie2)
382
- @frank.like(@movie1)
383
- @frank.like(@movie2)
384
- @frank.like(@movie4)
385
- @hal.like(@movie1)
386
- @hal.like(@movie3)
387
-
388
- @dave.send :update_similarities
389
- @dave.send :update_recommendations
390
-
391
- @dave.recommendations.must_equal [@movie4, @movie3]
392
- end
393
-
394
- it "should not recommend rated items" do
395
- @dave.like(@movie1)
396
- @dave.dislike(@movie2)
397
- @frank.like(@movie1)
398
- @frank.like(@movie2)
399
- @frank.like(@movie4)
400
- @hal.like(@movie1)
401
- @hal.like(@movie3)
402
-
403
- @dave.send :update_similarities
404
- @dave.send :update_recommendations
405
-
406
- @dave.recommendations.wont_include @movie1
407
- @dave.recommendations.wont_include @movie2
408
- end
409
-
410
- it "should not recommend ignored items" do
411
- @dave.like(@movie1)
412
- @dave.like(@movie2)
413
- @dave.ignore(@movie4)
414
- @frank.like(@movie1)
415
- @frank.like(@movie2)
416
- @frank.like(@movie4)
417
- @hal.like(@movie1)
418
- @hal.like(@movie3)
419
-
420
- @dave.send :update_similarities
421
- @dave.send :update_recommendations
422
-
423
- @dave.recommendations.wont_include @movie4
424
- end
425
-
426
- it "should not recommend stashed items" do
427
- @dave.like(@movie1)
428
- @dave.like(@movie2)
429
- @dave.stash(@movie4)
430
- @frank.like(@movie1)
431
- @frank.like(@movie2)
432
- @frank.like(@movie4)
433
- @hal.like(@movie1)
434
- @hal.like(@movie3)
435
-
436
- @dave.send :update_similarities
437
- @dave.send :update_recommendations
438
-
439
- @dave.recommendations.wont_include @movie4
440
- end
441
- end
442
- end
443
- end