money_extensions 0.0.2 → 1.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f56893765e2c83d2ffea6e7e80ca2cab0963370c
4
- data.tar.gz: 799f31640b6dc664c300e7ca4a01b3275e378cfb
2
+ SHA256:
3
+ metadata.gz: e3f8f70cfcaef8f46dcb30b9f80f2116b0d45210d043fa21c4e7fbbb8c3a4915
4
+ data.tar.gz: 949f3cee9063fc0a604087d06925739a8beacf6482cae52e3cb2f6ae3fb7126a
5
5
  SHA512:
6
- metadata.gz: a4144e85e7838f52c2cc39adb3e845cc4cbc48fa6c88c2e1836caf861e7592f65712b734e8b1c8306187b9a1040dfa0e7cc2e281c5344694e1b6cbac54c461a4
7
- data.tar.gz: c1d03bfdecca1db109625f7bd4f2ace3839f68ea389dfaf1460e48a01bd34802d37e172eb5dbe3404c5fe6ce7540dde68c50cc357bc998af567705660734117a
6
+ metadata.gz: fc5c87edadd0d2b03e45810f399037ea32b86f1d9aac412c7a79022b2202846e7b6a8f4be352d5c3705562b225123dbff71eb33c4aac3bb88fe1cc649d6f9300
7
+ data.tar.gz: c8caeb5dd952872c50805478ca22e04a8cd0caf63b934896133d30ea0d569e23e2f186bf9ce3726a04d8ed518ed0ea866a8ae99b8971969f09b25d92318b1f40
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "bundler"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "daily"
@@ -0,0 +1,59 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ name: Build
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout
14
+ uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ bundler-cache: true
18
+ - run: bundle exec rake
19
+
20
+ release:
21
+ needs: build
22
+ name: Release
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - name: Checkout
26
+ uses: actions/checkout@v2
27
+
28
+ - name: Generate Changelog
29
+ run: |
30
+ # Get version from github ref (remove 'refs/tags/' and prefix 'v')
31
+ version="${GITHUB_REF#refs/tags/v}"
32
+ npx changelog-parser CHANGELOG.md | jq -cr ".versions | .[] | select(.version == \"$version\") | .body" > ${{ github.workflow }}-CHANGELOG.txt
33
+
34
+ - name: Release
35
+ uses: softprops/action-gh-release@v1
36
+ with:
37
+ body_path: ${{ github.workflow }}-CHANGELOG.txt
38
+ env:
39
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40
+
41
+ publish:
42
+ needs: [build, release]
43
+ name: Publish
44
+ runs-on: ubuntu-latest
45
+
46
+ steps:
47
+ - uses: actions/checkout@v2
48
+ - uses: ruby/setup-ruby@v1
49
+
50
+ - name: Publish to RubyGems
51
+ run: |
52
+ mkdir -p $HOME/.gem
53
+ touch $HOME/.gem/credentials
54
+ chmod 0600 $HOME/.gem/credentials
55
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
56
+ gem build *.gemspec
57
+ gem push *.gem
58
+ env:
59
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
@@ -0,0 +1,24 @@
1
+ name: Build and Test
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ strategy:
6
+ fail-fast: false
7
+ matrix:
8
+ gemfile: [rails60, rails61, rails70]
9
+ ruby: ["2.7", "3.0", "3.1"]
10
+ runs-on: ubuntu-latest
11
+ env:
12
+ BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+ bundler-cache: true
19
+ - run: bundle exec rake
20
+ - name: Coveralls
21
+ uses: coverallsapp/github-action@master
22
+ with:
23
+ github-token: ${{ secrets.GITHUB_TOKEN }}
24
+ path-to-lcov: coverage/lcov.info
data/.gitignore CHANGED
@@ -2,3 +2,5 @@ pkg
2
2
  coverage
3
3
  Gemfile.lock
4
4
  tmp
5
+ vendor
6
+ .bundle
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.1.0
data/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ ## 1.2.0
4
+
5
+ - [PLAT-183] Build with Ruby 3.1 / Rails 7 and publish coverage with github action
6
+
7
+ ## 1.1.0
8
+
9
+ - [TT-8625] Update to build with github actions / ruby 3.0 / rails 6.1
10
+
11
+ ## 1.0.0
12
+
13
+ * [TT-5845] Update to support money gems >= 6
14
+
15
+ ## 0.1.0
16
+
17
+ * Using Fixnum is deprecated
18
+ * Drop rails 2 and old ruby support
19
+ * Use coverage kit to enforce maximum coverage
data/README.md CHANGED
@@ -1,9 +1,8 @@
1
- Money Extensions
2
- ================
1
+ # Money Extensions
3
2
 
4
- [![Build Status](https://travis-ci.org/sealink/money_extensions.png?branch=master)](https://travis-ci.org/sealink/money_extensions)
3
+ [![Gem Version](https://badge.fury.io/rb/money_extensions.svg)](http://badge.fury.io/rb/money_extensions)
4
+ [![Build Status](https://github.com/sealink/money_extensions/workflows/Build%20and%20Test/badge.svg?branch=master)](https://github.com/sealink/money_extensions/actions)
5
5
  [![Coverage Status](https://coveralls.io/repos/sealink/money_extensions/badge.png)](https://coveralls.io/r/sealink/money_extensions)
6
- [![Dependency Status](https://gemnasium.com/sealink/money_extensions.png?travis)](https://gemnasium.com/sealink/money_extensions)
7
6
  [![Code Climate](https://codeclimate.com/github/sealink/money_extensions.png)](https://codeclimate.com/github/sealink/money_extensions)
8
7
 
9
8
  # DESCRIPTION
@@ -11,7 +10,10 @@ Money Extensions
11
10
  Extends the money classes with helpful functions and currency functions
12
11
 
13
12
  e.g. in model
13
+
14
+ ```ruby
14
15
  money_fields :total, :discount
16
+ ```
15
17
 
16
18
  This will by default map a money object "total" to a database column total_in_cents and the same for discount.
17
19
 
@@ -24,3 +26,14 @@ See spec directory for examples.
24
26
  Add to your Gemfile:
25
27
  gem 'money_extensions'
26
28
 
29
+ # RELEASE
30
+
31
+ To publish a new version of this gem the following steps must be taken.
32
+
33
+ - Update the version in the following files
34
+ ```
35
+ CHANGELOG.md
36
+ lib/quick_travel/version.rb
37
+ ```
38
+ - Create a tag using the format v0.1.0
39
+ - Follow build progress in GitHub actions
@@ -1,8 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec :path => '../'
3
3
 
4
- gem 'money', '< 5.1', :platform => :ruby_18
5
-
6
4
  group :development, :test do
7
- gem 'activerecord', '~> 4.0'
5
+ gem 'activerecord', '~> 6.0'
6
+ gem 'activesupport', '~> 6.0'
8
7
  end
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+ gemspec :path => '../'
3
+
4
+ group :development, :test do
5
+ gem 'activerecord', '~> 6.1'
6
+ gem 'activesupport', '~> 6.1'
7
+ end
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+ gemspec :path => '../'
3
+
4
+ group :development, :test do
5
+ gem 'activerecord', '~> 7.0'
6
+ gem 'activesupport', '~> 7.0'
7
+ end
@@ -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, :class_name => "Money::Currency",
22
- :mapping => [field_name, 'iso_code'],
23
- :allow_nil => true,
24
- :constructor => Proc.new{|value| Money::Currency.new(value) unless value.blank?}
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
- if Rails.version > '3'
27
- scope :for_currency, lambda{ |currency|
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
 
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Array
2
4
  # Returns sum as a money - and returns 0 for empty arrays
3
5
  def total_money
4
6
  empty? ? ::Money.new(0) : inject(:+)
5
7
  end
6
- end
8
+ end
@@ -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
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Integer
4
+ # Returns self as a money (treated as cents)
5
+ def total_money
6
+ zero? ? ::Money.new(0) : ::Money.new(self)
7
+ end
8
+ end
@@ -1,5 +1,6 @@
1
- module MoneyField
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| self.money_field(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((self.to_f * 100).round, currency)
14
+ Money.new((to_f * 100).round, currency)
13
15
  end
14
- end
16
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MoneyExtensions
2
- VERSION = '0.0.2'
4
+ VERSION = '1.2.0'
3
5
  end
@@ -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
- require 'money_extensions/fixnum'
6
- require 'money_extensions/extensions'
4
+ require 'money_extensions/integer'
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
-
@@ -19,13 +19,14 @@ 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', '>= 3.0.0', '< 6.0.0'
22
+ spec.add_dependency 'money', '>= 6.0.0'
23
+ spec.add_dependency 'activesupport', '>= 6'
24
+
23
25
  spec.add_development_dependency 'rake'
26
+ spec.add_development_dependency 'rubocop'
24
27
  spec.add_development_dependency 'rspec'
25
- spec.add_development_dependency 'simplecov'
26
- spec.add_development_dependency 'simplecov-rcov'
27
- spec.add_development_dependency 'coveralls'
28
+ spec.add_development_dependency 'coverage-kit'
28
29
  spec.add_development_dependency 'sqlite3'
29
30
  spec.add_development_dependency 'activerecord'
30
- spec.add_development_dependency 'travis'
31
+ spec.add_development_dependency 'pry-byebug'
31
32
  end
@@ -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.new('-1')).to_not be_positive
7
- expect(BigDecimal.new('0')).to_not be_positive
8
- expect(BigDecimal.new('1')).to be_positive
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.new('-1')).to be_negative
13
- expect(BigDecimal.new('0')).to_not be_negative
14
- expect(BigDecimal.new('1')).to_not be_negative
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 [-32,-34,-34].map{ |i| Money.new(i)}
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.new("14.28")
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.new('1').to_money.cents).to eq money.cents
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
@@ -1,26 +1,3 @@
1
- MINIMUM_COVERAGE = 80
1
+ require 'coverage/kit'
2
2
 
3
- unless ENV['COVERAGE'] == 'off'
4
- require 'simplecov'
5
- require 'simplecov-rcov'
6
- require 'coveralls'
7
- Coveralls.wear!
8
-
9
- SimpleCov.formatters = [
10
- SimpleCov::Formatter::RcovFormatter,
11
- Coveralls::SimpleCov::Formatter
12
- ]
13
- SimpleCov.start do
14
- add_filter '/vendor/'
15
- add_filter '/spec/'
16
- add_group 'lib', 'lib'
17
- end
18
- SimpleCov.at_exit do
19
- SimpleCov.result.format!
20
- percent = SimpleCov.result.covered_percent
21
- unless percent >= MINIMUM_COVERAGE
22
- puts "Coverage must be above #{MINIMUM_COVERAGE}%. It is #{"%.2f" % percent}%"
23
- Kernel.exit(1)
24
- end
25
- end
26
- end
3
+ Coverage::Kit.setup(minimum_coverage: 86.6)
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: 0.0.2
4
+ version: 1.2.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: 2016-02-03 00:00:00.000000000 Z
12
+ date: 2022-01-24 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,27 +23,24 @@ 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
34
28
  - !ruby/object:Gem::Dependency
35
- name: rake
29
+ name: activesupport
36
30
  requirement: !ruby/object:Gem::Requirement
37
31
  requirements:
38
32
  - - ">="
39
33
  - !ruby/object:Gem::Version
40
- version: '0'
41
- type: :development
34
+ version: '6'
35
+ type: :runtime
42
36
  prerelease: false
43
37
  version_requirements: !ruby/object:Gem::Requirement
44
38
  requirements:
45
39
  - - ">="
46
40
  - !ruby/object:Gem::Version
47
- version: '0'
41
+ version: '6'
48
42
  - !ruby/object:Gem::Dependency
49
- name: rspec
43
+ name: rake
50
44
  requirement: !ruby/object:Gem::Requirement
51
45
  requirements:
52
46
  - - ">="
@@ -60,7 +54,7 @@ dependencies:
60
54
  - !ruby/object:Gem::Version
61
55
  version: '0'
62
56
  - !ruby/object:Gem::Dependency
63
- name: simplecov
57
+ name: rubocop
64
58
  requirement: !ruby/object:Gem::Requirement
65
59
  requirements:
66
60
  - - ">="
@@ -74,7 +68,7 @@ dependencies:
74
68
  - !ruby/object:Gem::Version
75
69
  version: '0'
76
70
  - !ruby/object:Gem::Dependency
77
- name: simplecov-rcov
71
+ name: rspec
78
72
  requirement: !ruby/object:Gem::Requirement
79
73
  requirements:
80
74
  - - ">="
@@ -88,7 +82,7 @@ dependencies:
88
82
  - !ruby/object:Gem::Version
89
83
  version: '0'
90
84
  - !ruby/object:Gem::Dependency
91
- name: coveralls
85
+ name: coverage-kit
92
86
  requirement: !ruby/object:Gem::Requirement
93
87
  requirements:
94
88
  - - ">="
@@ -130,7 +124,7 @@ dependencies:
130
124
  - !ruby/object:Gem::Version
131
125
  version: '0'
132
126
  - !ruby/object:Gem::Dependency
133
- name: travis
127
+ name: pry-byebug
134
128
  requirement: !ruby/object:Gem::Requirement
135
129
  requirements:
136
130
  - - ">="
@@ -149,29 +143,34 @@ executables: []
149
143
  extensions: []
150
144
  extra_rdoc_files: []
151
145
  files:
146
+ - ".github/dependabot.yml"
147
+ - ".github/workflows/release.yml"
148
+ - ".github/workflows/ruby.yml"
152
149
  - ".gitignore"
153
150
  - ".rspec"
154
- - ".travis.yml"
151
+ - ".ruby-version"
152
+ - CHANGELOG.md
155
153
  - Gemfile
156
154
  - LICENSE
157
155
  - README.md
158
156
  - Rakefile
159
- - gemfiles/rails2.gemfile
160
- - gemfiles/rails3.gemfile
161
- - gemfiles/rails4.gemfile
157
+ - gemfiles/rails60.gemfile
158
+ - gemfiles/rails61.gemfile
159
+ - gemfiles/rails70.gemfile
162
160
  - lib/money_extensions.rb
163
161
  - lib/money_extensions/active_record/extensions.rb
164
162
  - lib/money_extensions/array.rb
165
- - lib/money_extensions/big_decimal.rb
166
- - lib/money_extensions/extensions.rb
167
- - lib/money_extensions/fixnum.rb
163
+ - lib/money_extensions/html_format.rb
164
+ - lib/money_extensions/integer.rb
168
165
  - lib/money_extensions/money_field.rb
169
166
  - lib/money_extensions/numeric.rb
167
+ - lib/money_extensions/split_between.rb
170
168
  - lib/money_extensions/string.rb
171
169
  - lib/money_extensions/version.rb
172
170
  - money_extensions.gemspec
173
171
  - rails/init.rb
174
172
  - spec/big_decimal_spec.rb
173
+ - spec/html_format_spec.rb
175
174
  - spec/money_field_spec.rb
176
175
  - spec/money_spec.rb
177
176
  - spec/schema.rb
@@ -196,13 +195,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
196
195
  - !ruby/object:Gem::Version
197
196
  version: '0'
198
197
  requirements: []
199
- rubyforge_project:
200
- rubygems_version: 2.4.8
198
+ rubygems_version: 3.3.3
201
199
  signing_key:
202
200
  specification_version: 4
203
201
  summary: Set of extensions to the money gem used by TravelLink Technology.
204
202
  test_files:
205
203
  - spec/big_decimal_spec.rb
204
+ - spec/html_format_spec.rb
206
205
  - spec/money_field_spec.rb
207
206
  - spec/money_spec.rb
208
207
  - spec/schema.rb
data/.travis.yml DELETED
@@ -1,30 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 1.9
4
- - 2.0
5
- - 2.1
6
- - 2.2
7
- gemfile:
8
- - gemfiles/rails2.gemfile
9
- - gemfiles/rails3.gemfile
10
- - gemfiles/rails4.gemfile
11
- matrix:
12
- exclude:
13
- - rvm: 1.9
14
- gemfile: gemfiles/rails4.gemfile
15
- - rvm: 1.9
16
- gemfile: gemfiles/rails2.gemfile
17
- - rvm: 2.0
18
- gemfile: gemfiles/rails2.gemfile
19
- - rvm: 2.1
20
- gemfile: gemfiles/rails2.gemfile
21
- - rvm: 2.2
22
- gemfile: gemfiles/rails2.gemfile
23
- script: "bundle exec rake spec"
24
- notifications:
25
- email:
26
- - support@travellink.com.au
27
- flowdock:
28
- secure: A0Fr9j0kvKPEWuPbJu/DPMYPvx98UI8k43adKN9UjTB6FRVAQM3kXmKJIL3A495scc2Civrg2KHDkbwNwVThY+HdLeU7q71Bm6obP6ZkCe43MIoc9NiVJymCNguku6+tLEyusdWIceFiBW7P5p/sU1QU66GFj1t4wNTpVq9A4Kw=
29
- sudo: false
30
- cache: bundler
@@ -1,8 +0,0 @@
1
- source 'https://rubygems.org'
2
- gemspec :path => "../"
3
-
4
- gem 'money', '< 5.1', :platform => :ruby_18
5
-
6
- group :development, :test do
7
- gem 'activerecord', '~> 2.3.0'
8
- end
@@ -1,8 +0,0 @@
1
- source 'https://rubygems.org'
2
- gemspec :path => "../"
3
-
4
- gem 'money', '< 5.1', :platform => :ruby_18
5
-
6
- group :development, :test do
7
- gem 'activerecord', '~> 3.2.0'
8
- end
@@ -1,12 +0,0 @@
1
- class BigDecimal
2
-
3
- def negative?
4
- self < BigDecimal.new('0')
5
- end
6
-
7
- def positive?
8
- self > BigDecimal.new('0')
9
- end
10
-
11
- end
12
-
@@ -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?(Fixnum)
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 fixnum 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)
@@ -1,6 +0,0 @@
1
- class Fixnum
2
- #Returns self as a money (treated as cents)
3
- def total_money
4
- zero? ? ::Money.new(0) : ::Money.new(self)
5
- end
6
- end