Skip to content
Browse files

- gem dependencies updated

- added active support dependency for class_attribute
- removed deprecated class_inheritable_reader
- replaced Extlib::Inflection with DataMapper::Inflector
- replaced :nullable with :required
- changed default rater-options to :required => false, so the test pass
  • Loading branch information...
1 parent d510ba5 commit ca7ac0b13d96139a310c589002d713eb10890b60 @Ragmaanir committed Feb 11, 2012
Showing with 261 additions and 73 deletions.
  1. +27 −0 Gemfile
  2. +68 −0 Gemfile.lock
  3. +22 −8 Rakefile
  4. +6 −1 lib/dm-is-rateable.rb
  5. +52 −34 lib/dm-is-rateable/is/rateable.rb
  6. +77 −26 spec/integration/rateable_spec.rb
  7. +9 −4 spec/spec_helper.rb
View
27 Gemfile
@@ -1,5 +1,31 @@
source 'http://rubygems.org'
+DM_VERSION = '~> 1.2.0'
+
+gem 'dm-core', DM_VERSION
+
+gem 'dm-validations', DM_VERSION
+gem 'dm-aggregates', DM_VERSION
+gem 'dm-timestamps', DM_VERSION
+gem 'dm-types', DM_VERSION
+gem 'dm-is-remixable', DM_VERSION
+gem 'dm-migrations', DM_VERSION
+
+gem 'activesupport', '~> 3.1.1'
+
+group(:test) do
+ gem 'rspec'
+end
+
+group(:development) do
+ gem 'rake'
+ gem 'jeweler'
+ gem 'yard'
+end
+
+=begin
+source 'http://rubygems.org'
+
gem 'dm-core', '~> 0.10.2', :git => 'git://github.com/snusnu/dm-core.git', :branch => 'active_support'
git 'git://github.com/snusnu/dm-more.git', :branch => 'active_support' do
@@ -21,3 +47,4 @@ group(:development) do
gem 'jeweler', '~> 1.4'
gem 'yard', '~> 0.5'
end
+=end
View
68 Gemfile.lock
@@ -0,0 +1,68 @@
+GEM
+ remote: http://rubygems.org/
+ specs:
+ activesupport (3.1.1)
+ multi_json (~> 1.0)
+ addressable (2.2.6)
+ bcrypt-ruby (3.0.1)
+ diff-lcs (1.1.3)
+ dm-aggregates (1.2.0)
+ dm-core (~> 1.2.0)
+ dm-core (1.2.0)
+ addressable (~> 2.2.6)
+ dm-is-remixable (1.2.0)
+ dm-core (~> 1.2.0)
+ dm-migrations (1.2.0)
+ dm-core (~> 1.2.0)
+ dm-timestamps (1.2.0)
+ dm-core (~> 1.2.0)
+ dm-types (1.2.1)
+ bcrypt-ruby (~> 3.0.0)
+ dm-core (~> 1.2.0)
+ fastercsv (~> 1.5.4)
+ json (~> 1.6.1)
+ multi_json (~> 1.0.3)
+ stringex (~> 1.3.0)
+ uuidtools (~> 2.1.2)
+ dm-validations (1.2.0)
+ dm-core (~> 1.2.0)
+ fastercsv (1.5.4)
+ git (1.2.5)
+ jeweler (1.8.3)
+ bundler (~> 1.0)
+ git (>= 1.2.5)
+ rake
+ rdoc
+ json (1.6.5)
+ multi_json (1.0.4)
+ rake (0.9.2.2)
+ rdoc (3.12)
+ json (~> 1.4)
+ rspec (2.8.0)
+ rspec-core (~> 2.8.0)
+ rspec-expectations (~> 2.8.0)
+ rspec-mocks (~> 2.8.0)
+ rspec-core (2.8.0)
+ rspec-expectations (2.8.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.8.0)
+ stringex (1.3.0)
+ uuidtools (2.1.2)
+ yard (0.7.5)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activesupport (~> 3.1.1)
+ dm-aggregates (~> 1.2.0)
+ dm-core (~> 1.2.0)
+ dm-is-remixable (~> 1.2.0)
+ dm-migrations (~> 1.2.0)
+ dm-timestamps (~> 1.2.0)
+ dm-types (~> 1.2.0)
+ dm-validations (~> 1.2.0)
+ jeweler
+ rake
+ rspec
+ yard
View
30 Rakefile
@@ -25,14 +25,28 @@ begin
gem.homepage = 'http://github.com/snusnu/dm-is-rateable'
gem.authors = [ 'Martin Gamsjaeger (snusnu)' ]
- gem.add_dependency 'dm-core', '~> 0.10.2'
- gem.add_dependency 'dm-validations', '~> 0.10.2'
- gem.add_dependency 'dm-aggregates', '~> 0.10.2'
- gem.add_dependency 'dm-timestamps', '~> 0.10.2'
- gem.add_dependency 'dm-types', '~> 0.10.2'
- gem.add_dependency 'dm-is-remixable', '~> 0.10.2'
-
- gem.add_development_dependency 'rspec', '~> 1.3'
+ #gem.add_dependency 'dm-core', '~> 0.10.2'
+ #gem.add_dependency 'dm-validations', '~> 0.10.2'
+ #gem.add_dependency 'dm-aggregates', '~> 0.10.2'
+ #gem.add_dependency 'dm-timestamps', '~> 0.10.2'
+ #gem.add_dependency 'dm-types', '~> 0.10.2'
+ #gem.add_dependency 'dm-is-remixable', '~> 0.10.2'
+
+
+ DM_VERSION = '~> 1.2.0'
+
+ gem.add_dependency 'dm-core', DM_VERSION
+
+ gem.add_dependency 'dm-validations', DM_VERSION
+ gem.add_dependency 'dm-aggregates', DM_VERSION
+ gem.add_dependency 'dm-timestamps', DM_VERSION
+ gem.add_dependency 'dm-types', DM_VERSION
+ gem.add_dependency 'dm-is-remixable', DM_VERSION
+ gem.add_dependency 'dm-migrations', DM_VERSION
+
+ gem.add_dependency 'activesupport', '~> 3.1.1'
+
+ gem.add_development_dependency 'rspec', '~> 2.8'
gem.add_development_dependency 'yard', '~> 0.5'
end
View
7 lib/dm-is-rateable.rb
@@ -6,9 +6,14 @@
require 'dm-validations'
require 'dm-aggregates'
require 'dm-is-remixable'
+require 'dm-migrations'
+
+require 'active_support/core_ext/class'
+require 'active_support/inflector'
# Require plugin-files
-require Pathname(__FILE__).dirname.expand_path / 'dm-is-rateable' / 'is' / 'rateable.rb'
+#require Pathname(__FILE__).dirname.expand_path / 'dm-is-rateable' / 'is' / 'rateable.rb'
+require File.join('dm-is-rateable','is','rateable.rb')
# Include the plugin in Resource
DataMapper::Model.append_extensions DataMapper::Is::Rateable
View
86 lib/dm-is-rateable/is/rateable.rb
@@ -47,31 +47,43 @@ def is_rateable(options = {})
:model => "#{self}Rating"
}.merge(options)
- @allowed_ratings = options[:allowed_ratings]
- class_inheritable_accessor :allowed_ratings
+ #@allowed_ratings = options[:allowed_ratings]
+ #class_inheritable_accessor :allowed_ratings
- @rateable_model = options[:model]
- class_inheritable_accessor :rateable_model
+ #@rateable_model = options[:model]
+ #class_inheritable_accessor :rateable_model
- @rateable_key = @rateable_model.snake_case.to_sym
- class_inheritable_accessor :rateable_key
+ #@rateable_key = @rateable_model.snake_case.to_sym
+ #class_inheritable_accessor :rateable_key
+
+ class_attribute :allowed_ratings
+ self.allowed_ratings = options[:allowed_ratings]
+
+ class_attribute :rateable_model
+ self.rateable_model = options[:model]
+
+ class_attribute :rateable_key
+ self.rateable_key = rateable_model.underscore.to_sym
remix n, Rating, :as => options[:as], :model => options[:model]
- @remixed_rating = remixables[:rating]
- class_inheritable_reader :remixed_rating
+ #@remixed_rating = remixables[:rating]
+ #class_inheritable_reader :remixed_rating
+
+ class_attribute :remixed_rating
+ self.remixed_rating = remixables[:rating]
- if @remixed_rating[:reader] != :ratings
+ if remixed_rating[:reader] != :ratings
self.class_eval(<<-EOS, __FILE__, __LINE__ + 1)
- alias :ratings :#{@remixed_rating[rateable_key][:reader]}
+ alias :ratings :#{remixed_rating[rateable_key][:reader]}
EOS
end
# determine property type based on supplied values
rating_type = case options[:allowed_ratings]
- when Range then
+ when Range then
options[:allowed_ratings].first.is_a?(Integer) ? Integer : String
- when Enum then
+ when Enum then
require 'dm-types'
DataMapper::Types::Enum
else
@@ -83,48 +95,48 @@ def is_rateable(options = {})
# prepare rating enhancements
def rater_fk(name)
- name ? Extlib::Inflection.foreign_key(name.to_s.singular).to_sym : :user_id
+ name ? DataMapper::Inflector.foreign_key(name.to_s.singularize).to_sym : :user_id
end
- if options[:rater]
-
+ tmp_rater_fk = if options[:rater]
rater_opts = options[:rater]
rater_name = rater_opts.is_a?(Hash) ? (rater_opts.delete(:name) || :user_id) : rater_fk(rater_opts)
rater_type = rater_opts.is_a?(Hash) ? (rater_opts.delete(:type) || Integer) : Integer
- rater_property_opts = rater_opts.is_a?(Hash) ? rater_opts : { :required => true }
+ #rater_property_opts = rater_opts.is_a?(Hash) ? rater_opts : { :required => true }
+ rater_property_opts = rater_opts.is_a?(Hash) ? rater_opts : { :required => false }
rater_property_opts.merge!(:min => 0) if rater_type == Integer # Match referenced column type
rater_association = rater_name.to_s.gsub(/_id/, '').to_sym
- @rater_fk = rater_name
-
+ rater_name
else
- @rater_fk = nil # no rater association established
+ nil # no rater association established
end
- class_inheritable_reader :rater_fk
+ #class_inheritable_reader :rater_fk
+ class_attribute :rater_fk
+ self.rater_fk = tmp_rater_fk
# close on this because enhance will class_eval in remixable model scope
parent_key = self.rateable_fk
- enhance :rating, @rateable_model do
+ enhance :rating, rateable_model do
- property :rating, rating_type, :nullable => false
+ property :rating, rating_type, :required => true #, :nullable => false
property :rating, rating_type, :required => true
if options[:rater]
-
property rater_name, rater_type, rater_property_opts # rater
belongs_to rater_association
parent_assocation = parent_key.to_s.gsub(/_id/, '').to_sym
- validates_is_unique rater_name, :when => :testing_association, :scope => [parent_assocation]
- validates_is_unique rater_name, :when => :testing_property, :scope => [parent_key]
-
+ validates_uniqueness_of rater_name, :when => :testing_association, :scope => [parent_assocation]
+ validates_uniqueness_of rater_name, :when => :testing_property, :scope => [parent_key]
end
if options[:timestamps]
- property :created_at, DateTime
- property :updated_at, DateTime
+ #property :created_at, DateTime
+ #property :updated_at, DateTime
+ timestamps :at
end
end
@@ -146,8 +158,8 @@ def total_rating
end
def rateable_fk
- demodulized_name = Extlib::Inflection.demodulize(self.name)
- Extlib::Inflection.foreign_key(demodulized_name).to_sym
+ demodulized_name = DataMapper::Inflector.demodulize(self.name)
+ DataMapper::Inflector.foreign_key(demodulized_name).to_sym
end
end
@@ -244,14 +256,20 @@ def rate(rating, user = nil)
if user
if r = self.user_rating(user)
if r.rating != rating
- r.update(:rating => rating)
+ r.update(:rating => rating) or raise
end
else
- self.ratings.create(self.rater => user, :rating => rating)
+ # FIXME: save or raise
+ res = self.ratings.create(self.rater => user, :rating => rating)
+ raise(res.errors.inspect) unless res.saved?
+ res
end
else
if self.anonymous_rating_enabled?
- self.ratings.create(:rating => rating)
+ # FIXME: save or raise
+ res = self.ratings.create(:rating => rating)
+ raise(res.errors.inspect) unless res.saved?
+ res
else
msg = "Anonymous ratings are not enabled for #{self}"
raise AnonymousRatingDisabled, msg
@@ -275,4 +293,4 @@ def user_rating(user, conditions = {})
end
end
-end
+end
View
103 spec/integration/rateable_spec.rb
@@ -1,5 +1,5 @@
require 'pathname'
-require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
+#require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
@@ -20,7 +20,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every rating", :shared => true do
+ shared_examples "every rating" do
it "should define a remixed model that can be auto_migrated" do
# once it's migrated it stays in the database and can be used by the other specs
@@ -110,7 +110,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every rateable where ratings can be toggled", :shared => true do
+ shared_examples "every rateable where ratings can be toggled" do
it "should return true when 'rating_togglable?' class_level reader is called" do
Trip.rating_togglable?.should be_true
@@ -132,7 +132,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every rateable where ratings can't be toggled", :shared => true do
+ shared_examples "every rateable where ratings can't be toggled" do
it "should return false when 'rating_togglable?' class_level reader is called" do
Trip.rating_togglable?.should be_false
@@ -152,7 +152,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every rateable where anonymous ratings can be toggled", :shared => true do
+ shared_examples "every rateable where anonymous ratings can be toggled" do
it "should return true when 'anonymous_rating_togglable?' class_level reader is called" do
Trip.anonymous_rating_togglable?.should be_true
@@ -174,7 +174,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every rateable where anonymous ratings can't be toggled", :shared => true do
+ shared_examples "every rateable where anonymous ratings can't be toggled" do
it "should return false when 'anonymous_rating_togglable?' class_level reader is called" do
Trip.anonymous_rating_togglable?.should be_false
@@ -193,7 +193,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every anonymized timestamped rating", :shared => true do
+ shared_examples "every anonymized timestamped rating" do
it "should store timestamps for every anonymous rating" do
if @t1.anonymous_rating_enabled?
@@ -208,7 +208,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every anonymized non-timestamped rating", :shared => true do
+ shared_examples "every anonymized non-timestamped rating" do
it "should store timestamps for every anonymous rating" do
if @t1.anonymous_rating_enabled?
@@ -223,7 +223,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every personalized timestamped rating", :shared => true do
+ shared_examples "every personalized timestamped rating" do
it "should store timestamps for every personalized rating" do
if @t1.rating_enabled?
@@ -238,7 +238,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every personalized non-timestamped rating", :shared => true do
+ shared_examples "every personalized non-timestamped rating" do
it "should not store timestamps for every personalized rating" do
if @t1.rating_enabled?
@@ -253,7 +253,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every aliased rating", :shared => true do
+ shared_examples "every aliased rating" do
it "should set the specified alias on the 'ratings' reader" do
@t1.respond_to?(:my_trip_ratings).should be_true
@@ -264,7 +264,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every enabled rating", :shared => true do
+ shared_examples "every enabled rating" do
it "should have ratings enabled" do
@t1.rating_enabled?.should be_true
@@ -276,7 +276,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every disabled rating", :shared => true do
+ shared_examples "every disabled rating" do
it "should have ratings disabled" do
@t1.rating_enabled?.should be_false
@@ -288,7 +288,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every enabled anonymized rating", :shared => true do
+ shared_examples "every enabled anonymized rating" do
it "should have anonymized ratings enabled" do
@t1.anonymous_rating_enabled?.should be_true
@@ -308,7 +308,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every disabled anonymized rating", :shared => true do
+ shared_examples "every disabled anonymized rating" do
it "should have anonymized ratings disabled" do
@t1.anonymous_rating_disabled?.should be_true
@@ -327,7 +327,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every enabled personalized rating", :shared => true do
+ shared_examples "every enabled personalized rating" do
it "should accept allowed rating values from existing users" do
Trip.allowed_ratings = (0..4)
@@ -377,7 +377,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "every disabled personalized rating", :shared => true do
+ shared_examples "every disabled personalized rating" do
it "should not allow any ratings from any existing user" do
lambda { @t1.rate(-1, @u1) }.should raise_error(DataMapper::Is::Rateable::RatingDisabled)
@@ -391,7 +391,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "allowed_ratings have not been changed", :shared => true do
+ shared_examples "allowed_ratings have not been changed" do
it "should allow ratings between (0..5)" do
Trip.allowed_ratings.should == (0..5)
@@ -402,7 +402,7 @@ def unload_rating_infrastructure(remixer_name, user_model_name = nil)
# --------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------
- describe "rater association has not been changed", :shared => true do
+ shared_examples "rater association has not been changed" do
it "should return the name of the rater association" do
@t1.rater.should == :user
@@ -480,11 +480,15 @@ class Trip
include DataMapper::Resource
property :id, Serial
- property :rating_enabled, Boolean, :nullable => false, :default => true
- property :anonymous_rating_enabled, Boolean, :nullable => false, :default => true
+ #property :rating_enabled, Boolean, :nullable => false, :default => true
+ #property :anonymous_rating_enabled, Boolean, :nullable => false, :default => true
+
+ property :rating_enabled, Boolean, :required => true, :default => true
+ property :anonymous_rating_enabled, Boolean, :required => true, :default => true
# will define TripRating
- is :rateable, :rater => :user
+ is :rateable, :rater => :user # TODO this is the original, but it causes an validation error because :required => true
+ #is :rateable, :rater => {:name => :user_id, :required => false}
end
User.auto_migrate!
@@ -576,8 +580,11 @@ class Trip
include DataMapper::Resource
property :id, Serial
- property :rating_enabled, Boolean, :nullable => false, :default => true
- property :anonymous_rating_enabled, Boolean, :nullable => false, :default => true
+ #property :rating_enabled, Boolean, :nullable => false, :default => true
+ #property :anonymous_rating_enabled, Boolean, :nullable => false, :default => true
+
+ property :rating_enabled, Boolean, :required => true, :default => true
+ property :anonymous_rating_enabled, Boolean, :required => true, :default => true
# will define TripRating
is :rateable, :rater => :user, :as => :my_trip_ratings
@@ -672,8 +679,11 @@ class Trip
include DataMapper::Resource
property :id, Serial
- property :rating_enabled, Boolean, :nullable => false, :default => true
- property :anonymous_rating_enabled, Boolean, :nullable => false, :default => true
+ #property :rating_enabled, Boolean, :nullable => false, :default => true
+ #property :anonymous_rating_enabled, Boolean, :nullable => false, :default => true
+
+ property :rating_enabled, Boolean, :required => true, :default => true
+ property :anonymous_rating_enabled, Boolean, :required => true, :default => true
# will define TripRating
is :rateable, :rater => :user, :timestamps => false
@@ -792,6 +802,47 @@ class Trip
end
+ # --------------------------------------------------------------------------------------------------
+ # --------------------------------------------------------------------------------------------------
+ describe '#rate' do
+ before do
+ unload_rating_infrastructure 'Trip', 'User'
+
+ class User
+ include DataMapper::Resource
+ property :id, Serial
+ end
+
+ class Trip
+ include DataMapper::Resource
+ property :id, Serial
+
+ # will define TripRating
+ is :rateable, :rater => :user
+ end
+
+ User.auto_migrate!
+ Trip.auto_migrate!
+ TripRating.auto_migrate!
+ end
+ subject{ trip.rate(2, user) }
+ let!(:trip) { Trip.create }
+ let!(:user) { User.create }
+
+ it 'creates a new record' do
+ expect{ subject }.to change{TripRating.count}.by(1)
+ end
+
+ its(:created_at){ should_not be_nil }
+
+ context 'when called then' do
+ let!(:rating) { subject }
+ it '' do
+ trip.ratings[0].should == rating
+ end
+ end
+ end
+
end
end
View
13 spec/spec_helper.rb
@@ -1,9 +1,8 @@
-require 'rubygems'
-gem 'rspec', '>=1.1.3'
-require 'spec'
+
require 'pathname'
-require Pathname(__FILE__).dirname.expand_path.parent + 'lib/dm-is-rateable'
+require 'dm-is-rateable'
+#require Pathname(__FILE__).dirname.expand_path.parent + 'lib/dm-is-rateable'
def load_driver(name, default_uri)
return false if ENV['ADAPTER'] != name.to_s
@@ -27,3 +26,9 @@ def load_driver(name, default_uri)
HAS_SQLITE3 = load_driver(:sqlite3, 'sqlite3::memory:')
HAS_MYSQL = load_driver(:mysql, 'mysql://localhost/dm_core_test')
HAS_POSTGRES = load_driver(:postgres, 'postgres://postgres@localhost/dm_core_test')
+
+RSpec.configure do |c|
+ c.filter_run :focus => true
+ c.run_all_when_everything_filtered = true
+end
+

0 comments on commit ca7ac0b

Please sign in to comment.
Something went wrong with that request. Please try again.