acts_as_mongo_rateable 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 [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.
data/Manifest ADDED
@@ -0,0 +1,13 @@
1
+ MIT-LICENSE
2
+ README.markdown
3
+ Rakefile
4
+ install.rb
5
+ lib/acts_as_mongo_rateable/acts_as_mongo_rateable.rb
6
+ lib/acts_as_mongo_rateable/app/models/rating.rb
7
+ lib/mongo_rateable.rb
8
+ rails/init.rb
9
+ tasks/mongo_rateable_tasks.rake
10
+ test/mongo_rateable_test.rb
11
+ test/test_helper.rb
12
+ uninstall.rb
13
+ Manifest
data/README.markdown ADDED
@@ -0,0 +1,88 @@
1
+ ActsAsMongoRateable (with weights!)
2
+ ===================================
3
+
4
+ Inspired by the old Rails+AR standby "acts_as_rateable," this rating plugin works with MongoDB+MongoMapper
5
+ and has weighted ratings, as well as bayesian and straight averages, and some friendly class-level helpers.
6
+
7
+ Intends to be super-performant by taking advantage of the benefits of document-driven db denormalization.
8
+
9
+ Requirements
10
+ ------------
11
+
12
+ - MongoDB
13
+ - MongoMapper gem
14
+ - Expects you to have a User model that includes MongoMapper::Document
15
+
16
+ Installation
17
+ ------------
18
+
19
+ Install the plugin:
20
+
21
+ ./script/plugin install git://github.com/mepatterson/acts_as_mongo_rateable.git
22
+
23
+ Add the following 2 lines to the Model class that you want to make rateable:
24
+
25
+ include ActsAsMongoRateable
26
+ RATING_RANGE = (1..5)
27
+
28
+ Obviously, change the rating range if you want to rate on a 10-star system or a 14-star or whatever.
29
+
30
+ Usage
31
+ -----
32
+
33
+ class User
34
+ include MongoMapper::Document
35
+ end
36
+
37
+ class Widget
38
+ include ActsAsMongoRateable
39
+ RATING_RANGE = (1..5)
40
+ include MongoMapper::Document
41
+ end
42
+
43
+ widget = Widget.first
44
+
45
+ To rate it:
46
+
47
+ widget.rate(score, user, weight)
48
+
49
+ - score must be an Integer within your RATING_RANGE
50
+ - user is the User who is rating this widget
51
+ - weight is optional; defaults to 1)
52
+
53
+ Now try all these fun methods:
54
+
55
+ widget.average_rating
56
+
57
+ widget.bayesian_rating
58
+
59
+ widget.rating_stats
60
+
61
+ And some useful class methods:
62
+
63
+ Widget.highest_rated(how_many)
64
+
65
+ Widget.most_rated(how_many)
66
+
67
+ Widget.most_rated_by_authorities(how_many)
68
+
69
+ Widget.highest_bayesian_rated(how_many)
70
+
71
+ ('how_many' is a limit and is optional. i.e. Do you want a highest_rated list of 5, 10, 15 widgets?
72
+ Defaults to just 1 if you don't pass any argument.)
73
+
74
+ Future
75
+ ------
76
+ - Tests (I have tests in the project I cut this from, but they need to be extracted out and I'm lazy)
77
+ - More helper methods
78
+ - Performance improvements as I come across the need
79
+ - Investigate using map/reduce to improve the efficiency of the bayesian calc (?)
80
+
81
+ Thanks To...
82
+ ------------
83
+ - John Nunemaker and the rest of the folks on the MongoMapper Google Group
84
+ - The MongoDB peoples and the MongoDB Google Group
85
+ - juixe for the original acts_as_rateable plugin for ActiveRecord
86
+ - sunlightlabs 'datacatalog-api', from which I borrowed the ratings_stats hash methodology
87
+
88
+ Copyright (c) 2009 [M. E. Patterson], released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+ require 'rake/testtask'
5
+ require 'rake/rdoctask'
6
+
7
+ desc 'Default: run unit tests.'
8
+ task :default => :test
9
+
10
+ desc 'Test the mongo_rateable plugin.'
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs << 'lib'
13
+ t.libs << 'test'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = true
16
+ end
17
+
18
+ desc 'Generate documentation for the mongo_rateable plugin.'
19
+ Rake::RDocTask.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'MongoRateable'
22
+ rdoc.options << '--line-numbers' << '--inline-source'
23
+ rdoc.rdoc_files.include('README')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
26
+
27
+
28
+ Echoe.new('acts_as_mongo_rateable', '0.2.0') do |p|
29
+ p.description = "A ratings system for Rails apps using MongoDB, with bayesian and straight averages, and weighting."
30
+ p.url = "http://github.com/mepatterson/acts_as_mongo_rateable"
31
+ p.author = "M. E. Patterson"
32
+ p.email = "madraziel @nospam@ gmail.com"
33
+ p.ignore_pattern = ["tmp/*", "script/*"]
34
+ p.development_dependencies = []
35
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{acts_as_mongo_rateable}
5
+ s.version = "0.2.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["M. E. Patterson"]
9
+ s.cert_chain = ["/Users/mattp/gem-public_cert.pem"]
10
+ s.date = %q{2010-06-04}
11
+ s.description = %q{A ratings system for Rails apps using MongoDB, with bayesian and straight averages, and weighting.}
12
+ s.email = %q{madraziel @nospam@ gmail.com}
13
+ s.extra_rdoc_files = ["README.markdown", "lib/acts_as_mongo_rateable/acts_as_mongo_rateable.rb", "lib/acts_as_mongo_rateable/app/models/rating.rb", "lib/mongo_rateable.rb", "tasks/mongo_rateable_tasks.rake"]
14
+ s.files = ["MIT-LICENSE", "README.markdown", "Rakefile", "install.rb", "lib/acts_as_mongo_rateable/acts_as_mongo_rateable.rb", "lib/acts_as_mongo_rateable/app/models/rating.rb", "lib/mongo_rateable.rb", "rails/init.rb", "tasks/mongo_rateable_tasks.rake", "test/mongo_rateable_test.rb", "test/test_helper.rb", "uninstall.rb", "Manifest", "acts_as_mongo_rateable.gemspec"]
15
+ s.homepage = %q{http://github.com/mepatterson/acts_as_mongo_rateable}
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Acts_as_mongo_rateable", "--main", "README.markdown"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{acts_as_mongo_rateable}
19
+ s.rubygems_version = %q{1.3.7}
20
+ s.signing_key = %q{/Users/mattp/gem-private_key.pem}
21
+ s.summary = %q{A ratings system for Rails apps using MongoDB, with bayesian and straight averages, and weighting.}
22
+ s.test_files = ["test/mongo_rateable_test.rb", "test/test_helper.rb"]
23
+
24
+ if s.respond_to? :specification_version then
25
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
+ s.specification_version = 3
27
+
28
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
29
+ else
30
+ end
31
+ else
32
+ end
33
+ end
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,109 @@
1
+ module ActsAsMongoRateable
2
+
3
+ module ClassMethods
4
+ def highest_rated(limit=1)
5
+ all({:order => "rating_stats.average DESC", :limit => limit})
6
+ end
7
+
8
+ def most_rated(limit=1)
9
+ all({:order => "rating_stats.count DESC", :limit => limit})
10
+ end
11
+
12
+ def most_rated_by_authorities(limit=1)
13
+ all({:order => "rating_stats.sum_of_weights DESC", :limit => limit})
14
+ end
15
+
16
+ # TO DO this is awful, awful, awful! make it faster using map/reduce
17
+ def highest_bayesian_rated(limit=1)
18
+ stats = all({:select => 'id, rating_stats'})
19
+ all.sort_by do |doc|
20
+ rating = doc.bayesian_rating(stats)
21
+ doc.rating_stats['bayesian_rating'] = rating
22
+ rating
23
+ end.reverse[0,limit]
24
+ end
25
+
26
+ end
27
+
28
+ module InstanceMethods
29
+
30
+ def delete_all_ratings
31
+ ratings.delete_all
32
+ end
33
+
34
+ def average_rating
35
+ rating_stats['average']
36
+ end
37
+
38
+ def bayesian_rating(stats=nil)
39
+ return 0 if rating_stats['count'] == 0
40
+ stats ||= self.class.all({:select => 'id, rating_stats'})
41
+ system_counts = stats.map{ |p| [ p.id.to_s, p.rating_stats['count'] ] }
42
+ avg_rating = stats.map{|p| p.rating_stats['average'] || 0 }.sum / stats.size.to_f
43
+ avg_num_votes = system_counts.inject(0){|sum, r| sum += r.to_a.flatten[1] } / system_counts.size.to_f
44
+ my_rating = rating_stats['average'] || 0
45
+ my_count = rating_stats['count']
46
+ ( (avg_num_votes * avg_rating) + (my_count * my_rating) ) / (avg_num_votes + my_count)
47
+ end
48
+
49
+ def delete_ratings_by_user(user)
50
+ return false unless user
51
+ return 0 if ratings.blank?
52
+ ratings.delete_all(:user_id => user.id.to_s)
53
+ self.reload
54
+ end
55
+
56
+ def rate(value, user = nil, weight = 1)
57
+ delete_ratings_by_user(user)
58
+ validate_rating!(value)
59
+ r = Rating.new({
60
+ :value => value,
61
+ :user_id => user.id,
62
+ :rateable_id => self.id,
63
+ :rateable_class => self.class.to_s,
64
+ :weight => weight
65
+ })
66
+ self.ratings << r
67
+ self.reload
68
+ r
69
+ end
70
+
71
+ # returns the Rating object found if user has rated this project, else returns nil
72
+ def rated_by_user?(user)
73
+ return false unless user
74
+ ratings.detect{ |r| r.user_id == user.id}
75
+ end
76
+
77
+ protected
78
+
79
+ def validate_rating!(value)
80
+ if (range = self.class::RATING_RANGE) and !range.include?(value.to_i)
81
+ raise ArgumentError, "Rating not in range #{range}. Rating provided was #{value}."
82
+ end
83
+ end
84
+
85
+ end
86
+
87
+ def self.included(receiver)
88
+ receiver.class_eval do
89
+ many :ratings, :foreign_key => 'rateable_id', :dependent => :destroy
90
+ key :rating_stats, Hash, :default => {
91
+ :total => 0,
92
+ :count => 0,
93
+ :sum_of_weights => 0,
94
+ :average => nil
95
+ }
96
+ end
97
+ receiver.extend ClassMethods
98
+ receiver.send :include, InstanceMethods
99
+ end
100
+
101
+
102
+ end
103
+
104
+ %w{ models observers }.each do |dir|
105
+ path = File.join(File.dirname(__FILE__), 'app', dir)
106
+ $LOAD_PATH << path
107
+ ActiveSupport::Dependencies.load_paths << path
108
+ ActiveSupport::Dependencies.load_once_paths.delete(path)
109
+ end
@@ -0,0 +1,72 @@
1
+ class Rating
2
+ include MongoMapper::Document
3
+
4
+ key :user_id, ObjectId, :required => true
5
+ key :rateable_id, ObjectId, :required => true
6
+ key :rateable_class, String, :required => true
7
+ key :value, Integer, :required => true
8
+ key :previous_value, Integer, :default => 0
9
+ key :weight, Integer, :default => 1
10
+ timestamps!
11
+
12
+ ensure_index :user_id
13
+ ensure_index :rateable_id
14
+ ensure_index :rateable_class
15
+ ensure_index :created_at
16
+
17
+ belongs_to :user
18
+
19
+ after_create :set_rating_stats
20
+ after_update :update_rating_stats
21
+ before_update :set_previous_value
22
+ after_destroy :reduce_rating_stats
23
+
24
+ def set_rating_stats
25
+ doc = find_rated_document!
26
+ count = (doc.rating_stats[:count] += 1)
27
+ total = (doc.rating_stats[:total] += ( value * weight ))
28
+ sow = (doc.rating_stats[:sum_of_weights] += weight)
29
+ doc.rating_stats[:average] = total.to_f / sow
30
+ doc.save!
31
+ end
32
+
33
+ def set_previous_value
34
+ rating_from_db = Rating.find_by_id(id)
35
+ previous_value = (rating_from_db.value * weight) if rating_from_db
36
+ end
37
+
38
+ def update_rating_stats
39
+ doc = find_rated_document!
40
+ value_delta = (value * weight) - (previous_value * weight)
41
+ total = (doc.rating_stats[:total] += value_delta)
42
+ count = doc.rating_stats[:count]
43
+ doc.rating_stats[:average] = total.to_f / count
44
+ doc.save
45
+ end
46
+
47
+ def reduce_rating_stats
48
+ doc = find_rated_document
49
+ return if doc.nil?
50
+ count = (doc.rating_stats[:count] -= 1)
51
+ doc.rating_stats[:total] -= (value * weight)
52
+ doc.rating_stats[:sum_of_weights] -= weight
53
+ doc.rating_stats[:average] = nil if count == 0
54
+ doc.save
55
+ end
56
+
57
+
58
+ # == Various Instance Methods
59
+ def find_rated_document
60
+ klass = rateable_class.constantize
61
+ klass.find(rateable_id.to_s)
62
+ end
63
+
64
+ def find_rated_document!
65
+ doc = find_rated_document
66
+ raise "Associated document not found" if doc.nil?
67
+ doc
68
+ end
69
+
70
+ end
71
+
72
+
@@ -0,0 +1 @@
1
+ require 'acts_as_mongo_rateable/acts_as_mongo_rateable'
data/rails/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + '/../lib/mongo_rateable.rb'
2
+
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :mongo_rateable do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,171 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class MongoRateableTest < ActiveSupport::TestCase
4
+
5
+ def create_user(name)
6
+ u = User.create({:name => name})
7
+ puts u.errors unless u.valid?
8
+ u
9
+ end
10
+
11
+ def load_multiple_raters
12
+ @m_rater_1 = create_user "m_rater_1"
13
+ @m_rater_2 = create_user "m_rater_2"
14
+ @m_rater_3 = create_user "m_rater_3"
15
+ [@m_rater_1, @m_rater_2, @m_rater_3]
16
+ end
17
+
18
+ def load_multiple_widgets
19
+ @widget = @owner.widgets.create({:name => "Test Widget"})
20
+ @widget_2 = @owner.widgets.create({:name => "Test Widget 2"})
21
+ @widget_3 = @owner.widgets.create({:name => "Test Widget 3"})
22
+ [@widget, @widget_2, @widget_3]
23
+ end
24
+
25
+ def load_multiple_dongles
26
+ @dongle = @owner.dongles.create({:name => "Test dongle"})
27
+ @dongle_2 = @owner.dongles.create({:name => "Test dongle 2"})
28
+ @dongle_3 = @owner.dongles.create({:name => "Test dongle 3"})
29
+ [@dongle, @dongle_2, @dongle_3]
30
+ end
31
+
32
+ def rate_this_many_times(obj, count, authority=1)
33
+ x = 0
34
+ count.times do
35
+ x += 1
36
+ rater = create_user "fake_rater_#{x}"
37
+ obj.rate(4, rater, authority)
38
+ end
39
+ end
40
+
41
+ def load_and_randomly_rate_multiple_widgets
42
+ raters = load_multiple_raters
43
+ widgets = load_multiple_widgets
44
+ widgets.each do |w|
45
+ raters.each {|r| w.rate(rand(5)+1, r, rand(3)+1) }
46
+ end
47
+ end
48
+
49
+ def load_and_randomly_rate_multiple_dongles
50
+ raters = load_multiple_raters
51
+ dongles = load_multiple_dongles
52
+ dongles.each do |d|
53
+ raters.each {|r| d.rate(rand(5)+1, r, rand(3)+1) }
54
+ end
55
+ end
56
+
57
+ def multi_rate(obj)
58
+ load_multiple_raters
59
+ obj.rate(4, @m_rater_1, 1)
60
+ obj.rate(2, @m_rater_2, 3)
61
+ obj.rate(5, @m_rater_3, 5)
62
+ end
63
+
64
+ def multi_rate_many_widgets
65
+ load_multiple_widgets
66
+ raters = load_multiple_raters
67
+ raters.each do |r|
68
+ @widget.rate(5, r, 2)
69
+ @widget_2.rate(1, r, 2)
70
+ @widget_3.rate(3, r, 2)
71
+ end
72
+ end
73
+
74
+ def setup
75
+ @owner = create_user 'owner'
76
+ @rater = create_user 'rater'
77
+ @widget = @owner.widgets.create({:name => "Test Widget"})
78
+ end
79
+
80
+ test "single rating on a widget produces the correct rating stats" do
81
+ @widget.rate(3, @rater, 2)
82
+ expected_stats = {"total" => 6, "count" => 1, "average" => 3.to_f, "sum_of_weights" => 2}
83
+ %w( total count average sum_of_weights).each do |method|
84
+ assert_equal expected_stats[method], @widget.rating_stats[method]
85
+ end
86
+ end
87
+
88
+ test "multiple ratings on a widget produce the correct rating stats" do
89
+ multi_rate(@widget)
90
+ expected_stats = {"total" => 35, "count" => 3, "average" => 3.88888888888889, "sum_of_weights" => 9}
91
+ %w( total count sum_of_weights).each do |method|
92
+ assert_equal expected_stats[method], @widget.rating_stats[method]
93
+ end
94
+ # doing average seperately, since we don't need to test the whole long float
95
+ assert_equal sprintf('%.2f',expected_stats['average']), sprintf('%.2f',@widget.rating_stats['average'])
96
+ end
97
+
98
+ test "deleting all ratings for a specific widget works" do
99
+ load_and_randomly_rate_multiple_widgets
100
+ assert_equal 3, @widget.ratings.count
101
+ assert_equal 9, Rating.count
102
+ @widget.delete_all_ratings
103
+ assert_equal 0, @widget.ratings.count
104
+ assert_equal 6, Rating.count
105
+ end
106
+
107
+ test "deleting all ratings for a particular object doesn't delete ratings for other object" do
108
+ load_and_randomly_rate_multiple_widgets
109
+ load_and_randomly_rate_multiple_dongles
110
+ assert_equal 18, Rating.count
111
+ @widget.delete_all_ratings
112
+ assert_equal 0, @widget.ratings.count
113
+ assert_equal 3, @dongle.ratings.count
114
+ end
115
+
116
+ test "rated_by_user? works" do
117
+ multi_rate(@widget)
118
+ assert @widget.rated_by_user?(@m_rater_1)
119
+ end
120
+
121
+ test "delete by user only deletes ratings by that user for that object" do
122
+ @dongle = @owner.dongles.create({:name => "Test dongle"})
123
+ multi_rate(@widget)
124
+ widget_rater = @m_rater_1
125
+ multi_rate(@dongle)
126
+ assert_equal 6, Rating.count
127
+ assert_equal 3, @widget.ratings.count
128
+ assert @widget.rated_by_user?(widget_rater)
129
+ @widget.delete_ratings_by_user(widget_rater)
130
+ assert ! @widget.rated_by_user?(widget_rater)
131
+ assert_equal 2, @widget.ratings.count
132
+ assert_equal 5, Rating.count
133
+ end
134
+
135
+ test "bayesian_rating returns correct number" do
136
+ multi_rate_many_widgets
137
+ assert_equal sprintf('%.2f',3.82), sprintf('%.2f',@widget.bayesian_rating)
138
+ assert_equal sprintf('%.2f',1.54), sprintf('%.2f',@widget_2.bayesian_rating)
139
+ assert_equal sprintf('%.2f',2.68), sprintf('%.2f',@widget_3.bayesian_rating)
140
+ end
141
+
142
+ test "bayesian_rating for one class of objects not corrupted by other ratings for other classes" do
143
+ multi_rate_many_widgets
144
+ load_and_randomly_rate_multiple_dongles
145
+ assert_equal sprintf('%.2f',3.82), sprintf('%.2f',@widget.bayesian_rating)
146
+ assert_equal sprintf('%.2f',1.54), sprintf('%.2f',@widget_2.bayesian_rating)
147
+ assert_equal sprintf('%.2f',2.68), sprintf('%.2f',@widget_3.bayesian_rating)
148
+ end
149
+
150
+ test "highest_rated returns correct widgets in order" do
151
+ multi_rate_many_widgets
152
+ assert_equal [@widget, @widget_3, @widget_2], Widget.highest_rated(3)
153
+ end
154
+
155
+ test "most_rated returns correct widgets in order" do
156
+ load_multiple_widgets
157
+ rate_this_many_times(@widget, 6)
158
+ rate_this_many_times(@widget_2, 1)
159
+ rate_this_many_times(@widget_3, 3)
160
+ assert_equal [@widget, @widget_3, @widget_2], Widget.most_rated(3)
161
+ end
162
+
163
+ test "most_rated_by_authorities returns correct widgets in order" do
164
+ load_multiple_widgets
165
+ rate_this_many_times(@widget, 6, 2)
166
+ rate_this_many_times(@widget_2, 1, 5)
167
+ rate_this_many_times(@widget_3, 3, 1)
168
+ assert_equal [@widget, @widget_2, @widget_3], Widget.most_rated_by_authorities(3)
169
+ end
170
+
171
+ end
@@ -0,0 +1,58 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_support/test_case'
4
+
5
+ ENV['RAILS_ENV'] = 'test'
6
+ ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '/../../../..'
7
+
8
+ require 'test/unit'
9
+ require File.expand_path(File.join(ENV['RAILS_ROOT'], 'config/environment.rb'))
10
+
11
+ class ActiveSupport::TestCase
12
+ # Drop all columns after each test case.
13
+ def teardown
14
+ MongoMapper.database.collections.each do |coll|
15
+ coll.drop
16
+ end
17
+ end
18
+
19
+ # Make sure that each test case has a teardown
20
+ # method to clear the db after each test.
21
+ def inherited(base)
22
+ base.define_method teardown do
23
+ super
24
+ end
25
+ end
26
+ end
27
+
28
+ # kinda weird, but we have to do this so we can ignore the app's User class and use our own for testing
29
+ Object.send(:remove_const, :User) if Object.const_defined?(:User)
30
+
31
+ class User
32
+ include MongoMapper::Document
33
+ key :name, String
34
+ has_many :widgets
35
+ has_many :dongles
36
+ end
37
+
38
+ class Widget
39
+ include MongoMapper::Document
40
+ include ActsAsMongoRateable
41
+ RATING_RANGE = (1..5)
42
+
43
+ belongs_to :user
44
+
45
+ key :user_id, ObjectId
46
+ key :name, String
47
+ end
48
+
49
+ class Dongle
50
+ include MongoMapper::Document
51
+ include ActsAsMongoRateable
52
+ RATING_RANGE = (1..5)
53
+
54
+ belongs_to :user
55
+
56
+ key :user_id, ObjectId
57
+ key :name, String
58
+ end
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
data.tar.gz.sig ADDED
@@ -0,0 +1,3 @@
1
+ �Zw{��x�s;�s�wVa�ƌPoP5T@��}R`wm_;P���z�����ْM������3��NU�EQhWN�t=�w��)�����b�
2
+
3
+ Q '������d�� �I �#�u����i*�I~d.�fDY�6�Q��S��u�� ])ȬV��^�R�rI��-�h�\G^������3�_@�� ����{��*�}~����Z�N��W�x�\�5�M����!
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_mongo_rateable
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
+ platform: ruby
12
+ authors:
13
+ - M. E. Patterson
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain:
17
+ - |
18
+ -----BEGIN CERTIFICATE-----
19
+ MIIDNDCCAhygAwIBAgIBADANBgkqhkiG9w0BAQUFADBAMRIwEAYDVQQDDAltYWRy
20
+ YXppZWwxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
21
+ bTAeFw0xMDA2MDUwNDUxMThaFw0xMTA2MDUwNDUxMThaMEAxEjAQBgNVBAMMCW1h
22
+ ZHJhemllbDEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYD
23
+ Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2YYU8nBcWrz3Gls3
24
+ B4tKCLGU/v11vuLeDU51r0/mUL/ev4GAZOrlBRaIn4U3J53W4Wa3fHGNqDyB7dt4
25
+ eJS2a//eBv5MXtDxS0kuOeLen4sJiACN7WzoX/WaMiCdeLFebRFr6zDKtYMQZ1lM
26
+ x+DWXbFLBuWfihZ8TapkBBG8Yuw2J+OcJla7t0IR3KHJSpOe0e9D/rHydly2v7kH
27
+ 6naqt5n4jtpTXrmgLeGUQeVR60BJrHIbHXjgUCkPz3b/prreaRl/a4Cufv0cTPMD
28
+ BFSOlmK6AKLii9gdaZMnLbF7b1Jc3rAcYNAsLHoUBGoq0Top8CTC732YrNZ7NmFp
29
+ /Jn0nQIDAQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU
30
+ drmilB9ksqsW9hFPopqQEhcFdh8wDQYJKoZIhvcNAQEFBQADggEBAHPZLmxi4DYD
31
+ qdSsUv4oTlWoK5nCbEpnJRpJZXn1rn30Zaoc5v7kQfVwz/x/4uZmLdvfysZmuvKZ
32
+ GTMlYv/qSylO0SqbZeKhvsehQ+ENQdTon10zPtVvvnxiUE/As79eRmmxNGypJnwy
33
+ WZH2x1I+Hd25mRbt1UspT2vmuEwTgzkmxGHnl7cmiO4BYXlzHHk8KRSEdIDZUm5T
34
+ B+pavzaE15aDJrbpy+/awgxQEZb7O/mgzkFoTKlgV4VyDWSDjtU+aEI1sJk0DiSs
35
+ Zm3n8B2/BZXgeEcymjLxZGMrvkax12f02NF2l+C8f0/DzS+jlVsewUzux0WmYCR5
36
+ 47YifzlLjIM=
37
+ -----END CERTIFICATE-----
38
+
39
+ date: 2010-06-04 00:00:00 -05:00
40
+ default_executable:
41
+ dependencies: []
42
+
43
+ description: A ratings system for Rails apps using MongoDB, with bayesian and straight averages, and weighting.
44
+ email: madraziel @nospam@ gmail.com
45
+ executables: []
46
+
47
+ extensions: []
48
+
49
+ extra_rdoc_files:
50
+ - README.markdown
51
+ - lib/acts_as_mongo_rateable/acts_as_mongo_rateable.rb
52
+ - lib/acts_as_mongo_rateable/app/models/rating.rb
53
+ - lib/mongo_rateable.rb
54
+ - tasks/mongo_rateable_tasks.rake
55
+ files:
56
+ - MIT-LICENSE
57
+ - README.markdown
58
+ - Rakefile
59
+ - install.rb
60
+ - lib/acts_as_mongo_rateable/acts_as_mongo_rateable.rb
61
+ - lib/acts_as_mongo_rateable/app/models/rating.rb
62
+ - lib/mongo_rateable.rb
63
+ - rails/init.rb
64
+ - tasks/mongo_rateable_tasks.rake
65
+ - test/mongo_rateable_test.rb
66
+ - test/test_helper.rb
67
+ - uninstall.rb
68
+ - Manifest
69
+ - acts_as_mongo_rateable.gemspec
70
+ has_rdoc: true
71
+ homepage: http://github.com/mepatterson/acts_as_mongo_rateable
72
+ licenses: []
73
+
74
+ post_install_message:
75
+ rdoc_options:
76
+ - --line-numbers
77
+ - --inline-source
78
+ - --title
79
+ - Acts_as_mongo_rateable
80
+ - --main
81
+ - README.markdown
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ hash: 3
90
+ segments:
91
+ - 0
92
+ version: "0"
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ hash: 11
99
+ segments:
100
+ - 1
101
+ - 2
102
+ version: "1.2"
103
+ requirements: []
104
+
105
+ rubyforge_project: acts_as_mongo_rateable
106
+ rubygems_version: 1.3.7
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: A ratings system for Rails apps using MongoDB, with bayesian and straight averages, and weighting.
110
+ test_files:
111
+ - test/mongo_rateable_test.rb
112
+ - test/test_helper.rb
metadata.gz.sig ADDED
Binary file