recommendable 0.1.2

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.
Files changed (89) hide show
  1. data/.gitignore +57 -0
  2. data/.travis.yml +3 -0
  3. data/Gemfile +17 -0
  4. data/Gemfile.lock +118 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.markdown +340 -0
  7. data/Rakefile +26 -0
  8. data/TODO +6 -0
  9. data/app/jobs/recommendable/recommendation_refresher.rb +12 -0
  10. data/app/models/recommendable/dislike.rb +9 -0
  11. data/app/models/recommendable/ignore.rb +9 -0
  12. data/app/models/recommendable/like.rb +9 -0
  13. data/app/models/recommendable/stashed_item.rb +9 -0
  14. data/config/routes.rb +3 -0
  15. data/db/migrate/20120124193723_create_likes.rb +17 -0
  16. data/db/migrate/20120124193728_create_dislikes.rb +17 -0
  17. data/db/migrate/20120127092558_create_ignores.rb +17 -0
  18. data/db/migrate/20120131173909_create_stashed_items.rb +17 -0
  19. data/lib/generators/recommendable/USAGE +8 -0
  20. data/lib/generators/recommendable/install_generator.rb +47 -0
  21. data/lib/generators/recommendable/templates/initializer.rb +18 -0
  22. data/lib/recommendable.rb +19 -0
  23. data/lib/recommendable/acts_as_recommendable.rb +85 -0
  24. data/lib/recommendable/acts_as_recommended_to.rb +659 -0
  25. data/lib/recommendable/engine.rb +13 -0
  26. data/lib/recommendable/exceptions.rb +4 -0
  27. data/lib/recommendable/railtie.rb +6 -0
  28. data/lib/recommendable/version.rb +3 -0
  29. data/lib/tasks/recommendable_tasks.rake +1 -0
  30. data/recommendable.gemspec +32 -0
  31. data/script/rails +8 -0
  32. data/spec/configuration_spec.rb +9 -0
  33. data/spec/dummy/README.rdoc +261 -0
  34. data/spec/dummy/Rakefile +7 -0
  35. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  36. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  37. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  38. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  39. data/spec/dummy/app/mailers/.gitkeep +0 -0
  40. data/spec/dummy/app/models/.gitkeep +0 -0
  41. data/spec/dummy/app/models/bully.rb +2 -0
  42. data/spec/dummy/app/models/movie.rb +3 -0
  43. data/spec/dummy/app/models/php_framework.rb +2 -0
  44. data/spec/dummy/app/models/user.rb +3 -0
  45. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  46. data/spec/dummy/config.ru +4 -0
  47. data/spec/dummy/config/application.rb +56 -0
  48. data/spec/dummy/config/boot.rb +10 -0
  49. data/spec/dummy/config/database.yml +25 -0
  50. data/spec/dummy/config/environment.rb +5 -0
  51. data/spec/dummy/config/environments/development.rb +37 -0
  52. data/spec/dummy/config/environments/production.rb +67 -0
  53. data/spec/dummy/config/environments/test.rb +37 -0
  54. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  55. data/spec/dummy/config/initializers/inflections.rb +15 -0
  56. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  57. data/spec/dummy/config/initializers/recommendable.rb +16 -0
  58. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  59. data/spec/dummy/config/initializers/session_store.rb +8 -0
  60. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  61. data/spec/dummy/config/locales/en.yml +5 -0
  62. data/spec/dummy/config/routes.rb +4 -0
  63. data/spec/dummy/db/migrate/20120128005553_create_likes.recommendable.rb +18 -0
  64. data/spec/dummy/db/migrate/20120128005554_create_dislikes.recommendable.rb +18 -0
  65. data/spec/dummy/db/migrate/20120128005555_create_ignores.recommendable.rb +18 -0
  66. data/spec/dummy/db/migrate/20120128020228_create_users.rb +9 -0
  67. data/spec/dummy/db/migrate/20120128020413_create_movies.rb +10 -0
  68. data/spec/dummy/db/migrate/20120128024632_create_php_frameworks.rb +9 -0
  69. data/spec/dummy/db/migrate/20120128024804_create_bullies.rb +9 -0
  70. data/spec/dummy/db/migrate/20120131195416_create_stashed_items.recommendable.rb +18 -0
  71. data/spec/dummy/db/schema.rb +89 -0
  72. data/spec/dummy/lib/assets/.gitkeep +0 -0
  73. data/spec/dummy/log/.gitkeep +0 -0
  74. data/spec/dummy/public/404.html +26 -0
  75. data/spec/dummy/public/422.html +26 -0
  76. data/spec/dummy/public/500.html +25 -0
  77. data/spec/dummy/public/favicon.ico +0 -0
  78. data/spec/dummy/recommendable_dummy_development +0 -0
  79. data/spec/dummy/recommendable_dummy_test +0 -0
  80. data/spec/dummy/script/rails +6 -0
  81. data/spec/factories.rb +16 -0
  82. data/spec/models/dislike_spec.rb +27 -0
  83. data/spec/models/ignore_spec.rb +27 -0
  84. data/spec/models/like_spec.rb +28 -0
  85. data/spec/models/stashed_item_spec.rb +27 -0
  86. data/spec/models/user_benchmark_spec.rb +49 -0
  87. data/spec/models/user_spec.rb +320 -0
  88. data/spec/spec_helper.rb +28 -0
  89. metadata +254 -0
data/.gitignore ADDED
@@ -0,0 +1,57 @@
1
+ # RVM / rbenv version files
2
+ .rvmrc
3
+ .rbenv-version
4
+
5
+ # rcov generated
6
+ coverage
7
+
8
+ # rdoc generated
9
+ rdoc
10
+
11
+ # yard generated
12
+ doc
13
+ .yardoc
14
+
15
+ # bundler
16
+ .bundle
17
+ vendor/bundle
18
+
19
+ # jeweler generated
20
+ pkg
21
+
22
+ # logging
23
+ *.log
24
+
25
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
26
+ #
27
+ # * Create a file at ~/.gitignore
28
+ # * Include files you want ignored
29
+ # * Run: git config --global core.excludesfile ~/.gitignore
30
+ #
31
+ # After doing this, these files will be ignored in all your git projects,
32
+ # saving you from having to 'pollute' every project you touch with them
33
+ #
34
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
35
+ #
36
+ # For MacOS:
37
+
38
+ .DS_Store
39
+
40
+ # For TextMate
41
+ *.tmproj
42
+ tmtags
43
+
44
+ # For emacs:
45
+ #*~
46
+ #\#*
47
+ #.\#*
48
+
49
+ # For vim:
50
+ *.swp
51
+
52
+ # For redcar:
53
+ #.redcar
54
+
55
+ # For rubinius:
56
+ #*.rbc
57
+ .rake_tasks*
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ gem "rails", ">= 3.0.0"
4
+ gem "redis", "~> 2.2.0"
5
+ gem "resque", "~> 1.19.0"
6
+ gem "resque-loner", "~> 1.2.0"
7
+
8
+ # Add dependencies to develop your gem here.
9
+ # Include everything needed to run rake, tests, features, etc.
10
+ group :development do
11
+ gem "sqlite3"
12
+ gem "minitest"
13
+ gem "shoulda"
14
+ gem "miniskirt"
15
+ gem "yard", "~> 0.6.0"
16
+ gem "bundler", "~> 1.0.0"
17
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,118 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ actionmailer (3.2.0)
5
+ actionpack (= 3.2.0)
6
+ mail (~> 2.4.0)
7
+ actionpack (3.2.0)
8
+ activemodel (= 3.2.0)
9
+ activesupport (= 3.2.0)
10
+ builder (~> 3.0.0)
11
+ erubis (~> 2.7.0)
12
+ journey (~> 1.0.0)
13
+ rack (~> 1.4.0)
14
+ rack-cache (~> 1.1)
15
+ rack-test (~> 0.6.1)
16
+ sprockets (~> 2.1.2)
17
+ activemodel (3.2.0)
18
+ activesupport (= 3.2.0)
19
+ builder (~> 3.0.0)
20
+ activerecord (3.2.0)
21
+ activemodel (= 3.2.0)
22
+ activesupport (= 3.2.0)
23
+ arel (~> 3.0.0)
24
+ tzinfo (~> 0.3.29)
25
+ activeresource (3.2.0)
26
+ activemodel (= 3.2.0)
27
+ activesupport (= 3.2.0)
28
+ activesupport (3.2.0)
29
+ i18n (~> 0.6)
30
+ multi_json (~> 1.0)
31
+ arel (3.0.0)
32
+ builder (3.0.0)
33
+ erubis (2.7.0)
34
+ hike (1.2.1)
35
+ i18n (0.6.0)
36
+ journey (1.0.0)
37
+ json (1.6.5)
38
+ mail (2.4.1)
39
+ i18n (>= 0.4.0)
40
+ mime-types (~> 1.16)
41
+ treetop (~> 1.4.8)
42
+ mime-types (1.17.2)
43
+ miniskirt (1.1.1)
44
+ activesupport (>= 2.2)
45
+ minitest (2.10.1)
46
+ multi_json (1.0.4)
47
+ polyglot (0.3.3)
48
+ rack (1.4.0)
49
+ rack-cache (1.1)
50
+ rack (>= 0.4)
51
+ rack-protection (1.2.0)
52
+ rack
53
+ rack-ssl (1.3.2)
54
+ rack
55
+ rack-test (0.6.1)
56
+ rack (>= 1.0)
57
+ rails (3.2.0)
58
+ actionmailer (= 3.2.0)
59
+ actionpack (= 3.2.0)
60
+ activerecord (= 3.2.0)
61
+ activeresource (= 3.2.0)
62
+ activesupport (= 3.2.0)
63
+ bundler (~> 1.0)
64
+ railties (= 3.2.0)
65
+ railties (3.2.0)
66
+ actionpack (= 3.2.0)
67
+ activesupport (= 3.2.0)
68
+ rack-ssl (~> 1.3.2)
69
+ rake (>= 0.8.7)
70
+ rdoc (~> 3.4)
71
+ thor (~> 0.14.6)
72
+ rake (0.9.2.2)
73
+ rdoc (3.12)
74
+ json (~> 1.4)
75
+ redis (2.2.2)
76
+ redis-namespace (1.0.3)
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)
85
+ shoulda (2.11.3)
86
+ sinatra (1.3.2)
87
+ rack (~> 1.3, >= 1.3.6)
88
+ rack-protection (~> 1.2)
89
+ tilt (~> 1.3, >= 1.3.3)
90
+ sprockets (2.1.2)
91
+ hike (~> 1.2)
92
+ rack (~> 1.0)
93
+ tilt (~> 1.1, != 1.3.0)
94
+ sqlite3 (1.3.5)
95
+ thor (0.14.6)
96
+ tilt (1.3.3)
97
+ treetop (1.4.10)
98
+ polyglot
99
+ polyglot (>= 0.3.1)
100
+ tzinfo (0.3.31)
101
+ vegas (0.1.11)
102
+ rack (>= 1.0.0)
103
+ yard (0.6.8)
104
+
105
+ PLATFORMS
106
+ ruby
107
+
108
+ DEPENDENCIES
109
+ bundler (~> 1.0.0)
110
+ miniskirt
111
+ minitest
112
+ rails (>= 3.0.0)
113
+ redis (~> 2.2.0)
114
+ resque (~> 1.19.0)
115
+ resque-loner (~> 1.2.0)
116
+ shoulda
117
+ sqlite3
118
+ yard (~> 0.6.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 David Celis
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,340 @@
1
+ # recommendable [![Build Status](https://secure.travis-ci.org/davidcelis/recommendable.png)](http://travis-ci.org/davidcelis/recommendable)
2
+
3
+ Recommendable is a Rails Engine to add Like/Dislike functionality to your
4
+ application. It uses Redis to generate recommendations quickly through a
5
+ collaborative filtering algorithm that I modified myself. Your users' tastes
6
+ are compared with one another and used to give them great recommendations!
7
+ Yes, Redis is required. Scroll to the end of the README for more info on that.
8
+
9
+ Why Likes and Dislikes?
10
+ -----------------------
11
+
12
+ [I hate five-star rating scales][0].
13
+
14
+ **tl;dr:** Binary voting habits are most certainly not an odd phenomenon.
15
+ People tend to vote in only two different ways. Some folks give either 1 star
16
+ or 5 stars. Some people fluctuate between 3 and 4 stars. There are always
17
+ outliers, but what it comes down to is this: a person's binary votes indicate,
18
+ in general, a dislike or like of what they're voting on. I'm just giving the
19
+ people what they want.
20
+
21
+ Installation
22
+ ------------
23
+
24
+ Add the following to your Rails application's `Gemfile`:
25
+
26
+ ``` ruby
27
+ gem "recommendable"
28
+ ```
29
+
30
+ After your `bundle install`, you can then run:
31
+
32
+ $ rails g recommendable:install (--user-class=User)
33
+
34
+ After running the installation generator, you should double check
35
+ `config/initializers/recommendable.rb` for options on configuring your Redis
36
+ connection.
37
+
38
+ Finally, Recommendable uses Resque to place users in a queue. Users must wait
39
+ their turn to regenerate recommendations so that your application does not get
40
+ throttled. Don't worry, though! Most of the time, your users will barely have
41
+ to wait. In fact, you can run multiple resque workers if you wish.
42
+
43
+ Assuming you have `redis-server` running...
44
+
45
+ $ QUEUE=recommendable rake environment resque:work
46
+
47
+ You can run this command multiple times if you wish to start more than one
48
+ worker. This is the standard rake task for starting a Resque worker so, for
49
+ more options on this task, head over to [defunkt/resque][1]
50
+
51
+ Usage
52
+ -----
53
+
54
+ In your Rails model that represents your application's user:
55
+
56
+ ``` ruby
57
+ class User < ActiveRecord::Base
58
+ acts_as_recommended_to
59
+
60
+ # ...
61
+ end
62
+ ```
63
+
64
+ Then, from any Rails model you wish your `user` to be able to `like` or `dislike`:
65
+
66
+ ``` ruby
67
+ class Movie < ActiveRecord::Base
68
+ acts_as_recommendable
69
+
70
+ # ...
71
+ end
72
+
73
+ class Show < ActiveRecord::Base
74
+ acts_as_recommendable
75
+
76
+ # ...
77
+ end
78
+ ````
79
+
80
+ And that's it!
81
+
82
+ ### Liking/Disliking
83
+
84
+ At this point, your user will be ready to `like` movies...
85
+
86
+ ``` ruby
87
+ current_user.like Movie.create(:title => '2001: A Space Odyssey', :year => 1968)
88
+ #=> true
89
+ ```
90
+
91
+ ... or `dislike` them:
92
+
93
+ ``` ruby
94
+ current_user.dislike Movie.create(:title => 'Star Wars: Episode I - The Phantom Menace', :year => 1999)
95
+ #=> true
96
+ ```
97
+
98
+ In addition, several helpful methods are available to your user now:
99
+
100
+ ``` ruby
101
+ current_user.likes? Movie.find_by_title('2001: A Space Odyssey')
102
+ #=> true
103
+ current_user.dislikes? Movie.find_by_title('Star Wars: Episode I - The Phantom Menace')
104
+ #=> true
105
+ other_movie = Movie.create('Back to the Future', :year => 1985)
106
+ current_user.dislikes? other_movie
107
+ #=> false
108
+ current_user.like other_movie
109
+ #=> true
110
+ current_user.liked
111
+ #=> [#<Movie name: '2001: A Space Odyssey', year: 1968>, #<Movie name: 'Back to the Future', :year => 1985>]
112
+ current_user.disliked
113
+ #=> [#<Movie name: 'Star Wars: Episode I - The Phantom Menace', year: 1999>]
114
+ ```
115
+
116
+ Because you are allowed to declare multiple models as recommendable, you may
117
+ wish to return a set of liked or disliked objects for only one of those
118
+ models.
119
+
120
+ ``` ruby
121
+ current_user.liked_for(Movie)
122
+ #=> [#<Movie name: '2001: A Space Odyssey', year: 1968>, #<Movie name: 'Back to the Future', :year => 1985>]
123
+ current_user.disliked_for(Show)
124
+ #=> []
125
+ ```
126
+
127
+ ### Ignoring
128
+
129
+ If you want to give your user the ability to `ignore` recommendations or even
130
+ just hide stuff on your website that they couldn't care less about, you can!
131
+
132
+ ``` ruby
133
+ weird_movie_nobody_wants_to_watch = Movie.create(:title => 'Cool World', :year => 1998)
134
+ current_user.ignore weird_movie_nobody_wants_to_watch
135
+ #=> true
136
+ current_user.ignored
137
+ #=> [#<Movie name: 'Cool World', year: 1998>]
138
+ current_user.ignored_for(Show)
139
+ #=> []
140
+ ```
141
+
142
+ Do what you will with this list of records. The power is yours.
143
+
144
+ ### Saving for later
145
+
146
+ Your user might want to maintain a list of items to try later but still receive
147
+ new recommendations. For this, you can use Recommendable::StashedItems. Note that
148
+ adding an item to a user's stash will remove it from their list of recommendations.
149
+ Additionally, an item can not be stashed if the user already likes or dislikes it.
150
+
151
+ ``` ruby
152
+ movie_to_watch_later = Movie.create(:title => 'The Descendants', :year => 2011)
153
+ current_user.stash(movie_to_watch_later)
154
+ #=> true
155
+ current_user.stashed
156
+ #=> [#<Movie name: 'The Descendants', year: 2011>]
157
+ # Later...
158
+ current_user.like(movie_to_watch_later)
159
+ #=> true
160
+ current_user.stash(movie_to_watch_later)
161
+ #=> nil
162
+ current_user.has_stashed?(movie_to_watch_later)
163
+ #=> false
164
+ ```
165
+
166
+ ### Unliking/Undisliking/Unignoring/Unstashing
167
+
168
+ Note that liking a movie that has already been disliked (or vice versa) will
169
+ simply destroy the old rating and create a new one. If a user attempts to `like`
170
+ a movie that they already like, however, nothing happens and `nil` is returned.
171
+ If you wish to manually remove an item from a user's likes or dislikes or
172
+ ignored records, you can:
173
+
174
+ ``` ruby
175
+ current_user.like Movie.create(:title => 'Avatar', :year => 2009)
176
+ #=> true
177
+ current_user.unlike Movie.find_by_title('Avatar')
178
+ #=> true
179
+ current_user.liked
180
+ #=> []
181
+ ```
182
+
183
+ You can use `undislike`, `unignore` and `unstash` in the same fashion. So, as
184
+ far as the Likes and Dislikes go, do you think that's enough? Because I didn't.
185
+
186
+ ``` ruby
187
+ friend = User.create(:username => 'joeblow')
188
+ awesome_movie = Movie.find_by_title('2001: A Space Odyssey')
189
+ friend.like awesome_movie
190
+ #=> true
191
+ awesome_movie.liked_by
192
+ #=> [#<User username: 'davidcelis'>, #<User username: 'joeblow'>]
193
+ Movie.find_by_title('Star Wars: Episode I - The Phantom Menace').disliked_by
194
+ #=> [#<User username: 'davidcelis'>]
195
+ current_user.common_likes_with(friend)
196
+ #=> [#<Movie title: '2001: A Space Odyssey', year: 1968>]
197
+ ```
198
+
199
+ `common_dislikes_with` and `disagreements_with` are available for similar use.
200
+
201
+ Recommendations
202
+ ---------------
203
+
204
+ When a user submits a new `Like` or `Dislike`, they enter a queue to have their
205
+ recommendations refreshed. Once that user exits the queue, you can retrieve
206
+ these like so:
207
+
208
+ ``` ruby
209
+ current_user.recommendations
210
+ #=> [#<Movie highly_recommended>, #<Show somewhat_recommended>, #<Movie meh>]
211
+ current_user.recommendations_for(Show)
212
+ #=> [#<Show somewhat_recommended>]
213
+ ```
214
+
215
+ The top recommendations are returned in an array ordered by how good recommendable
216
+ believes the recommendation to be (from best to worst).
217
+
218
+ ``` ruby
219
+ current_user.like somewhat_recommended_show
220
+ #=> true
221
+ current_user.recommendations
222
+ #=> [#<Movie highly_recommended>, #<Movie meh>]
223
+ ```
224
+
225
+ Finally, you can also get a list of the users found to be most similar to your
226
+ current user:
227
+
228
+ ``` ruby
229
+ current_user.similar_raters
230
+ #=> [#<User username: 'joe-blow'>, #<User username: 'less-so-than-joe-blow']
231
+ ```
232
+
233
+ Likewise, this list is ordered from most similar to least similar.
234
+
235
+ Documentation
236
+ -------------
237
+
238
+ Some of the above methods are tweakable with options. For example, you can
239
+ adjust the number of recommendations returned to you (the default is 10) and
240
+ the number of similar uses returned (also 10). To see these options, check
241
+ the documentation.
242
+
243
+ A note on Redis
244
+ ---------------
245
+
246
+ Recommendable currently depends on [Redis](http://redis.io/). It will install
247
+ the redis-rb gem as a dependency, but you must install Redis and run it
248
+ yourself. Also note that your Redis database must be persistent. Recommendable
249
+ will use Redis to permanently store sorted sets to quickly access recommendations.
250
+ Please take care with your Redis database! Fortunately, if you do lose your
251
+ Redis database, there's hope (more on that later).
252
+
253
+ Installing Redis
254
+ ----------------
255
+
256
+ Recommendable requires Redis to deliver recommendations. Why? Because my
257
+ collaborative filtering algorithm is based almost entirely on set math, and
258
+ Ruby's Set class just won't cut it for fast recommendations.
259
+
260
+ ### Homebrew
261
+
262
+ For Mac OS X users, homebrew is by far the easiest way to install Redis.
263
+
264
+ $ brew install redis
265
+ $ redis-server /usr/local/etc/redis.conf
266
+
267
+ You should now have Redis running as a daemon on localhost:6379
268
+
269
+ ### Via Resque
270
+
271
+ Resque (which is also a dependency of recommendable) includes Rake tasks that
272
+ will install and run Redis for you:
273
+
274
+ $ git clone git://github.com/defunkt/resque.git
275
+ $ cd resque
276
+ $ rake redis:install dtach:install
277
+ $ rake redis:start
278
+
279
+ If you do not have admin rights to your machine:
280
+
281
+ $ git clone git://github.com/defunkt/resque.git
282
+ $ cd resque
283
+ $ PREFIX=<your_prefix> rake redis:install dtach:install
284
+ $ rake redis:start
285
+
286
+ Redis will now be running on localhost:6379. After a second, you can hit `ctrl-\`
287
+ to detach and keep Redis running in the background.
288
+
289
+ (Thanks to [defunkt][1] for mentioning this
290
+ method, and thanks to [ezmobius][2] for
291
+ making it possible)
292
+
293
+ Manually regenerating recommendations
294
+ -------------------------------------
295
+
296
+ If a catastrophe occurs and your Redis database is either destroyed or rendered
297
+ unusable in some other way, there is hope. You can run the following from your
298
+ application's console (assuming your user class is User):
299
+
300
+ User.all.each do |user|
301
+ user.update_similarities
302
+ user.update_recommendations
303
+ end
304
+
305
+ But please try not to have to do this manually!
306
+
307
+ Contributing to recommendable
308
+ -----------------------------
309
+
310
+ Read the [Contributing][3] wiki page first.
311
+
312
+ Once you've made your great commits:
313
+
314
+ 1. [Fork][4] recommendable
315
+ 2. Create a feature branch
316
+ 3. Write your code (and tests please)
317
+ 4. Push to your branch's origin
318
+ 5. Create a [Pull Request][5] from your branch
319
+ 6. That's it!
320
+
321
+ Links
322
+ -----
323
+ * Code: `git clone git://github.com/davidcelis/recommendable.git`
324
+ * Home: <http://github.com/davidcelis/recommendable>
325
+ * Docs: <http://rubydoc.info/gems/recommendable/0.1.0/frames>
326
+ * Bugs: <http://github.com/davidcelis/recommendable/issues>
327
+ * Gems: <http://rubygems.org/gems/recommendable>
328
+
329
+ Copyright
330
+ ---------
331
+
332
+ Copyright © 2012 David Celis. See LICENSE.txt for
333
+ further details.
334
+
335
+ [0]: http://davidcelis.com/blog/2012/02/01/why-i-hate-five-star-ratings/
336
+ [1]: https://github.com/defunkt/resque
337
+ [2]: https://github.com/ezmobius/redis-rb
338
+ [3]: http://wiki.github.com/defunkt/resque/contributing
339
+ [4]: http://help.github.com/forking/
340
+ [5]: http://help.github.com/pull-requests/