ShadowBelmolve-money 2.3.1
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/History.txt +0 -0
- data/MIT-LICENSE +21 -0
- data/Manifest.txt +25 -0
- data/README.rdoc +122 -0
- data/Rakefile +27 -0
- data/lib/money/acts_as_money.rb +41 -0
- data/lib/money/core_extensions.rb +139 -0
- data/lib/money/errors.rb +4 -0
- data/lib/money/money.rb +302 -0
- data/lib/money/variable_exchange_bank.rb +72 -0
- data/lib/money.rb +29 -0
- data/money.gemspec +37 -0
- data/rails/init.rb +3 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/db/database.yml +4 -0
- data/spec/db/schema.rb +14 -0
- data/spec/money/acts_as_money_spec.rb +98 -0
- data/spec/money/core_extensions_spec.rb +44 -0
- data/spec/money/exchange_bank_spec.rb +44 -0
- data/spec/money/money_spec.rb +216 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +20 -0
- metadata +100 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
require 'money/errors'
|
|
3
|
+
|
|
4
|
+
# Class for aiding in exchanging money between different currencies.
|
|
5
|
+
# By default, the Money class uses an object of this class (accessible through
|
|
6
|
+
# Money#bank) for performing currency exchanges.
|
|
7
|
+
#
|
|
8
|
+
# By default, VariableExchangeBank has no knowledge about conversion rates.
|
|
9
|
+
# One must manually specify them with +add_rate+, after which one can perform
|
|
10
|
+
# exchanges with +exchange+. For example:
|
|
11
|
+
#
|
|
12
|
+
# bank = Money::VariableExchangeBank.new
|
|
13
|
+
# bank.add_rate("USD", "CAD", 1.24515)
|
|
14
|
+
# bank.add_rate("CAD", "USD", 0.803115)
|
|
15
|
+
#
|
|
16
|
+
# # Exchange 100 CAD to USD:
|
|
17
|
+
# bank.exchange(100_00, "CAD", "USD") # => 124
|
|
18
|
+
# # Exchange 100 USD to CAD:
|
|
19
|
+
# bank.exchange(100_00, "USD", "CAD") # => 80
|
|
20
|
+
class Money
|
|
21
|
+
class VariableExchangeBank
|
|
22
|
+
# Returns the singleton instance of VariableExchangeBank.
|
|
23
|
+
#
|
|
24
|
+
# By default, <tt>Money.default_bank</tt> returns the same object.
|
|
25
|
+
def self.instance
|
|
26
|
+
@@singleton
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def initialize
|
|
30
|
+
@rates = {}
|
|
31
|
+
@mutex = Mutex.new
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Registers a conversion rate. +from+ and +to+ are both currency names.
|
|
35
|
+
def add_rate(from, to, rate)
|
|
36
|
+
@mutex.synchronize do
|
|
37
|
+
@rates["#{from}_TO_#{to}".upcase] = rate
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Gets the rate for exchanging the currency named +from+ to the currency
|
|
42
|
+
# named +to+. Returns nil if the rate is unknown.
|
|
43
|
+
def get_rate(from, to)
|
|
44
|
+
@mutex.synchronize do
|
|
45
|
+
@rates["#{from}_TO_#{to}".upcase]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Given two currency names, checks whether they're both the same currency.
|
|
50
|
+
#
|
|
51
|
+
# bank = VariableExchangeBank.new
|
|
52
|
+
# bank.same_currency?("usd", "USD") # => true
|
|
53
|
+
# bank.same_currency?("usd", "EUR") # => false
|
|
54
|
+
def same_currency?(currency1, currency2)
|
|
55
|
+
currency1.upcase == currency2.upcase
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Exchange the given amount of cents in +from_currency+ to +to_currency+.
|
|
59
|
+
# Returns the amount of cents in +to_currency+ as an integer, rounded down.
|
|
60
|
+
#
|
|
61
|
+
# If the conversion rate is unknown, then Money::UnknownRate will be raised.
|
|
62
|
+
def exchange(cents, from_currency, to_currency)
|
|
63
|
+
rate = get_rate(from_currency, to_currency)
|
|
64
|
+
if !rate
|
|
65
|
+
raise Money::UnknownRate, "No conversion rate known for '#{from_currency}' -> '#{to_currency}'"
|
|
66
|
+
end
|
|
67
|
+
(cents * rate).floor
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
@@singleton = VariableExchangeBank.new
|
|
71
|
+
end
|
|
72
|
+
end
|
data/lib/money.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Copyright (c) 2005 Tobias Luetke
|
|
2
|
+
# Copyright (c) 2008 Phusion
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__))
|
|
24
|
+
require 'money/money'
|
|
25
|
+
require 'money/core_extensions'
|
|
26
|
+
|
|
27
|
+
class Money
|
|
28
|
+
VERSION = "2.3.1"
|
|
29
|
+
end
|
data/money.gemspec
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |s|
|
|
4
|
+
s.name = %q{money}
|
|
5
|
+
s.version = "2.3.1"
|
|
6
|
+
|
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
8
|
+
s.authors = ["Money Team"]
|
|
9
|
+
s.date = %q{2009-03-15}
|
|
10
|
+
s.description = %q{This library aids one in handling money and different currencies.}
|
|
11
|
+
s.email = ["see@readme"]
|
|
12
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
|
|
13
|
+
s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "lib/money.rb", "lib/money/acts_as_money.rb", "lib/money/core_extensions.rb", "lib/money/errors.rb", "lib/money/money.rb", "lib/money/variable_exchange_bank.rb", "money.gemspec", "rails/init.rb", "script/console", "script/destroy", "script/generate", "spec/db/database.yml", "spec/db/schema.rb", "spec/money/acts_as_money_spec.rb", "spec/money/core_extensions_spec.rb", "spec/money/exchange_bank_spec.rb", "spec/money/money_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tmp/acts_as_money.sqlite3"]
|
|
14
|
+
s.has_rdoc = true
|
|
15
|
+
s.homepage = %q{http://github.com/ShadowBelmolve/money}
|
|
16
|
+
s.rdoc_options = ["--main", "README.rdoc"]
|
|
17
|
+
s.require_paths = ["lib"]
|
|
18
|
+
s.rubyforge_project = %q{money}
|
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
|
20
|
+
s.summary = %q{This library aids one in handling money and different currencies.}
|
|
21
|
+
|
|
22
|
+
if s.respond_to? :specification_version then
|
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
24
|
+
s.specification_version = 2
|
|
25
|
+
|
|
26
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
|
27
|
+
s.add_development_dependency(%q<newgem>, [">= 1.2.3"])
|
|
28
|
+
s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
|
|
29
|
+
else
|
|
30
|
+
s.add_dependency(%q<newgem>, [">= 1.2.3"])
|
|
31
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
s.add_dependency(%q<newgem>, [">= 1.2.3"])
|
|
35
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
|
36
|
+
end
|
|
37
|
+
end
|
data/rails/init.rb
ADDED
data/script/console
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# File: script/console
|
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
|
4
|
+
|
|
5
|
+
libs = " -r irb/completion"
|
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/postgis_adapter.rb'}"
|
|
9
|
+
puts "Loading postgis_adapter gem"
|
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
require 'rubigen'
|
|
6
|
+
rescue LoadError
|
|
7
|
+
require 'rubygems'
|
|
8
|
+
require 'rubigen'
|
|
9
|
+
end
|
|
10
|
+
require 'rubigen/scripts/destroy'
|
|
11
|
+
|
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
require 'rubigen'
|
|
6
|
+
rescue LoadError
|
|
7
|
+
require 'rubygems'
|
|
8
|
+
require 'rubigen'
|
|
9
|
+
end
|
|
10
|
+
require 'rubigen/scripts/generate'
|
|
11
|
+
|
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
data/spec/db/schema.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
ActiveRecord::Schema.define() do
|
|
2
|
+
|
|
3
|
+
create_table :accounts, :force => true do |t|
|
|
4
|
+
t.integer :value_cents, :total_cents
|
|
5
|
+
t.string :value_currency, :total_currency
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
create_table :products, :force => true do |t|
|
|
9
|
+
t.integer :value_cents, :tax_pennys
|
|
10
|
+
t.string :value_currency
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
|
2
|
+
require File.dirname(__FILE__) + '/../../rails/init.rb'
|
|
3
|
+
|
|
4
|
+
# Uncomment this once to create the db
|
|
5
|
+
load_schema
|
|
6
|
+
|
|
7
|
+
class Account < ActiveRecord::Base
|
|
8
|
+
has_money :value, :total, :allow_nil => true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class Product < ActiveRecord::Base
|
|
12
|
+
has_money :value, :allow_nil => false
|
|
13
|
+
has_money :tax, :cents => "pennys", :with_currency => false
|
|
14
|
+
|
|
15
|
+
validates_numericality_of :value_cents, :greater_than => 0
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "Acts as Money" do
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
it "should accept nil" do
|
|
22
|
+
@account = Account.create(:value => nil)
|
|
23
|
+
@account.should be_valid
|
|
24
|
+
@account.value.should be_nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should require money" do
|
|
28
|
+
@product = Product.create(:value => nil)
|
|
29
|
+
@product.should have(1).errors
|
|
30
|
+
@product.value.should == Money.new(0)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should require money" do
|
|
34
|
+
@product_fake = Product.create(:value => nil)
|
|
35
|
+
@product_fake.value_cents.should eql(0)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should create" do
|
|
39
|
+
@account = Account.create!(:value => 10, :total => "20 BRL")
|
|
40
|
+
@account.should be_valid
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should write to the db" do
|
|
44
|
+
lambda do
|
|
45
|
+
@account = Account.create!(:value => 10, :total => "20 BRL")
|
|
46
|
+
end.should change(Account, :count).by(1)
|
|
47
|
+
Account.last.total.format.should eql("R$20,00")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
describe "Account" do
|
|
53
|
+
|
|
54
|
+
before(:each) do
|
|
55
|
+
@account = Account.create!(:value => 10, :total => "20 BRL")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should return an instance of Money" do
|
|
59
|
+
@account.value.should be_instance_of(Money)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should format out nicely" do
|
|
63
|
+
@account.value.format.should eql("$10.00")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should include nicely" do
|
|
67
|
+
@account.value.to_s.should eql("10.00")
|
|
68
|
+
@account.total.to_s.should eql("20.00")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "should map cents" do
|
|
72
|
+
@account.value_cents.to_s.should eql("1000")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "should map currency" do
|
|
76
|
+
@account.value_currency.should eql("USD")
|
|
77
|
+
@account.total_currency.should eql("BRL")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
describe "Product" do
|
|
83
|
+
|
|
84
|
+
before(:each) do
|
|
85
|
+
@product = Product.create(:value => 10, :tax => 2)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should map attributes" do
|
|
89
|
+
@product.pennys.should eql(200)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "should map currency on tax" do
|
|
93
|
+
@product.should_not respond_to(:tax_currency)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
|
2
|
+
|
|
3
|
+
describe "Money core extensions" do
|
|
4
|
+
describe "Numberic#to_money works" do
|
|
5
|
+
it "should convert integer to money" do
|
|
6
|
+
money = 1234.to_money
|
|
7
|
+
money.cents.should == 1234_00
|
|
8
|
+
money.currency.should == Money.default_currency
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should convert float to money" do
|
|
12
|
+
money = 100.37.to_money
|
|
13
|
+
money.cents.should == 100_37
|
|
14
|
+
money.currency.should == Money.default_currency
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "String#to_money works" do
|
|
19
|
+
it { "100".to_money.should == Money.new(100_00) }
|
|
20
|
+
it { "100.37".to_money.should == Money.new(100_37) }
|
|
21
|
+
it { "100,37".to_money.should == Money.new(100_37) }
|
|
22
|
+
it { "100 000".to_money.should == Money.new(100_000_00) }
|
|
23
|
+
it { "100.000,45".to_money.should == Money.new(100_000_45) }
|
|
24
|
+
it { "-100.100,45".to_money.should == Money.new(-100_100_45) }
|
|
25
|
+
|
|
26
|
+
it { "100 USD".to_money.should == Money.new(100_00, "USD") }
|
|
27
|
+
it { "-100 USD".to_money.should == Money.new(-100_00, "USD") }
|
|
28
|
+
it { "100 EUR".to_money.should == Money.new(100_00, "EUR") }
|
|
29
|
+
it { "100.37 EUR".to_money.should == Money.new(100_37, "EUR") }
|
|
30
|
+
it { "100,37 EUR".to_money.should == Money.new(100_37, "EUR") }
|
|
31
|
+
|
|
32
|
+
it { "USD 100".to_money.should == Money.new(100_00, "USD") }
|
|
33
|
+
it { "EUR 100".to_money.should == Money.new(100_00, "EUR") }
|
|
34
|
+
it { "EUR 100.37".to_money.should == Money.new(100_37, "EUR") }
|
|
35
|
+
it { "CAD -100.37".to_money.should == Money.new(-100_37, "CAD") }
|
|
36
|
+
it { "EUR 100,37".to_money.should == Money.new(100_37, "EUR") }
|
|
37
|
+
it { "EUR -100,37".to_money.should == Money.new(-100_37, "EUR") }
|
|
38
|
+
|
|
39
|
+
it { "BRL 100,37".to_money.should == Money.new(100_37, "BRL") }
|
|
40
|
+
it { "BRL -100,37".to_money.should == Money.new(-100_37, "BRL") }
|
|
41
|
+
|
|
42
|
+
it {"$100 USD".to_money.should == Money.new(100_00, "USD") }
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
|
2
|
+
|
|
3
|
+
describe Money::VariableExchangeBank do
|
|
4
|
+
before :each do
|
|
5
|
+
@bank = Money::VariableExchangeBank.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "returns the previously specified conversion rate" do
|
|
9
|
+
@bank.add_rate("USD", "EUR", 0.788332676)
|
|
10
|
+
@bank.add_rate("EUR", "YEN", 122.631477)
|
|
11
|
+
@bank.get_rate("USD", "EUR").should == 0.788332676
|
|
12
|
+
@bank.get_rate("EUR", "YEN").should == 122.631477
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "treats currency names case-insensitively" do
|
|
16
|
+
@bank.add_rate("usd", "eur", 1)
|
|
17
|
+
@bank.get_rate("USD", "EUR").should == 1
|
|
18
|
+
@bank.same_currency?("USD", "usd").should be_true
|
|
19
|
+
@bank.same_currency?("EUR", "usd").should be_false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "returns nil if the conversion rate is unknown" do
|
|
23
|
+
@bank.get_rate("American Pesos", "EUR").should be_nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "exchanges money from one currency to another according to the specified conversion rates" do
|
|
27
|
+
@bank.add_rate("USD", "EUR", 0.5)
|
|
28
|
+
@bank.add_rate("EUR", "YEN", 10)
|
|
29
|
+
@bank.exchange(10_00, "USD", "EUR").should == 5_00
|
|
30
|
+
@bank.exchange(500_00, "EUR", "YEN").should == 5000_00
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "rounds the exchanged result down" do
|
|
34
|
+
@bank.add_rate("USD", "EUR", 0.788332676)
|
|
35
|
+
@bank.add_rate("EUR", "YEN", 122.631477)
|
|
36
|
+
@bank.exchange(10_00, "USD", "EUR").should == 788
|
|
37
|
+
@bank.exchange(500_00, "EUR", "YEN").should == 6131573
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "raises Money::UnknownRate upon conversion if the conversion rate is unknown" do
|
|
41
|
+
block = lambda { @bank.exchange(10, "USD", "EUR") }
|
|
42
|
+
block.should raise_error(Money::UnknownRate)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
|
3
|
+
|
|
4
|
+
describe Money do
|
|
5
|
+
it "is associated to the singleton instance of VariableExchangeBank by default" do
|
|
6
|
+
Money.new(0).bank.object_id.should == Money::VariableExchangeBank.instance.object_id
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should return the amount of cents passed to the constructor" do
|
|
10
|
+
Money.new(200_00, "USD").cents.should == 200_00
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should rounds the given cents to an integer" do
|
|
14
|
+
Money.new(1.00, "USD").cents.should == 1
|
|
15
|
+
Money.new(1.01, "USD").cents.should == 1
|
|
16
|
+
Money.new(1.50, "USD").cents.should == 2
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "#currency returns the currency passed to the constructor" do
|
|
20
|
+
Money.new(200_00, "USD").currency.should == "USD"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "#zero? returns whether the amount is 0" do
|
|
24
|
+
Money.new(0, "USD").should be_zero
|
|
25
|
+
Money.new(0, "EUR").should be_zero
|
|
26
|
+
Money.new(1, "USD").should_not be_zero
|
|
27
|
+
Money.new(10, "YEN").should_not be_zero
|
|
28
|
+
Money.new(-1, "EUR").should_not be_zero
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should exchange_to exchanges the amount via its exchange bank" do
|
|
32
|
+
money = Money.new(100_00, "USD")
|
|
33
|
+
money.bank.should_receive(:exchange).with(100_00, "USD", "EUR").and_return(200_00)
|
|
34
|
+
money.exchange_to("EUR")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "#exchange_to exchanges the amount properly" do
|
|
38
|
+
money = Money.new(100_00, "USD")
|
|
39
|
+
money.bank.should_receive(:exchange).with(100_00, "USD", "EUR").and_return(200_00)
|
|
40
|
+
money.exchange_to("EUR").should == Money.new(200_00, "EUR")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "#== returns true if and only if their amount and currency are equal" do
|
|
44
|
+
Money.new(1_00, "USD").should == Money.new(1_00, "USD")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "#* multiplies the money's amount by the multiplier while retaining the currency" do
|
|
48
|
+
(Money.new(1_00, "USD") * 10).should == Money.new(10_00, "USD")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "#* divides the money's amount by the divisor while retaining the currency" do
|
|
52
|
+
(Money.new(10_00, "USD") / 10).should == Money.new(1_00, "USD")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "# divides the money ammout in installments add last" do
|
|
56
|
+
@money = Money.new(10_00).split_in_installments(3)
|
|
57
|
+
@money[0].cents.should eql(334)
|
|
58
|
+
@money[1].cents.should eql(333)
|
|
59
|
+
@money[2].cents.should eql(333)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "# divides the money ammout in installments add first" do
|
|
63
|
+
@money = Money.new(10_00).split_in_installments(3,true)
|
|
64
|
+
@money.to_s.should eql(["3.34", "3.33", "3.33"])
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "# divides the money ammout in installments base on payment" do
|
|
68
|
+
money = Money.new(3_00)
|
|
69
|
+
Money.new(10_00).in_installments_of(money)[0].cents.should eql(334)
|
|
70
|
+
Money.new(10_00).in_installments_of(money)[1].cents.should eql(333)
|
|
71
|
+
Money.new(10_00).in_installments_of(money)[2].cents.should eql(333)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "shuld sum array" do
|
|
75
|
+
Money.new(10_00).split_in_installments(3).sum.cents.should eql(1000)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "should calculate tax" do
|
|
79
|
+
Money.new(100).add_tax(20).cents.should eql(120)
|
|
80
|
+
Money.new(100).add_tax(-20).cents.should eql(80)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "should calculate compound tax" do
|
|
84
|
+
@ma = Money.new(1000_00)
|
|
85
|
+
@ma.compound_interest(12.99,12).to_s.should eql("137.92")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should calculate compound tax" do
|
|
89
|
+
@ma = Money.new(1000_00)
|
|
90
|
+
@ma.simple_interest(12.99,12).to_s.should eql("129.90")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "should calculate compound tax" do
|
|
94
|
+
@ma = Money.new(2500_00)
|
|
95
|
+
@ma.compound_interest(12.99,3).to_s.should eql("82.07")
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "shuld sum array" do
|
|
99
|
+
@money = Money.new(10_00).add_tax(10)
|
|
100
|
+
@money.split_in_installments(3).sum.cents.should eql(1100)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it { Money.new(10_00).to_f.should eql(10.0) }
|
|
104
|
+
it { Money.new(10_00).to_s.should eql("10.00") }
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
it "should create a new Money object of 0 cents if empty" do
|
|
108
|
+
Money.empty.should == Money.new(0)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "Money.ca_dollar creates a new Money object of the given value in CAD" do
|
|
112
|
+
Money.ca_dollar(50).should == Money.new(50, "CAD")
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "Money.us_dollar creates a new Money object of the given value in USD" do
|
|
116
|
+
Money.us_dollar(50).should == Money.new(50, "USD")
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "Money.euro creates a new Money object of the given value in EUR" do
|
|
120
|
+
Money.euro(50).should == Money.new(50, "EUR")
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "Money.real creates a new Money object of the given value in BRL" do
|
|
124
|
+
Money.real(50).should == Money.new(50, "BRL")
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "Money.add_rate works" do
|
|
128
|
+
Money.add_rate("EUR", "USD", 10)
|
|
129
|
+
Money.new(10_00, "EUR").exchange_to("USD").should == Money.new(100_00, "USD")
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "Money method missing exchange" do
|
|
133
|
+
Money.add_rate("EUR", "BRL", 10)
|
|
134
|
+
Money.new(10_00, "EUR").as_brl.should == Money.new(100_00, "BRL")
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
describe "Format out " do
|
|
138
|
+
|
|
139
|
+
describe "Options" do
|
|
140
|
+
before(:each) do
|
|
141
|
+
@cash = Money.new(200)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it { @cash.format.should eql("$2.00") }
|
|
145
|
+
it { @cash.format(:symbol => "R$ ").should eql("R$ 2.00") }
|
|
146
|
+
it { @cash.format(:no_cents => true).should eql("$2") }
|
|
147
|
+
it { @cash.format(:no_cents => true, :symbol => "R$ ").should eql("R$ 2") }
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it { Money.new(0).format.should eql("$0.00") }
|
|
151
|
+
it { Money.new(0).format(:display_free => true).should eql("free") }
|
|
152
|
+
it { Money.new(0).format(:display_free => "GRATIS").should eql("GRATIS") }
|
|
153
|
+
|
|
154
|
+
it { Money.new(9).format.should eql("$0.09") }
|
|
155
|
+
it { Money.new(99).format.should eql("$0.99") }
|
|
156
|
+
it { Money.new(800).format.should eql("$8.00") }
|
|
157
|
+
it { Money.new(-8000).format(:no_cents => true).should eql("$-80") }
|
|
158
|
+
it { Money.new(80000).format.should eql("$800.00") }
|
|
159
|
+
it { Money.new(800000).format.should eql("$8,000.00") }
|
|
160
|
+
it { Money.new(-8000000, "JPY").format(:no_cents => true).should eql("¥-80.000") }
|
|
161
|
+
it { Money.new(87654321, "BRL").format.should eql("R$876.543,21") }
|
|
162
|
+
it { Money.new(800000000, "BRL").format.should eql("R$8.000.000,00") }
|
|
163
|
+
it { Money.new(8000000000, "BRL").format.should eql("R$80.000.000,00") }
|
|
164
|
+
it { Money.new(80000000000, "CAD").format.should eql("$800,000,000.00") }
|
|
165
|
+
it { Money.new(880000000000, "GBP").format(:no_cents => true).should eql("£8,800,000,000") }
|
|
166
|
+
it { Money.new(8800000000088, "EUR").format.should eql("€88,000,000,000.88") }
|
|
167
|
+
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
describe "Actions involving two Money objects" do
|
|
172
|
+
describe "if the other Money object has the same currency" do
|
|
173
|
+
it "#<=> compares the two objects' amounts" do
|
|
174
|
+
(Money.new(1_00, "USD") <=> Money.new(1_00, "USD")).should == 0
|
|
175
|
+
(Money.new(1_00, "USD") <=> Money.new(99, "USD")).should > 0
|
|
176
|
+
(Money.new(1_00, "USD") <=> Money.new(2_00, "USD")).should < 0
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it "#+ adds the other object's amount to the current object's amount while retaining the currency" do
|
|
180
|
+
(Money.new(10_00, "USD") + Money.new(90, "USD")).should == Money.new(10_90, "USD")
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
it "#- substracts the other object's amount from the current object's amount while retaining the currency" do
|
|
184
|
+
(Money.new(10_00, "USD") - Money.new(90, "USD")).should == Money.new(9_10, "USD")
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
describe "if the other Money object has a different currency" do
|
|
189
|
+
it "#<=> compares the two objects' amount after converting the other object's amount to its own currency" do
|
|
190
|
+
target = Money.new(200_00, "EUR")
|
|
191
|
+
target.should_receive(:exchange_to).with("USD").and_return(Money.new(300_00, "USD"))
|
|
192
|
+
(Money.new(100_00, "USD") <=> target).should < 0
|
|
193
|
+
|
|
194
|
+
target = Money.new(200_00, "EUR")
|
|
195
|
+
target.should_receive(:exchange_to).with("USD").and_return(Money.new(100_00, "USD"))
|
|
196
|
+
(Money.new(100_00, "USD") <=> target).should == 0
|
|
197
|
+
|
|
198
|
+
target = Money.new(200_00, "EUR")
|
|
199
|
+
target.should_receive(:exchange_to).with("USD").and_return(Money.new(99_00, "USD"))
|
|
200
|
+
(Money.new(100_00, "USD") <=> target).should > 0
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it "#+ adds the other object's amount, converted to this object's currency, to this object's amount while retaining its currency" do
|
|
204
|
+
other = Money.new(90, "EUR")
|
|
205
|
+
other.should_receive(:exchange_to).with("USD").and_return(Money.new(9_00, "USD"))
|
|
206
|
+
(Money.new(10_00, "USD") + other).should == Money.new(19_00, "USD")
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it "#- substracts the other object's amount, converted to this object's currency, from this object's amount while retaining its currency" do
|
|
210
|
+
other = Money.new(90, "EUR")
|
|
211
|
+
other.should_receive(:exchange_to).with("USD").and_return(Money.new(9_00, "USD"))
|
|
212
|
+
(Money.new(10_00, "USD") - other).should == Money.new(1_00, "USD")
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'spec'
|
|
3
|
+
require 'active_record'
|
|
4
|
+
rescue LoadError
|
|
5
|
+
require 'rubygems'
|
|
6
|
+
gem 'rspec'
|
|
7
|
+
require 'spec'
|
|
8
|
+
end
|
|
9
|
+
require 'active_record'
|
|
10
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
|
11
|
+
require 'money'
|
|
12
|
+
|
|
13
|
+
config = YAML.load_file(File.dirname(__FILE__) + '/db/database.yml')
|
|
14
|
+
ActiveRecord::Base.logger = Logger.new("/tmp/money-debug.log")
|
|
15
|
+
ActiveRecord::Base.establish_connection(config)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def load_schema
|
|
19
|
+
load(File.dirname(__FILE__) + "/db/schema.rb")
|
|
20
|
+
end
|