Skip to content

Instantly share code, notes, and snippets.

@gregbell
Created April 28, 2010 18:00
Show Gist options
  • Save gregbell/382462 to your computer and use it in GitHub Desktop.
Save gregbell/382462 to your computer and use it in GitHub Desktop.
module HasMoney
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
#
# has_money :default_price
#
# def default_price_in_dollars
# end
#
# def default_price_in_dollars=(dollars)
# end
def has_money(*attributes)
attributes.each do |attribute|
class_eval <<-EOS
def #{attribute}_in_dollars
self.class.calculate_dollars_from_cents(#{attribute})
end
def #{attribute}_in_dollars=(dollars)
self.#{attribute} = self.class.calculate_cents_from_dollars(dollars)
end
EOS
end
end
def calculate_dollars_from_cents(cents)
return nil if cents.nil? || cents == ''
cents.to_f / 100
end
def calculate_cents_from_dollars(dollars)
return nil if dollars.nil? || dollars == ''
(dollars.gsub(/[^0]/).to_f * 100).round
end
end
end
# Inlcude in all AR Models
ActiveRecord::Base.send :include, HasMoney
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe HasMoney do
describe "including has money" do
it "should extend the class with class methods when included" do
klass = Class.new
klass.send :include, HasMoney
klass.should respond_to(:has_money)
end
end
describe "working with money" do
before(:each) do
@klass = Class.new
@klass.class_eval do
include HasMoney
attr_accessor :price
has_money :price
end
@product = @klass.new
@product.price = 2999
end
it "should create an accessor method named in_dollars for the attribute" do
@product.should respond_to(:price_in_dollars)
end
it "should create a setter method named in_dollars for the attribute" do
@product.should respond_to(:price_in_dollars=)
end
it "should return the amount in dollars" do
@product.price_in_dollars.should == 29.99
end
it "should set the amount in dollars with a float" do
@product.price_in_dollars = 39.99
@product.price.should == 3999
end
it "should set the amount in dollars with a string" do
@product.price_in_dollars = '39.99'
@product.price.should == 3999
end
it "should round the amount up to the nearest cent" do
@product.price_in_dollars = '39.998'
@product.price.should == 4000
end
it "should round the amount down to the nearest cent" do
@product.price_in_dollars = '39.992'
@product.price.should == 3999
end
it "should set nil if nil is passed as dollars" do
@product.price_in_dollars = nil
@product.price.should == nil
end
it "should set nil if an empty string is passed in as dollars" do
@product.price_in_dollars = ''
@product.price.should == nil
end
it "should return nil if the attribute is nil" do
@product.price = nil
@product.price_in_dollars.should == nil
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment