Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit 76d852723842279a620ed1d823f862fd0a0fca10 @jeroeningen committed Apr 25, 2011
Showing with 394 additions and 0 deletions.
  1. +14 −0 Gemfile
  2. +20 −0 MIT-LICENSE
  3. +46 −0 README
  4. +23 −0 Rakefile
  5. +1 −0 init.rb
  6. 0 install.rb
  7. +46 −0 lib/acts_as_price.rb
  8. +76 −0 lib/acts_as_price_helper.rb
  9. +62 −0 spec/car_spec.rb
  10. +62 −0 spec/fueltype_spec.rb
  11. +7 −0 spec/models/car.rb
  12. +6 −0 spec/models/fueltype.rb
  13. +31 −0 spec/spec_helper.rb
  14. 0 uninstall.rb
@@ -0,0 +1,14 @@
+source 'http://rubygems.org'
+
+gem 'rails', '3.0.7'
+
+#only use in test envirnoment
+group :test do
+ gem 'rspec-rails'
+ gem 'shoulda-matchers'
+ gem 'autotest'
+ gem 'autotest-growl'
+ gem 'rcov'
+ gem 'metrical'
+ gem 'activerecord-nulldb-adapter'
+end
@@ -0,0 +1,20 @@
+Copyright (c) 2011 [name of plugin creator]
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,46 @@
+=INSTALLATION
+rails plugin install git@github.com:jeroeningen/acts_as_price.git
+
+=USAGE
+In your model add the following:
+- acts_as_price <column_name>, :validates = true
+
+<column_name> is the name of your database column e.g. price or price_per_liter.
+
+This plugin creates the following getters and setters:
+- 'price_in_cents' and '<column_name>_in_cents' #sets and returns the price in cents
+- 'price' and '<column_name>' #sets and returns the price
+
+=EXAMPLES
+car = Car.new :price => 12999
+
+car.price #12999.00
+
+car.price_in_cents #1299900
+
+fuel = Fueltype.new :price_per_liter => 1.12
+
+fuel.price #1.12
+
+fuel.price_in_cents #112
+
+fuel.price_per_liter #1.12
+
+fuel.price_per_liter_in_cents #1.12
+
+=RSPEC INTERGRATION
+Acts As Price comes with a helper method to automatically test the plugin using Rspec.
+
+To use this method please add the following to your spec_helper.rb file:
+- config.include(ActsAsPriceHelper)
+Now you may add the following code to your spec-files for your models:
+ context "given an valid model" do
+ it "should acts as price" do
+ test_acts_as_price_methods <column_name>, <fixture or stub>
+ end
+ end
+
+
+=NOTES
+This plugin comes with Rspec tests.
+However this plugin assumes that you have a database configuration, it actually don't use the database for the Rspec tests.
@@ -0,0 +1,23 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the acts_as_price plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the acts_as_price plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'ActsAsPrice'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
@@ -0,0 +1 @@
+require 'acts_as_price'
No changes.
@@ -0,0 +1,46 @@
+module ActiveRecord
+ module Acts
+ module Price
+
+ def self.included(base)
+ base.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ # Specify the column_name that needs to act as price
+ #
+ # Valid options:
+ # * :validates => true (performs validates_presence_of and validates_numericality_of)
+ def acts_as_price column_name, options = {}
+ validates column_name, :presence => true, :numericality => {:greater_than => 0} if options[:validates] == true
+
+ #setters
+ define_method("#{column_name}=") do |val|
+ super((val.to_f * 100).to_s)
+ end
+ alias_method("price=", "#{column_name}=")
+
+ define_method("price_in_cents=") do |val|
+ self.send("price=", val.to_f / 100)
+ end
+ alias_method "#{column_name}_in_cents=", "price_in_cents="
+
+ #getters
+ define_method(column_name) do
+ if super == 0.0
+ ""
+ else
+ sprintf("%.2f", super.to_f / 100)
+ end
+ end
+ alias_method "price", column_name
+
+ define_method("price_in_cents") {((send column_name).to_f * 100).to_s.to_i}
+ alias_method "#{column_name}_in_cents", "price_in_cents"
+ end
+ end
+ end
+ end
+end
+
+ActiveRecord::Base.send(:include, ActiveRecord::Acts::Price)
@@ -0,0 +1,76 @@
+module ActsAsPriceHelper
+ # Test the acts_as_price plugin for the specified column_name and model
+ #
+ # Note the you can also specify the model in a before block in your tests
+ def test_acts_as_price_methods column_name, acts_as_price_model = nil
+ @acts_as_price_model = acts_as_price_model if acts_as_price_model
+
+ @column_name = column_name
+ columns_in_cents.each do |column|
+ @acts_as_price_model.send(column).should == @acts_as_price_model.price_in_cents
+ end
+ columns_in_doubles.each do |column|
+ @acts_as_price_model.send(column).should == @acts_as_price_model.price
+ end
+
+ #normal test for setter
+ test_setter_in_cents "144"
+ test_setter_in_doubles "1.41"
+
+ #test for special cases
+ #test if 1.5 is returned as 1.50
+ test_setter_in_doubles "1.5"
+
+ #test if float returns 2.05 correctly
+ #float can return 2.05 as 2.04 in some cases
+ test_setter_in_doubles "2.05"
+
+ #test an empty_setter
+ test_setter_in_cents ""
+ test_setter_in_doubles ""
+ end
+
+ def test_setter_in_cents cents
+ columns_in_cents.each do |setter|
+ @acts_as_price_model.send("#{setter}=", cents)
+ columns_in_cents.each do |getter|
+ @acts_as_price_model.send(getter).should == cents.to_i
+ end
+ columns_in_doubles.each do |getter|
+ if cents == ""
+ @acts_as_price_model.send(getter).should == ""
+ else
+ @acts_as_price_model.send(getter).should == sprintf("%.2f", (cents.to_f / 100).to_s)
+ end
+ end
+ end
+ end
+
+ def test_setter_in_doubles double
+ columns_in_doubles.each do |setter|
+ @acts_as_price_model.send("#{setter}=", double)
+ columns_in_cents.each do |getter|
+ @acts_as_price_model.send(getter).should == (double.to_f * 100).to_s.to_i
+ end
+ columns_in_doubles.each do |getter|
+ if double == ""
+ @acts_as_price_model.send(getter).should == ""
+ else
+ @acts_as_price_model.send(getter).should == sprintf("%.2f", double)
+ end
+ end
+ end
+ end
+
+ def columns_in_cents
+ [:price_in_cents, "#{@column_name}_in_cents"]
+ end
+
+ def columns_in_doubles
+ [:price, @column_name]
+ end
+
+ def columns
+ columns_in_doubles + columns_in_cents
+ end
+end
@@ -0,0 +1,62 @@
+require "#{File.dirname(__FILE__)}/spec_helper"
+
+describe Car do
+ before(:each) do
+ @column_name = :price
+ @acts_as_price_model = stub_model(Car, :brand => "Ford", :cartype => "Focus", :price => "23995.99")
+ end
+
+ context "given an empty car" do
+ it "should return an invalid car" do
+ car = Car.new
+ should validate_presence_of :brand
+ should validate_presence_of :cartype
+ car.valid?.should be_false
+ car.save.should be_false
+ end
+ end
+
+ context "given an valid car" do
+ it "should succesfully save" do
+ car = Car.new @acts_as_price_model.attributes
+ car.valid?.should be_true
+ car.save.should be_true
+ end
+ end
+
+ context "return the fueltype price" do
+ it "should return the price in cents" do
+ columns_in_cents.each do |column|
+ @acts_as_price_model.send(column).should == 2399599
+ end
+ end
+ it "should return the price" do
+ columns_in_doubles.each do |column|
+ @acts_as_price_model.send(column).should == "23995.99"
+ end
+ end
+ end
+
+ context "set the price per liter" do
+ it "should set the price per liter in cents and return it correctly" do
+ test_setter_in_cents "2209998"
+ end
+ it "should set the price per liter and return it correctly" do
+ test_setter_in_doubles "25499.97"
+ end
+ end
+
+ context "given a float as price per liter" do
+ it "should convert it to the right price in cents" do
+ test_setter_in_doubles "25500.5"
+ test_setter_in_doubles "21599.05"
+ end
+ end
+
+ context "given the price is zero" do
+ it "should return an empty price per liter" do
+ test_setter_in_cents ""
+ test_setter_in_doubles ""
+ end
+ end
+end
@@ -0,0 +1,62 @@
+require "#{File.dirname(__FILE__)}/spec_helper"
+
+describe Fueltype do
+ before(:each) do
+ @column_name = :price_per_liter
+ @acts_as_price_model = stub_model(Fueltype, :name => "Euro 95", :price_per_liter => "1.55")
+ end
+
+ context "given an empty fueltype" do
+ it "should give an invalid fueltype and not save it" do
+ fueltype = Fueltype.new
+ should validate_presence_of :name
+ should validate_presence_of @column_name
+ fueltype.valid?.should be_false
+ fueltype.save.should be_false
+ end
+ end
+
+ context "given an valid fueltype" do
+ it "should be valid and saved" do
+ fueltype = Fueltype.new @acts_as_price_model.attributes
+ fueltype.valid?.should be_true
+ fueltype.save.should be_true
+ end
+ end
+
+ context "return the fueltype price" do
+ it "should return the price in cents" do
+ columns_in_cents.each do |column|
+ @acts_as_price_model.send(column).should == 155
+ end
+ end
+ it "should return the price" do
+ columns_in_doubles.each do |column|
+ @acts_as_price_model.send(column).should == "1.55"
+ end
+ end
+ end
+
+ context "set the price per liter" do
+ it "should set the price per liter in cents and return it correctly" do
+ test_setter_in_cents "144"
+ end
+ it "should set the price per liter and return it correctly" do
+ test_setter_in_doubles "1.41"
+ end
+ end
+
+ context "given a float as price per liter" do
+ it "should convert it to the right price in cents" do
+ test_setter_in_doubles "1.5"
+ test_setter_in_doubles "2.05"
+ end
+ end
+
+ context "given the price is zero" do
+ it "should return an empty price per liter" do
+ test_setter_in_cents ""
+ test_setter_in_doubles ""
+ end
+ end
+end
@@ -0,0 +1,7 @@
+#car model
+class Car < ActiveRecord::Base
+ validates :brand, :presence => true
+ validates :cartype, :presence => true
+
+ acts_as_price :price
+end
@@ -0,0 +1,6 @@
+#fueltype model
+class Fueltype < ActiveRecord::Base
+ validates :name, :presence => true
+
+ acts_as_price :price_per_liter, :validates => true
+end
Oops, something went wrong. Retry.

0 comments on commit 76d8527

Please sign in to comment.