has_ratings 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,23 @@
1
+ == master
2
+
3
+ == 0.3.0 / 2009-04-30
4
+
5
+ * Replace acts_as_enumeration with enumerate_by
6
+ * Add dependency on Rails 2.3
7
+
8
+ == 0.2.0 / 2008-12-14
9
+
10
+ * Remove the PluginAWeek namespace
11
+
12
+ == 0.1.0 / 2008-10-26
13
+
14
+ * Change how the base module is included to prevent namespacing conflicts
15
+ * Round to two decimal places for rating averages
16
+
17
+ == 0.0.2 / 2008-06-22
18
+
19
+ * Remove log files from gems
20
+
21
+ == 0.0.1 / 2008-05-09
22
+
23
+ * Initial public release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006-2009 Aaron Pfeifer
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/README.rdoc ADDED
@@ -0,0 +1,60 @@
1
+ == has_ratings
2
+
3
+ +has_ratings+ demonstrates a reference implementation for handling ratings.
4
+
5
+ == Resources
6
+
7
+ API
8
+
9
+ * http://api.pluginaweek.org/has_ratings
10
+
11
+ Bugs
12
+
13
+ * http://pluginaweek.lighthouseapp.com/projects/13276-has_ratings
14
+
15
+ Development
16
+
17
+ * http://github.com/pluginaweek/has_ratings
18
+
19
+ Source
20
+
21
+ * git://github.com/pluginaweek/has_ratings.git
22
+
23
+ == Description
24
+
25
+ Storing ratings is a pretty common task when building web applications with a
26
+ community-based focus. Ratings can have names and values associated with them.
27
+ This plugin demonstrate a simple way to manage what ratings can be used and
28
+ how they are persisted.
29
+
30
+ == Usage
31
+
32
+ Note that this is a reference implementation and, most likely, should be
33
+ modified for your own usage.
34
+
35
+ === Example
36
+
37
+ user = User.find(1)
38
+ video = Video.find(1)
39
+
40
+ video.ratings.create(:rater => user, :value => 'poor')
41
+ video.ratings.average # => 1.0
42
+
43
+ == Assets
44
+
45
+ Included with the plugin are image/stylesheet assets for creating raters using
46
+ css as described at http://www.komodomedia.com/blog/2007/01/css-star-rating-redux
47
+
48
+ == Testing
49
+
50
+ Before you can run any tests, the following gem must be installed:
51
+ * plugin_test_helper[http://github.com/pluginaweek/plugin_test_helper]
52
+
53
+ To run against a specific version of Rails:
54
+
55
+ rake test RAILS_FRAMEWORK_ROOT=/path/to/rails
56
+
57
+ == Dependencies
58
+
59
+ * Rails 2.3 or later
60
+ * enumerate_by[http://github.com/pluginaweek/enumerate_by]
data/Rakefile ADDED
@@ -0,0 +1,89 @@
1
+ require 'rake/testtask'
2
+ require 'rake/rdoctask'
3
+ require 'rake/gempackagetask'
4
+ require 'rake/contrib/sshpublisher'
5
+
6
+ spec = Gem::Specification.new do |s|
7
+ s.name = 'has_ratings'
8
+ s.version = '0.3.0'
9
+ s.platform = Gem::Platform::RUBY
10
+ s.summary = 'Demonstrates a reference implementation for handling ratings.'
11
+
12
+ s.files = FileList['{app,assets,db,lib,test}/**/*'] + %w(CHANGELOG.rdoc init.rb LICENSE Rakefile README.rdoc) - FileList['test/app_root/{log,log/*,script,script/*}']
13
+ s.require_path = 'lib'
14
+ s.has_rdoc = true
15
+ s.test_files = Dir['test/**/*_test.rb']
16
+ s.add_dependency 'enumerate_by', '>= 0.4.0'
17
+
18
+ s.author = 'Aaron Pfeifer'
19
+ s.email = 'aaron@pluginaweek.org'
20
+ s.homepage = 'http://www.pluginaweek.org'
21
+ s.rubyforge_project = 'pluginaweek'
22
+ end
23
+
24
+ desc 'Default: run all tests.'
25
+ task :default => :test
26
+
27
+ desc "Test the #{spec.name} plugin."
28
+ Rake::TestTask.new(:test) do |t|
29
+ t.libs << 'lib'
30
+ t.test_files = spec.test_files
31
+ t.verbose = true
32
+ end
33
+
34
+ begin
35
+ require 'rcov/rcovtask'
36
+ namespace :test do
37
+ desc "Test the #{spec.name} plugin with Rcov."
38
+ Rcov::RcovTask.new(:rcov) do |t|
39
+ t.libs << 'lib'
40
+ t.test_files = spec.test_files
41
+ t.rcov_opts << '--exclude="^(?!lib/|app/)"'
42
+ t.verbose = true
43
+ end
44
+ end
45
+ rescue LoadError
46
+ end
47
+
48
+ desc "Generate documentation for the #{spec.name} plugin."
49
+ Rake::RDocTask.new(:rdoc) do |rdoc|
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = spec.name
52
+ rdoc.template = '../rdoc_template.rb'
53
+ rdoc.options << '--line-numbers' << '--inline-source'
54
+ rdoc.rdoc_files.include('README.rdoc', 'CHANGELOG.rdoc', 'LICENSE', 'lib/**/*.rb', 'app/**/*.rb')
55
+ end
56
+
57
+ Rake::GemPackageTask.new(spec) do |p|
58
+ p.gem_spec = spec
59
+ p.need_tar = true
60
+ p.need_zip = true
61
+ end
62
+
63
+ desc 'Publish the beta gem.'
64
+ task :pgem => [:package] do
65
+ Rake::SshFilePublisher.new('aaron@pluginaweek.org', '/home/aaron/gems.pluginaweek.org/public/gems', 'pkg', "#{spec.name}-#{spec.version}.gem").upload
66
+ end
67
+
68
+ desc 'Publish the API documentation.'
69
+ task :pdoc => [:rdoc] do
70
+ Rake::SshDirPublisher.new('aaron@pluginaweek.org', "/home/aaron/api.pluginaweek.org/public/#{spec.name}", 'rdoc').upload
71
+ end
72
+
73
+ desc 'Publish the API docs and gem'
74
+ task :publish => [:pgem, :pdoc, :release]
75
+
76
+ desc 'Publish the release files to RubyForge.'
77
+ task :release => [:gem, :package] do
78
+ require 'rubyforge'
79
+
80
+ ruby_forge = RubyForge.new.configure
81
+ ruby_forge.login
82
+
83
+ %w(gem tgz zip).each do |ext|
84
+ file = "pkg/#{spec.name}-#{spec.version}.#{ext}"
85
+ puts "Releasing #{File.basename(file)}..."
86
+
87
+ ruby_forge.add_release(spec.rubyforge_project, spec.name, spec.version, file)
88
+ end
89
+ end
@@ -0,0 +1,15 @@
1
+ # A rating of a particular record. Ratings consist of three components:
2
+ # * +rater+ - The person who is actually creating the rating
3
+ # * +ratable+ - The object which is being rated
4
+ # * +value+ - The value being assigned to the rating
5
+ #
6
+ # *Note* that the value does not represent the actual integer value, but rather
7
+ # the enumeration record in the RatingValue model.
8
+ class Rating < ActiveRecord::Base
9
+ belongs_to :rater, :polymorphic => true
10
+ belongs_to :ratable, :polymorphic => true
11
+ belongs_to :value, :class_name => 'RatingValue'
12
+
13
+ validates_presence_of :rater_id, :rater_type, :ratable_id, :ratable_type,
14
+ :value_id
15
+ end
@@ -0,0 +1,31 @@
1
+ # The type of rating that can be assigned. This is an enumeration which
2
+ # consists of a pre-determined set of possible rating values. Each value has
3
+ # the following attributes:
4
+ # * +name+ - The actual name to refer to the value as
5
+ # * +value+ - The numeric value of the rating (higher is better)
6
+ #
7
+ # Values should normally be referred to by name. For example,
8
+ #
9
+ # RatingValue['poor'] # => #<RatingValue id: 1, name: "poor", value: 1>
10
+ # RatingValue['excellent'] # => #<RatingValue id: 5, name: "excellent", value: 5>
11
+ class RatingValue < ActiveRecord::Base
12
+ enumerate_by :name
13
+
14
+ has_many :ratings, :foreign_key => 'value_id'
15
+
16
+ validates_presence_of :value
17
+
18
+ # Returns the integer value of the rating
19
+ def to_i
20
+ value
21
+ end
22
+
23
+ # Represent the possible values for ratings
24
+ bootstrap(
25
+ {:id => 1, :name => 'poor', :value => 1},
26
+ {:id => 2, :name => 'below_average', :value => 2},
27
+ {:id => 3, :name => 'average', :value => 3},
28
+ {:id => 4, :name => 'above_average', :value => 4},
29
+ {:id => 5, :name => 'excellent', :value => 5}
30
+ )
31
+ end
Binary file
@@ -0,0 +1,84 @@
1
+ .star-rating {
2
+ position: relative;
3
+ float: left;
4
+ width: 150px;
5
+ height: 25px;
6
+ margin: 0px;
7
+ padding: 0px;
8
+ list-style:none;
9
+ background: url(../images/star.gif) top left repeat-x;
10
+ }
11
+
12
+ .star-rating li {
13
+ padding: 0px;
14
+ margin: 0px;
15
+ /*\*/
16
+ float: left;
17
+ /* */
18
+ }
19
+
20
+ .star-rating li a {
21
+ position: absolute;
22
+ display: block;
23
+ width: 30px;
24
+ height: 25px;
25
+ padding: 0px;
26
+ text-decoration: none;
27
+ text-indent: -9000px;
28
+ z-index: 20;
29
+ }
30
+
31
+ .star-rating li a:hover {
32
+ left: 0px;
33
+ background: url(../images/star.gif) left bottom;
34
+ z-index: 2;
35
+ }
36
+
37
+ .star-rating a.star1 {
38
+ left: 0px;
39
+ }
40
+
41
+ .star-rating a.star1:hover {
42
+ width: 30px;
43
+ }
44
+
45
+ .star-rating a.star2 {
46
+ left: 30px;
47
+ }
48
+
49
+ .star-rating a.star2:hover {
50
+ width: 60px;
51
+ }
52
+
53
+ .star-rating a.star3 {
54
+ left: 60px;
55
+ }
56
+
57
+ .star-rating a.star3:hover {
58
+ width: 90px;
59
+ }
60
+
61
+ .star-rating a.star4 {
62
+ left: 90px;
63
+ }
64
+
65
+ .star-rating a.star4:hover {
66
+ width: 120px;
67
+ }
68
+
69
+ .star-rating a.star5 {
70
+ left: 120px;
71
+ }
72
+
73
+ .star-rating a.star5:hover {
74
+ width: 150px;
75
+ }
76
+
77
+ .star-rating li.current-rating {
78
+ position: absolute;
79
+ display: block;
80
+ height: 25px;
81
+ background: url(../images/star.gif) left center;
82
+ text-indent: -9000px;
83
+ z-index: 1;
84
+ }
@@ -0,0 +1,12 @@
1
+ class CreateRatingValues < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :rating_values do |t|
4
+ t.string :name, :null => false
5
+ t.integer :value, :null => false
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ drop_table :rating_values
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ class CreateRatings < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :ratings do |t|
4
+ t.references :ratable, :rater, :polymorphic => true, :null => false
5
+ t.references :value, :null => false
6
+ t.timestamps
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_table :ratings
12
+ end
13
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'has_ratings'
@@ -0,0 +1,50 @@
1
+ # Adds a generic implementation for dealing with ratings
2
+ module HasRatings
3
+ module MacroMethods
4
+ # Creates the following association:
5
+ # * +ratings+ - All ratings associated with the current record
6
+ #
7
+ # This association assumes that it is being created on the +ratable+
8
+ # model. If you want to create an association on the +rater+ model,
9
+ # it will have to be created manually like so:
10
+ #
11
+ # has_many :ratings, :as => :rater
12
+ #
13
+ # == Creating new ratings
14
+ #
15
+ # Creating new ratings is very similar to creating other records within
16
+ # a has_many association:
17
+ #
18
+ # user = User.find(1)
19
+ #
20
+ # video = Video.find_by_name('The Shawshank Redemption')
21
+ # video.ratings.create(:rater => user, :value => 'excellent')
22
+ # video.ratings.average # => 5
23
+ def has_ratings
24
+ has_many :ratings, :as => :ratable, :extend => RatingExtension
25
+ end
26
+ end
27
+
28
+ module RatingExtension
29
+ # Gets the average of all the ratings, up to a precision of 2 decimals.
30
+ # If no ratings have ever been made, then 0.0 is returned.
31
+ #
32
+ # For example,
33
+ #
34
+ # video = Video.find_by_name('The Shawshank Redemption')
35
+ # video.ratings.map {|rating| rating.value.to_i} # => [4, 5, 5]
36
+ # video.ratings.average # => 4.67
37
+ def average
38
+ if empty?
39
+ 0.0
40
+ else
41
+ average = inject(0) {|total, rating| total += rating.value.to_i} / size.to_f
42
+ average.round(2)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ ActiveRecord::Base.class_eval do
49
+ extend HasRatings::MacroMethods
50
+ end
@@ -0,0 +1,2 @@
1
+ class User < ActiveRecord::Base
2
+ end
@@ -0,0 +1,3 @@
1
+ class Video < ActiveRecord::Base
2
+ has_ratings
3
+ end
@@ -0,0 +1,12 @@
1
+ require 'config/boot'
2
+
3
+ Rails::Initializer.run do |config|
4
+ config.plugin_paths << '..'
5
+ config.plugins = %w(enumerate_by has_ratings)
6
+ config.cache_classes = false
7
+ config.whiny_nils = true
8
+ config.action_controller.session = {:key => 'rails_session', :secret => 'd229e4d22437432705ab3985d4d246'}
9
+ config.after_initialize do
10
+ EnumerateBy.perform_caching = false
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :users do |t|
4
+ t.string :login, :null => false
5
+ end
6
+ end
7
+
8
+ def self.down
9
+ drop_table :users
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class CreateVideos < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :videos do |t|
4
+ t.string :name, :null => false
5
+ end
6
+ end
7
+
8
+ def self.down
9
+ drop_table :videos
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ class MigrateHasRatingsToVersion2 < ActiveRecord::Migration
2
+ def self.up
3
+ ActiveRecord::Migrator.new(:up, "#{Rails.root}/../../db/migrate", 0).migrations.each do |migration|
4
+ migration.migrate(:up)
5
+ end
6
+ end
7
+
8
+ def self.down
9
+ ActiveRecord::Migrator.new(:up, "#{Rails.root}/../../db/migrate", 0).migrations.each do |migration|
10
+ migration.migrate(:down)
11
+ end
12
+ end
13
+ end
data/test/factory.rb ADDED
@@ -0,0 +1,60 @@
1
+ module Factory
2
+ # Build actions for the model
3
+ def self.build(model, &block)
4
+ name = model.to_s.underscore
5
+
6
+ define_method("#{name}_attributes", block)
7
+ define_method("valid_#{name}_attributes") {|*args| valid_attributes_for(model, *args)}
8
+ define_method("new_#{name}") {|*args| new_record(model, *args)}
9
+ define_method("create_#{name}") {|*args| create_record(model, *args)}
10
+ end
11
+
12
+ # Get valid attributes for the model
13
+ def valid_attributes_for(model, attributes = {})
14
+ name = model.to_s.underscore
15
+ send("#{name}_attributes", attributes)
16
+ attributes.stringify_keys!
17
+ attributes
18
+ end
19
+
20
+ # Build an unsaved record
21
+ def new_record(model, *args)
22
+ attributes = valid_attributes_for(model, *args)
23
+ record = model.new(attributes)
24
+ attributes.each {|attr, value| record.send("#{attr}=", value) if model.accessible_attributes && !model.accessible_attributes.include?(attr) || model.protected_attributes && model.protected_attributes.include?(attr)}
25
+ record
26
+ end
27
+
28
+ # Build and save/reload a record
29
+ def create_record(model, *args)
30
+ record = new_record(model, *args)
31
+ record.save!
32
+ record.reload
33
+ record
34
+ end
35
+
36
+ build Rating do |attributes|
37
+ attributes[:ratable] = create_video unless attributes.include?(:ratable)
38
+ attributes[:rater] = create_user unless attributes.include?(:rater)
39
+ attributes[:value] = create_rating_value unless attributes.include?(:value)
40
+ end
41
+
42
+ build RatingValue do |attributes|
43
+ attributes.reverse_merge!(
44
+ :name => 'awesome',
45
+ :value => 10
46
+ )
47
+ end
48
+
49
+ build User do |attributes|
50
+ attributes.reverse_merge!(
51
+ :login => 'admin'
52
+ )
53
+ end
54
+
55
+ build Video do |attributes|
56
+ attributes.reverse_merge!(
57
+ :name => 'Rick Roll'
58
+ )
59
+ end
60
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class VideoTest < ActiveRecord::TestCase
4
+ def setup
5
+ @video = create_video
6
+ end
7
+
8
+ def test_should_not_have_any_ratings
9
+ assert @video.ratings.empty?
10
+ end
11
+
12
+ def test_should_have_an_average_of_0
13
+ assert_equal 0.0, @video.ratings.average
14
+ end
15
+ end
16
+
17
+ class VideoWithRatingsTest < ActiveRecord::TestCase
18
+ def setup
19
+ @video = create_video
20
+
21
+ rater = create_user
22
+ @poor_rating = create_rating(:rater => rater, :ratable => @video, :value => 'poor')
23
+ @average_rating = create_rating(:rater => rater, :ratable => @video, :value => 'average')
24
+ end
25
+
26
+ def test_should_have_ratings
27
+ assert_equal [@poor_rating, @average_rating], @video.ratings
28
+ end
29
+
30
+ def test_should_have_an_average
31
+ assert_equal 2.0, @video.ratings.average
32
+ end
33
+ end
34
+
35
+ class VideoWithRoundedAverageTest < ActiveRecord::TestCase
36
+ def setup
37
+ @video = create_video
38
+
39
+ rater = create_user
40
+ create_rating(:rater => rater, :ratable => @video, :value => 'above_average')
41
+ create_rating(:rater => rater, :ratable => @video, :value => 'excellent')
42
+ create_rating(:rater => rater, :ratable => @video, :value => 'excellent')
43
+ end
44
+
45
+ def test_should_round_to_two_decimal_places
46
+ assert_equal 4.67, @video.ratings.average
47
+ end
48
+ end
@@ -0,0 +1,13 @@
1
+ # Load the plugin testing framework
2
+ $:.unshift("#{File.dirname(__FILE__)}/../../plugin_test_helper/lib")
3
+ require 'rubygems'
4
+ require 'plugin_test_helper'
5
+
6
+ # Run the migrations
7
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate")
8
+
9
+ # Mixin the factory helper
10
+ require File.expand_path("#{File.dirname(__FILE__)}/factory")
11
+ Test::Unit::TestCase.class_eval do
12
+ include Factory
13
+ end
@@ -0,0 +1,82 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class RatingByDefaultTest < ActiveRecord::TestCase
4
+ def setup
5
+ @rating = Rating.new
6
+ end
7
+
8
+ def test_should_not_have_a_ratable_association
9
+ assert_nil @rating.ratable_id
10
+ end
11
+
12
+ def test_should_not_have_a_ratable_type
13
+ assert_nil @rating.ratable_type
14
+ end
15
+
16
+ def test_should_not_have_a_rater
17
+ assert_nil @rating.rater_id
18
+ end
19
+
20
+ def test_should_not_have_a_rater_type
21
+ assert_nil @rating.rater_type
22
+ end
23
+
24
+ def test_should_not_have_a_value
25
+ assert_nil @rating.value_id
26
+ end
27
+ end
28
+
29
+ class RatingTest < ActiveRecord::TestCase
30
+ def test_should_be_valid_with_a_valid_set_of_attributes
31
+ rating = new_rating
32
+ assert rating.valid?
33
+ end
34
+
35
+ def test_should_require_a_ratable_association
36
+ rating = new_rating(:ratable => nil)
37
+ assert !rating.valid?
38
+ assert rating.errors.invalid?(:ratable_id)
39
+ end
40
+
41
+ def test_should_require_a_ratable_type
42
+ rating = new_rating(:ratable => nil)
43
+ assert !rating.valid?
44
+ assert rating.errors.invalid?(:ratable_type)
45
+ end
46
+
47
+ def test_should_require_a_rater
48
+ rating = new_rating(:rater => nil)
49
+ assert !rating.valid?
50
+ assert rating.errors.invalid?(:rater_id)
51
+ end
52
+
53
+ def test_should_require_a_rater_type
54
+ rating = new_rating(:rater => nil)
55
+ assert !rating.valid?
56
+ assert rating.errors.invalid?(:rater_type)
57
+ end
58
+
59
+ def test_should_require_a_value
60
+ rating = new_rating(:value => nil)
61
+ assert !rating.valid?
62
+ assert rating.errors.invalid?(:value_id)
63
+ end
64
+ end
65
+
66
+ class RatingAfterBeingCreatedTest < ActiveRecord::TestCase
67
+ def setup
68
+ @rating = create_rating
69
+ end
70
+
71
+ def test_should_have_a_value
72
+ assert_not_nil @rating.value
73
+ end
74
+
75
+ def test_should_have_a_ratable_association
76
+ assert_not_nil @rating.ratable
77
+ end
78
+
79
+ def test_should_have_a_rater
80
+ assert_not_nil @rating.rater
81
+ end
82
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class RatingValueByDefaultTest < ActiveRecord::TestCase
4
+ def setup
5
+ @rating_value = RatingValue.new
6
+ end
7
+
8
+ def test_should_not_have_a_name
9
+ assert @rating_value.name.blank?
10
+ end
11
+
12
+ def test_should_not_have_a_value
13
+ assert_nil @rating_value.value
14
+ end
15
+ end
16
+
17
+ class RatingValueTest < ActiveRecord::TestCase
18
+ def test_should_be_valid_with_a_valid_set_of_attributes
19
+ rating_value = new_rating_value
20
+ assert rating_value.valid?
21
+ end
22
+
23
+ def test_should_require_a_name
24
+ rating_value = new_rating_value(:name => nil)
25
+ assert !rating_value.valid?
26
+ assert rating_value.errors.invalid?(:name)
27
+ end
28
+
29
+ def test_should_require_a_value
30
+ rating_value = new_rating_value(:value => nil)
31
+ assert !rating_value.valid?
32
+ assert rating_value.errors.invalid?(:value)
33
+ end
34
+
35
+ def test_should_convert_to_an_integer
36
+ rating_value = new_rating_value(:value => 1)
37
+ assert_equal 1, rating_value.to_i
38
+ end
39
+ end
40
+
41
+ class RatingValueAfterBeingCreatedTest < ActiveRecord::TestCase
42
+ def setup
43
+ @rating_value = create_rating_value
44
+ end
45
+
46
+ def test_should_not_have_any_ratings
47
+ assert @rating_value.ratings.empty?
48
+ end
49
+ end
50
+
51
+ class RatingValueWithRatingsTest < ActiveRecord::TestCase
52
+ def setup
53
+ @rating_value = create_rating_value
54
+ @poor_rating = create_rating(:value => @rating_value)
55
+ @second_poor_rating = create_rating(:value => @rating_value)
56
+ end
57
+
58
+ def test_should_have_ratings
59
+ assert_equal [@poor_rating, @second_poor_rating], @rating_value.ratings
60
+ end
61
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: has_ratings
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Aaron Pfeifer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-30 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: enumerate_by
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.4.0
24
+ version:
25
+ description:
26
+ email: aaron@pluginaweek.org
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - app/models
35
+ - app/models/rating.rb
36
+ - app/models/rating_value.rb
37
+ - assets/images
38
+ - assets/images/star.gif
39
+ - assets/stylesheets
40
+ - assets/stylesheets/star.css
41
+ - db/migrate
42
+ - db/migrate/002_create_ratings.rb
43
+ - db/migrate/001_create_rating_values.rb
44
+ - lib/has_ratings.rb
45
+ - test/factory.rb
46
+ - test/test_helper.rb
47
+ - test/functional
48
+ - test/functional/has_ratings_test.rb
49
+ - test/unit
50
+ - test/unit/rating_value_test.rb
51
+ - test/unit/rating_test.rb
52
+ - test/app_root
53
+ - test/app_root/db
54
+ - test/app_root/db/migrate
55
+ - test/app_root/db/migrate/003_migrate_has_ratings_to_version_2.rb
56
+ - test/app_root/db/migrate/002_create_videos.rb
57
+ - test/app_root/db/migrate/001_create_users.rb
58
+ - test/app_root/config
59
+ - test/app_root/config/environment.rb
60
+ - test/app_root/app
61
+ - test/app_root/app/models
62
+ - test/app_root/app/models/user.rb
63
+ - test/app_root/app/models/video.rb
64
+ - CHANGELOG.rdoc
65
+ - init.rb
66
+ - LICENSE
67
+ - Rakefile
68
+ - README.rdoc
69
+ has_rdoc: true
70
+ homepage: http://www.pluginaweek.org
71
+ post_install_message:
72
+ rdoc_options: []
73
+
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "0"
81
+ version:
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: "0"
87
+ version:
88
+ requirements: []
89
+
90
+ rubyforge_project: pluginaweek
91
+ rubygems_version: 1.3.1
92
+ signing_key:
93
+ specification_version: 2
94
+ summary: Demonstrates a reference implementation for handling ratings.
95
+ test_files:
96
+ - test/functional/has_ratings_test.rb
97
+ - test/unit/rating_value_test.rb
98
+ - test/unit/rating_test.rb