davidcelis / recommendable Goto Github PK
View Code? Open in Web Editor NEW:+1::-1: A recommendation engine using Likes and Dislikes for your Ruby app
Home Page: http://davidcelis.github.io/recommendable/
License: MIT License
:+1::-1: A recommendation engine using Likes and Dislikes for your Ruby app
Home Page: http://davidcelis.github.io/recommendable/
License: MIT License
Hello David,
I'm having some trouble using recommendable with models in Forem (Forem::Post for example).
I can't just do recommends :post
as no one knows that model and doing recommends "Forem::Post"
works but then I don't have access to dynamic methods like liked_
.
Any idea how to manage that would be welcome!
Thanks
Getting this strange error:
06:02:24 web.1 | Started POST "/links" for 127.0.0.1 at 2012-07-22 06:02:24 -0500
06:02:24 web.1 | Processing by LinksController#create as HTML
06:02:24 web.1 | Parameters: {"utf8"=>"โ", "authenticity_token"=>"ZCPrWZIpt3nfePkT0oCgyKd0Od4rYDe1LAAKXF9FCic=", "link"=>{"title"=>"test", "url"=>"testse", "body"=>"testset"}, "commit"=>"Create Link"}
06:02:24 web.1 | Account Load (0.2ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = 2 LIMIT 1
06:02:24 web.1 | (0.1ms) begin transaction
06:02:24 web.1 | SQL (0.5ms) INSERT INTO "links" ("account_id", "approved", "body", "created_at", "title", "updated_at", "url") VALUES (?, ?, ?, ?, ?, ?, ?) [["account_id", 2], ["approved", false], ["body", "testset"], ["created_at", Sun, 22 Jul 2012 11:02:24 UTC +00:00], ["title", "test"], ["updated_at", Sun, 22 Jul 2012 11:02:24 UTC +00:00], ["url", "testse"]]
06:02:24 web.1 | (1.8ms) commit transaction
06:02:24 web.1 | Recommendable::Like Exists (0.1ms) SELECT 1 AS one FROM "recommendable_likes" WHERE "recommendable_likes"."user_id" = 2 AND "recommendable_likes"."likeable_id" = 3 AND "recommendable_likes"."likeable_type" = 'Link' LIMIT 1
06:02:24 web.1 | CACHE (0.0ms) SELECT 1 AS one FROM "recommendable_likes" WHERE "recommendable_likes"."user_id" = 2 AND "recommendable_likes"."likeable_id" = 3 AND "recommendable_likes"."likeable_type" = 'Link' LIMIT 1
06:02:24 web.1 | Recommendable::Dislike Exists (0.1ms) SELECT 1 AS one FROM "recommendable_dislikes" WHERE "recommendable_dislikes"."user_id" = 2 AND "recommendable_dislikes"."dislikeable_id" = 3 AND "recommendable_dislikes"."dislikeable_type" = 'Link' LIMIT 1
06:02:24 web.1 | Recommendable::Stash Exists (0.1ms) SELECT 1 AS one FROM "recommendable_stashes" WHERE "recommendable_stashes"."user_id" = 2 AND "recommendable_stashes"."stashable_id" = 3 AND "recommendable_stashes"."stashable_type" = 'Link' LIMIT 1
06:02:24 web.1 | Recommendable::Ignore Exists (0.1ms) SELECT 1 AS one FROM "recommendable_ignores" WHERE "recommendable_ignores"."user_id" = 2 AND "recommendable_ignores"."ignorable_id" = 3 AND "recommendable_ignores"."ignorable_type" = 'Link' LIMIT 1
06:02:24 web.1 | (0.1ms) begin transaction
06:02:24 web.1 | Recommendable::Like Exists (0.2ms) SELECT 1 AS one FROM "recommendable_likes" WHERE ("recommendable_likes"."user_id" = 2 AND "recommendable_likes"."likeable_id" = 3 AND "recommendable_likes"."likeable_type" = 'Link') LIMIT 1
06:02:24 web.1 | SQL (0.5ms) INSERT INTO "recommendable_likes" ("created_at", "likeable_id", "likeable_type", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?) [["created_at", Sun, 22 Jul 2012 11:02:24 UTC +00:00], ["likeable_id", 3], ["likeable_type", "Link"], ["updated_at", Sun, 22 Jul 2012 11:02:24 UTC +00:00], ["user_id", 2]]
06:02:24 web.1 | (1.8ms) commit transaction
06:02:24 web.1 | (0.2ms) SELECT COUNT(*) FROM "recommendable_likes" WHERE "recommendable_likes"."likeable_id" = 3 AND "recommendable_likes"."likeable_type" = 'Link'
06:02:24 web.1 | (0.1ms) SELECT COUNT(*) FROM "recommendable_dislikes" WHERE "recommendable_dislikes"."dislikeable_id" = 3 AND "recommendable_dislikes"."dislikeable_type" = 'Link'
06:02:24 web.1 | CACHE (0.0ms) SELECT COUNT(*) FROM "recommendable_likes" WHERE "recommendable_likes"."likeable_id" = 3 AND "recommendable_likes"."likeable_type" = 'Link'
06:02:24 web.1 | CACHE (0.0ms) SELECT COUNT(*) FROM "recommendable_dislikes" WHERE "recommendable_dislikes"."dislikeable_id" = 3 AND "recommendable_dislikes"."dislikeable_type" = 'Link'
06:02:24 web.1 | CACHE (0.0ms) SELECT COUNT(*) FROM "recommendable_likes" WHERE "recommendable_likes"."likeable_id" = 3 AND "recommendable_likes"."likeable_type" = 'Link'
06:02:24 web.1 | Completed 500 Internal Server Error in 153ms
06:02:24 web.1 | NoMethodError (undefined method `get' for nil:NilClass):
06:02:24 web.1 | app/controllers/links_controller.rb:28:in `create'
06:02:24 web.1 | Rendered ...gems/actionpack-3.2.6/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms)
06:02:24 web.1 | Rendered ...gems/actionpack-3.2.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.1ms)
06:02:24 web.1 | Rendered ...gems/actionpack-3.2.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (10.6ms)
06:02:24 web.1 | 127.0.0.1 - - [22/Jul/2012 06:02:24] "POST /links HTTP/1.1" 500 16284 0.2039
Here's the controller action:
def create
if @_link.valid?
@_link.save
current_user.like @_link
redirect_to @_link, notice: "Link submitted, waiting for approval."
else
render :new
end
end
All the migrations and such refer to the ignore-able table as ignorable, but in the acts_as_recommended_to.rb file, lines 377 and 379 refer to "ignoreables". This breaks the ability for a user to see their ignores. See skord/recommendable@8ab714a for a patch. pull request incoming
I went ahead and wrote this code for my own model, but thought you might want it:
MODIFIER = 1.96
def score
unless total_score == 0
phat = total_likes / total_score.to_f
a = 1 - phat
b = 4 * total_score
c = MODIFIER * MODIFIER
d = c / b
e = phat * a
f = e + d
g = f / total_score
h = Math.sqrt g
i = 2 * total_score
j = c / i
k = MODIFIER * h
l = phat + j
m = l - k
n = c / total_score
o = 1 + n
m / o
end
end
def total_score
total_likes + total_dislikes
end
def total_likes
liked_by.size
end
def total_dislikes
disliked_by.size
end
Thanks for the quick fix !
I've not been able to make it work yet so I'll keep trying.
But I have now a problem with stashed items.
First the def stashed_for klass was like this :
def stashed_for klass
liked = if klass.sti?
stashes.joins manual_join(klass, 'stash')
else
stashes.where(:stashable_type => klass).includes(:stashable)
end
stashed.map(&:stashable)
end
When it should more be like this I guess :
def stashed_for klass
stashed = if klass.sti?
stashed_items.joins manual_join(klass, 'stash')
else
stashed_items.where(:stashable_type => klass).includes(:stashable)
end
stashed.map(&:stashable)
end
Cause I had undefined method "stashes" for identity.
But when I fix it with what I've just pasted here, now I have a problem with the manual_join helper.
Because the stashed_item table name and its polymorphic columns are not really consistent.
So when I call the helper with "stash" as a second argument, I get
PGError: ERROR: missing FROM-clause entry for table "recommendable_stashes"
LINE 1: ... FROM "recommendable_stashed_items" JOIN items ON recommenda...
^
: SELECT "recommendable_stashed_items".* FROM "recommendable_stashed_items" JOIN items ON recommendable_stashes.stashable_id = items.id AND ....
In the join we see recommendable_stashes is not a valid table name
And when I call it with "stashed_item", then the table name is ok, but not the name of the column :
PGError: ERROR: column recommendable_stashed_items.stashed_itemable_id does not exist
LINE 1: ... FROM "recommendable_stashed_items" JOIN items ON recommenda...
^
: SELECT "recommendable_stashed_items".* FROM "recommendable_stashed_items" JOIN items ON recommendable_stashed_items.stashed_itemable_id = items.id AND
I think renaming one of those would be the solution but I'm not really sure about what direction you want to take.
Sorry for the really long answer.
Regards and thanks again !
Right now, I could alias_method chain the like and dislike to do something when an object is liked or disliked, but it would be cleaner to have it as a callback, like
class User < AR::Base
after_like :do_something
def do_something(object)
MyLog.create message: "#{object.to_s} was liked by User##{self.id}"
end
end
When i execute the command to process the resque queue, i get:
podstore :: (master) ยป heroku run rake resque:work QUEUE=recommendable --trace ~/git/podstore
Running rake resque:work QUEUE=recommendable --trace attached to terminal... up, run.1
** Invoke resque:work (first_time)
** Invoke resque:preload (first_time)
** Invoke resque:setup (first_time)
** Execute resque:setup
** Execute resque:preload
rake aborted!
No such file to load -- recommendable/dislike
/app/vendor/bundle/ruby/1.9.1/gems/activesupport-3.1.3/lib/active_support/dependencies.rb:306:in rescue in depend_on' /app/vendor/bundle/ruby/1.9.1/gems/activesupport-3.1.3/lib/active_support/dependencies.rb:301:in
depend_on'
/app/vendor/bundle/ruby/1.9.1/gems/activesupport-3.1.3/lib/active_support/dependencies.rb:214:in require_dependency' /app/vendor/bundle/ruby/1.9.1/gems/railties-3.1.3/lib/rails/engine.rb:417:in
block (2 levels) in eager_load!'
/app/vendor/bundle/ruby/1.9.1/gems/railties-3.1.3/lib/rails/engine.rb:416:in each' /app/vendor/bundle/ruby/1.9.1/gems/railties-3.1.3/lib/rails/engine.rb:416:in
block in eager_load!'
/app/vendor/bundle/ruby/1.9.1/gems/railties-3.1.3/lib/rails/engine.rb:414:in each' /app/vendor/bundle/ruby/1.9.1/gems/railties-3.1.3/lib/rails/engine.rb:414:in
eager_load!'
/app/vendor/bundle/ruby/1.9.1/gems/railties-3.1.3/lib/rails/application/railties.rb:8:in each' /app/vendor/bundle/ruby/1.9.1/gems/railties-3.1.3/lib/rails/application/railties.rb:8:in
all'
/app/vendor/bundle/ruby/1.9.1/gems/railties-3.1.3/lib/rails/engine.rb:412:in eager_load!' /app/vendor/bundle/ruby/1.9.1/gems/resque-1.20.0/lib/resque/tasks.rb:54:in
block (2 levels) in <top (required)>'
/app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:205:in call' /app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:205:in
block in execute'
/app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:200:in each' /app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:200:in
execute'
/app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:158:in block in invoke_with_call_chain' /usr/local/lib/ruby/1.9.1/monitor.rb:201:in
mon_synchronize'
/app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:151:in invoke_with_call_chain' /app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:176:in
block in invoke_prerequisites'
/app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:174:in each' /app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:174:in
invoke_prerequisites'
/app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:157:in block in invoke_with_call_chain' /usr/local/lib/ruby/1.9.1/monitor.rb:201:in
mon_synchronize'
/app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:151:in invoke_with_call_chain' /app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:144:in
invoke'
/app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:116:in invoke_task' /app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:94:in
block (2 levels) in top_level'
/app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:94:in each' /app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:94:in
block in top_level'
/app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:133:in standard_exception_handling' /app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:88:in
top_level'
/app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:66:in block in run' /app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:133:in
standard_exception_handling'
/app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:63:in run' /app/vendor/bundle/ruby/1.9.1/gems/rake-0.9.2.2/bin/rake:33:in
<top (required)>'
/app/vendor/bundle/ruby/1.9.1/bin/rake:19:in load' /app/vendor/bundle/ruby/1.9.1/bin/rake:19:in
Suppose I have a User model that recommends Events. How would I create a named scope for the top Events? How about for all of the Events that a User likes?
I upgraded recommendable and my app doesn't boot. Not sure if I'm missing something essential but browsing quickly through the 0.2.1 source code, the gem requires recommendable/hooks
but I can't seem to find that module anywhere.
Hi
First of all, I'm using Ruby 1.9.3-p125, Rails 3.2.3 and Postgresql
My user class is Identity
I have several identities in my database.
2 of them like 100 items with at least 50 items in common.
but when I get an Identity from the database and do identity.recommendations, it always returns []
u.recommendations
(11.1ms) SELECT COUNT() FROM "recommendable_likes" WHERE "recommendable_likes"."user_id" = 5
(0.4ms) SELECT COUNT() FROM "recommendable_dislikes" WHERE "recommendable_dislikes"."user_id" = 5
=> []
I have no error nowhere, only empty arrays (I also have a problem with Item.top but we'll discuss it in an other issue)
Here are few details as you asked in the other issue about recommendations :
Recommendable.redis.zcard "Identity:5:similarities"
=> 2
Recommendable.redis.zrangebyscore("Identity:5:similarities", -1, 1).map do |user|
Recommendable.redis.zscore "Identity:5:similarities", user
end
=> ["0.0098039215686274508", "0.5"]
One thing that may be a problem in my project is that I have STI.
In fact Item is the parent Class but what I really "like" in my project is Event, Place or Exhibition
Maybe it's the source of the problem, don't really know.
Because when I like, it likes Event or Place in the recommendable_* tables, no problem, but maybe it loads Item (the parent class) in Redis.
But I have no problems with similar_raters which uses Redis also.
If someone has any clue to help me.
rails g recommendable:install
Connecting to database specified by database.yml
Adding Recommendable initializer (config/initializers/recommendable.rb)
create config/initializers/recommendable.rb
Copying migrations...
rake aborted!
cannot load such file -- resque/tasks
(See full trace by running task with --trace)
Running rake db:migrate
rake aborted!
cannot load such file -- resque/tasks
(See full trace by running task with --trace)
Done! Recommendable has been successfully installed. Please configure it in config/intializers/recommendable.rb
Hi
When I use the method "where" with "top" I have the following problem:
Oeuvre.select([:id,:name]).top(15)
ActiveRecord::RecordNotFound: Couldn't find all Oeuvres with IDs (25, 22, 20, 11) [WHERE `oeuvres`.`scraper` = 1] (found 3 results, but was looking for 4)
Do you have a workaround for me?
I just finished upgrading my Rails application to 3.2.8 and when attempting to start the server I get this error message:
/home/cyle/vrg/my_app/config/initializers/recommendable.rb:6:in `<top (required)>': undefined method `redis=' for Recommendable:Module (NoMethodError)
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:245:in `load'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:245:in `block in load'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:236:in `load_dependency'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:245:in `load'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/bundler/gems/rails-dev-boost-c62c1b3763c8/lib/rails_development_boost/loadable_patch.rb:14:in `load'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/engine.rb:588:in `block (2 levels) in <class:Engine>'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/engine.rb:587:in `each'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/engine.rb:587:in `block in <class:Engine>'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/initializable.rb:30:in `instance_exec'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/initializable.rb:30:in `run'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/initializable.rb:55:in `block in run_initializers'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/initializable.rb:54:in `each'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/initializable.rb:54:in `run_initializers'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/application.rb:136:in `initialize!'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/railtie/configurable.rb:30:in `method_missing'
from /home/cyle/vrg/Roboteer.Virtual-Robot-Games-Assignemnts/config/environment.rb:5:in `<top (required)>'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:251:in `require'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:251:in `block in require'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:236:in `load_dependency'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:251:in `require'
from /home/cyle/vrg/Roboteer.Virtual-Robot-Games-Assignemnts/config.ru:4:in `block in <main>'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/rack-1.4.1/lib/rack/builder.rb:51:in `instance_eval'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/rack-1.4.1/lib/rack/builder.rb:51:in `initialize'
from /home/cyle/vrg/Roboteer.Virtual-Robot-Games-Assignemnts/config.ru:1:in `new'
from /home/cyle/vrg/Roboteer.Virtual-Robot-Games-Assignemnts/config.ru:1:in `<main>'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/rack-1.4.1/lib/rack/builder.rb:40:in `eval'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/rack-1.4.1/lib/rack/builder.rb:40:in `parse_file'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/rack-1.4.1/lib/rack/server.rb:200:in `app'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/commands/server.rb:46:in `app'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/rack-1.4.1/lib/rack/server.rb:301:in `wrapped_app'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/rack-1.4.1/lib/rack/server.rb:252:in `start'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/commands/server.rb:70:in `start'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/commands.rb:55:in `block in <top (required)>'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/commands.rb:50:in `tap'
from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/commands.rb:50:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
Here is my config file:
require "redis"
# Recommendable requires a connection to a running redis-server. Either create
# a new instance based on a host/port or UNIX socket, or pass in an existing
# Redis client instance.
Recommendable.redis = Redis.new(:host => "localhost", :port => 6379)
# Connect to Redis via a UNIX socket instead
# Recommendable.redis = Redis.new(:sock => "")
# Tell Redis which database to use (usually between 0 and 15). The default of 0
# is most likely okay unless you have another application using that database.
# Recommendable.redis.select "0"
# If using Sidekiq, uncomment the following or place it in config/initializers/sidekiq.rb:
# Sidekiq.configure_server do |config|
# require 'sidekiq/middleware/server/unique_jobs'
# config.server_middleware do |chain|
# chain.add Sidekiq::Middleware::Server::UniqueJobs
# end
# end
#
# Sidekiq.configure_client do |config|
# require 'sidekiq/middleware/client/unique_jobs'
# config.client_middleware do |chain|
# chain.add Sidekiq::Middleware::Client::UniqueJobs
# end
# end
For instance in my User model I have:
#Enable users to recommend objects (thumbs up/down)
recommends :posts
In my console I have access to:
> Post.last.disliked_by
=> [#<User id: ......
>Post.last.dislike_count
=> 1
But if I try to use these helper methods in my model, views, or controllers in the exact same fashion all I get are undefined_method errors. What's the deal?
It will be nice to have the counter cache or some fields in the recommendable models to store the number of likes, dislikes...
Hi, I'm new to Recommendable (v1.1.1) and, after installing and trying, I wasn't receiving any recommendation. I looked for similar issues and checked my redis and resque conections are OK, and if I do user.send :update_recommendations
, then it works. I've been tracing the bug and I've found that only "sometimes" a job is enqueued in the Resque queue. That's how I went into this piece of code:
%w(like unlike dislike undislike).each do |action|
send "after_#{action}", lambda { |obj| obj.send(:update_score) and Recommendable.enqueue(self.id) }
end
I tried by executing Recommendable.enqueue(user.id)
in the console and it worked too.
Then I realized Recommendable.enqueue(self.id)
was only called when update_score
returns true (because of the "and" operator), and that only happens when it returns 0 (that is when the object has not been rated).
I've followed the commits of acts_as_recommended_to.rb
and I've seen that before, it made the two actions.
object.send :update_score
Recommendable.enqueue self.id
So I think it's maybe a bug. I've solved it quick and dirty by a return true at the end of the update_score
method.
Now I'm getting my recommendations :)
Another question is why when I do:
alice.like thing1
alice.like thing2
alice.like thing3
bob.like thing1
bob.recommendations
=> Bob is only recommended thing3
bob.like thing3
bob.recommendations
=> Bob is recommended thing2
bob.unlike thing3
bob.recommendations
=> Bob is recommended thing3 and thing2
Is that normal? Thank you!!!
Bundler could not find compatible versions for gem "redis":
In Gemfile:
recommendable (= 1.1.2) ruby depends on
redis (~> 2.2.0) ruby
sidekiq (= 2.0.3) ruby depends on
redis (3.0.1)
I'm not sure if this is by design or not, but if you call
User.ignore Model.instance
and then
User.unignore Model.instance
It's not added back to the recommended items list. I would only think that might be a desired option in case someone accidentally ignores something.
Is it possible to specify the number of recommendations that are returned? Something like:
>> current_user.recommendations(4)
=> [#<Movie name: "A Clockwork Orange">, #<Show name: "Arrested Development">, #<Movie name: "The Dark Knight">, #<Show name: "Big Bang Theory">]
I'm getting the following stack trace and unsure why
NameError: uninitialized constant MyModelName::
Stacktrace seems to be pointing to:
acts_as_recommendable.rb:81:in `create_liked_by_set'
I'm using rails 3.1 and ruby 1.9.2
Sidekiq seems to have much better threading and can handle more work than a single Resque worker. Additionally, workers process unique jobs by default and this functionality does not require a plugin. Look into switching from Resque to Sidekiq.
In my app i'm building, I already use delayed_job
I'd prefer not to have to run another worker on heroku to use reccomendable. What code do i need to run to process updates in delayed_job? Is it just that manual snippet mentioned for rebuilding recs if the redis store gets destroyed? (but run on individual users as they are updated?)
The gems seems cool but in my project I have a model which is not User, it's Identity.
Do you plan on having the ability to choose the liker model in the near future ?
class User < ActiveRecord::Base
recommends :users
# ...
end
I always get the error.
ActiveRecord::RecordInvalid: Validation failed: User has already liked this item
"Dynamically defined finders return ActiveRecord::Relations" introduces a hard dependency on ActiveRecord::Base. Would be nice to be able to use recommendable in projects that don't use activerecord but use an activemodel compliant orm. This would enable recommendable to be fairly orm agnostic.
Thanks,
Michael
So I found myself needing a count of the above types. I realized I could do some_movie.liked_by.size
, but that the data returned (an integer) might be one of those "eventually consistant" things. Since we're already using Redis and a queue system perhaps store the counts in memory that get updated at-some-point?
I could do a pull request after I look through the code.
not working with rails 3.2 and ruby 1.8.7...I tried several times but every time there are several syntax errors on acts_as_recommendable_to.rb
In case you didn't catch the commit, Sidekiq no longer contains the UniqueJobs middleware, see - sidekiq/sidekiq@2cdb106
Might want to either implement your own, or edit the README, " If bundling Resque, you should also include 'resque-loner' in your Gemfile to ensure your users only get queued once (Sidekiq does this by default, and there is no current way to avoid duplicate jobs in DelayedJob)."
We have similar raters in the gem right now, but i would love to query similar recommendable items(Users who liked x also liked y)?
This is embarrassing... Recommendable items will stay in users recommendation sets after being destroyed (unless they have these sets refreshed before checking). When a recommendable item is destroyed, each user should have it removed from their recommendation sets.
Both libraries are rather heavily used now; I'd like to support both of them side by side. Adding this into the code is trivial, but I don't know how to gracefully handle dependencies.
I'm trying to get recommendable up and running, and from the docs it looks amazing.
The problem is, when i do
device.like feed
(Where device reccomends :feeds)
i get the following error:
device.likes? feed
(0.3ms) SELECT 1 FROM "recommendable_likes" WHERE "recommendable_likes"."device_id" = 3 AND "recommendable_likes"."likeable_id" = 4977 AND "recommendable_likes"."likeable_type" = 'Feed' LIMIT 1
SQLite3::SQLException: no such column: recommendable_likes.device_id: SELECT 1 FROM "recommendable_likes" WHERE "recommendable_likes"."device_id" = 3 AND "recommendable_likes"."likeable_id" = 4977 AND "recommendable_likes"."likeable_type" = 'Feed' LIMIT 1
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: recommendable_likes.device_id: SELECT 1 FROM "recommendable_likes" WHERE "recommendable_likes"."device_id" = 3 AND "recommendable_likes"."likeable_id" = 4977 AND "recommendable_likes"."likeable_type" = 'Feed' LIMIT 1
from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/sqlite3-1.3.5/lib/sqlite3/database.rb:91:in initialize' from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/sqlite3-1.3.5/lib/sqlite3/database.rb:91:in
new'
from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/sqlite3-1.3.5/lib/sqlite3/database.rb:91:in prepare' from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/connection_adapters/sqlite_adapter.rb:227:in
block in exec_query'
from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/connection_adapters/abstract_adapter.rb:244:in block in log' from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/activesupport-3.1.3/lib/active_support/notifications/instrumenter.rb:21:in
instrument'
from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/connection_adapters/abstract_adapter.rb:239:in log' from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/connection_adapters/sqlite_adapter.rb:223:in
exec_query'
from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/connection_adapters/sqlite_adapter.rb:434:in select' from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in
select_all'
from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in select_all' from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/connection_adapters/abstract/database_statements.rb:24:in
select_one'
from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/connection_adapters/abstract/database_statements.rb:30:in select_value' from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/relation/finder_methods.rb:203:in
exists?'
from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/associations/collection_proxy.rb:102:in method_missing' from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/bundler/gems/recommendable-e500aefa34a3/lib/recommendable/acts_as_recommended_to.rb:56:in
likes?'
from (irb):3
from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.1.3/lib/rails/commands/console.rb:45:in start' from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.1.3/lib/rails/commands/console.rb:8:in
start'
from /Users/svanter/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.1.3/lib/rails/commands.rb:40:in <top (required)>' from script/rails:6:in
require'
from script/rails:6:in `
The widget doesn't have the helper methods until the user has called it's helper methods.
[4] pry(main)> Link.first.liked_by
Link Load (0.2ms) SELECT "links".* FROM "links" LIMIT 1
NoMethodError: undefined method `liked_by' for #<Link:0x007fdcd6372958>
[7] pry(main)> Account.last.likes
Account Load (0.2ms) SELECT "accounts".* FROM "accounts" ORDER BY "accounts"."id" DESC LIMIT 1
NoMethodError: private method `likes' called for #<Account:0x007fdcd5c057b0>
[9] pry(main)> Link.first.liked_by
Link Load (0.3ms) SELECT "links".* FROM "links" LIMIT 1
Account Load (14.9ms) SELECT "accounts".* FROM "accounts" INNER JOIN "recommendable_likes" ON "accounts"."id" = "recommendable_likes"."user_id" WHERE "recommendable_likes"."likeable_id" = 1 AND "recommendable_likes"."likeable_type" = 'Link'
=> []
I found after setting up the gem, it DOES install resque, but it does not put the resque configuration in the recommendable initializer. That might be appropriate (ruby noob here), but it probably should be mentioned somewhere. I was stuck for a while trying to figure out why resque wasn't working
Items that have already been rated, hidden, or bookmarked currently appear in
recommendations. Fixing this SHOULD be easy, but is currently messing with
one of the tests. The solution (in update_recommendations_for
) should be:
For some reason, this causes
RecommenderTest#test_that_it_is_removed_from_recommendable_after_destroy
to
fail.
It seems the likable migration is hard coded to a user table. Am I understanding that the liking class must be named User?
In test and production, models are automatically eager loaded when the application boots. This is good, as acts_as_recommendable
appends the class's constant into the Recommendable.recommendable_classes
array for use internally. In development, however, eager loading can cause too much slowdown in requests. This means that, in the development environment, these class constants have to be referenced manually before attempting to get recommendations. If possible, I need to find a way to either:
Hi David,
Ran into an error whole testing out the gem and was wondering if you could help? So did the following:
u1 = User.first
u1.like(Movie.find(1))
u2 = User.last
u2.like(Movie.find(2))
u2.like(Movie.find(3))
u2.like(Movie.find(4))
When I tried to do:
u1.recommendations
I got this error:
a.recommendations
NoMethodError: undefined method `recommendations' for #User:0x007ff15bbc3ed8
My User model looks like this:
class User < ActiveRecord::Base
....
recommends :movies
Since you've already built this awesome system to track Likes / Dislikes and give recommendations and similarities... what do you think of extending it to sort the recommendable models using an algorithm similar to:
http://evanmiller.org/how-not-to-sort-by-average-rating.html
Anyways, just thought it could fit in nicely into the Redis background and this system...
ActiveModel::MassAssignmentSecurity::Error in IdeasController#upvote
Can't mass-assign protected attributes: likeable_id, likeable_type
Apparently it trips up MA? Adding those as accessible to the User class doesn't fix it, and sadly the error page doesn't tell me which model it was trying to assign it to.
Hello.
I get recommendable working perfectly local, but when i try it on heroku, i can like and dislike objects fine, but the recommended method returns me an empty array.
Do i need some special configuration for make it work on heroku?
I'm using Redis to Go Mini that is persistent.
Any thing else?
Thanks in advance!
After sucessfully doing device.like feed for several devices,
I tried to update the recommendations. I tried sending the command to the 'user' model (in my case, device), and it gave the following error
Device.first.send :update_recommendations
Device Load (2.6ms) SELECT "devices".* FROM "devices" LIMIT 1
Feed Load (80.8ms) SELECT "feeds".* FROM "feeds" WHERE ("feeds"."id" >= 0) ORDER BY "feeds"."id" ASC LIMIT 1000
(3.7ms) SELECT 1 FROM "recommendable_likes" WHERE "recommendable_likes"."user_id" = 31 AND "recommendable_likes"."likeable_id" = 13457 AND "recommendable_likes"."likeable_type" = 'Feed' LIMIT 1
(3.9ms) SELECT 1 FROM "recommendable_dislikes" WHERE "recommendable_dislikes"."user_id" = 31 AND "recommendable_dislikes"."dislikeable_id" = 13457 AND "recommendable_dislikes"."dislikeable_type" = 'Feed' LIMIT 1
(4.3ms) SELECT COUNT(*) FROM "recommendable_likes" WHERE "recommendable_likes"."likeable_id" = 13457 AND "recommendable_likes"."likeable_type" = 'Feed'
(2.2ms) SELECT COUNT(*) FROM "recommendable_dislikes" WHERE "recommendable_dislikes"."dislikeable_id" = 13457 AND "recommendable_dislikes"."dislikeable_type" = 'Feed'
(2.5ms) SELECT 1 FROM "recommendable_likes" WHERE "recommendable_likes"."user_id" = 31 AND "recommendable_likes"."likeable_id" = 13458 AND "recommendable_likes"."likeable_type" = 'Feed' LIMIT 1
(2.5ms) SELECT 1 FROM "recommendable_dislikes" WHERE "recommendable_dislikes"."user_id" = 31 AND "recommendable_dislikes"."dislikeable_id" = 13458 AND "recommendable_dislikes"."dislikeable_type" = 'Feed' LIMIT 1
(3.1ms) SELECT COUNT(*) FROM "recommendable_likes" WHERE "recommendable_likes"."likeable_id" = 13458 AND "recommendable_likes"."likeable_type" = 'Feed'
(3.1ms) SELECT COUNT(*) FROM "recommendable_dislikes" WHERE "recommendable_dislikes"."dislikeable_id" = 13458 AND "recommendable_dislikes"."dislikeable_type" = 'Feed'
(3.6ms) SELECT 1 FROM "recommendable_ignores" WHERE "recommendable_ignores"."user_id" = 31 AND "recommendable_ignores"."ignoreable_id" = 13458 AND "recommendable_ignores"."ignoreable_type" = 'Feed' LIMIT 1
(3.7ms) SELECT 1 FROM "recommendable_stashed_items" WHERE "recommendable_stashed_items"."user_id" = 31 AND "recommendable_stashed_items"."stashable_id" = 13458 AND "recommendable_stashed_items"."stashable_type" = 'Feed' LIMIT 1
NameError: uninitialized constant Feed::
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/base.rb:1341:in `compute_type'
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/reflection.rb:173:in `klass'
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/associations/association.rb:118:in `klass'
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/associations/association.rb:166:in `find_target?'
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/associations/collection_association.rb:327:in `load_target'
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/associations/collection_proxy.rb:51:in `load_target'
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/associations/collection_proxy.rb:89:in `method_missing'
from /app/vendor/bundle/ruby/1.9.1/bundler/gems/recommendable-92dcb32f95d0/lib/recommendable/acts_as_recommendable.rb:81:in `create_liked_by_set'
from /app/vendor/bundle/ruby/1.9.1/bundler/gems/recommendable-92dcb32f95d0/lib/recommendable/acts_as_recommendable.rb:40:in `create_recommendable_sets'
from /app/vendor/bundle/ruby/1.9.1/bundler/gems/recommendable-92dcb32f95d0/lib/recommendable/acts_as_recommended_to.rb:604:in `predict'
from /app/vendor/bundle/ruby/1.9.1/bundler/gems/recommendable-92dcb32f95d0/lib/recommendable/acts_as_recommended_to.rb:588:in `block in update_recommendations_for'
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/relation/batches.rb:21:in `block (2 levels) in find_each'
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/relation/batches.rb:21:in `each'
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/relation/batches.rb:21:in `block in find_each'
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/relation/batches.rb:69:in `find_in_batches'
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/relation/batches.rb:20:in `find_each'
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.1.3/lib/active_record/base.rb:443:in `find_each'
from /app/vendor/bundle/ruby/1.9.1/bundler/gems/recommendable-92dcb32f95d0/lib/recommendable/acts_as_recommended_to.rb:586:in `update_recommendations_for'
from /app/vendor/bundle/ruby/1.9.1/bundler/gems/recommendable-92dcb32f95d0/lib/recommendable/acts_as_recommended_to.rb:577:in `block in update_recommendations'
from /app/vendor/bundle/ruby/1.9.1/bundler/gems/recommendable-92dcb32f95d0/lib/recommendable/acts_as_recommended_to.rb:577:in `each'
from /app/vendor/bundle/ruby/1.9.1/bundler/gems/recommendable-92dcb32f95d0/lib/recommendable/acts_as_recommended_to.rb:577:in `update_recommendations'
from (irb):4
from /app/vendor/bundle/ruby/1.9.1/gems/railties-3.1.3/lib/rails/commands/console.rb:45:in `start'
from /app/vendor/bundle/ruby/1.9.1/gems/railties-3.1.3/lib/rails/commands/console.rb:8:in `start'
from /app/vendor/bundle/ruby/1.9.1/gems/railties-3.1.3/lib/rails/commands.rb:40:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
It would be nice to be able to select the desired features by setting the respective config options in initializer. For example, if I don't wish to use Ignores, I could just set it to false
and avoid the overhead of having another table and extra queries when doing Like/Dislike.
Look into supporting other ORMs. If it's easy enough, I'll do this myself. Anybody can feel free to submit a pull request to add support for their preferred ORM (mongoid, mongomapper, datamapper, etc.)
Whenever I call, current_user.recommendations, I always receive a blank list.
The likes and dislikes worked perfectly with my user model in the console, however I'm not able to generate recommendations. I opened reque-web
and the stats page seems to indicate that the jobs have not failed.
I just tested it with two users each liking one overlapping recipe. The first user's recommendations fail with the error below and the similar raters list is empty. The second user's similar raters does work correctly, but the recommendations still produce this zunionstore
error. Any advice?
1.9.3-p0 :002 > user.recommendations
(0.1ms) SELECT COUNT(*) FROM "likes" WHERE "likes"."user_id" = 1
(0.1ms) SELECT COUNT(*) FROM "dislikes" WHERE "dislikes"."user_id" = 1
RuntimeError: ERR wrong number of arguments for 'zunionstore' command
from /Users/neil/.rvm/gems/ruby-1.9.3-p0/gems/redis-2.2.2/lib/redis/client.rb:47:in `call'
from /Users/neil/.rvm/gems/ruby-1.9.3-p0/gems/redis-2.2.2/lib/redis.rb:660:in `block in zunionstore'
from /Users/neil/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/monitor.rb:211:in `mon_synchronize'
from /Users/neil/.rvm/gems/ruby-1.9.3-p0/gems/redis-2.2.2/lib/redis.rb:659:in `zunionstore'
from /Users/neil/.rvm/gems/ruby-1.9.3-p0/gems/recommendable-0.1.3/lib/recommendable/acts_as_recommended_to.rb:351:in `recommendations'
from (irb):2
from /Users/neil/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.2.1/lib/rails/commands/console.rb:47:in `start'
from /Users/neil/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.2.1/lib/rails/commands/console.rb:8:in `start'
from /Users/neil/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.2.1/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
1.9.3-p0 :003 > user.similar_raters
User Load (0.2ms) SELECT "users".* FROM "users" WHERE (ID IN (NULL))
[]
The project is already awesome but I'm using it on a projet where it's required to leave a comment with the like or dislike.
I'm wondering if it should be handled inside recommendable.
Not sure about that, I wonder what you think.
When attempting to push an app to heroku.
$ heroku rake db:migrate
rake aborted!
Illegal name for migration file: /app/db/migrate/20120213063406_create_stashed_items.recommendable.rb
(only lower case letters, numbers, and '_' allowed)
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
It looks like it doesn't like the period after items.
May want to correct with an underscore?
Hi, I've been working on my summer project for a few weeks now and everything is going smoothly. Unfortunately for me the Recommendable gem is acting a bit weird. I am able to like and dislike certain instances of my model, but I can't get recommendations for my users.
Here are my console results:
irb(main):034:0> Resque.size(:recommendable)
=> 3
Recommendable.redis.zcard "User:1:similarities"
=> 2
Recommendable.redis.zcard "User:2:similarities"
=> 2
So far I have only two users registered for testing, therefore these results. Although everything is working regarding Resque and Recommendable, in the console when I look for recommendation for a given user this is what I get after running the following command:
User.find_each { |u| u.send :update_similarities; u.send :update_recommendations }
irb(main):038:0> x.recommendations
(0.2ms) SELECT COUNT(*) FROM "recommendable_likes" WHERE "recommendable_likes"."user_id" = 1
(0.1ms) SELECT COUNT(*) FROM "recommendable_dislikes" WHERE "recommendable_dislikes"."user_id" = 1
=> []
Why can this be happening? Any ideas? I found this article #7 and I tried to do as blackgold9 but I can't find the act_as_recommendable file in my project. Can that be a problem? Thank you in advance.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.