money 2.1.3 → 2.1.4

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.
@@ -17,7 +17,8 @@ class String
17
17
  # '100.37'.to_money # => #<Money @cents=10037>
18
18
  # '100 USD'.to_money # => #<Money @cents=10000, @currency="USD">
19
19
  # 'USD 100'.to_money # => #<Money @cents=10000, @currency="USD">
20
- # '$100 USD'.to_money # => #<Money @cents=10000, @currency="USD">
20
+ # '$100 USD'.to_money # => #<Money @cents=10000, @currency="USD">
21
+ # 'hello 2000 world'.to_money # => #<Money @cents=200000 @currency="USD")>
21
22
  def to_money
22
23
  # Get the currency.
23
24
  matches = scan /([A-Z]{2,3})/
@@ -79,6 +80,8 @@ class String
79
80
  # ex: 1,000 - 1.0000 - 10001.000
80
81
  # split number into possible major (dollars) and minor (cents) values
81
82
  possible_major, possible_minor = num.split(separator)
83
+ possible_major ||= "0"
84
+ possible_minor ||= "00"
82
85
 
83
86
  # if the minor (cents) length isn't 3, assign major/minor from the possibles
84
87
  # e.g.
@@ -114,8 +117,19 @@ class String
114
117
  end
115
118
 
116
119
  # build the string based on major/minor since separator/delimiters have been removed
117
- # transform to a float, multiply by 100 to convert to cents
118
- cents = "#{major}.#{minor}".to_f * 100
120
+ # avoiding floating point arithmetic here to ensure accuracy
121
+ cents = (major.to_i * 100)
122
+ # add the minor number as well. this may have any number of digits,
123
+ # so we treat minor as a string and truncate or right-fill it with zeroes
124
+ # until it becomes a two-digit number string, which we add to cents.
125
+ minor = minor.to_s
126
+ truncated_minor = minor[0..1]
127
+ truncated_minor << "0" * (2 - truncated_minor.size) if truncated_minor.size < 2
128
+ cents += truncated_minor.to_i
129
+ # respect rounding rules
130
+ if minor.size >= 3 && minor[2..2].to_i >= 5
131
+ cents += 1
132
+ end
119
133
 
120
134
  # if negative, multiply by -1; otherwise, return positive cents
121
135
  negative ? cents * -1 : cents
data/lib/money/money.rb CHANGED
@@ -3,7 +3,7 @@ require 'money/variable_exchange_bank'
3
3
  # Represents an amount of money in a certain currency.
4
4
  class Money
5
5
  include Comparable
6
-
6
+
7
7
  attr_reader :cents, :currency, :bank
8
8
 
9
9
  class << self
@@ -127,22 +127,30 @@ class Money
127
127
  end
128
128
 
129
129
 
130
- # Format the price according to several rules. The following options are
131
- # supported: :display_free, :with_currency, :no_cents, :symbol and :html
130
+ # Creates a formatted price string according to several rules. The following
131
+ # options are supported: :display_free, :with_currency, :no_cents, :symbol
132
+ # and :html.
132
133
  #
133
- # display_free:
134
+ # === +:display_free+
134
135
  #
135
- # Money.us_dollar(0).format(:display_free => true) => "free"
136
- # Money.us_dollar(0).format(:display_free => "gratis") => "gratis"
136
+ # Whether a zero amount of money should be formatted of "free" or as the
137
+ # supplied string.
138
+ #
139
+ # Money.us_dollar(0).format(:display_free => true) => "free"
140
+ # Money.us_dollar(0).format(:display_free => "gratis") => "gratis"
137
141
  # Money.us_dollar(0).format => "$0.00"
138
142
  #
139
- # with_currency:
143
+ # === +:with_currency+
144
+ #
145
+ # Whether the currency name should be appended to the result string.
140
146
  #
141
147
  # Money.ca_dollar(100).format => "$1.00"
142
148
  # Money.ca_dollar(100).format(:with_currency => true) => "$1.00 CAD"
143
- # Money.us_dollar(85).format(:with_currency => true) => "$0.85 USD"
149
+ # Money.us_dollar(85).format(:with_currency => true) => "$0.85 USD"
144
150
  #
145
- # no_cents:
151
+ # === +:no_cents+
152
+ #
153
+ # Whether cents should be omitted.
146
154
  #
147
155
  # Money.ca_dollar(100).format(:no_cents => true) => "$1"
148
156
  # Money.ca_dollar(599).format(:no_cents => true) => "$5"
@@ -150,13 +158,43 @@ class Money
150
158
  # Money.ca_dollar(570).format(:no_cents => true, :with_currency => true) => "$5 CAD"
151
159
  # Money.ca_dollar(39000).format(:no_cents => true) => "$390"
152
160
  #
153
- # symbol:
161
+ # === +:symbol+
162
+ #
163
+ # Whether a money symbol should be prepended to the result string. The default is true.
164
+ # This method attempts to pick a symbol that's suitable for the given currency.
165
+ #
166
+ # Money.new(100, :currency => "USD") => "$1.00"
167
+ # Money.new(100, :currency => "GBP") => "£1.00"
168
+ # Money.new(100, :currency => "EUR") => "€1.00"
169
+ #
170
+ # # Same thing.
171
+ # Money.new(100, :currency => "USD").format(:symbol => true) => "$1.00"
172
+ # Money.new(100, :currency => "GBP").format(:symbol => true) => "£1.00"
173
+ # Money.new(100, :currency => "EUR").format(:symbol => true) => "€1.00"
174
+ #
175
+ # You can specify a false expression or an empty string to disable prepending
176
+ # a money symbol:
177
+ #
178
+ # Money.new(100, :currency => "USD").format(:symbol => false) => "1.00"
179
+ # Money.new(100, :currency => "GBP").format(:symbol => nil) => "1.00"
180
+ # Money.new(100, :currency => "EUR").format(:symbol => "") => "1.00"
181
+ #
182
+ #
183
+ # If the symbol for the given currency isn't known, then it will default
184
+ # to "$" as symbol:
185
+ #
186
+ # Money.new(100, :currency => "AWG").format(:symbol => true) => "$1.00"
187
+ #
188
+ # You can specify a string as value to enforce using a particular symbol:
154
189
  #
155
- # Money.new(100, :currency => "GBP").format(:symbol => "£") => "£1.00"
190
+ # Money.new(100, :currency => "AWG").format(:symbol => "ƒ") => "ƒ1.00"
156
191
  #
157
- # html:
192
+ # === +:html+
158
193
  #
159
- # Money.ca_dollar(570).format(:html => true, :with_currency => true) => "$5.70 <span class=\"currency\">CAD</span>"
194
+ # Whether the currency should be HTML-formatted. Only useful in combination with +:with_currency+.
195
+ #
196
+ # Money.ca_dollar(570).format(:html => true, :with_currency => true)
197
+ # => "$5.70 <span class=\"currency\">CAD</span>"
160
198
  def format(*rules)
161
199
  # support for old format parameters
162
200
  rules = normalize_formatting_rules(rules)
@@ -170,7 +208,9 @@ class Money
170
208
  end
171
209
 
172
210
  if rules.has_key?(:symbol)
173
- if rules[:symbol]
211
+ if rules[:symbol] === true
212
+ symbol = SYMBOLS[currency[:currency]] || "$"
213
+ elsif rules[:symbol]
174
214
  symbol = rules[:symbol]
175
215
  else
176
216
  symbol = ""
@@ -197,7 +237,9 @@ class Money
197
237
  formatted
198
238
  end
199
239
 
200
- # Money.ca_dollar(100).to_s => "1.00"
240
+ # Returns the amount of money as a string.
241
+ #
242
+ # Money.ca_dollar(100).to_s => "1.00"
201
243
  def to_s
202
244
  sprintf("%.2f", cents / 100.00)
203
245
  end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ # Add more from http://www.xe.com/symbols.php
4
+ Money::SYMBOLS = {
5
+ "GBP" => "£",
6
+ "JPY" => "¥",
7
+ "EUR" => "€",
8
+ "ZWD" => "Z$",
9
+ "CNY" => "¥",
10
+ "INR" => "₨",
11
+ "NPR" => "₨",
12
+ "SCR" => "₨",
13
+ "LKR" => "₨",
14
+ "SEK" => "kr",
15
+ "GHC" => "¢"
16
+
17
+ # Everything else defaults to $
18
+ }
data/lib/money.rb CHANGED
@@ -22,4 +22,5 @@
22
22
 
23
23
  $LOAD_PATH << File.expand_path(File.dirname(__FILE__))
24
24
  require 'money/money'
25
+ require 'money/symbols'
25
26
  require 'money/core_extensions'
data/money.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "money"
3
- s.version = "2.1.3"
3
+ s.version = "2.1.4"
4
4
  s.summary = "Money and currency exchange support library"
5
5
  s.email = "hongli@phusion.nl"
6
6
  s.homepage = "http://money.rubyforge.org/"
@@ -15,6 +15,7 @@ Gem::Specification.new do |s|
15
15
  "lib/money/core_extensions.rb",
16
16
  "lib/money/errors.rb",
17
17
  "lib/money/money.rb",
18
+ "lib/money/symbols.rb",
18
19
  "lib/money/variable_exchange_bank.rb",
19
20
  "test/core_extensions_spec.rb",
20
21
  "test/exchange_bank_spec.rb",
@@ -1,4 +1,4 @@
1
- $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../lib")
1
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
2
2
  require 'money/core_extensions'
3
3
 
4
4
  describe "Money core extensions" do
@@ -13,6 +13,7 @@ describe "Money core extensions" do
13
13
  end
14
14
 
15
15
  specify "String#to_money works" do
16
+ "20.15".to_money.should == Money.new(20_15)
16
17
  "100".to_money.should == Money.new(100_00)
17
18
  "100.37".to_money.should == Money.new(100_37)
18
19
  "100,37".to_money.should == Money.new(100_37)
@@ -20,9 +21,16 @@ describe "Money core extensions" do
20
21
  "100,000.00".to_money.should == Money.new(100_000_00)
21
22
  "1,000".to_money.should == Money.new(1_000_00)
22
23
  "-1,000".to_money.should == Money.new(-1_000_00)
24
+ "1,000.5".to_money.should == Money.new(1_000_50)
25
+ "1,000.51".to_money.should == Money.new(1_000_51)
26
+ "1,000.505".to_money.should == Money.new(1_000_51)
27
+ "1,000.504".to_money.should == Money.new(1_000_50)
23
28
  "1,000.0000".to_money.should == Money.new(1_000_00)
24
29
  "1,000.5000".to_money.should == Money.new(1_000_50)
30
+ "1,000.5099".to_money.should == Money.new(1_000_51)
25
31
  "1.550".to_money.should == Money.new(1_55)
32
+ "25.".to_money.should == Money.new(25_00)
33
+ ".75".to_money.should == Money.new(75)
26
34
 
27
35
  "100 USD".to_money.should == Money.new(100_00, "USD")
28
36
  "-100 USD".to_money.should == Money.new(-100_00, "USD")
@@ -58,4 +66,8 @@ describe "Money core extensions" do
58
66
  "$-1,955.000 USD".to_money.should == Money.new(-1_955_00, "USD")
59
67
  "$1.99000 USD".to_money.should == Money.new(1_99, "USD")
60
68
  end
69
+
70
+ specify "String#to_money ignores unrecognized data" do
71
+ "hello 2000 world".to_money.should == Money.new(2000_00)
72
+ end
61
73
  end
@@ -1,4 +1,4 @@
1
- $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../lib")
1
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
2
2
  require 'money/variable_exchange_bank'
3
3
 
4
4
  describe Money::VariableExchangeBank do
data/test/money_spec.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
- $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../lib")
2
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
3
3
  require 'money/money'
4
+ require 'money/symbols'
4
5
 
5
6
  describe Money do
6
7
  it "is associated to the singleton instance of VariableExchangeBank by default" do
@@ -127,10 +128,51 @@ describe Money do
127
128
  Money.ca_dollar(39000).format(:no_cents).should == "$390"
128
129
  end
129
130
 
130
- specify "#format(:symbol => ...) works as documented" do
131
+ specify "#format(:symbol => a symbol string) uses the given value as the money symbol" do
131
132
  Money.new(100, :currency => "GBP").format(:symbol => "£").should == "£1.00"
132
133
  end
133
134
 
135
+ specify "#format(:symbol => true) returns symbol based on the given currency code" do
136
+ one = Proc.new {|currency| Money.new(100, :currency => currency).format(:symbol => true) }
137
+
138
+ # Pounds
139
+ one["GBP"].should == "£1.00"
140
+
141
+ # Dollars
142
+ one["USD"].should == "$1.00"
143
+ one["CAD"].should == "$1.00"
144
+ one["AUD"].should == "$1.00"
145
+ one["NZD"].should == "$1.00"
146
+ one["ZWD"].should == "Z$1.00"
147
+
148
+ # Yen
149
+ one["JPY"].should == "¥1.00"
150
+ one["CNY"].should == "¥1.00"
151
+
152
+ # Euro
153
+ one["EUR"].should == "€1.00"
154
+
155
+ # Rupees
156
+ one["INR"].should == "₨1.00"
157
+ one["NPR"].should == "₨1.00"
158
+ one["SCR"].should == "₨1.00"
159
+ one["LKR"].should == "₨1.00"
160
+
161
+ # Other
162
+ one["SEK"].should == "kr1.00"
163
+ one["GHC"].should == "¢1.00"
164
+ end
165
+
166
+ specify "#format(:symbol => true) returns $ when currency code is not recognized" do
167
+ Money.new(100, :currency => "XYZ").format(:symbol => true).should == "$1.00"
168
+ end
169
+
170
+ specify "#format(:symbol => some non-Boolean value that evaluates to true) returs symbol based on the given currency code" do
171
+ Money.new(100, :currency => "GBP").format(:symbol => true).should == "£1.00"
172
+ Money.new(100, :currency => "EUR").format(:symbol => true).should == "€1.00"
173
+ Money.new(100, :currency => "SEK").format(:symbol => true).should == "kr1.00"
174
+ end
175
+
134
176
  specify "#format with :symbol == "", nil or false returns the amount without a symbol" do
135
177
  money = Money.new(100, :currency => "GBP")
136
178
  money.format(:symbol => "").should == "1.00"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: money
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.3
4
+ version: 2.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Luetke
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2009-02-21 00:00:00 +01:00
14
+ date: 2009-08-02 00:00:00 +02:00
15
15
  default_executable:
16
16
  dependencies: []
17
17
 
@@ -32,6 +32,7 @@ files:
32
32
  - lib/money/core_extensions.rb
33
33
  - lib/money/errors.rb
34
34
  - lib/money/money.rb
35
+ - lib/money/symbols.rb
35
36
  - lib/money/variable_exchange_bank.rb
36
37
  - test/core_extensions_spec.rb
37
38
  - test/exchange_bank_spec.rb