money_extensions 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +8 -12
- data/CHANGELOG.md +3 -1
- data/gemfiles/rails5.gemfile +2 -1
- data/gemfiles/{rails4.gemfile → rails6.gemfile} +2 -3
- data/lib/money_extensions.rb +2 -3
- data/lib/money_extensions/active_record/extensions.rb +9 -18
- data/lib/money_extensions/array.rb +3 -1
- data/lib/money_extensions/html_format.rb +37 -0
- data/lib/money_extensions/integer.rb +3 -1
- data/lib/money_extensions/money_field.rb +4 -7
- data/lib/money_extensions/numeric.rb +4 -2
- data/lib/money_extensions/split_between.rb +54 -0
- data/lib/money_extensions/string.rb +4 -2
- data/lib/money_extensions/version.rb +3 -1
- data/money_extensions.gemspec +5 -1
- data/spec/big_decimal_spec.rb +6 -6
- data/spec/html_format_spec.rb +48 -0
- data/spec/money_spec.rb +3 -45
- data/spec/support/coverage_loader.rb +1 -1
- metadata +51 -14
- data/gemfiles/rails3.gemfile +0 -8
- data/lib/money_extensions/big_decimal.rb +0 -12
- data/lib/money_extensions/extensions.rb +0 -189
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 664c218fac6464fdf5789d5a301bd50d5ab9b4270dc537c199f451a4c1c8da1c
|
4
|
+
data.tar.gz: e824d3b3e10bde7a5c20c26c9668db8ca4b09d2f513adddf82466909d14702c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbd0b0d8a7f25d7601bea3006156e8324b0a211155431ea2bcfa65a3ce62c24efbfee701429ce544765cf80a1f77bd75518fce0e90647a5000be26a4de6b2b0c
|
7
|
+
data.tar.gz: 6828b8a3401ea874852b0804c695b06f97b107830d610c25f0ad99aed9d1b29db7c91b5594fec8782fe3233173e66fbd84377b7b98c398bae5a599a4c220c3c4
|
data/.gitignore
CHANGED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.6.3
|
data/.travis.yml
CHANGED
@@ -1,22 +1,18 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 2.2.2
|
4
|
-
- 2.3.0
|
5
3
|
- 2.4
|
4
|
+
- 2.5
|
5
|
+
- 2.6
|
6
6
|
matrix:
|
7
|
-
fast_finish: true
|
8
7
|
exclude:
|
9
8
|
- rvm: 2.4
|
10
|
-
gemfile: gemfiles/
|
9
|
+
gemfile: gemfiles/rails6.gemfile
|
10
|
+
|
11
|
+
script: "bundle exec rake spec"
|
11
12
|
gemfile:
|
12
|
-
- gemfiles/rails3.gemfile
|
13
|
-
- gemfiles/rails4.gemfile
|
14
13
|
- gemfiles/rails5.gemfile
|
15
|
-
|
16
|
-
notifications:
|
17
|
-
email:
|
18
|
-
- support@travellink.com.au
|
19
|
-
flowdock:
|
20
|
-
secure: A0Fr9j0kvKPEWuPbJu/DPMYPvx98UI8k43adKN9UjTB6FRVAQM3kXmKJIL3A495scc2Civrg2KHDkbwNwVThY+HdLeU7q71Bm6obP6ZkCe43MIoc9NiVJymCNguku6+tLEyusdWIceFiBW7P5p/sU1QU66GFj1t4wNTpVq9A4Kw=
|
14
|
+
- gemfiles/rails6.gemfile
|
21
15
|
sudo: false
|
22
16
|
cache: bundler
|
17
|
+
before_install:
|
18
|
+
- gem install bundler
|
data/CHANGELOG.md
CHANGED
data/gemfiles/rails5.gemfile
CHANGED
data/lib/money_extensions.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module MoneyExtensions
|
2
2
|
require 'money'
|
3
3
|
require 'money_extensions/array'
|
4
|
-
require 'money_extensions/big_decimal'
|
5
4
|
require 'money_extensions/integer'
|
6
|
-
require 'money_extensions/
|
5
|
+
require 'money_extensions/split_between'
|
6
|
+
require 'money_extensions/html_format'
|
7
7
|
require 'money_extensions/money_field'
|
8
8
|
require 'money_extensions/numeric'
|
9
9
|
require 'money_extensions/string'
|
@@ -14,4 +14,3 @@ module MoneyExtensions
|
|
14
14
|
end
|
15
15
|
|
16
16
|
end
|
17
|
-
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Extensions
|
3
|
-
|
4
5
|
def self.included(base)
|
5
6
|
base.extend(ClassMethods)
|
6
7
|
end
|
@@ -18,20 +19,14 @@ module ActiveRecord
|
|
18
19
|
|
19
20
|
field_name = "#{attr_name}_iso_code"
|
20
21
|
|
21
|
-
composed_of attr_name, :
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
composed_of attr_name, class_name: 'Money::Currency',
|
23
|
+
mapping: [field_name, 'iso_code'],
|
24
|
+
allow_nil: true,
|
25
|
+
constructor: proc { |value| Money::Currency.new(value) unless value.blank? }
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
where(:currency_iso_code => currency.iso_code)
|
27
|
+
scope :for_currency, lambda { |currency|
|
28
|
+
where(currency_iso_code: currency.iso_code)
|
29
29
|
}
|
30
|
-
else
|
31
|
-
named_scope :for_currency, lambda{ |currency|
|
32
|
-
{:conditions => {:currency_iso_code => currency.iso_code}}
|
33
|
-
}
|
34
|
-
end
|
35
30
|
|
36
31
|
if options[:default]
|
37
32
|
before_validation :set_default_currency
|
@@ -43,13 +38,9 @@ module ActiveRecord
|
|
43
38
|
METHOD
|
44
39
|
end
|
45
40
|
|
46
|
-
if options[:required]
|
47
|
-
validates_presence_of :currency_iso_code
|
48
|
-
end
|
41
|
+
validates_presence_of :currency_iso_code if options[:required]
|
49
42
|
end
|
50
|
-
|
51
43
|
end
|
52
|
-
|
53
44
|
end
|
54
45
|
end
|
55
46
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/string/output_safety'
|
4
|
+
|
5
|
+
module HtmlFormat
|
6
|
+
def format(**rules)
|
7
|
+
html_wrap = rules.delete(:html_wrap)
|
8
|
+
return html_wrap(super(**rules)) if html_wrap
|
9
|
+
|
10
|
+
super(**rules)
|
11
|
+
end
|
12
|
+
|
13
|
+
def as_html(**rules)
|
14
|
+
rules[:html_wrap] = true
|
15
|
+
format(**rules).html_safe
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def html_wrap(str)
|
21
|
+
"<span class=\"money #{direction_class}\">#{str}</span>"
|
22
|
+
end
|
23
|
+
|
24
|
+
def direction_class
|
25
|
+
if cents > 0
|
26
|
+
'positive'
|
27
|
+
elsif cents < 0
|
28
|
+
'negative'
|
29
|
+
else
|
30
|
+
'zero'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Money
|
36
|
+
prepend HtmlFormat
|
37
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module MoneyField
|
3
4
|
def self.included(base)
|
4
5
|
base.extend(ClassMethods)
|
5
6
|
end
|
@@ -23,12 +24,10 @@ module MoneyField
|
|
23
24
|
METHOD
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
27
|
def money_fields(*attributes)
|
28
|
-
attributes.each {|a|
|
28
|
+
attributes.each { |a| money_field(a) }
|
29
29
|
end
|
30
30
|
|
31
|
-
|
32
31
|
def money(*fields)
|
33
32
|
fields.each do |field|
|
34
33
|
class_eval <<-METHOD
|
@@ -38,7 +37,5 @@ module MoneyField
|
|
38
37
|
METHOD
|
39
38
|
end
|
40
39
|
end
|
41
|
-
|
42
40
|
end
|
43
|
-
|
44
|
-
end
|
41
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Numeric
|
2
4
|
# Converts this numeric to a Money object in the default currency. It
|
3
5
|
# multiplies the numeric value by 100 and treats that as cents.
|
@@ -11,6 +13,6 @@ class Numeric
|
|
11
13
|
# require 'bigdecimal'
|
12
14
|
# BigDecimal.new('100').to_money => #<Money @cents=10000>
|
13
15
|
def to_money(currency = nil)
|
14
|
-
::Money.new((self * 100).round, currency)
|
16
|
+
::Money.new((self * 100).round, currency || Money.default_currency)
|
15
17
|
end
|
16
|
-
end
|
18
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SplitBetween
|
4
|
+
# Override division -- should not do it, but use split_between
|
5
|
+
def /(*_params)
|
6
|
+
raise "Division of money NOT allowed - use 'split_between' to avoid rounding errors"
|
7
|
+
end
|
8
|
+
|
9
|
+
# Split the money between the specified number - and return an array of money
|
10
|
+
# Remainder in splits are given to the highest value e.g.
|
11
|
+
# $2.00 splits [40, 81, 40] into [49, 102, 49]
|
12
|
+
# $1.01 splits [ 1, 1, 1] into [35, 33, 33]
|
13
|
+
def split_between(params)
|
14
|
+
# if just a number is passed in, then money is split equally
|
15
|
+
if params.is_a?(Integer)
|
16
|
+
divisor = params
|
17
|
+
raise ArgumentError, 'Can only split up over a positive number' if divisor < 1
|
18
|
+
|
19
|
+
rounded_split = lossy_divide(divisor)
|
20
|
+
results = Array.new(divisor, rounded_split) # Create with 'divisor' num elements
|
21
|
+
|
22
|
+
# if an array of monies is passed in, then split in proportions
|
23
|
+
elsif params.is_a?(Array)
|
24
|
+
|
25
|
+
raise ArgumentError, 'Can only split up over at least one ration' if params.empty? && !zero?
|
26
|
+
|
27
|
+
results = params.map { |p| p.is_a?(::Money) ? p.cents : p }
|
28
|
+
|
29
|
+
total = results.inject(:+)
|
30
|
+
if total.zero?
|
31
|
+
return Array.new(results.size, ::Money.new(0)) if zero?
|
32
|
+
|
33
|
+
raise ArgumentError, "Total of ratios should not be zero! You sent in: #{params.inspect}"
|
34
|
+
end
|
35
|
+
|
36
|
+
results.map! do |ratio|
|
37
|
+
::Money.new((cents * (ratio.to_f / total)).round)
|
38
|
+
end
|
39
|
+
else
|
40
|
+
raise 'Either a Integer or array has to be passed in for splitting money'
|
41
|
+
end
|
42
|
+
|
43
|
+
# Distribute rounding to max absolute to avoid a $0 amount getting the rounding
|
44
|
+
biggest_value_index = results.index(results.max_by(&:abs))
|
45
|
+
results[biggest_value_index] += self - results.total_money
|
46
|
+
|
47
|
+
results
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Money
|
52
|
+
alias lossy_divide /
|
53
|
+
include SplitBetween
|
54
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class String
|
2
4
|
# Converts this string to a float and then to a Money object in the default currency.
|
3
5
|
# It multiplies the converted numeric value by 100 and treats that as cents.
|
@@ -9,6 +11,6 @@ class String
|
|
9
11
|
# '100'.to_money => #<Money @cents=10000>
|
10
12
|
# '100.37'.to_money => #<Money @cents=10037>
|
11
13
|
def to_money(currency = nil)
|
12
|
-
Money.new((
|
14
|
+
Money.new((to_f * 100).round, currency)
|
13
15
|
end
|
14
|
-
end
|
16
|
+
end
|
data/money_extensions.gemspec
CHANGED
@@ -19,8 +19,12 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
-
spec.add_dependency 'money', '>=
|
22
|
+
spec.add_dependency 'money', '>= 6.0.0'
|
23
|
+
spec.add_dependency 'activesupport', '>= 5'
|
24
|
+
|
23
25
|
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'pry'
|
27
|
+
spec.add_development_dependency 'rubocop'
|
24
28
|
spec.add_development_dependency 'rspec'
|
25
29
|
spec.add_development_dependency 'coverage-kit'
|
26
30
|
spec.add_development_dependency 'simplecov-rcov'
|
data/spec/big_decimal_spec.rb
CHANGED
@@ -3,15 +3,15 @@ require 'spec_helper'
|
|
3
3
|
describe BigDecimal do
|
4
4
|
|
5
5
|
it "should allow verifying if it's a positive value" do
|
6
|
-
expect(BigDecimal
|
7
|
-
expect(BigDecimal
|
8
|
-
expect(BigDecimal
|
6
|
+
expect(BigDecimal('-1')).to_not be_positive
|
7
|
+
expect(BigDecimal('0')).to_not be_positive
|
8
|
+
expect(BigDecimal('1')).to be_positive
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should allow verifying if it's a negative value" do
|
12
|
-
expect(BigDecimal
|
13
|
-
expect(BigDecimal
|
14
|
-
expect(BigDecimal
|
12
|
+
expect(BigDecimal('-1')).to be_negative
|
13
|
+
expect(BigDecimal('0')).to_not be_negative
|
14
|
+
expect(BigDecimal('1')).to_not be_negative
|
15
15
|
end
|
16
16
|
|
17
17
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'money'
|
2
|
+
require 'money_extensions/string'
|
3
|
+
require 'money_extensions/html_format'
|
4
|
+
|
5
|
+
RSpec.describe Money do
|
6
|
+
before { Money.locale_backend = nil }
|
7
|
+
after { Money.locale_backend = :legacy }
|
8
|
+
|
9
|
+
let(:money_positive) { Money.new(100) }
|
10
|
+
let(:money_negative) { Money.new(-100) }
|
11
|
+
let(:money_zero) { Money.new(0) }
|
12
|
+
|
13
|
+
subject { money_positive.format(*rules) }
|
14
|
+
|
15
|
+
it "should format the output correctly" do
|
16
|
+
expect(money_negative.format(html_wrap: true, sign_before_symbol: true)).to eq "<span class=\"money negative\">-$1.00</span>"
|
17
|
+
expect(money_positive.format(html_wrap: true)).to eq "<span class=\"money positive\">$1.00</span>"
|
18
|
+
expect(money_zero.format(html_wrap: true)).to eq "<span class=\"money zero\">$0.00</span>"
|
19
|
+
|
20
|
+
expect(money_positive.format(html_wrap: true)).to eq "<span class=\"money positive\">$1.00</span>"
|
21
|
+
expect(money_negative.format(html_wrap: true, sign_before_symbol: true)).to eq "<span class=\"money negative\">-$1.00</span>"
|
22
|
+
expect(money_zero.format(html_wrap: true)).to eq "<span class=\"money zero\">$0.00</span>"
|
23
|
+
|
24
|
+
expect(money_positive.format(signed: true, sign_positive: true, sign_before_symbol: true)).to eq "+$1.00"
|
25
|
+
expect(money_negative.format(signed: true, sign_before_symbol: true)).to eq "-$1.00"
|
26
|
+
expect(money_zero.format(signed: true)).to eq "$0.00"
|
27
|
+
|
28
|
+
expect(money_positive.format(separator: '~')).to eq "$1~00"
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should work with as_html' do
|
32
|
+
expect(money_negative.as_html(sign_before_symbol: true)).to eq "<span class=\"money negative\">-$1.00</span>"
|
33
|
+
expect(money_positive.as_html).to eq "<span class=\"money positive\">$1.00</span>"
|
34
|
+
expect(money_zero.as_html).to eq "<span class=\"money zero\">$0.00</span>"
|
35
|
+
|
36
|
+
expect(money_positive.as_html).to eq "<span class=\"money positive\">$1.00</span>"
|
37
|
+
expect(money_negative.as_html(sign_before_symbol: true)).to eq "<span class=\"money negative\">-$1.00</span>"
|
38
|
+
expect(money_zero.as_html).to eq "<span class=\"money zero\">$0.00</span>"
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should format cents where appropriate' do
|
42
|
+
expect('1.50'.to_money.format(no_cents: true)).to eq '$1'
|
43
|
+
expect('1.00'.to_money.format(no_cents: true)).to eq '$1'
|
44
|
+
|
45
|
+
expect('1.50'.to_money.format(no_cents_if_whole: true)).to eq '$1.50'
|
46
|
+
expect('1.00'.to_money.format(no_cents_if_whole: true)).to eq '$1'
|
47
|
+
end
|
48
|
+
end
|
data/spec/money_spec.rb
CHANGED
@@ -1,23 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Money do
|
4
|
-
it "should get correct direction class" do
|
5
|
-
expect(Money.new(-1).direction_class).to eq 'negative'
|
6
|
-
expect(Money.new(0).direction_class).to eq 'zero'
|
7
|
-
expect(Money.new(1).direction_class).to eq 'positive'
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should round correctly" do
|
11
|
-
money = Money.new(511)
|
12
|
-
expect(money.round.cents).to eq 500
|
13
|
-
expect(money.round(10).cents).to eq 510
|
14
|
-
expect(money.round(1).cents).to eq 511
|
15
|
-
|
16
|
-
expect(money.round(100, 'up').cents).to eq 600
|
17
|
-
expect(money.round(100, 'down').cents).to eq 500
|
18
|
-
expect(money.round(100, 'nearest').cents).to eq 500
|
19
|
-
end
|
20
|
-
|
21
4
|
it "should deny division of money (to prevent rounding errors)" do
|
22
5
|
expect { Money.new(50)/10 }.to raise_error(RuntimeError)
|
23
6
|
end
|
@@ -38,7 +21,7 @@ describe Money do
|
|
38
21
|
expect(money.split_between([1,2])).to eq [33,67].map{ |i| Money.new(i)}
|
39
22
|
|
40
23
|
money_negative = Money.new(-100)
|
41
|
-
expect(money_negative.split_between(3)).to eq [-
|
24
|
+
expect(money_negative.split_between(3)).to eq [-34,-33,-33].map{ |i| Money.new(i)}
|
42
25
|
expect(money_negative.split_between([1,2,2,5])).to eq [-10,-20,-20,-50].map{ |i| Money.new(i)}
|
43
26
|
expect(money_negative.split_between([1,2])).to eq [-33,-67].map{ |i| Money.new(i)}
|
44
27
|
|
@@ -60,14 +43,14 @@ describe Money do
|
|
60
43
|
|
61
44
|
it "should return a nice, Big Decimal if so converted" do
|
62
45
|
money = Money.new(1428)
|
63
|
-
bigdecimal = BigDecimal
|
46
|
+
bigdecimal = BigDecimal("14.28")
|
64
47
|
expect(money.to_d).to eq bigdecimal
|
65
48
|
end
|
66
49
|
|
67
50
|
it "should be createable from strings and numbers" do
|
68
51
|
money = Money.new(100)
|
69
52
|
expect("1".to_money.cents).to eq money.cents
|
70
|
-
expect(BigDecimal
|
53
|
+
expect(BigDecimal('1').to_money.cents).to eq money.cents
|
71
54
|
expect(100.total_money.cents).to eq money.cents
|
72
55
|
end
|
73
56
|
|
@@ -89,29 +72,4 @@ describe Money do
|
|
89
72
|
expect(money_negative.abs).to eq money_positive
|
90
73
|
expect(money_zero.abs).to eq money_zero
|
91
74
|
end
|
92
|
-
|
93
|
-
it "should format the output correctly" do
|
94
|
-
expect(money_positive.format).to eq "<span class=\"money positive\">$1.00</span>"
|
95
|
-
expect(money_negative.format).to eq "<span class=\"money negative\">-$1.00</span>"
|
96
|
-
expect(money_zero.format).to eq "<span class=\"money zero\">$0.00</span>"
|
97
|
-
|
98
|
-
expect(money_positive.format(:html)).to eq "<span class=\"money positive\">$1.00</span>"
|
99
|
-
expect(money_negative.format(:html)).to eq "<span class=\"money negative\">-$1.00</span>"
|
100
|
-
expect(money_zero.format(:html)).to eq "<span class=\"money zero\">$0.00</span>"
|
101
|
-
|
102
|
-
expect(money_positive.format(:signed)).to eq "+$1.00"
|
103
|
-
expect(money_negative.format(:signed)).to eq "-$1.00"
|
104
|
-
expect(money_zero.format(:signed)).to eq "$0.00"
|
105
|
-
|
106
|
-
expect("1.50".to_money.format(:separator => '~')).to eq "$1~50"
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'should format cents where appropriate' do
|
110
|
-
expect('1.50'.to_money.format(:no_cents)).to eq '$1'
|
111
|
-
expect('1.00'.to_money.format(:no_cents)).to eq '$1'
|
112
|
-
|
113
|
-
expect('1.50'.to_money.format(:hide_zero_cents)).to eq '$1.50'
|
114
|
-
expect('1.00'.to_money.format(:hide_zero_cents)).to eq '$1'
|
115
|
-
end
|
116
|
-
|
117
75
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: money_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Noack
|
@@ -9,16 +9,13 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2019-08-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: money
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: 3.0.0
|
21
|
-
- - "<"
|
22
19
|
- !ruby/object:Gem::Version
|
23
20
|
version: 6.0.0
|
24
21
|
type: :runtime
|
@@ -26,11 +23,22 @@ dependencies:
|
|
26
23
|
version_requirements: !ruby/object:Gem::Requirement
|
27
24
|
requirements:
|
28
25
|
- - ">="
|
29
|
-
- !ruby/object:Gem::Version
|
30
|
-
version: 3.0.0
|
31
|
-
- - "<"
|
32
26
|
- !ruby/object:Gem::Version
|
33
27
|
version: 6.0.0
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: activesupport
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '5'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '5'
|
34
42
|
- !ruby/object:Gem::Dependency
|
35
43
|
name: rake
|
36
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -45,6 +53,34 @@ dependencies:
|
|
45
53
|
- - ">="
|
46
54
|
- !ruby/object:Gem::Version
|
47
55
|
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: pry
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rubocop
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
48
84
|
- !ruby/object:Gem::Dependency
|
49
85
|
name: rspec
|
50
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -151,28 +187,29 @@ extra_rdoc_files: []
|
|
151
187
|
files:
|
152
188
|
- ".gitignore"
|
153
189
|
- ".rspec"
|
190
|
+
- ".ruby-version"
|
154
191
|
- ".travis.yml"
|
155
192
|
- CHANGELOG.md
|
156
193
|
- Gemfile
|
157
194
|
- LICENSE
|
158
195
|
- README.md
|
159
196
|
- Rakefile
|
160
|
-
- gemfiles/rails3.gemfile
|
161
|
-
- gemfiles/rails4.gemfile
|
162
197
|
- gemfiles/rails5.gemfile
|
198
|
+
- gemfiles/rails6.gemfile
|
163
199
|
- lib/money_extensions.rb
|
164
200
|
- lib/money_extensions/active_record/extensions.rb
|
165
201
|
- lib/money_extensions/array.rb
|
166
|
-
- lib/money_extensions/
|
167
|
-
- lib/money_extensions/extensions.rb
|
202
|
+
- lib/money_extensions/html_format.rb
|
168
203
|
- lib/money_extensions/integer.rb
|
169
204
|
- lib/money_extensions/money_field.rb
|
170
205
|
- lib/money_extensions/numeric.rb
|
206
|
+
- lib/money_extensions/split_between.rb
|
171
207
|
- lib/money_extensions/string.rb
|
172
208
|
- lib/money_extensions/version.rb
|
173
209
|
- money_extensions.gemspec
|
174
210
|
- rails/init.rb
|
175
211
|
- spec/big_decimal_spec.rb
|
212
|
+
- spec/html_format_spec.rb
|
176
213
|
- spec/money_field_spec.rb
|
177
214
|
- spec/money_spec.rb
|
178
215
|
- spec/schema.rb
|
@@ -197,13 +234,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
197
234
|
- !ruby/object:Gem::Version
|
198
235
|
version: '0'
|
199
236
|
requirements: []
|
200
|
-
|
201
|
-
rubygems_version: 2.6.14.1
|
237
|
+
rubygems_version: 3.0.3
|
202
238
|
signing_key:
|
203
239
|
specification_version: 4
|
204
240
|
summary: Set of extensions to the money gem used by TravelLink Technology.
|
205
241
|
test_files:
|
206
242
|
- spec/big_decimal_spec.rb
|
243
|
+
- spec/html_format_spec.rb
|
207
244
|
- spec/money_field_spec.rb
|
208
245
|
- spec/money_spec.rb
|
209
246
|
- spec/schema.rb
|
data/gemfiles/rails3.gemfile
DELETED
@@ -1,189 +0,0 @@
|
|
1
|
-
require 'money'
|
2
|
-
|
3
|
-
module Extensions
|
4
|
-
|
5
|
-
def self.included(base)
|
6
|
-
base.class_eval do
|
7
|
-
alias_method :to_s_without_currency_hack, :to_s
|
8
|
-
alias_method :to_s, :to_s_with_currency_hack
|
9
|
-
alias_method :to_d_without_currency_hack, :to_d
|
10
|
-
alias_method :to_d, :to_d_with_currency_hack
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
# Override division -- should not do it, but use split_between
|
15
|
-
def /(*params)
|
16
|
-
raise "Division of money NOT allowed - use 'split_between' to avoid rounding errors"
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_d_with_currency_hack
|
20
|
-
BigDecimal.new("#{cents/100.0}")
|
21
|
-
end
|
22
|
-
|
23
|
-
# Split the money between the specified number - and return an array of money
|
24
|
-
# Remainder in splits are given to the highest value e.g.
|
25
|
-
# $2.00 splits [40, 81, 40] into [49, 102, 49]
|
26
|
-
# $1.01 splits [ 1, 1, 1] into [35, 33, 33]
|
27
|
-
def split_between(params)
|
28
|
-
#if just a number is passed in, then money is split equally
|
29
|
-
if params.is_a?(Integer)
|
30
|
-
divisor = params
|
31
|
-
raise ArgumentError, "Can only split up over a positive number" if divisor < 1
|
32
|
-
|
33
|
-
rounded_split = self.lossy_divide(divisor)
|
34
|
-
results = Array.new(divisor, rounded_split) # Create with 'divisor' num elements
|
35
|
-
|
36
|
-
#if an array of monies is passed in, then split in proportions
|
37
|
-
elsif params.is_a?(Array)
|
38
|
-
|
39
|
-
raise ArgumentError, "Can only split up over at least one ration" if params.empty? && !self.zero?
|
40
|
-
|
41
|
-
|
42
|
-
results = params.map { |p| p.is_a?(::Money) ? p.cents : p }
|
43
|
-
|
44
|
-
total = results.inject(:+)
|
45
|
-
if total.zero?
|
46
|
-
return Array.new(results.size, ::Money.new(0)) if self.zero?
|
47
|
-
raise ArgumentError, "Total of ratios should not be zero! You sent in: #{params.inspect}"
|
48
|
-
end
|
49
|
-
|
50
|
-
results.map! do |ratio|
|
51
|
-
::Money.new((self.cents * (ratio.to_f / total)).round)
|
52
|
-
end
|
53
|
-
else
|
54
|
-
raise "Either a Integer or array has to be passed in for splitting money"
|
55
|
-
end
|
56
|
-
|
57
|
-
# Distribute rounding to max absolute to avoid a $0 amount getting the rounding
|
58
|
-
biggest_value_index = results.index(results.max_by(&:abs))
|
59
|
-
results[biggest_value_index] += self - results.total_money
|
60
|
-
|
61
|
-
return results
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
|
-
DEFAULT_FORMAT_RULES = [:html]
|
66
|
-
# HACK COZ WE ARE PRETENDING WE DON'T HAVE CURRENCY!!!
|
67
|
-
#
|
68
|
-
# TODO: Make this not a hack...
|
69
|
-
def to_s_with_currency_hack
|
70
|
-
sprintf("%.2f", cents.to_f / 100) #currency.subunit_to_unit)
|
71
|
-
end
|
72
|
-
|
73
|
-
def inspect
|
74
|
-
inbuilt_inspect_style_id = '%x' % (object_id << 1)
|
75
|
-
"\#<Money:0x#{inbuilt_inspect_style_id} $#{self}>"
|
76
|
-
end
|
77
|
-
|
78
|
-
# Money's default formatted is not flexible enought.
|
79
|
-
# - we don't want it to say 'free' when 0 (not correct for 'discounts' and such)
|
80
|
-
def format(*rules)
|
81
|
-
rules = rules.empty? ? DEFAULT_FORMAT_RULES.dup : rules.flatten
|
82
|
-
|
83
|
-
options = {}
|
84
|
-
rules.each do |rule|
|
85
|
-
if rule.is_a? Hash
|
86
|
-
options = rule
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
html_wrap = rules.include?(:html)
|
91
|
-
|
92
|
-
options[:delimiter] ||= ','
|
93
|
-
options[:separator] ||= '.'
|
94
|
-
|
95
|
-
''.tap do |formatted|
|
96
|
-
formatted << "<span class=\"money #{direction_class}\">" if html_wrap
|
97
|
-
|
98
|
-
rules << :signed if cents < 0
|
99
|
-
|
100
|
-
if rules.include?(:signed)
|
101
|
-
formatted << if cents > 0
|
102
|
-
'+'
|
103
|
-
elsif cents < 0
|
104
|
-
'-'
|
105
|
-
else
|
106
|
-
''
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
no_cents = rules.include?(:no_cents) ||
|
111
|
-
(rules.include?(:hide_zero_cents) && cents % 100 == 0)
|
112
|
-
format_string = no_cents ? "$%d" : "$%.2f"
|
113
|
-
amount = format_string % (cents.abs.to_f / 100)
|
114
|
-
amount.gsub!('.', options[:separator])
|
115
|
-
amount.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
|
116
|
-
formatted << amount
|
117
|
-
|
118
|
-
formatted << "</span>" if html_wrap
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def direction_class
|
123
|
-
if cents > 0
|
124
|
-
'positive'
|
125
|
-
elsif cents < 0
|
126
|
-
'negative'
|
127
|
-
else
|
128
|
-
'zero'
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
def mark_up(mark_up_definition)
|
133
|
-
mark_up_cents = mark_up_definition.cents || 0
|
134
|
-
rounding_direction = mark_up_definition.rounding_direction.try(:to_sym)
|
135
|
-
multiplier = ((100 + mark_up_definition.percent)/100.0)
|
136
|
-
(self * multiplier).round(mark_up_definition.rounding_cents, rounding_direction) + ::Money.new(mark_up_cents)
|
137
|
-
end
|
138
|
-
|
139
|
-
# money = Money.new(501)
|
140
|
-
# money.round
|
141
|
-
# => 500
|
142
|
-
# money.round(10)
|
143
|
-
# => 510
|
144
|
-
# money.round(1)
|
145
|
-
# => 511
|
146
|
-
|
147
|
-
# money.round(100, 'up')
|
148
|
-
# => 600
|
149
|
-
# money.round(100, 'down')
|
150
|
-
# => 500
|
151
|
-
# money.round(100, 'nearest')
|
152
|
-
# => 500
|
153
|
-
def round(round_to_cents = 100, direction = :nearest)
|
154
|
-
round_to_cents = 100 if round_to_cents.nil?
|
155
|
-
case direction.to_sym
|
156
|
-
when :nearest
|
157
|
-
rounded_cents = (cents + round_to_cents/2) / round_to_cents * round_to_cents
|
158
|
-
when :up
|
159
|
-
rounded_cents = (cents + round_to_cents) / round_to_cents * round_to_cents
|
160
|
-
when :down
|
161
|
-
rounded_cents = (cents) / round_to_cents * round_to_cents
|
162
|
-
else
|
163
|
-
end
|
164
|
-
::Money.new(rounded_cents)
|
165
|
-
end
|
166
|
-
|
167
|
-
def abs
|
168
|
-
if cents >= 0
|
169
|
-
self.clone
|
170
|
-
else
|
171
|
-
::Money.new(0 - cents)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
def positive?
|
176
|
-
cents > 0
|
177
|
-
end
|
178
|
-
|
179
|
-
def negative?
|
180
|
-
cents < 0
|
181
|
-
end
|
182
|
-
|
183
|
-
end
|
184
|
-
|
185
|
-
::Money.class_eval do
|
186
|
-
alias_method :lossy_divide, :/
|
187
|
-
end
|
188
|
-
|
189
|
-
::Money.send(:include, Extensions)
|