active_currency 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6712c0205342cb855a5c816cbcf29a9d2d81266f12b34cf580055e4ad66977fe
4
- data.tar.gz: a8b33afc0657a7164bffa81fc6d0fa7115c6863d30af7fe2f52b93d223a51998
3
+ metadata.gz: dc61cac61fcc7b74bf7288a1145b89af079cb527f49dc3991dd7147ebe5b824a
4
+ data.tar.gz: fc8da46d16ceae4822a6f6e3974c050bafa732122d5918276bc33b5fd09531ff
5
5
  SHA512:
6
- metadata.gz: c138d27d24190e33af49618b03adbd2df9a2e3e72fc9b39ad7ad8e2ffefa47b6b73a17216221677732d7392b8b5998fb23b9b6ca8ba3f32f020372e63f924cf4
7
- data.tar.gz: 36b38e8effcd0566ef0f6c4ed48d1d53d4da140a208673c3747e89a7afca32fd18f6a9405c2589f3b559ae91bf79f0e42e46ac276384a920a29f278c28d1a0a2
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,13 +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](https://github.com/Moove-it/sidekiq-scheduler),
29
- [whenever](https://github.com/javan/whenever),
30
- or [active_scheduler](https://github.com/JustinAiken/active_scheduler))
31
- with the currencies you want to store:
26
+ like [sidekiq-scheduler], [whenever], or [active_scheduler]) with the currencies
27
+ you want to store:
32
28
 
33
29
  ```rb
34
- ActiveCurrency::AddRates.call(%w[EUR USD])
30
+ ActiveCurrency::AddRates.call(currencies: %w[EUR USD])
35
31
  ```
36
32
 
37
33
  You can then exchange money by using the Money gem helpers:
@@ -51,7 +47,7 @@ ActiveCurrency::Rate.where(from: 'EUR', to: 'USD').pluck(:value)
51
47
 
52
48
  ## Installation
53
49
 
54
- Add these lines to your application's `Gemfile`:
50
+ Add these lines to your applications `Gemfile`:
55
51
 
56
52
  ```rb
57
53
  # Store and retrieve the currency from the database.
@@ -71,23 +67,52 @@ the currency rates and fill it for the first time.
71
67
 
72
68
  ## Fetching rates
73
69
 
74
- 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.
75
82
 
76
- If you prefer another API, you can provide any Money-compatible bank when
77
- calling `ActiveCurrency::AddRates`. For example with the
78
- [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:
79
87
 
80
88
  ```rb
81
- 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
82
96
 
83
- bank = Money::Bank::OpenExchangeRatesBank.new(Money::RatesStore::Memory.new)
84
- bank.app_id = '…'
97
+ You can provide any Money-compatible bank when calling
98
+ `ActiveCurrency::AddRates`:
85
99
 
86
- ActiveCurrency::AddRates.call(%w[EUR USD], bank: bank)
100
+ ```rb
101
+ ActiveCurrency::AddRates.call(…, bank: …)
87
102
  ```
88
103
 
89
- The first currency you give to `AddRates` is considered the default currency
90
- 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
+ ```
91
116
 
92
117
  ## Tests
93
118
 
@@ -100,7 +125,7 @@ For that, you can use a fake rate store in your `rails_helper.rb`:
100
125
  MoneyRails.configure do |config|
101
126
  rate_store = Money::RatesStore::Memory.new.tap do |store|
102
127
  store.add_rate('USD', 'EUR', 1.5)
103
- store.add_rate('EUR', 'USD', 1.4)
128
+ store.add_rate('EUR', 'USD', 0.67)
104
129
  end
105
130
  config.default_bank = Money::Bank::VariableExchange.new(rate_store)
106
131
  end
@@ -108,21 +133,20 @@ end
108
133
 
109
134
  ## Contributing
110
135
 
111
- Please file issues and pull requests
112
- [on GitHub](https://github.com/sunny/active_currency).
136
+ Please file issues and pull requests [on GitHub].
113
137
 
114
138
  ## Development
115
139
 
116
140
  Install:
117
141
 
118
142
  ```sh
119
- BUNDLE_GEMFILE=Gemfile-rails6.0 bundle install
143
+ BUNDLE_GEMFILE=Gemfile-rails7.0 bundle install
120
144
  ```
121
145
 
122
146
  Launch specs and linters:
123
147
 
124
148
  ```sh
125
- BUNDLE_GEMFILE=Gemfile-rails6.0 bin/rake
149
+ BUNDLE_GEMFILE=Gemfile-rails7.0 bin/rake
126
150
  ```
127
151
 
128
152
  ## Release
@@ -132,22 +156,23 @@ Update `CHANGELOG.md`, update version in `lib/active_currency/version.rb`.
132
156
  Then:
133
157
 
134
158
  ```sh
135
- gem install bundler:1.17.2
136
- BUNDLE_GEMFILE=Gemfile-rails4.2 bundle update
137
- BUNDLE_GEMFILE=Gemfile-rails5.2 bundle update
138
-
139
- gem install bundler:2.1.2
140
- BUNDLE_GEMFILE=Gemfile-rails6.0 bundle update
159
+ BUNDLE_GEMFILE=Gemfile-rails6.1 bundle update
160
+ BUNDLE_GEMFILE=Gemfile-rails7.0 bundle update
141
161
 
142
- git add CHANGELOG.md lib/active_currency/version.rb Gemfile-rails*.lock
162
+ git add CHANGELOG.md lib/active_currency/version.rb Gemfile-rails*
143
163
  git commit -m v`ruby -r./lib/active_currency/version <<< 'puts ActiveCurrency::VERSION'`
144
164
  bin/rake release
145
165
  ```
146
166
 
147
167
  ## License
148
168
 
149
- The gem is available as open source under the terms of the
150
- [MIT License](http://opensource.org/licenses/MIT).
169
+ The gem is available as open source under the terms of the [MIT License].
151
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
152
175
  [eu_central_bank]: https://github.com/RubyMoney/eu_central_bank
153
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
@@ -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
@@ -15,11 +16,12 @@ class CreateActiveCurrencyRates < ActiveCurrency::Migration
15
16
  dir.up do
16
17
  add_index :active_currency_rates,
17
18
  %i[from to created_at],
18
- name: 'index_active_currency_rates'
19
+ name: "index_active_currency_rates"
19
20
  end
20
21
  dir.down do
21
- remove_index :active_currency_rates, 'index_active_currency_rates'
22
+ remove_index :active_currency_rates, "index_active_currency_rates"
22
23
  end
23
24
  end
24
25
  end
26
+ # rubocop:enable Metrics/MethodLength
25
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
@@ -8,7 +8,7 @@ module ActiveCurrency
8
8
  next if app.root.to_s.match(root.to_s)
9
9
 
10
10
  paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
11
- config.paths['db/migrate'].expanded.each do |path|
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.3.0'
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.3.0
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: 2021-04-29 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
@@ -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: []