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 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. You can also specify the
63
- :precision and :round_mode option for more fine control of the results.
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.8
1
+ 0.0.9
data/bd_money.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{bd_money}
8
- s.version = "0.0.8"
8
+ s.version = "0.0.9"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Adrian Madrid"]
@@ -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
- YAML_TYPE_CLASS = 'npadv.com,2012-03-12' unless const_defined?(:YAML_TYPE_CLASS)
26
- YAML_TYPE_MODE = 'money' unless const_defined?(:YAML_TYPE_MODE)
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
- "!#{YAML_TYPE_FULL}"
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
- return value if value.is_a?(Money)
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::YAML_TYPE_CLASS, Money::YAML_TYPE_MODE) do |_, map|
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
@@ -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[:precision], options[:round_mode]).amount
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[:precision], options[:round_mode]
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, :precision => 2, :round_mode => :half_up
25
- money :apr, :precision => 5, :round_mode => :floor
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
- it "should allow dynamic finders to work with money objects" do
31
- record = DefaultLoanExample.create! :amount => '325.75', :apr => '0.01234'
32
- DefaultLoanExample.find_by_amount(0.to_money).should be_nil
33
- found = DefaultLoanExample.find_by_amount('325.75'.to_money)
34
- found.should == record
35
- found.amount.should be_a(Money)
36
- found.amount.to_s.should == '325.75'
37
- found.apr.should be_a(Money)
38
- found.apr.to_s.should == '0.01'
39
- end
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.01234'
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: 15
4
+ hash: 13
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 8
10
- version: 0.0.8
9
+ - 9
10
+ version: 0.0.9
11
11
  platform: ruby
12
12
  authors:
13
13
  - Adrian Madrid