monetize 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c1c2a9a44b80e3d27927f8d5a0771ecd796f7061
4
+ data.tar.gz: da0255a4102dec917a27f22808b4ec2f6535fa12
5
+ SHA512:
6
+ metadata.gz: 28eb3b256dc924f5d643c61dcd3b17e0f7d9df444c4daca6077b7ac0dff29741149ad1b5ddc55d83e8d12fe79abe45d1c595638f52a77af6db129bbfa59761b3
7
+ data.tar.gz: 800592844fdfdf4fb66df3855b14c51240a7516f44c687eaea16bd6a7a27d713b41f4a2ea8096e4eb43aa64137e318efbc930921afea5e7e9bbbb90943cc018c
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Shane Emmons
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Monetize
2
+
3
+ A library for converting various objects into `Money` objects.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'monetize'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install monetize
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ # Coming Soon
23
+ ```
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/lib/monetize.rb ADDED
@@ -0,0 +1,135 @@
1
+ require "money"
2
+ require "monetize/version"
3
+
4
+ module Monetize
5
+ def self.parse(input, currency = Money.default_currency)
6
+ input = input.to_s.strip
7
+
8
+ computed_currency = if Money.assume_from_symbol && input =~ /^(\$|€|£)/
9
+ case input
10
+ when /^\$/ then "USD"
11
+ when /^€/ then "EUR"
12
+ when /^£/ then "GBP"
13
+ end
14
+ else
15
+ input[/[A-Z]{2,3}/]
16
+ end
17
+
18
+ currency = computed_currency || currency || Money.default_currency
19
+ currency = Money::Currency.wrap(currency)
20
+
21
+ fractional = extract_cents(input, currency)
22
+ Money.new(fractional, currency)
23
+ end
24
+
25
+ def self.from_string(value, currency = Money.default_currency)
26
+ value = BigDecimal.new(value.to_s)
27
+ from_bigdecimal(value, currency)
28
+ end
29
+
30
+ def self.from_fixnum(value, currency = Money.default_currency)
31
+ currency = Money::Currency.wrap(currency)
32
+ value = value * currency.subunit_to_unit
33
+ Money.new(value, currency)
34
+ end
35
+
36
+ def self.from_float(value, currency = Money.default_currency)
37
+ value = BigDecimal.new(value.to_s)
38
+ from_bigdecimal(value, currency)
39
+ end
40
+
41
+ def self.from_bigdecimal(value, currency = Money.default_currency)
42
+ currency = Money::Currency.wrap(currency)
43
+ value = value * currency.subunit_to_unit
44
+ value = value.round unless Money.infinite_precision
45
+ Money.new(value, currency)
46
+ end
47
+
48
+ def self.from_numeric(value, currency = Money.default_currency)
49
+ case value
50
+ when Fixnum
51
+ from_fixnum(value, currency)
52
+ when Numeric
53
+ value = BigDecimal.new(value.to_s)
54
+ from_bigdecimal(value, currency)
55
+ else
56
+ raise ArgumentError, "'value' should be a type of Numeric"
57
+ end
58
+ end
59
+
60
+ def self.extract_cents(input, currency = Money.default_currency)
61
+ num = input.gsub(/[^\d.,'-]/, '')
62
+
63
+ negative = num =~ /^-|-$/ ? true : false
64
+
65
+ decimal_char = currency.decimal_mark
66
+
67
+ num = num.sub(/^-|-$/, '') if negative
68
+
69
+ if num.include?('-')
70
+ raise ArgumentError, "Invalid currency amount (hyphen)"
71
+ end
72
+
73
+ num.chop! if num.match(/[\.|,]$/)
74
+
75
+ used_delimiters = num.scan(/[^\d]/)
76
+
77
+ case used_delimiters.uniq.length
78
+ when 0
79
+ major, minor = num, 0
80
+ when 2
81
+ thousands_separator, decimal_mark = used_delimiters.uniq
82
+
83
+ major, minor = num.gsub(thousands_separator, '').split(decimal_mark)
84
+ min = 0 unless min
85
+ when 1
86
+ decimal_mark = used_delimiters.first
87
+
88
+ if decimal_char == decimal_mark
89
+ major, minor = num.split(decimal_char)
90
+ else
91
+ if num.scan(decimal_mark).length > 1 # multiple matches; treat as decimal_mark
92
+ major, minor = num.gsub(decimal_mark, ''), 0
93
+ else
94
+ possible_major, possible_minor = num.split(decimal_mark)
95
+ possible_major ||= "0"
96
+ possible_minor ||= "00"
97
+
98
+ if possible_minor.length != 3 # thousands_separator
99
+ major, minor = possible_major, possible_minor
100
+ else
101
+ if possible_major.length > 3
102
+ major, minor = possible_major, possible_minor
103
+ else
104
+ if decimal_mark == '.'
105
+ major, minor = possible_major, possible_minor
106
+ else
107
+ major, minor = "#{possible_major}#{possible_minor}", 0
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ else
114
+ raise ArgumentError, "Invalid currency amount"
115
+ end
116
+
117
+ cents = major.to_i * currency.subunit_to_unit
118
+ minor = minor.to_s
119
+ minor = if minor.size < currency.decimal_places
120
+ (minor + ("0" * currency.decimal_places))[0,currency.decimal_places].to_i
121
+ elsif minor.size > currency.decimal_places
122
+ if minor[currency.decimal_places,1].to_i >= 5
123
+ minor[0,currency.decimal_places].to_i+1
124
+ else
125
+ minor[0,currency.decimal_places].to_i
126
+ end
127
+ else
128
+ minor.to_i
129
+ end
130
+
131
+ cents += minor
132
+
133
+ negative ? cents * -1 : cents
134
+ end
135
+ end
@@ -0,0 +1,3 @@
1
+ require "monetize/core_extensions/numeric"
2
+ require "monetize/core_extensions/string"
3
+ require "monetize/core_extensions/symbol"
@@ -0,0 +1,5 @@
1
+ class Numeric
2
+ def to_money(currency = nil)
3
+ Monetize.from_numeric(self, currency || Money.default_currency)
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ class String
2
+ def to_money(currency = nil)
3
+ Monetize.parse(self, currency)
4
+ end
5
+
6
+ def to_currency
7
+ Money::Currency.new(self)
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class Symbol
2
+ def to_currency
3
+ Money::Currency.new(self)
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Monetize
2
+ VERSION = "0.1.0"
3
+ end
data/monetize.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "monetize/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "monetize"
8
+ spec.version = Monetize::VERSION
9
+ spec.authors = ["Shane Emmons"]
10
+ spec.email = ["shane@emmons.io"]
11
+ spec.description = "A library for converting various objects into `Money` objects."
12
+ spec.summary = "A library for converting various objects into `Money` objects."
13
+ spec.homepage = "https://github.com/RubyMoney/monetize"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "money", "~> 6.0"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec", "~> 3.0.0.beta1"
26
+ end
@@ -0,0 +1,161 @@
1
+ require "spec_helper"
2
+ require "monetize"
3
+ require "monetize/core_extensions"
4
+
5
+ describe Monetize, "core extensions" do
6
+ describe Numeric do
7
+ describe "#to_money" do
8
+ it "work as documented" do
9
+ money = 1234.to_money
10
+ expect(money.cents).to eq 1234_00
11
+ expect(money.currency).to eq Money.default_currency
12
+
13
+ money = 100.37.to_money
14
+ expect(money.cents).to eq 100_37
15
+ expect(money.currency).to eq Money.default_currency
16
+
17
+ money = BigDecimal.new('1234').to_money
18
+ expect(money.cents).to eq 1234_00
19
+ expect(money.currency).to eq Money.default_currency
20
+ end
21
+
22
+ it "accepts optional currency" do
23
+ expect(1234.to_money('USD')).to eq Money.new(123400, 'USD')
24
+ expect(1234.to_money('EUR')).to eq Money.new(123400, 'EUR')
25
+ end
26
+
27
+ it "respects :subunit_to_unit currency property" do
28
+ expect(10.to_money('USD')).to eq Money.new(10_00, 'USD')
29
+ expect(10.to_money('TND')).to eq Money.new(10_000, 'TND')
30
+ expect(10.to_money('CLP')).to eq Money.new(10, 'CLP')
31
+ end
32
+
33
+ specify "GH-15" do
34
+ amount = 555.55.to_money
35
+ expect(amount).to eq Money.new(55555)
36
+ end
37
+ end
38
+ end
39
+
40
+ describe String do
41
+ describe "#to_money" do
42
+
43
+ STRING_TO_MONEY = {
44
+ "20.15" => Money.new(20_15) ,
45
+ "100" => Money.new(100_00) ,
46
+ "100.37" => Money.new(100_37) ,
47
+ "100,37" => Money.new(100_37) ,
48
+ "100 000" => Money.new(100_000_00) ,
49
+ "100,000.00" => Money.new(100_000_00) ,
50
+ "1,000" => Money.new(1_000_00) ,
51
+ "-1,000" => Money.new(-1_000_00) ,
52
+ "1,000.5" => Money.new(1_000_50) ,
53
+ "1,000.51" => Money.new(1_000_51) ,
54
+ "1,000.505" => Money.new(1_000_51) ,
55
+ "1,000.504" => Money.new(1_000_50) ,
56
+ "1,000.0000" => Money.new(1_000_00) ,
57
+ "1,000.5000" => Money.new(1_000_50) ,
58
+ "1,000.5099" => Money.new(1_000_51) ,
59
+ "1.550" => Money.new(1_55) ,
60
+ "25." => Money.new(25_00) ,
61
+ ".75" => Money.new(75) ,
62
+
63
+ "100 USD" => Money.new(100_00, "USD") ,
64
+ "-100 USD" => Money.new(-100_00, "USD") ,
65
+ "100 EUR" => Money.new(100_00, "EUR") ,
66
+ "100.37 EUR" => Money.new(100_37, "EUR") ,
67
+ "100,37 EUR" => Money.new(100_37, "EUR") ,
68
+ "100,000.00 USD" => Money.new(100_000_00, "USD") ,
69
+ "100.000,00 EUR" => Money.new(100_000_00, "EUR") ,
70
+ "1,000 USD" => Money.new(1_000_00, "USD") ,
71
+ "-1,000 USD" => Money.new(-1_000_00, "USD") ,
72
+ "1,000.5500 USD" => Money.new(1_000_55, "USD") ,
73
+ "-1,000.6500 USD" => Money.new(-1_000_65, "USD") ,
74
+ "1.550 USD" => Money.new(1_55, "USD") ,
75
+
76
+ "USD 100" => Money.new(100_00, "USD") ,
77
+ "EUR 100" => Money.new(100_00, "EUR") ,
78
+ "EUR 100.37" => Money.new(100_37, "EUR") ,
79
+ "CAD -100.37" => Money.new(-100_37, "CAD") ,
80
+ "EUR 100,37" => Money.new(100_37, "EUR") ,
81
+ "EUR -100,37" => Money.new(-100_37, "EUR") ,
82
+ "USD 100,000.00" => Money.new(100_000_00, "USD") ,
83
+ "EUR 100.000,00" => Money.new(100_000_00, "EUR") ,
84
+ "USD 1,000" => Money.new(1_000_00, "USD") ,
85
+ "USD -1,000" => Money.new(-1_000_00, "USD") ,
86
+ "USD 1,000.9000" => Money.new(1_000_90, "USD") ,
87
+ "USD -1,000.090" => Money.new(-1_000_09, "USD") ,
88
+ "USD 1.5500" => Money.new(1_55, "USD") ,
89
+
90
+ "$100 USD" => Money.new(100_00, "USD") ,
91
+ "$1,194.59 USD" => Money.new(1_194_59, "USD") ,
92
+ "$-1,955 USD" => Money.new(-1_955_00, "USD") ,
93
+ "$1,194.5900 USD" => Money.new(1_194_59, "USD") ,
94
+ "$-1,955.000 USD" => Money.new(-1_955_00, "USD") ,
95
+ "$1.99000 USD" => Money.new(1_99, "USD") ,
96
+ }
97
+
98
+ it "works as documented" do
99
+ STRING_TO_MONEY.each do |string, money|
100
+ expect(string.to_money).to eq money
101
+ end
102
+ end
103
+
104
+ it "coerces input to string" do
105
+ expect(Monetize.parse(20, "USD")).to eq Money.new(20_00, "USD")
106
+ end
107
+
108
+ it "accepts optional currency" do
109
+ expect("10.10".to_money('USD')).to eq Money.new(1010, 'USD')
110
+ expect("10.10".to_money('EUR')).to eq Money.new(1010, 'EUR')
111
+ expect("10.10 USD".to_money('USD')).to eq Money.new(1010, 'USD')
112
+ end
113
+
114
+ it "uses parsed currency, even if currency is passed" do
115
+ expect("10.10 USD".to_money("EUR")).to eq(Money.new(1010, "USD"))
116
+ end
117
+
118
+ it "ignores unrecognized data" do
119
+ expect("hello 2000 world".to_money).to eq Money.new(2000_00)
120
+ end
121
+
122
+ it "respects :subunit_to_unit currency property" do
123
+ expect("1".to_money("USD")).to eq Money.new(1_00, "USD")
124
+ expect("1".to_money("TND")).to eq Money.new(1_000, "TND")
125
+ expect("1".to_money("CLP")).to eq Money.new(1, "CLP")
126
+ expect("1.5".to_money("KWD").cents).to eq 1500
127
+ end
128
+ end
129
+
130
+ describe "#to_currency" do
131
+ it "converts String to Currency" do
132
+ expect("USD".to_currency).to eq Money::Currency.new("USD")
133
+ expect("EUR".to_currency).to eq Money::Currency.new("EUR")
134
+ end
135
+
136
+ it "raises Money::Currency::UnknownCurrency with unknown Currency" do
137
+ expect { "XXX".to_currency }.to raise_error(Money::Currency::UnknownCurrency)
138
+ expect { " ".to_currency }.to raise_error(Money::Currency::UnknownCurrency)
139
+ end
140
+ end
141
+ end
142
+
143
+ describe Symbol do
144
+ describe "#to_currency" do
145
+ it "converts Symbol to Currency" do
146
+ expect(:usd.to_currency).to eq Money::Currency.new("USD")
147
+ expect(:ars.to_currency).to eq Money::Currency.new("ARS")
148
+ end
149
+
150
+ it "is case-insensitive" do
151
+ expect(:EUR.to_currency).to eq Money::Currency.new("EUR")
152
+ end
153
+
154
+ it "raises Money::Currency::UnknownCurrency with unknown Currency" do
155
+ expect { :XXX.to_currency }.to raise_error(Money::Currency::UnknownCurrency)
156
+ expect { :" ".to_currency }.to raise_error(Money::Currency::UnknownCurrency)
157
+ end
158
+ end
159
+ end
160
+
161
+ end
@@ -0,0 +1,323 @@
1
+ require "spec_helper"
2
+ require "monetize"
3
+
4
+ describe Monetize do
5
+
6
+ bar = '{ "priority": 1, "iso_code": "BAR", "iso_numeric": "840", "name": "Dollar with 4 decimal places", "symbol": "$", "subunit": "Cent", "subunit_to_unit": 10000, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": "," }'
7
+ eu4 = '{ "priority": 1, "iso_code": "EU4", "iso_numeric": "841", "name": "Euro with 4 decimal places", "symbol": "€", "subunit": "Cent", "subunit_to_unit": 10000, "symbol_first": true, "html_entity": "€", "decimal_mark": ",", "thousands_separator": "." }'
8
+
9
+ describe ".parse" do
10
+
11
+ it "parses european-formatted inputs under 10EUR" do
12
+ expect(Monetize.parse('EUR 5,95')).to eq Money.new(595, 'EUR')
13
+ end
14
+
15
+ it "parses european-formatted inputs with multiple thousands-seperators" do
16
+ expect(Monetize.parse('EUR 1.234.567,89')).to eq Money.new(123456789, 'EUR')
17
+ expect(Monetize.parse('EUR 1.111.234.567,89')).to eq Money.new(111123456789, 'EUR')
18
+ end
19
+
20
+ describe 'currency assumption' do
21
+ context 'opted in' do
22
+ before do
23
+ Money.assume_from_symbol = true
24
+ end
25
+
26
+ it "parses formatted inputs with the currency passed as a symbol" do
27
+ original_currency = Money.default_currency
28
+ Money.default_currency = "EUR"
29
+ Money.default_currency = original_currency
30
+ expect(Monetize.parse("€5.95")).to eq Money.new(595, 'EUR')
31
+ expect(Monetize.parse(" €5.95 ")).to eq Money.new(595, 'EUR')
32
+ expect(Monetize.parse("£9.99")).to eq Money.new(999, 'GBP')
33
+ end
34
+
35
+ it 'should assume default currency if not a recognised symbol' do
36
+ expect(Monetize.parse("L9.99")).to eq Money.new(999, 'USD')
37
+ end
38
+ end
39
+ context 'opted out' do
40
+ before do
41
+ Money.assume_from_symbol = false
42
+ end
43
+ it "parses formatted inputs with the currency passed as a symbol but ignores the symbol" do
44
+ expect(Monetize.parse("$5.95")).to eq Money.new(595, 'USD')
45
+ expect(Monetize.parse("€5.95")).to eq Money.new(595, 'USD')
46
+ expect(Monetize.parse(" €5.95 ")).to eq Money.new(595, 'USD')
47
+ expect(Monetize.parse("£9.99")).to eq Money.new(999, 'USD')
48
+
49
+ end
50
+ end
51
+ it 'should opt out by default' do
52
+ expect(Money.assume_from_symbol).to be false
53
+ end
54
+ end
55
+
56
+ it "parses USD-formatted inputs under $10" do
57
+ five_ninety_five = Money.new(595, 'USD')
58
+
59
+ expect(Monetize.parse(5.95)).to eq five_ninety_five
60
+ expect(Monetize.parse('5.95')).to eq five_ninety_five
61
+ expect(Monetize.parse('$5.95')).to eq five_ninety_five
62
+ expect(Monetize.parse("\n $5.95 \n")).to eq five_ninety_five
63
+ expect(Monetize.parse('$ 5.95')).to eq five_ninety_five
64
+ expect(Monetize.parse('$5.95 ea.')).to eq five_ninety_five
65
+ expect(Monetize.parse('$5.95, each')).to eq five_ninety_five
66
+ end
67
+
68
+ it "parses USD-formatted inputs with multiple thousands-seperators" do
69
+ expect(Monetize.parse('1,234,567.89')).to eq Money.new(123456789, 'USD')
70
+ expect(Monetize.parse('1,111,234,567.89')).to eq Money.new(111123456789, 'USD')
71
+ end
72
+
73
+ it "does not return a price if there is a price range" do
74
+ expect { Monetize.parse('$5.95-10.95') }.to raise_error ArgumentError
75
+ expect { Monetize.parse('$5.95 - 10.95') }.to raise_error ArgumentError
76
+ expect { Monetize.parse('$5.95 - $10.95') }.to raise_error ArgumentError
77
+ end
78
+
79
+ it "does not return a price for completely invalid input" do
80
+ expect(Monetize.parse(nil)).to eq Money.empty
81
+ expect(Monetize.parse('hellothere')).to eq Money.empty
82
+ expect(Monetize.parse('')).to eq Money.empty
83
+ end
84
+
85
+ it "handles negative inputs" do
86
+ five_ninety_five = Money.new(-595, 'USD')
87
+
88
+ expect(Monetize.parse("$-5.95")).to eq five_ninety_five
89
+ expect(Monetize.parse("-$5.95")).to eq five_ninety_five
90
+ expect(Monetize.parse("$5.95-")).to eq five_ninety_five
91
+ end
92
+
93
+ it "raises ArgumentError when unable to detect polarity" do
94
+ expect { Monetize.parse('-$5.95-') }.to raise_error ArgumentError
95
+ end
96
+
97
+ it "parses correctly strings with exactly 3 decimal digits" do
98
+ expect(Monetize.parse("6,534", "EUR")).to eq Money.new(653, "EUR")
99
+ end
100
+
101
+ context "custom currencies with 4 decimal places" do
102
+ before :each do
103
+ Money::Currency.register(JSON.parse(bar, :symbolize_names => true))
104
+ Money::Currency.register(JSON.parse(eu4, :symbolize_names => true))
105
+ end
106
+
107
+ after :each do
108
+ Money::Currency.unregister(JSON.parse(bar, :symbolize_names => true))
109
+ Money::Currency.unregister(JSON.parse(eu4, :symbolize_names => true))
110
+ end
111
+
112
+ # String#to_money(Currency) is equivalent to Monetize.parse(String, Currency)
113
+ it "parses strings respecting subunit to unit, decimal and thousands separator" do
114
+ expect("$0.4".to_money("BAR")).to eq Money.new(4000, "BAR")
115
+ expect("€0,4".to_money("EU4")).to eq Money.new(4000, "EU4")
116
+
117
+ expect("$0.04".to_money("BAR")).to eq Money.new(400, "BAR")
118
+ expect("€0,04".to_money("EU4")).to eq Money.new(400, "EU4")
119
+
120
+ expect("$0.004".to_money("BAR")).to eq Money.new(40, "BAR")
121
+ expect("€0,004".to_money("EU4")).to eq Money.new(40, "EU4")
122
+
123
+ expect("$0.0004".to_money("BAR")).to eq Money.new(4, "BAR")
124
+ expect("€0,0004".to_money("EU4")).to eq Money.new(4, "EU4")
125
+
126
+ expect("$0.0024".to_money("BAR")).to eq Money.new(24, "BAR")
127
+ expect("€0,0024".to_money("EU4")).to eq Money.new(24, "EU4")
128
+
129
+ expect("$0.0324".to_money("BAR")).to eq Money.new(324, "BAR")
130
+ expect("€0,0324".to_money("EU4")).to eq Money.new(324, "EU4")
131
+
132
+ expect("$0.5324".to_money("BAR")).to eq Money.new(5324, "BAR")
133
+ expect("€0,5324".to_money("EU4")).to eq Money.new(5324, "EU4")
134
+
135
+ expect("$6.5324".to_money("BAR")).to eq Money.new(65324, "BAR")
136
+ expect("€6,5324".to_money("EU4")).to eq Money.new(65324, "EU4")
137
+
138
+ expect("$86.5324".to_money("BAR")).to eq Money.new(865324, "BAR")
139
+ expect("€86,5324".to_money("EU4")).to eq Money.new(865324, "EU4")
140
+
141
+ expect("$186.5324".to_money("BAR")).to eq Money.new(1865324, "BAR")
142
+ expect("€186,5324".to_money("EU4")).to eq Money.new(1865324, "EU4")
143
+
144
+ expect("$3,331.0034".to_money("BAR")).to eq Money.new(33310034, "BAR")
145
+ expect("€3.331,0034".to_money("EU4")).to eq Money.new(33310034, "EU4")
146
+
147
+ expect("$8,883,331.0034".to_money("BAR")).to eq Money.new(88833310034, "BAR")
148
+ expect("€8.883.331,0034".to_money("EU4")).to eq Money.new(88833310034, "EU4")
149
+ end
150
+ end
151
+ end
152
+
153
+ describe ".from_string" do
154
+ it "converts given amount to cents" do
155
+ expect(Monetize.from_string("1")).to eq Money.new(1_00)
156
+ expect(Monetize.from_string("1")).to eq Money.new(1_00, "USD")
157
+ expect(Monetize.from_string("1", "EUR")).to eq Money.new(1_00, "EUR")
158
+ end
159
+
160
+ it "respects :subunit_to_unit currency property" do
161
+ expect(Monetize.from_string("1", "USD")).to eq Money.new(1_00, "USD")
162
+ expect(Monetize.from_string("1", "TND")).to eq Money.new(1_000, "TND")
163
+ expect(Monetize.from_string("1", "CLP")).to eq Money.new(1, "CLP")
164
+ end
165
+
166
+ it "accepts a currency options" do
167
+ m = Monetize.from_string("1")
168
+ expect(m.currency).to eq Money.default_currency
169
+
170
+ m = Monetize.from_string("1", Money::Currency.wrap("EUR"))
171
+ expect(m.currency).to eq Money::Currency.wrap("EUR")
172
+
173
+ m = Monetize.from_string("1", "EUR")
174
+ expect(m.currency).to eq Money::Currency.wrap("EUR")
175
+ end
176
+ end
177
+
178
+ describe ".from_fixnum" do
179
+ it "converts given amount to cents" do
180
+ expect(Monetize.from_fixnum(1)).to eq Money.new(1_00)
181
+ expect(Monetize.from_fixnum(1)).to eq Money.new(1_00, "USD")
182
+ expect(Monetize.from_fixnum(1, "EUR")).to eq Money.new(1_00, "EUR")
183
+ end
184
+
185
+ it "should respect :subunit_to_unit currency property" do
186
+ expect(Monetize.from_fixnum(1, "USD")).to eq Money.new(1_00, "USD")
187
+ expect(Monetize.from_fixnum(1, "TND")).to eq Money.new(1_000, "TND")
188
+ expect(Monetize.from_fixnum(1, "CLP")).to eq Money.new(1, "CLP")
189
+ end
190
+
191
+ it "accepts a currency options" do
192
+ m = Monetize.from_fixnum(1)
193
+ expect(m.currency).to eq Money.default_currency
194
+
195
+ m = Monetize.from_fixnum(1, Money::Currency.wrap("EUR"))
196
+ expect(m.currency).to eq Money::Currency.wrap("EUR")
197
+
198
+ m = Monetize.from_fixnum(1, "EUR")
199
+ expect(m.currency).to eq Money::Currency.wrap("EUR")
200
+ end
201
+ end
202
+
203
+ describe ".from_float" do
204
+ it "converts given amount to cents" do
205
+ expect(Monetize.from_float(1.2)).to eq Money.new(1_20)
206
+ expect(Monetize.from_float(1.2)).to eq Money.new(1_20, "USD")
207
+ expect(Monetize.from_float(1.2, "EUR")).to eq Money.new(1_20, "EUR")
208
+ end
209
+
210
+ it "respects :subunit_to_unit currency property" do
211
+ expect(Monetize.from_float(1.2, "USD")).to eq Money.new(1_20, "USD")
212
+ expect(Monetize.from_float(1.2, "TND")).to eq Money.new(1_200, "TND")
213
+ expect(Monetize.from_float(1.2, "CLP")).to eq Money.new(1, "CLP")
214
+ end
215
+
216
+ it "accepts a currency options" do
217
+ m = Monetize.from_float(1.2)
218
+ expect(m.currency).to eq Money.default_currency
219
+
220
+ m = Monetize.from_float(1.2, Money::Currency.wrap("EUR"))
221
+ expect(m.currency).to eq Money::Currency.wrap("EUR")
222
+
223
+ m = Monetize.from_float(1.2, "EUR")
224
+ expect(m.currency).to eq Money::Currency.wrap("EUR")
225
+ end
226
+ end
227
+
228
+ describe ".from_bigdecimal" do
229
+ it "converts given amount to cents" do
230
+ expect(Monetize.from_bigdecimal(BigDecimal.new("1"))).to eq Money.new(1_00)
231
+ expect(Monetize.from_bigdecimal(BigDecimal.new("1"))).to eq Money.new(1_00, "USD")
232
+ expect(Monetize.from_bigdecimal(BigDecimal.new("1"), "EUR")).to eq Money.new(1_00, "EUR")
233
+ end
234
+
235
+ it "respects :subunit_to_unit currency property" do
236
+ expect(Monetize.from_bigdecimal(BigDecimal.new("1"), "USD")).to eq Money.new(1_00, "USD")
237
+ expect(Monetize.from_bigdecimal(BigDecimal.new("1"), "TND")).to eq Money.new(1_000, "TND")
238
+ expect(Monetize.from_bigdecimal(BigDecimal.new("1"), "CLP")).to eq Money.new(1, "CLP")
239
+ end
240
+
241
+ it "accepts a currency options" do
242
+ m = Monetize.from_bigdecimal(BigDecimal.new("1"))
243
+ expect(m.currency).to eq Money.default_currency
244
+
245
+ m = Monetize.from_bigdecimal(BigDecimal.new("1"), Money::Currency.wrap("EUR"))
246
+ expect(m.currency).to eq Money::Currency.wrap("EUR")
247
+
248
+ m = Monetize.from_bigdecimal(BigDecimal.new("1"), "EUR")
249
+ expect(m.currency).to eq Money::Currency.wrap("EUR")
250
+ end
251
+
252
+ context "infinite_precision = true" do
253
+ before do
254
+ Money.infinite_precision = true
255
+ end
256
+
257
+ after do
258
+ Money.infinite_precision = false
259
+ end
260
+
261
+ it "keeps precision" do
262
+ expect(Monetize.from_bigdecimal(BigDecimal.new("1.23456"))).to eq Money.new(123.456)
263
+ expect(Monetize.from_bigdecimal(BigDecimal.new("-1.23456"))).to eq Money.new(-123.456)
264
+ expect(Monetize.from_bigdecimal(BigDecimal.new("1.23456"))).to eq Money.new(123.456, "USD")
265
+ expect(Monetize.from_bigdecimal(BigDecimal.new("1.23456"), "EUR")).to eq Money.new(123.456, "EUR")
266
+ end
267
+ end
268
+ end
269
+
270
+ describe ".from_numeric" do
271
+ it "converts given amount to cents" do
272
+ expect(Monetize.from_numeric(1)).to eq Money.new(1_00)
273
+ expect(Monetize.from_numeric(1.0)).to eq Money.new(1_00)
274
+ expect(Monetize.from_numeric(BigDecimal.new("1"))).to eq Money.new(1_00)
275
+ end
276
+
277
+ it "raises ArgumentError with unsupported argument" do
278
+ expect { Monetize.from_numeric("100") }.to raise_error(ArgumentError)
279
+ end
280
+
281
+ it "optimizes workload" do
282
+ expect(Monetize).to receive(:from_fixnum).with(1, "USD").and_return(Money.new(1_00, "USD"))
283
+ expect(Monetize.from_numeric(1, "USD")).to eq Money.new(1_00, "USD")
284
+ expect(Monetize).to receive(:from_bigdecimal).with(BigDecimal.new("1.0"), "USD").and_return(Money.new(1_00, "USD"))
285
+ expect(Monetize.from_numeric(1.0, "USD")).to eq Money.new(1_00, "USD")
286
+ end
287
+
288
+ it "respects :subunit_to_unit currency property" do
289
+ expect(Monetize.from_numeric(1, "USD")).to eq Money.new(1_00, "USD")
290
+ expect(Monetize.from_numeric(1, "TND")).to eq Money.new(1_000, "TND")
291
+ expect(Monetize.from_numeric(1, "CLP")).to eq Money.new(1, "CLP")
292
+ end
293
+
294
+ it "accepts a bank option" do
295
+ expect(Monetize.from_numeric(1)).to eq Money.new(1_00)
296
+ expect(Monetize.from_numeric(1)).to eq Money.new(1_00, "USD")
297
+ expect(Monetize.from_numeric(1, "EUR")).to eq Money.new(1_00, "EUR")
298
+ end
299
+
300
+ it "accepts a currency options" do
301
+ m = Monetize.from_numeric(1)
302
+ expect(m.currency).to eq Money.default_currency
303
+
304
+ m = Monetize.from_numeric(1, Money::Currency.wrap("EUR"))
305
+ expect(m.currency).to eq Money::Currency.wrap("EUR")
306
+
307
+ m = Monetize.from_numeric(1, "EUR")
308
+ expect(m.currency).to eq Money::Currency.wrap("EUR")
309
+ end
310
+ end
311
+
312
+ describe ".extract_cents" do
313
+ it "correctly treats pipe marks '|' in input (regression test)" do
314
+ expect(Monetize.extract_cents('100|0')).to eq Monetize.extract_cents('100!0')
315
+ end
316
+ end
317
+
318
+ context "given the same inputs to .parse and .from_*" do
319
+ it "gives the same results" do
320
+ expect(4.635.to_money).to eq "4.635".to_money
321
+ end
322
+ end
323
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure do |config|
2
+ config.order = "random"
3
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: monetize
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Shane Emmons
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: money
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 3.0.0.beta1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 3.0.0.beta1
69
+ description: A library for converting various objects into `Money` objects.
70
+ email:
71
+ - shane@emmons.io
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - lib/monetize.rb
82
+ - lib/monetize/core_extensions.rb
83
+ - lib/monetize/core_extensions/numeric.rb
84
+ - lib/monetize/core_extensions/string.rb
85
+ - lib/monetize/core_extensions/symbol.rb
86
+ - lib/monetize/version.rb
87
+ - monetize.gemspec
88
+ - spec/core_extensions_spec.rb
89
+ - spec/monetize_spec.rb
90
+ - spec/spec_helper.rb
91
+ homepage: https://github.com/RubyMoney/monetize
92
+ licenses:
93
+ - MIT
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 2.0.14
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: A library for converting various objects into `Money` objects.
115
+ test_files:
116
+ - spec/core_extensions_spec.rb
117
+ - spec/monetize_spec.rb
118
+ - spec/spec_helper.rb