acts_as_rateable 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ == 2.0 released 2009-7-22
2
+
3
+ * Refactored database structure for better performance: the average rating and ratings count are now pre-computed and updated when new ratings are recorded
4
+ * The API now requires consistently the user object instead of the user_id
5
+ * Added testing framework and unit tests
6
+ * Made available as ruby gem
7
+
8
+ == 1.0 released 2008
9
+
10
+ * The original acts_as_rateable plugin, first release by Ferenc Fekete
11
+
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 [name of plugin creator]
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.
@@ -0,0 +1,77 @@
1
+ = Acts As Rateble
2
+
3
+ Acts_as_rateable is a rails plugin providing a rating interface for ActiveRecord models.
4
+ It is released under the MIT license.
5
+ The original plugin is used on cotcot.hu for article rating, sponsored quizzes, etc.
6
+
7
+ = Features
8
+
9
+ * Rating scores are recorded by user
10
+ * Users can update previous ratings
11
+ * Uses a polymorphic association to your model, so no changes to your existing models in the database are required
12
+ * Stores computed score and number of ratings for efficient data access
13
+ * Possibility to change range of the ratings (1..5 is default)
14
+
15
+ = Installation
16
+
17
+ == Install as gem (recommended)
18
+
19
+ Install as a gem:
20
+
21
+ $ sudo gem install mreinsch-acts_as_rateable
22
+
23
+ Then add the gem dependency in your config:
24
+
25
+ # config/environment.rb
26
+ config.gem "mreinsch-acts_as_rateable", :source => "http://gems.github.com", :lib => "acts_as_rateable"
27
+
28
+ == Install as plugin
29
+
30
+ To install as a plugin, use:
31
+
32
+ $ ./script/plugin install git://github.com/mreinsch/acts_as_rateable.git
33
+
34
+ = Example Usage
35
+
36
+ Install the plugin into your vendor/plugins directory, insert 'acts_as_rateable' into your model, then restart your application.
37
+
38
+ class Post < ActiveRecord::Base
39
+ acts_as_rateable
40
+ end
41
+
42
+ Now your model is extended by the plugin, you can rate it (1-#) or calculate the average rating.
43
+
44
+ @post.rate_it(4, current_user)
45
+
46
+ @post.average_rating #=> 4.0
47
+ @post.average_rating_round #=> 4
48
+ @post.average_rating_percent #=> 80
49
+ @post.rated_by?(current_user) #=> true
50
+ @post.rating_by(current_user) #=> 4
51
+ @post.ratings_couunt #=> 1
52
+
53
+ Post.find_top_rated #=> top rated records
54
+
55
+ Optional you can specify the highest score using the :max_rating paramter as follows. The default for :max_rating is 5.
56
+
57
+ class Comment < ActiveRecord::Base
58
+ acts_as_rateable :max_rating => 10
59
+ end
60
+
61
+ See acts_as_rateable.rb for further details!
62
+
63
+ = Updating
64
+
65
+ == Updating from Ferenc Fekete's acts_as_rateable v1.0
66
+
67
+ 1. Remove the old plugin, and install this version.
68
+ 1. Check your code and make sure you pass the user object instead of the user ID for the rate_it, rated_by? and rating_by methods.
69
+ 1. Generate an update migration using: ./script/generate acts_as_rateable_update1
70
+ 1. Run your test cases
71
+
72
+
73
+ = Copyright
74
+
75
+ Copyright (c) 2007 Ferenc Fekete, http://xpnindustries.com , released under the MIT license
76
+
77
+ Copyright (c) 2009 mobalean LLC, http://www.mobalean.com
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the acts_as_ratable plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the acts_as_ratable plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'ActsAsRatable'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README.rdoc', 'CHANGELOG.rdoc')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
@@ -0,0 +1,7 @@
1
+ class ActsAsRateableMigrationGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'migration.rb', 'db/migrate', :migration_file_name => "acts_as_rateable_migration"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,24 @@
1
+ class ActsAsRateableMigration < ActiveRecord::Migration
2
+ def self.up
3
+ create_table "ratings" do |t|
4
+ t.references "rateable", :polymorphic => true, :nil => false
5
+ t.float "average_rating"
6
+ t.integer "ratings_count"
7
+ t.timestamps
8
+ end
9
+ add_index "ratings", ["rateable_id", "rateable_type"]
10
+
11
+ create_table "user_ratings" do |t|
12
+ t.references "rating", :nil => false
13
+ t.references "user", :nil => false
14
+ t.integer "score", :nil => false
15
+ t.timestamps
16
+ end
17
+ add_index "user_ratings", ["user_id", "rating_id"]
18
+ end
19
+
20
+ def self.down
21
+ drop_table "user_ratings"
22
+ drop_table "ratings"
23
+ end
24
+ end
@@ -0,0 +1,7 @@
1
+ class ActsAsRateableUpdate1Generator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'migration.rb', 'db/migrate', :migration_file_name => "acts_as_rateable_update1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,48 @@
1
+ class ActsAsRateableUpdate1 < ActiveRecord::Migration
2
+ def self.up
3
+ rename_table "rates", "old_rates"
4
+ rename_table "ratings", "old_ratings"
5
+
6
+ create_table "ratings" do |t|
7
+ t.references "rateable", :polymorphic => true, :nil => false
8
+ t.float "average_rating"
9
+ t.integer "ratings_count"
10
+ t.timestamps
11
+ end
12
+ add_index "ratings", ["rateable_id", "rateable_type"]
13
+
14
+ create_table "user_ratings" do |t|
15
+ t.references "rating", :nil => false
16
+ t.references "user", :nil => false
17
+ t.integer "score", :nil => false
18
+ t.timestamps
19
+ end
20
+ add_index "user_ratings", ["user_id", "rating_id"]
21
+
22
+ say_with_time "migrating exsting ratings" do
23
+ connection.transaction do
24
+ sql = "SELECT rateable_id, rateable_type, user_id, score, old_ratings.created_at, old_ratings.updated_at " +
25
+ "FROM old_ratings INNER JOIN old_rates ON old_ratings.rate_id = old_rates.id"
26
+ connection.select_all(sql).each do |row|
27
+ rating = Rating.find_or_create_by_rateable_id_and_rateable_type(
28
+ :rateable_id => row['rateable_id'],
29
+ :rateable_type => row['rateable_type'],
30
+ :created_at => row['created_at'])
31
+ rating.user_ratings.find_or_create_by_user_id(
32
+ :user_id => row['user_id'],
33
+ :score => row['score'],
34
+ :created_at => row['created_at'],
35
+ :updated_at => row['updated_at'])
36
+ end
37
+ Rating.find(:all).each {|rating| rating.update_rating }
38
+ end
39
+ end
40
+
41
+ drop_table "old_rates"
42
+ drop_table "old_ratings"
43
+ end
44
+
45
+ def self.down
46
+ raise ActiveRecord::IrreversibleMigration, "Can't recover old ratings tables"
47
+ end
48
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + "/rails/init.rb"
@@ -0,0 +1,80 @@
1
+ module ActiveRecord
2
+ module Acts
3
+ module Rateable
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def acts_as_rateable(options = {})
10
+ has_one :rating, :as => :rateable, :dependent => :destroy
11
+
12
+ unless respond_to?(:max_rating)
13
+ class_inheritable_accessor :max_rating
14
+ attr_protected :max_rating
15
+ self.max_rating = options[:max_rating] || 5
16
+ end
17
+
18
+ include ActiveRecord::Acts::Rateable::ClassMethods
19
+ include ActiveRecord::Acts::Rateable::InstanceMethods
20
+ end
21
+ end
22
+
23
+ module ClassMethods
24
+ # Returns the top rated records, ordered by their average rating.
25
+ # You can use the usual finder parameters to narrow down the records
26
+ # to return.
27
+ # The finder limits the number of returned records to 20 by default.
28
+ # Specify :limit to change it.
29
+ def find_top_rated(params = {})
30
+ find_params = params.merge(:include => :rating)
31
+ find_params[:order] = ['ratings.average_rating DESC', find_params.delete(:order)].compact.join(", ")
32
+ find_params[:limit] = 20 unless find_params.key?(:limit)
33
+ find(:all, find_params)
34
+ end
35
+ end
36
+
37
+ module InstanceMethods
38
+ # Rates the object by a given score. A user object should be passed to the method.
39
+ def rate_it(score, user)
40
+ create_rating unless rating
41
+ rating.rate(score, user)
42
+ end
43
+
44
+ # Returns the average rating. Calculation based on the already given scores.
45
+ def average_rating
46
+ rating && rating.average_rating || 0.0
47
+ end
48
+
49
+ # Rounds the average rating value.
50
+ def average_rating_round
51
+ average_rating.round
52
+ end
53
+
54
+ # Returns the average rating in percent.
55
+ def average_rating_percent
56
+ f = 100 / max_rating.to_f
57
+ average_rating * f
58
+ end
59
+
60
+ # Returns the number of ratings.
61
+ def ratings_count
62
+ rating && rating.ratings_count || 0
63
+ end
64
+
65
+ # Checks whether a user rated the object or not.
66
+ def rated_by?(user)
67
+ rating && rating.user_ratings.exists?(:user_id => user)
68
+ end
69
+
70
+ # Returns the rating a specific user has given the object.
71
+ def rating_by(user)
72
+ user_rating = rating && rating.user_ratings.find_by_user_id(user.id)
73
+ user_rating ? user_rating.score : nil
74
+ end
75
+
76
+ end
77
+
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,21 @@
1
+ class Rating < ActiveRecord::Base
2
+ belongs_to :rateable, :polymorphic => true
3
+ has_many :user_ratings
4
+
5
+ delegate :max_rating, :to => :rateable
6
+
7
+ def rate(score, user)
8
+ user_ratings.find_or_initialize_by_user_id(user.id).update_attributes!(:score => score)
9
+ reload
10
+ end
11
+
12
+ # Call this method the update the avarage rating; you don't normally need to
13
+ # do this manually, saving or updating a user rating already takes care of
14
+ # updating the avarage rating.
15
+ def update_rating
16
+ self.average_rating = user_ratings.average(:score)
17
+ self.ratings_count = user_ratings.count
18
+ save!
19
+ end
20
+
21
+ end
@@ -0,0 +1,24 @@
1
+ class UserRating < ActiveRecord::Base
2
+ belongs_to :rating
3
+
4
+ delegate :max_rating, :to => :rating
5
+
6
+ validates_presence_of :score
7
+ validates_uniqueness_of :user_id, :scope => :rating_id
8
+ validate :max_rating_allowed_by_parent
9
+
10
+ after_save do |user_rating|
11
+ user_rating.rating.update_rating
12
+ end
13
+
14
+ private
15
+
16
+ def max_rating_allowed_by_parent
17
+ if score < 1
18
+ errors.add(:score, "must be greater than or equal to 1")
19
+ elsif score > max_rating
20
+ errors.add(:score, "must be less than or equal to #{max_rating}")
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,2 @@
1
+ require 'acts_as_rateable'
2
+ ActiveRecord::Base.send(:include, ActiveRecord::Acts::Rateable)
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_rateable
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ferenc Fekete
8
+ - Gabriel Gironda
9
+ - Michael Reinsch
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+
14
+ date: 2009-09-23 00:00:00 +02:00
15
+ default_executable:
16
+ dependencies: []
17
+
18
+ description: Acts_as_rateable is a rails plugin providing a rating interface for ActiveRecord models.
19
+ email: michael@mobalean.com
20
+ executables: []
21
+
22
+ extensions: []
23
+
24
+ extra_rdoc_files:
25
+ - README.rdoc
26
+ - CHANGELOG.rdoc
27
+ - MIT-LICENSE
28
+ files:
29
+ - README.rdoc
30
+ - CHANGELOG.rdoc
31
+ - MIT-LICENSE
32
+ - Rakefile
33
+ - init.rb
34
+ - rails/init.rb
35
+ - lib/rating.rb
36
+ - lib/user_rating.rb
37
+ - lib/acts_as_rateable.rb
38
+ - generators/acts_as_rateable_update1/templates/migration.rb
39
+ - generators/acts_as_rateable_update1/acts_as_rateable_update1_generator.rb
40
+ - generators/acts_as_rateable_migration/templates/migration.rb
41
+ - generators/acts_as_rateable_migration/acts_as_rateable_migration_generator.rb
42
+ has_rdoc: true
43
+ homepage: http://github.com/mreinsch/acts_as_rateable
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --main
49
+ - README.rdoc
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.3.5
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Rails plugin providing a rating interface for ActiveRecord models
71
+ test_files: []
72
+