Skip to content

Commit

Permalink
Correct the generator
Browse files Browse the repository at this point in the history
  • Loading branch information
David Celis committed Jan 25, 2012
1 parent 0ebcd93 commit eea92c9
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 109 deletions.
8 changes: 8 additions & 0 deletions lib/generators/install/USAGE
@@ -0,0 +1,8 @@
Description:
Explain the generator

Example:
rails generate install Thing

This will create:
what/will/it/create
@@ -1,7 +1,7 @@
require 'rails/generators'
module Recommendable
module Generators
class InstallGenerator < Rails::Generators
class InstallGenerator < Rails::Generators::Base
class_option "no-migrate", :type => :boolean
class_option "user-class", :type => :string
class_option "redis-host", :type => :string
Expand All @@ -28,25 +28,25 @@ def run_migrations
end

def finished
puts "Done! Recommendable has been successfully installed."
puts "Done! Recommendable has been successfully installed. Please configure it in config/intializers/recommendable.rb"
end

private

def user_class
@user_class ||= "User"
@user_class.to_sym || :user
end

def redis_host
@redis_host ||= "127.0.0.1"
@redis_host || "127.0.0.1"
end

def redis_port
@redis_port ||= 6379
@redis_port || 6379
end

def redis_socket
@redis_socket
@redis_socket || "/tmp/redis.sock"
end
end
end
Expand Down
14 changes: 10 additions & 4 deletions lib/generators/install/templates/initializer.rb
@@ -1,4 +1,10 @@
Recommendable.user_class = <%= user_class %>
Recommendable.redis_host = <%= redis_host %>
Recommendable.redis_port = <%= redis_port %>
Recommendable.redis_socket = <%= redis_socket %>
# What class will be liking/disliking objects and receiving recommendations?
Recommendable.user_class = <%= user_class %>
# 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.
<% if redis_socket %>#<% end %>Recommendable.redis = Redis.new(:host => <%= redis_host %>, :port => <%= redis_port %>)

# Connect to Redis via a UNIX socket instead
<% unless redis_socket %>#<% end %> Recommendable.redis = Redis.new(:sock => <%= redis_socket %>)
16 changes: 3 additions & 13 deletions lib/recommendable.rb
Expand Up @@ -2,19 +2,9 @@
require "recommendable/rater"

module Recommendable
mattr_accessor :user_class, :redis, :redis_host, :redis_port, :redis_socket
mattr_accessor :user_class, :redis

class << self
def user_class
@@user_class.constantize
end

def redis
if @@redis_socket
@@redis ||= Redis.new(:path => @@redis_socket)
else
@@redis ||= Redis.new(@@redis_host, @@redis_port)
end
end
def self.user_class
@@user_class.to_s.camelize.constantize
end
end
172 changes: 86 additions & 86 deletions lib/recommendable/rater.rb
Expand Up @@ -75,92 +75,92 @@ def dislikes_for(klass)
end

module RecommendationMethods
def similarity_with(rater)
similarity = 0.0

return similarity if like_count + dislike_count == 0

agreements = common_likes_with(rater).size + common_dislikes(rater).size
disagreements = disagreements_with(rater).size
similarity = (agreements - disagreements).to_f / (like_count + dislike_count)

return similarity
end

def common_likes_with(rater)
Recommendable.redis.sinter "rater:#{id}:likes", "rater:#{rater.id}:likes"
end

def common_dislikes_with(rater)
Recommendable.redis.sinter "rater:#{id}:dislikes", "rater:#{rater.id}:dislikes"
end

def disagreements_with(rater)
Recommendable.redis.sinter("rater:#{id}:likes", "rater:#{rater.id}:dislikes") +
Recommendable.redis.sinter("rater:#{id}:dislikes", "rater:#{rater.id}:likes")
end

def similar_raters(options)
defaults = { :count => 10 }
options.merge! defaults

ids = Recommendable.redis.zrevrange "user_#{id}:similarities", 0, options[:count] - 1
class.find ids, order: "field(id, #{ids.join(',')})"
end


def update_similarities
self.class.find_each do |rater|
next if self == rater

similarity = similarity_with(rater)
Recommendable.redis.zadd "rater:#{id}:similarities", similarity, rater.id
Recommendable.redis.zadd "rater:#{rater.id}:similarities", similarity, id
end
end

def update_predictions_for(klass)
klass.find_each do |item|
unless has_liked?(item) || has_disliked?(item)
prediction = predict(item)
Recommendable.redis.zadd "rater:#{id}:predictions", prediction, item.id if prediction
end
end
end

def recommend_for(klass)
predictions = []
return predictions if like_count + dislike_count == 0
return predictions if Recommendable.redis.zcard("rater:#{id}:predictions") == 0
i = options[:offset]

until predictions.size == count
item = klass.find Recommendable.redis.zrevrange("rater:#{id}:predictions", i, i).first
predictions << item unless has_rated?(item) || has_hidden?(beer)
i += 1
end

return predictions
end

def predict(item)
sum = 0.0
prediction = 0.0

Recommendable.redis.smembers("rateable:#{item.id}:liked_by").inject(sum) {|r, sum| sum += Recommendable.redis.zscore("rater:#{id}:similarities", r)}
Recommendable.redis.smembers("rateable:#{item.id}:disliked_by").inject(sum) {|r, sum| sum -= Recommendable.redis.zscore("rater:#{id}:similarities", r)}

rated_by = Recommendable.redis.scard("rateable:#{item.id}:liked_by") + Recommendable.redis.scard("rateable:#{item.id}:disliked_by")
prediction = similarity_sum / rated_by.to_f unless rated_by == 0
end

def probability_of_liking(item)
Recommendable.redis.zscore "rater:#{id}:predictions", item.id
end

def probability_of_disliking(item)
-probability_of_liking(item)
end
# def similarity_with(rater)
# similarity = 0.0
#
# return similarity if like_count + dislike_count == 0
#
# agreements = common_likes_with(rater).size + common_dislikes(rater).size
# disagreements = disagreements_with(rater).size
# similarity = (agreements - disagreements).to_f / (like_count + dislike_count)
#
# return similarity
# end
#
# def common_likes_with(rater)
# Recommendable.redis.sinter "rater:#{id}:likes", "rater:#{rater.id}:likes"
# end
#
# def common_dislikes_with(rater)
# Recommendable.redis.sinter "rater:#{id}:dislikes", "rater:#{rater.id}:dislikes"
# end
#
# def disagreements_with(rater)
# Recommendable.redis.sinter("rater:#{id}:likes", "rater:#{rater.id}:dislikes") +
# Recommendable.redis.sinter("rater:#{id}:dislikes", "rater:#{rater.id}:likes")
# end
#
# def similar_raters(options)
# defaults = { :count => 10 }
# options.merge! defaults
#
# ids = Recommendable.redis.zrevrange "user_#{id}:similarities", 0, options[:count] - 1
# class.find ids, order: "field(id, #{ids.join(',')})"
# end
#
#
# def update_similarities
# self.class.find_each do |rater|
# next if self == rater
#
# similarity = similarity_with(rater)
# Recommendable.redis.zadd "rater:#{id}:similarities", similarity, rater.id
# Recommendable.redis.zadd "rater:#{rater.id}:similarities", similarity, id
# end
# end
#
# def update_predictions_for(klass)
# klass.find_each do |item|
# unless has_liked?(item) || has_disliked?(item)
# prediction = predict(item)
# Recommendable.redis.zadd "rater:#{id}:predictions", prediction, item.id if prediction
# end
# end
# end
#
# def recommend_for(klass)
# predictions = []
# return predictions if like_count + dislike_count == 0
# return predictions if Recommendable.redis.zcard("rater:#{id}:predictions") == 0
# i = options[:offset]
#
# until predictions.size == count
# item = klass.find Recommendable.redis.zrevrange("rater:#{id}:predictions", i, i).first
# predictions << item unless has_rated?(item) || has_hidden?(beer)
# i += 1
# end
#
# return predictions
# end
#
# def predict(item)
# sum = 0.0
# prediction = 0.0
#
# Recommendable.redis.smembers("rateable:#{item.id}:liked_by").inject(sum) {|r, sum| sum += Recommendable.redis.zscore("rater:#{id}:similarities", r)}
# Recommendable.redis.smembers("rateable:#{item.id}:disliked_by").inject(sum) {|r, sum| sum -= Recommendable.redis.zscore("rater:#{id}:similarities", r)}
#
# rated_by = Recommendable.redis.scard("rateable:#{item.id}:liked_by") + Recommendable.redis.scard("rateable:#{item.id}:disliked_by")
# prediction = similarity_sum / rated_by.to_f unless rated_by == 0
# end
#
# def probability_of_liking(item)
# Recommendable.redis.zscore "rater:#{id}:predictions", item.id
# end
#
# def probability_of_disliking(item)
# -probability_of_liking(item)
# end
end
end
end

0 comments on commit eea92c9

Please sign in to comment.