bd_money 0.0.8 → 0.0.9
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/README.rdoc +14 -4
- data/VERSION +1 -1
- data/bd_money.gemspec +1 -1
- data/lib/bd_money/bd_money.rb +15 -15
- data/lib/bd_money/rails.rb +8 -2
- data/spec/rails_spec.rb +22 -13
- metadata +3 -3
data/README.rdoc
CHANGED
@@ -59,14 +59,24 @@ There is a rails extension that makes it easier to store money values in the dat
|
|
59
59
|
validates_numericality_of :price, :greater_than => 0
|
60
60
|
end
|
61
61
|
|
62
|
-
This assumes that there is a price (decimal highly recommended) column in the database.
|
63
|
-
|
62
|
+
This assumes that there is a price (decimal highly recommended) column in the database.
|
63
|
+
|
64
|
+
You can also specify the :precision, :round_mode and :format options for more fine control of the results. If you don't
|
65
|
+
specify the :precision option it will try to guess it out of the scale column definition (recommended). Precision is
|
66
|
+
important since the values will get rounded on every change internally to stay consistent with the database.
|
64
67
|
|
65
68
|
class Loan < ActiveRecord::Base
|
66
|
-
money :amount, :round_mode => :half_up
|
67
|
-
money :apr, :precision => 5, :round_mode => :floor
|
69
|
+
money :amount, :round_mode => :half_up, :format => :no_cents
|
70
|
+
money :apr, :precision => 5, :round_mode => :floor, :format => :no_commas
|
68
71
|
end
|
69
72
|
|
73
|
+
loan = Loan.create! :amount => '325.75', :apr => '0.01234'
|
74
|
+
loan.amount #=> 325.75
|
75
|
+
loan.amount.formatted #=> $ 325.75
|
76
|
+
loan.apr #=> 0.0123
|
77
|
+
loan.apr.formatted #=> $ 0.01
|
78
|
+
loan.apr.formatted(:precision => 5, :unit => "", :spacer => "") #=> 0.01234
|
79
|
+
|
70
80
|
You can set the attribute to a String, Fixnum, or Float and it will call #to_money to
|
71
81
|
convert it to a Money object. This makes it convenient for using money fields in forms.
|
72
82
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.9
|
data/bd_money.gemspec
CHANGED
data/lib/bd_money/bd_money.rb
CHANGED
@@ -14,17 +14,17 @@ class Money
|
|
14
14
|
} unless const_defined?(:ROUND_MODES)
|
15
15
|
|
16
16
|
FORMATS = {
|
17
|
-
:default => { :unit => "$", :spacer => " ", :delimiter => ",", :separator => ".", :precision => 2 },
|
18
|
-
:no_cents => { :unit => "$", :spacer => " ", :delimiter => ",", :separator => ".", :precision => 0 },
|
19
|
-
:no_commas => { :unit => "$", :spacer => " ", :delimiter => "", :separator => ".", :precision => 2 },
|
17
|
+
:default => { :unit => "$", :spacer => " ", :delimiter => ",", :separator => ".", :precision => 2, :last => "" },
|
18
|
+
:no_cents => { :unit => "$", :spacer => " ", :delimiter => ",", :separator => ".", :precision => 0, :last => "" },
|
19
|
+
:no_commas => { :unit => "$", :spacer => " ", :delimiter => "", :separator => ".", :precision => 2, :last => "" },
|
20
|
+
:general => { :unit => "", :spacer => "", :delimiter => "", :separator => ".", :precision => 2, :last => "" },
|
20
21
|
} unless const_defined?(:FORMATS)
|
21
22
|
|
22
23
|
REMOVE_RE = %r{[$,_ ]} unless const_defined?(:REMOVE_RE)
|
23
24
|
VALID_RE = %r{^(-)?(\d)+(\.\d{1,30}(e-\d{1,10})?)?$} unless const_defined?(:VALID_RE)
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
YAML_TYPE_FULL = "#{YAML_TYPE_CLASS}/#{YAML_TYPE_MODE}" unless const_defined?(:YAML_TYPE_FULL)
|
26
|
+
YAML_TYPE_ROOT = 'npadv.com,2012-03-12' unless const_defined?(:YAML_TYPE_ROOT)
|
27
|
+
YAML_TYPE_NAME = 'money' unless const_defined?(:YAML_TYPE_NAME)
|
28
28
|
|
29
29
|
include Comparable
|
30
30
|
|
@@ -79,8 +79,8 @@ class Money
|
|
79
79
|
@format || self.class.format
|
80
80
|
end
|
81
81
|
|
82
|
-
def convert(value)
|
83
|
-
self.class.convert value
|
82
|
+
def convert(value, this_precision = precision, this_round_mode = round_mode)
|
83
|
+
self.class.convert value, this_precision, this_round_mode
|
84
84
|
end
|
85
85
|
|
86
86
|
def eql?(other)
|
@@ -187,15 +187,16 @@ class Money
|
|
187
187
|
spacer = options[:spacer] || defaults[:spacer]
|
188
188
|
delimiter = options[:delimiter] || defaults[:delimiter]
|
189
189
|
separator = options[:separator] || defaults[:separator]
|
190
|
-
precision = options[:precision] || defaults[:precision]
|
191
190
|
separator = '' if precision == 0
|
191
|
+
precision = options[:precision] || defaults[:precision]
|
192
|
+
last = options[:last] || defaults[:last]
|
192
193
|
|
193
194
|
number = to_s precision
|
194
195
|
begin
|
195
196
|
parts = number.to_s.split('.')
|
196
197
|
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")
|
197
198
|
number = parts.join(separator)
|
198
|
-
"#{unit}#{spacer}#{number}"
|
199
|
+
"#{unit}#{spacer}#{number}#{last}"
|
199
200
|
rescue
|
200
201
|
number
|
201
202
|
end
|
@@ -215,7 +216,7 @@ class Money
|
|
215
216
|
end
|
216
217
|
|
217
218
|
def to_yaml_type
|
218
|
-
"!#{
|
219
|
+
"!#{YAML_TYPE_ROOT}/#{YAML_TYPE_NAME}"
|
219
220
|
end
|
220
221
|
|
221
222
|
def to_yaml(options = { })
|
@@ -258,9 +259,8 @@ class Money
|
|
258
259
|
@format || :default
|
259
260
|
end
|
260
261
|
|
261
|
-
def convert(value)
|
262
|
-
|
263
|
-
new value
|
262
|
+
def convert(value, precision = nil, round_mode = nil)
|
263
|
+
new value, precision, round_mode
|
264
264
|
end
|
265
265
|
|
266
266
|
def clean(value)
|
@@ -275,6 +275,6 @@ class Money
|
|
275
275
|
|
276
276
|
end
|
277
277
|
|
278
|
-
YAML::add_domain_type(Money::
|
278
|
+
YAML::add_domain_type(Money::YAML_TYPE_ROOT, Money::YAML_TYPE_NAME) do |_, map|
|
279
279
|
Money.new map['amount'], map['precision'], map['round_mode'], map['format']
|
280
280
|
end
|
data/lib/bd_money/rails.rb
CHANGED
@@ -27,16 +27,22 @@ module ActiveRecord #:nodoc:
|
|
27
27
|
def money(*names)
|
28
28
|
options = names.extract_options!
|
29
29
|
names.each do |name|
|
30
|
+
if options[:precision]
|
31
|
+
this_precision = options[:precision]
|
32
|
+
else
|
33
|
+
db_column = columns.select { |x| x.name == name.to_s }.first
|
34
|
+
this_precision = (db_column && db_column.respond_to?(:scale)) ? db_column.scale : nil
|
35
|
+
end
|
30
36
|
define_method "#{name}=" do |value|
|
31
37
|
if value.present?
|
32
|
-
self[name] = ::Money.new(value, options[:
|
38
|
+
self[name] = ::Money.new(value, this_precision, options[:round_mode], options[:format]).round.amount
|
33
39
|
else
|
34
40
|
self[name] = nil
|
35
41
|
end
|
36
42
|
end
|
37
43
|
define_method "#{name}" do
|
38
44
|
return nil unless self[name].present?
|
39
|
-
::Money.new self[name], options[:
|
45
|
+
::Money.new self[name], this_precision, options[:round_mode], options[:format]
|
40
46
|
end
|
41
47
|
end
|
42
48
|
end
|
data/spec/rails_spec.rb
CHANGED
@@ -21,22 +21,25 @@ end
|
|
21
21
|
class BetterLoanExample < ActiveRecord::Base
|
22
22
|
set_table_name "money_examples"
|
23
23
|
|
24
|
-
money :amount, :
|
25
|
-
money :apr, :precision =>
|
24
|
+
money :amount, :round_mode => :half_up, :format => :no_cents
|
25
|
+
money :apr, :precision => 4, :round_mode => :floor, :format => :no_commas
|
26
26
|
end
|
27
27
|
|
28
28
|
describe Money do
|
29
29
|
describe "default settings" do
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
30
|
+
before(:all) { @record = BetterLoanExample.create! :amount => '325.75', :apr => '0.01234' }
|
31
|
+
subject { BetterLoanExample.find_by_amount('325.75'.to_money) }
|
32
|
+
it { BetterLoanExample.find_by_amount(0.to_money).should be_nil }
|
33
|
+
it { subject.id.should == @record.id }
|
34
|
+
it { subject.amount.should be_a(Money) }
|
35
|
+
it { subject.amount.to_s.should == '325.75' }
|
36
|
+
it { subject.amount.format.should == :no_cents }
|
37
|
+
it { subject.amount.formatted.should == '$ 325.75' }
|
38
|
+
it { subject.apr.should be_a(Money) }
|
39
|
+
it { subject.apr.to_s.should == '0.0123' }
|
40
|
+
it { subject.apr.format.should == :no_commas }
|
41
|
+
it { subject.apr.formatted.should == '$ 0.01' }
|
42
|
+
it { subject.apr.formatted(:precision => 3, :unit => "", :spacer => "").should == '0.012' }
|
40
43
|
end
|
41
44
|
describe "custom settings" do
|
42
45
|
it "should allow dynamic finders to work with money objects" do
|
@@ -47,7 +50,7 @@ describe Money do
|
|
47
50
|
found.amount.should be_a(Money)
|
48
51
|
found.amount.to_s.should == '123.45'
|
49
52
|
found.apr.should be_a(Money)
|
50
|
-
found.apr.to_s.should == '0.
|
53
|
+
found.apr.to_s.should == '0.0123'
|
51
54
|
end
|
52
55
|
end
|
53
56
|
describe "setter method" do
|
@@ -72,5 +75,11 @@ describe Money do
|
|
72
75
|
me.update_attribute :amount, nil
|
73
76
|
me.amount.should be_nil
|
74
77
|
end
|
78
|
+
|
79
|
+
describe "should round numbers to the column's' precision" do
|
80
|
+
subject { BetterLoanExample.new :amount => 300, :apr => 0.123456789 }
|
81
|
+
it { subject.amount.amount.to_s('F').should == '300.0' }
|
82
|
+
it { subject.apr.amount.to_s('F').should == '0.1234' }
|
83
|
+
end
|
75
84
|
end
|
76
85
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bd_money
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 9
|
10
|
+
version: 0.0.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Adrian Madrid
|