active_currency 1.2.1 → 1.4.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
2
  SHA256:
3
- metadata.gz: 938c7b875052bf9d26b9ade8d9f1f268a94da7949a1685961a4265b01ed70a1c
4
- data.tar.gz: cd167c1b911156c2025d75b29be92cfdfceed15aac7533b736db5bb63a59d3bc
3
+ metadata.gz: dc61cac61fcc7b74bf7288a1145b89af079cb527f49dc3991dd7147ebe5b824a
4
+ data.tar.gz: fc8da46d16ceae4822a6f6e3974c050bafa732122d5918276bc33b5fd09531ff
5
5
  SHA512:
6
- metadata.gz: 51af4e890792d65780f3ce822ca6bef58465b2a34578b7edb0c6776d8d104ba569ef282dd7004715944e7d388b44a3935c5e0659ae87fdbf3f01ce1b36fd1cec
7
- data.tar.gz: 2b66ea9433ccf5e35b54e22296b95a765dd9b249930e02c056d49afcc0c9f8a6731e7340db6db606fcbda33be7b4bc5d4f6fac53dc75dbae7e4a1b6991f634cc
6
+ metadata.gz: 96554a896dd94c5b23d274c2805421dade360cec6f77eeba451f41f0be49783264f191dd23f555df0a54230c6eb387562577fb470580223af411b22211fbeaa2
7
+ data.tar.gz: 0e2b4b110edede9724552d7ff36c35d8f6c80cd0d8449950092a84452d1fe5f64043116ccfb3f8aef1a2e7b9793973c09e47546c11d9afa31e3d98b3ce0abaa2
data/README.md CHANGED
@@ -1,14 +1,12 @@
1
1
  # ActiveCurrency
2
2
 
3
- [![CircleCI](https://circleci.com/gh/sunny/active_currency.svg?style=svg)](https://circleci.com/gh/sunny/active_currency)
4
-
5
3
  Rails plugin to retrieve and store the currency rates daily to integrate
6
- with the `money-rails` gem.
4
+ with the [money-rails] gem.
7
5
 
8
6
  ## Rationale
9
7
 
10
- Storing the current currency rates in the database using ActiveCurrency
11
- provides the following advantages:
8
+ Storing the current currency rates with ActiveCurrency provides the following
9
+ advantages:
12
10
 
13
11
  - Lets you query for the currency rate you actually used in your application at
14
12
  any given time.
@@ -25,11 +23,11 @@ a call to the database.
25
23
  ## Usage
26
24
 
27
25
  Store the current rate regularly by calling in a scheduled job (using something
28
- like `sidekiq-scheduler`, `whenever`, or `active_scheduler`) with the currencies
26
+ like [sidekiq-scheduler], [whenever], or [active_scheduler]) with the currencies
29
27
  you want to store:
30
28
 
31
29
  ```rb
32
- ActiveCurrency::AddRates.call(%w[EUR USD])
30
+ ActiveCurrency::AddRates.call(currencies: %w[EUR USD])
33
31
  ```
34
32
 
35
33
  You can then exchange money by using the Money gem helpers:
@@ -49,7 +47,7 @@ ActiveCurrency::Rate.where(from: 'EUR', to: 'USD').pluck(:value)
49
47
 
50
48
  ## Installation
51
49
 
52
- Add these lines to your application's `Gemfile`:
50
+ Add these lines to your applications `Gemfile`:
53
51
 
54
52
  ```rb
55
53
  # Store and retrieve the currency from the database.
@@ -69,23 +67,52 @@ the currency rates and fill it for the first time.
69
67
 
70
68
  ## Fetching rates
71
69
 
72
- By defaut it uses the [eu_central_bank] to update the currency rates.
70
+ Call the following regularly in a scheduled job:
71
+
72
+ ```rb
73
+ ActiveCurrency::AddRates.call(currencies: %w[EUR USD])
74
+ ```
75
+
76
+ The first currency you give in `currencies` is considered the default currency
77
+ against which other currency rates will be guessed if they are unavailable.
78
+
79
+ ### Fetching from the European Central Bank
80
+
81
+ By defaut it uses the [eu_central_bank] to fill the currency rates.
73
82
 
74
- If you prefer another API, you can provide any Money-compatible bank when
75
- calling `ActiveCurrency::AddRates`. For example with the
76
- [money-open-exchange-rates] gem:
83
+ ### Fetching from openexchangerates.org
84
+
85
+ To use the [money-open-exchange-rates] gem, add the gem to your `Gemfile`, then
86
+ add the following to your application’s initializers:
77
87
 
78
88
  ```rb
79
- require 'money/bank/open_exchange_rates_bank'
89
+ ActiveCurrency.configure do |config|
90
+ config.remote_bank = :open_exchange_rates
91
+ config.open_exchange_rates_app_id = '…'
92
+ end
93
+ ```
94
+
95
+ ### Fetching from a custom bank
80
96
 
81
- bank = Money::Bank::OpenExchangeRatesBank.new(Money::RatesStore::Memory.new)
82
- bank.app_id = '…'
97
+ You can provide any Money-compatible bank when calling
98
+ `ActiveCurrency::AddRates`:
83
99
 
84
- ActiveCurrency::AddRates.call(%w[EUR USD], bank: bank)
100
+ ```rb
101
+ ActiveCurrency::AddRates.call(…, bank: …)
85
102
  ```
86
103
 
87
- The first currency you give to `AddRates` is considered the default currency
88
- against which other currency rates will be guessed if they are unavailable.
104
+ ## Apply a multiplier
105
+
106
+ If you want to increase or decrease the currency rates by a given multiplier,
107
+ you can do so by setting the `multiplier` option:
108
+
109
+ ```rb
110
+ ActiveCurrency.configure do |config|
111
+ config.multiplier = {
112
+ ["EUR", "USD"] => 1.01,
113
+ }
114
+ end
115
+ ```
89
116
 
90
117
  ## Tests
91
118
 
@@ -98,7 +125,7 @@ For that, you can use a fake rate store in your `rails_helper.rb`:
98
125
  MoneyRails.configure do |config|
99
126
  rate_store = Money::RatesStore::Memory.new.tap do |store|
100
127
  store.add_rate('USD', 'EUR', 1.5)
101
- store.add_rate('EUR', 'USD', 1.4)
128
+ store.add_rate('EUR', 'USD', 0.67)
102
129
  end
103
130
  config.default_bank = Money::Bank::VariableExchange.new(rate_store)
104
131
  end
@@ -106,21 +133,20 @@ end
106
133
 
107
134
  ## Contributing
108
135
 
109
- Please file issues and pull requests
110
- [on GitHub](https://github.com/sunny/active_currency).
136
+ Please file issues and pull requests [on GitHub].
111
137
 
112
138
  ## Development
113
139
 
114
140
  Install:
115
141
 
116
142
  ```sh
117
- BUNDLE_GEMFILE=Gemfile-rails6.0 bundle install
143
+ BUNDLE_GEMFILE=Gemfile-rails7.0 bundle install
118
144
  ```
119
145
 
120
146
  Launch specs and linters:
121
147
 
122
148
  ```sh
123
- BUNDLE_GEMFILE=Gemfile-rails6.0 bin/rake
149
+ BUNDLE_GEMFILE=Gemfile-rails7.0 bin/rake
124
150
  ```
125
151
 
126
152
  ## Release
@@ -130,23 +156,23 @@ Update `CHANGELOG.md`, update version in `lib/active_currency/version.rb`.
130
156
  Then:
131
157
 
132
158
  ```sh
133
- gem install bundler:1.3.0
134
- BUNDLE_GEMFILE=Gemfile-rails3.2 bundle update
135
- BUNDLE_GEMFILE=Gemfile-rails4.2 bundle update
136
- BUNDLE_GEMFILE=Gemfile-rails5.2 bundle update
137
-
138
- gem install bundler:2.1.2
139
- BUNDLE_GEMFILE=Gemfile-rails6.0 bundle update
159
+ BUNDLE_GEMFILE=Gemfile-rails6.1 bundle update
160
+ BUNDLE_GEMFILE=Gemfile-rails7.0 bundle update
140
161
 
141
- git add CHANGELOG.md lib/active_currency/version.rb Gemfile-rails*.lock
162
+ git add CHANGELOG.md lib/active_currency/version.rb Gemfile-rails*
142
163
  git commit -m v`ruby -r./lib/active_currency/version <<< 'puts ActiveCurrency::VERSION'`
143
164
  bin/rake release
144
165
  ```
145
166
 
146
167
  ## License
147
168
 
148
- The gem is available as open source under the terms of the
149
- [MIT License](http://opensource.org/licenses/MIT).
169
+ The gem is available as open source under the terms of the [MIT License].
150
170
 
171
+ [money-rails]: https://github.com/RubyMoney/money-rails
172
+ [sidekiq-scheduler]: https://github.com/Moove-it/sidekiq-scheduler
173
+ [whenever]: https://github.com/javan/whenever
174
+ [active_scheduler]: https://github.com/JustinAiken/active_scheduler
151
175
  [eu_central_bank]: https://github.com/RubyMoney/eu_central_bank
152
176
  [money-open-exchange-rates]: https://github.com/spk/money-open-exchange-rates
177
+ [on GitHub]: https://github.com/sunny/active_currency
178
+ [MIT License]: http://opensource.org/licenses/MIT
@@ -15,17 +15,12 @@ module ActiveCurrency
15
15
  to = Money::Currency.new(to)
16
16
  return 1 if from == to
17
17
 
18
- scope = date ? before(date) : all_scope
18
+ scope = date ? before(date) : all
19
19
  scope
20
20
  .where(from: from.iso_code, to: to.iso_code)
21
21
  .order(:created_at)
22
22
  .last
23
23
  &.value
24
24
  end
25
-
26
- # Scope retrocompatibility for Rails 3.2.
27
- def self.all_scope
28
- respond_to?(:scoped) ? scoped : all
29
- end
30
25
  end
31
26
  end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_currency/migration'
3
+ require "active_currency/migration"
4
4
 
5
5
  class CreateActiveCurrencyRates < ActiveCurrency::Migration
6
+ # rubocop:disable Metrics/MethodLength
6
7
  def change
7
8
  create_table :active_currency_rates do |t|
8
9
  t.string :from
@@ -11,8 +12,16 @@ class CreateActiveCurrencyRates < ActiveCurrency::Migration
11
12
  t.datetime :created_at
12
13
  end
13
14
 
14
- add_index :active_currency_rates,
15
- %i[from to created_at],
16
- name: 'index_active_currency_rates'
15
+ reversible do |dir|
16
+ dir.up do
17
+ add_index :active_currency_rates,
18
+ %i[from to created_at],
19
+ name: "index_active_currency_rates"
20
+ end
21
+ dir.down do
22
+ remove_index :active_currency_rates, "index_active_currency_rates"
23
+ end
24
+ end
17
25
  end
26
+ # rubocop:enable Metrics/MethodLength
18
27
  end
@@ -3,27 +3,41 @@
3
3
  module ActiveCurrency
4
4
  # Store the latest currency rates.
5
5
  class AddRates
6
- def initialize(currencies, bank: EuCentralBank.new)
6
+ include AfterCommitEverywhere
7
+
8
+ def self.call(deprecated_currencies = nil, currencies: nil, bank: nil)
9
+ currencies ||= deprecated_currencies
10
+ bank ||= ActiveCurrency.remote_bank
11
+
12
+ new(currencies: currencies, bank: bank).send(:call)
13
+ end
14
+
15
+ private
16
+
17
+ def initialize(currencies:, bank:)
18
+ if currencies.size < 2
19
+ raise ArgumentError, "At least two currencies are required"
20
+ end
21
+
7
22
  @currencies = currencies.map(&:to_s).map(&:upcase)
8
23
  @bank = bank
9
24
  end
10
25
 
26
+ private_class_method :new
27
+
11
28
  def call
12
29
  bank.update_rates
13
30
 
14
- rates_hash.each do |(from, to), rate|
15
- store.add_rate(from, to, rate)
31
+ in_transaction do
32
+ rates_hash.each do |(from, to), rate|
33
+ rate = multiply_rate(from, to, rate)
34
+ store.add_rate(from, to, rate)
35
+ end
16
36
  end
17
37
 
18
38
  nil
19
39
  end
20
40
 
21
- def self.call(currencies, *options)
22
- new(currencies, *options).call
23
- end
24
-
25
- private
26
-
27
41
  attr_accessor :bank, :currencies
28
42
 
29
43
  def store
@@ -48,7 +62,7 @@ module ActiveCurrency
48
62
  inverse = hash[[to, from]]
49
63
  return 1.fdiv(inverse) if inverse
50
64
 
51
- # Rate going through the first currency (desperate)
65
+ # Rate going through the main currency (desperate)
52
66
  from_main = hash[[from, main_currency]]
53
67
  to_main = hash[[main_currency, to]]
54
68
  return from_main * to_main if from_main && to_main
@@ -56,6 +70,10 @@ module ActiveCurrency
56
70
  raise "Unknown rate between #{from} and #{to}"
57
71
  end
58
72
 
73
+ def multiply_rate(from, to, rate)
74
+ rate * ActiveCurrency.configuration.multiplier.fetch([from, to], 1)
75
+ end
76
+
59
77
  def main_currency
60
78
  currencies.first
61
79
  end
@@ -4,6 +4,8 @@ module ActiveCurrency
4
4
  # Mixin to add caching capability to a rate store when getting the current
5
5
  # cache.
6
6
  module CacheableStore
7
+ include AfterCommitEverywhere
8
+
7
9
  def get_rate(from, to, date = nil)
8
10
  return super if date
9
11
 
@@ -15,13 +17,15 @@ module ActiveCurrency
15
17
  def add_rate(from, to, rate, date = nil)
16
18
  super
17
19
 
18
- Rails.cache.delete(cache_key(from, to))
20
+ after_commit do
21
+ Rails.cache.delete(cache_key(from, to))
22
+ end
19
23
  end
20
24
 
21
25
  private
22
26
 
23
27
  def cache_key(from, to)
24
- ['active_currency_rate', from, to]
28
+ ["active_currency_rate", from, to]
25
29
  end
26
30
  end
27
31
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveCurrency
4
+ class Configuration
5
+ def initialize
6
+ @remote_bank = :eu_central_bank
7
+ @open_exchange_rates_app_id = nil
8
+ @multiplier = {}
9
+ end
10
+
11
+ attr_accessor :remote_bank,
12
+ :open_exchange_rates_app_id,
13
+ :multiplier
14
+ end
15
+ end
@@ -7,8 +7,8 @@ module ActiveCurrency
7
7
  initializer :append_migrations do |app|
8
8
  next if app.root.to_s.match(root.to_s)
9
9
 
10
- paths = ActiveRecord::Migrator.migrations_paths
11
- config.paths['db/migrate'].expanded.each do |path|
10
+ paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
11
+ config.paths["db/migrate"].expanded.each do |path|
12
12
  paths << path
13
13
  end
14
14
  paths.uniq!
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ActiveCurrency
4
4
  # Helps support previous version of Rails in migrations.
5
- if Rails.version > '5.0'
5
+ if Rails.version > "5.0"
6
6
  class Migration < ActiveRecord::Migration[5.0]; end
7
7
  else
8
8
  class Migration < ActiveRecord::Migration; end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveCurrency
4
- VERSION = '1.2.1'
4
+ VERSION = "1.4.0"
5
5
  end
@@ -1,14 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'money-rails'
4
- require 'eu_central_bank'
3
+ require "money-rails"
4
+ require "after_commit_everywhere"
5
5
 
6
- require 'active_currency/engine'
7
- require 'active_currency/database_store'
8
- require 'active_currency/cacheable_store'
9
- require 'active_currency/rate_store'
10
- require 'active_currency/add_rates'
11
- require 'active_currency/bank'
6
+ require "active_currency/configuration"
7
+ require "active_currency/engine"
8
+ require "active_currency/database_store"
9
+ require "active_currency/cacheable_store"
10
+ require "active_currency/rate_store"
11
+ require "active_currency/add_rates"
12
+ require "active_currency/bank"
12
13
 
13
14
  module ActiveCurrency
15
+ class << self
16
+ def configure
17
+ yield configuration
18
+ end
19
+
20
+ def configuration
21
+ @configuration ||= Configuration.new
22
+ end
23
+
24
+ def remote_bank
25
+ case configuration.remote_bank
26
+ when :eu_central_bank then eu_central_bank_instance
27
+ when :open_exchange_rates then open_exchange_rates_instance
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def eu_central_bank_instance
34
+ require "eu_central_bank"
35
+
36
+ EuCentralBank.new
37
+ end
38
+
39
+ def open_exchange_rates_instance
40
+ require "money/bank/open_exchange_rates_bank"
41
+
42
+ store = Money::RatesStore::Memory.new
43
+ bank = Money::Bank::OpenExchangeRatesBank.new(store)
44
+ bank.app_id = configuration.open_exchange_rates_app_id
45
+ bank
46
+ end
47
+ end
14
48
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_currency
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sunny Ripert
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-03 00:00:00.000000000 Z
11
+ date: 2023-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '3.2'
19
+ version: '4.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '3.2'
26
+ version: '4.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: money-rails
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: after_commit_everywhere
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 1.3.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.3.0
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: eu_central_bank
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - ">="
53
67
  - !ruby/object:Gem::Version
54
68
  version: 1.3.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: money-open-exchange-rates
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: sqlite3
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +122,20 @@ dependencies:
94
122
  - - ">="
95
123
  - !ruby/object:Gem::Version
96
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec-github
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
97
139
  - !ruby/object:Gem::Dependency
98
140
  name: rspec_junit_formatter
99
141
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +206,20 @@ dependencies:
164
206
  - - ">="
165
207
  - !ruby/object:Gem::Version
166
208
  version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: rubocop-rspec
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
167
223
  description: Store your currency.
168
224
  email:
169
225
  - sunny@sunfox.org
@@ -179,6 +235,7 @@ files:
179
235
  - lib/active_currency/add_rates.rb
180
236
  - lib/active_currency/bank.rb
181
237
  - lib/active_currency/cacheable_store.rb
238
+ - lib/active_currency/configuration.rb
182
239
  - lib/active_currency/database_store.rb
183
240
  - lib/active_currency/engine.rb
184
241
  - lib/active_currency/migration.rb
@@ -187,8 +244,9 @@ files:
187
244
  homepage: https://github.com/sunny/active_currency
188
245
  licenses:
189
246
  - MIT
190
- metadata: {}
191
- post_install_message:
247
+ metadata:
248
+ rubygems_mfa_required: 'true'
249
+ post_install_message:
192
250
  rdoc_options: []
193
251
  require_paths:
194
252
  - lib
@@ -203,8 +261,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
203
261
  - !ruby/object:Gem::Version
204
262
  version: '0'
205
263
  requirements: []
206
- rubygems_version: 3.0.3
207
- signing_key:
264
+ rubygems_version: 3.3.26
265
+ signing_key:
208
266
  specification_version: 4
209
267
  summary: Rails plugin to store your currency regularly
210
268
  test_files: []