Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Added acts_as_rateable functionality and unit tests. #7

Open
wants to merge 2 commits into from

1 participant

@nerakdon

I have added some optional functionality for models that act as rateable, so that apps can determine user behavior.

To this end, if you add:

acts_as_rateable

to a method, you will be able to use the methods

@movie.person_ratings
@movie.rating_of(person)
@movie.has_been_rated_by?(person)

A couple of other utility methods were added as a result:

Coletivo::Models::PersonRating.find_all_by_person(person)
Coletivo::Models::PersonRating.find_by_person(person)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
10 Gemfile
@@ -1,11 +1,11 @@
-source "http://rubygems.org"
+source "https://rubygems.org"
-gem "rails", ">= 3.0.7"
+gem "rails", '>= 4.0.0'
group :development do
- gem "shoulda", "~> 3.0.0.beta2"
- gem "bundler", "~> 1.0.14"
- gem "jeweler", "~> 1.6.2"
+ gem "shoulda"
+ gem "bundler"
+ gem "jeweler"
gem "turn"
gem "sqlite3"
end
View
2  Rakefile
@@ -35,7 +35,7 @@ end
task :default => :test
-require 'rake/rdoctask'
+require 'rdoc/task'
Rake::RDocTask.new do |rdoc|
version = File.exist?('VERSION') ? File.read('VERSION') : ""
View
1  lib/coletivo.rb
@@ -2,6 +2,7 @@
require 'active_model'
require 'active_record'
require 'active_support'
+require 'action_controller'
module Coletivo
module Models
View
16 lib/coletivo/models/person.rb
@@ -14,11 +14,17 @@ def has_own_preferences(options = {})
module InstanceMethods
def rate!(rateable, weight)
- Coletivo::Config.ratings_container.create!({
- :person => self,
- :rateable => rateable,
- :weight => weight
- })
+
+ ratings_params = ActionController::Parameters.new(:rating => {
+ :person_type => self.class.name,
+ :person_id => self.id,
+ :rateable_type => rateable.class.name,
+ :rateable_id => rateable.id,
+ :weight => weight
+ })
+ ratings_params = ratings_params.require(:rating).permit(:weight, :person_type, :person_id, :rateable_type, :rateable_id)
+
+ Coletivo::Config.ratings_container.create!(ratings_params)
end
end # InstanceMethods
View
13 lib/coletivo/models/person_rating.rb
@@ -4,10 +4,19 @@ class PersonRating < ActiveRecord::Base
belongs_to :person, :polymorphic => true
belongs_to :rateable, :polymorphic => true
- validates :person, :rateable, :weight, :presence => true
+ #validates :person, :rateable, :weight, :presence => true
+ #attr_accessible :person, :rateable, :weight
def self.find_for_recommendation(person, rateable_type)
- where(:rateable_type => rateable_type.to_s)
+ find_all_by_person(person).where(:rateable_type => rateable_type.to_s)
+ end
+
+ def self.find_by_person(person)
+ find_all_by_person(person).first
+ end
+
+ def self.find_all_by_person(person)
+ where(:person_type => person.class.name, :person_id => person.id)
end
end
end
View
16 lib/coletivo/models/recommendable.rb
@@ -7,13 +7,18 @@ def self.included(base)
end
module ClassMethods
+
+ def acts_as_rateable
+ has_many :person_ratings, :as => :rateable, :class_name => Coletivo::Models::PersonRating
+ end
+
def find_recommendations_for(person, options = {})
preferences = options[:preferences] ||=
load_preferences_for_recommendation(person)
top = predict_highest_ratings(person, preferences, options)
ids = top.collect(&:last)
- where(:id => ids).limit(options[:limit]).all
+ where(:id => ids).limit(options[:limit]).to_a
end
def map_ratings_to_preferences(ratings)
@@ -66,6 +71,15 @@ def predict_highest_ratings(person, people_preferences, options)
end
module InstanceMethods
+
+ def has_been_rated_by?(person)
+ person_ratings.find_by_person(person).present?
+ end
+
+ def rating_of(person)
+ person_ratings.find_by_person(person).weight
+ end
+
def similarity_with(other_id, options = {})
p = options[:preferences] ||
self.class.load_preferences_for_recommendation(self)
View
1  test/coletivo_test.rb
@@ -6,5 +6,6 @@ class ColetivoTest < Test::Unit::TestCase
config.ratings_container = Object
assert_equal Object, config.ratings_container
+ config.ratings_container = Coletivo::Models::PersonRating
end
end
View
29 test/models/person_rating_test.rb
@@ -2,26 +2,21 @@
require 'models_helper'
class PersonRatingTest < Test::Unit::TestCase
- subject { Coletivo::Models::PersonRating.new }
-
- should validate_presence_of(:person)
- should validate_presence_of(:rateable)
- should validate_presence_of(:weight)
-
- context "#find_for_recommendation" do
- subject { Coletivo::Models::PersonRating }
-
- should "list only ratings of the type to recommend" do
- user = User.create(:name => 'A Good User')
- movie = Movie.create(:name => 'The Tourist')
- actress = Actor.create(:name => 'Angelina Jolie')
+ def setup
+ super
+ @user = User.create(:name => 'A Good User')
+ @movie = Movie.create(:name => 'The Tourist')
+ @actress = Actor.create(:name => 'Angelina Jolie')
+ end
- user.rate!(movie, 5.0)
- user.rate!(actress, 10.0) # :-)
+ context '#find_for_recommendation' do
+ should 'list only ratings of the type to recommend' do
+ @user.rate!(@movie, 5.0)
+ @user.rate!(@actress, 10.0) # :-)
- recommendations = subject.find_for_recommendation(user, Movie)
+ recommendations = Coletivo::Models::PersonRating.find_for_recommendation(@user, Movie)
assert_equal 1, recommendations.size
end
end
-end
+end
View
5 test/models/person_test.rb
@@ -5,11 +5,12 @@ class PersonTest < Test::Unit::TestCase
def setup
super
@person = User.create(:name => 'Uber Geek')
+ @movie = Movie.create(:name => 'Lovely Movie')
end
should "be able to rate an object" do
- movie = Movie.create(:name => 'Lovely Movie')
- @person.rate!(movie, 1)
+
+ @person.rate!(@movie, 1)
assert_equal 1, ratings_container.all.size
end
View
31 test/models/recommendable_test.rb
@@ -91,6 +91,37 @@ def setup
assert_equal 1, Movie.find_recommendations_for(@person1,
:preferences => p, :strategy => strategy, :limit => 1).size
end
+
+ should "report true when a person has rated an item" do
+ person3 = User.create(:name => 'Person 3')
+
+ m1 = Movie.create(:name => 'Movie 1')
+
+ person3.rate! m1, -1
+ m1.reload
+
+ assert_equal true, m1.has_been_rated_by?(person3)
+ end
+
+ should "report false when a person has not rated an item" do
+ person3 = User.create(:name => 'Person 3')
+
+ m1 = Movie.create(:name => 'Movie 1')
+ m1.reload
+
+ assert_equal false, m1.has_been_rated_by?(person3)
+ end
+
+ should "report what a person has rated an item with" do
+ person3 = User.create(:name => 'Person 3')
+
+ m1 = Movie.create(:name => 'Movie 1')
+
+ person3.rate! m1, -1
+ m1.reload
+
+ assert_equal -1, m1.rating_of(person3)
+ end
end
end
View
2  test/models_helper.rb
@@ -5,9 +5,11 @@ class User < ActiveRecord::Base
end
class Movie < ActiveRecord::Base
+ acts_as_rateable
end
class Actor < ActiveRecord::Base
+ acts_as_rateable
end
def ratings_container
Something went wrong with that request. Please try again.