active_currency 1.0.1 → 1.3.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: e714ea208f9bd8ebded58b96bde8497a9f9c47c2
4
- data.tar.gz: fdd79e4b7ed274966cc932f7f4ba8536040ba02c
2
+ SHA256:
3
+ metadata.gz: 6712c0205342cb855a5c816cbcf29a9d2d81266f12b34cf580055e4ad66977fe
4
+ data.tar.gz: a8b33afc0657a7164bffa81fc6d0fa7115c6863d30af7fe2f52b93d223a51998
5
5
  SHA512:
6
- metadata.gz: ef833fcd22cf76b2511ff68a4930d1026e3687c129674abb6f96a79b2fdd64899f5c962d9fe582c911f10835c6d40363199a3876e0669e48d17c69982a734864
7
- data.tar.gz: f2d8a04600e685729c538a47323c43504a7ad939ade1b425c1e940e5acdd9d09d9ad639dbbfa0b7dcd16e3a71945a0799314f1e02cdc6c4ed9951cfba6b74a4f
6
+ metadata.gz: c138d27d24190e33af49618b03adbd2df9a2e3e72fc9b39ad7ad8e2ffefa47b6b73a17216221677732d7392b8b5998fb23b9b6ca8ba3f32f020372e63f924cf4
7
+ data.tar.gz: 36b38e8effcd0566ef0f6c4ed48d1d53d4da140a208673c3747e89a7afca32fd18f6a9405c2589f3b559ae91bf79f0e42e46ac276384a920a29f278c28d1a0a2
data/README.md CHANGED
@@ -10,21 +10,25 @@ with the `money-rails` gem.
10
10
  Storing the current currency rates in the database using ActiveCurrency
11
11
  provides the following advantages:
12
12
 
13
- - Lets you find out what the currency rate you used in your application was
14
- at any given time.
13
+ - Lets you query for the currency rate you actually used in your application at
14
+ any given time.
15
15
  - Does not need to call an API to get the rates when starting or restarting
16
16
  your web server.
17
- - Choose how often you want to check for a currency (daily for example).
17
+ - Does not depend on the file system to store cached rates.
18
+ - Choose how often you want to update the currency rates (daily for example).
18
19
  - Your users do not suffer the cost of making calls to the bank rates API.
19
20
  - Your app does not go down when the bank rates API does.
20
21
 
21
- To fetch the rates, it uses the [eu_central_bank] gem and uses your application
22
- cache when getting the current rate in order to save on database queries.
22
+ To fetch the *current* rate it uses your application cache instead of making
23
+ a call to the database.
23
24
 
24
25
  ## Usage
25
26
 
26
27
  Store the current rate regularly by calling in a scheduled job (using something
27
- like `sidekiq-scheduler` or `whenever`) with the currencies you want to store:
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:
28
32
 
29
33
  ```rb
30
34
  ActiveCurrency::AddRates.call(%w[EUR USD])
@@ -62,9 +66,29 @@ MoneyRails.configure do |config|
62
66
  end
63
67
  ```
64
68
 
65
- Then call `bundle exec rake db:migrate` to create the table that holds
69
+ Then call `bin/rake db:migrate` to create the table that holds
66
70
  the currency rates and fill it for the first time.
67
71
 
72
+ ## Fetching rates
73
+
74
+ By defaut it uses the [eu_central_bank] to update the currency rates.
75
+
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:
79
+
80
+ ```rb
81
+ require 'money/bank/open_exchange_rates_bank'
82
+
83
+ bank = Money::Bank::OpenExchangeRatesBank.new(Money::RatesStore::Memory.new)
84
+ bank.app_id = '…'
85
+
86
+ ActiveCurrency::AddRates.call(%w[EUR USD], bank: bank)
87
+ ```
88
+
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.
91
+
68
92
  ## Tests
69
93
 
70
94
  In your app test suite you may not want to have to fill your database to be
@@ -92,13 +116,32 @@ Please file issues and pull requests
92
116
  Install:
93
117
 
94
118
  ```sh
95
- BUNDLE_GEMFILE=Gemfile-rails4.2 bundle install
119
+ BUNDLE_GEMFILE=Gemfile-rails6.0 bundle install
96
120
  ```
97
121
 
98
122
  Launch specs and linters:
99
123
 
100
124
  ```sh
101
- BUNDLE_GEMFILE=Gemfile-rails4.2 bundle exec rake
125
+ BUNDLE_GEMFILE=Gemfile-rails6.0 bin/rake
126
+ ```
127
+
128
+ ## Release
129
+
130
+ Update `CHANGELOG.md`, update version in `lib/active_currency/version.rb`.
131
+
132
+ Then:
133
+
134
+ ```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
141
+
142
+ git add CHANGELOG.md lib/active_currency/version.rb Gemfile-rails*.lock
143
+ git commit -m v`ruby -r./lib/active_currency/version <<< 'puts ActiveCurrency::VERSION'`
144
+ bin/rake release
102
145
  ```
103
146
 
104
147
  ## License
@@ -107,3 +150,4 @@ The gem is available as open source under the terms of the
107
150
  [MIT License](http://opensource.org/licenses/MIT).
108
151
 
109
152
  [eu_central_bank]: https://github.com/RubyMoney/eu_central_bank
153
+ [money-open-exchange-rates]: https://github.com/spk/money-open-exchange-rates
@@ -11,18 +11,16 @@ module ActiveCurrency
11
11
  }
12
12
 
13
13
  def self.value_for(from, to, date = nil)
14
- scope = date ? before(date) : all_scope
14
+ from = Money::Currency.new(from)
15
+ to = Money::Currency.new(to)
16
+ return 1 if from == to
15
17
 
18
+ scope = date ? before(date) : all
16
19
  scope
17
- .where(from: from, to: to)
20
+ .where(from: from.iso_code, to: to.iso_code)
18
21
  .order(:created_at)
19
22
  .last
20
23
  &.value
21
24
  end
22
-
23
- # Scope retrocompatibility for Rails 3.2.
24
- def self.all_scope
25
- respond_to?(:scoped) ? scoped : all
26
- end
27
25
  end
28
26
  end
@@ -11,8 +11,15 @@ class CreateActiveCurrencyRates < ActiveCurrency::Migration
11
11
  t.datetime :created_at
12
12
  end
13
13
 
14
- add_index :active_currency_rates,
15
- %i[from to created_at],
16
- name: 'index_active_currency_rates'
14
+ reversible do |dir|
15
+ dir.up do
16
+ add_index :active_currency_rates,
17
+ %i[from to created_at],
18
+ name: 'index_active_currency_rates'
19
+ end
20
+ dir.down do
21
+ remove_index :active_currency_rates, 'index_active_currency_rates'
22
+ end
23
+ end
17
24
  end
18
25
  end
@@ -3,51 +3,61 @@
3
3
  module ActiveCurrency
4
4
  # Store the latest currency rates.
5
5
  class AddRates
6
- def initialize(currencies)
7
- @currencies = currencies
6
+ def initialize(currencies, bank: EuCentralBank.new)
7
+ @currencies = currencies.map(&:to_s).map(&:upcase)
8
+ @bank = bank
8
9
  end
9
10
 
10
11
  def call
11
- other_currencies.each do |to|
12
- store_rate(from, to)
12
+ bank.update_rates
13
+
14
+ rates_hash.each do |(from, to), rate|
15
+ store.add_rate(from, to, rate)
13
16
  end
14
- end
15
17
 
16
- def self.call(currencies)
17
- new(currencies).call
18
+ nil
18
19
  end
19
20
 
20
- private
21
-
22
- def currencies
23
- @currencies.map(&:to_s).map(&:upcase)
21
+ def self.call(currencies, *options)
22
+ new(currencies, *options).call
24
23
  end
25
24
 
26
- def other_currencies
27
- currencies - [from]
28
- end
25
+ private
29
26
 
30
- def from
31
- 'EUR'
32
- end
27
+ attr_accessor :bank, :currencies
33
28
 
34
29
  def store
35
30
  @store ||= ActiveCurrency::RateStore.new
36
31
  end
37
32
 
38
- def bank
39
- @bank ||= EuCentralBank.new.tap(&:update_rates)
33
+ def rates_hash
34
+ currencies.each_with_object({}) do |from, hash|
35
+ currencies.each do |to|
36
+ next if from == to
37
+
38
+ hash[[from, to]] = get_rate(hash, from, to)
39
+ end
40
+ end
40
41
  end
41
42
 
42
- def store_rate(from, to)
43
+ def get_rate(hash, from, to)
43
44
  rate = bank.get_rate(from, to)
45
+ return rate if rate
44
46
 
45
- if rate.nil? || rate.zero?
46
- raise "Bank rate must be set but bank returned #{rate.inpsect}"
47
- end
47
+ # Inverse rate (not so good)
48
+ inverse = hash[[to, from]]
49
+ return 1.fdiv(inverse) if inverse
50
+
51
+ # Rate going through the first currency (desperate)
52
+ from_main = hash[[from, main_currency]]
53
+ to_main = hash[[main_currency, to]]
54
+ return from_main * to_main if from_main && to_main
55
+
56
+ raise "Unknown rate between #{from} and #{to}"
57
+ end
48
58
 
49
- store.add_rate(from, to, rate)
50
- store.add_rate(to, from, 1.fdiv(rate))
59
+ def main_currency
60
+ currencies.first
51
61
  end
52
62
  end
53
63
  end
@@ -5,13 +5,13 @@ module ActiveCurrency
5
5
  isolate_namespace ActiveCurrency
6
6
 
7
7
  initializer :append_migrations do |app|
8
- # This prevents migrations from being loaded twice from the inside of the
9
- # gem itself (dummy test app)
10
- if app.root.to_s !~ /#{root}/
11
- config.paths['db/migrate'].expanded.each do |migration_path|
12
- app.config.paths['db/migrate'] << migration_path
13
- end
8
+ next if app.root.to_s.match(root.to_s)
9
+
10
+ paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
11
+ config.paths['db/migrate'].expanded.each do |path|
12
+ paths << path
14
13
  end
14
+ paths.uniq!
15
15
  end
16
16
  end
17
17
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  module ActiveCurrency
4
4
  # Helps support previous version of Rails in migrations.
5
- if Rails.version > '4.1'
6
- class Migration < ActiveRecord::Migration[4.2]; end
5
+ if Rails.version > '5.0'
6
+ class Migration < ActiveRecord::Migration[5.0]; end
7
7
  else
8
8
  class Migration < ActiveRecord::Migration; end
9
9
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveCurrency
4
- VERSION = '1.0.1'
4
+ VERSION = '1.3.0'
5
5
  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.0.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sunny Ripert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-01 00:00:00.000000000 Z
11
+ date: 2021-04-29 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
@@ -56,16 +56,30 @@ dependencies:
56
56
  name: sqlite3
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
60
67
  - !ruby/object:Gem::Version
61
- version: 1.3.6
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - "~>"
80
+ - - ">="
67
81
  - !ruby/object:Gem::Version
68
- version: 1.3.6
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rspec-rails
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +150,20 @@ dependencies:
136
150
  - - ">="
137
151
  - !ruby/object:Gem::Version
138
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-rails
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
139
167
  description: Store your currency.
140
168
  email:
141
169
  - sunny@sunfox.org
@@ -175,8 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
203
  - !ruby/object:Gem::Version
176
204
  version: '0'
177
205
  requirements: []
178
- rubyforge_project:
179
- rubygems_version: 2.5.2.3
206
+ rubygems_version: 3.0.3
180
207
  signing_key:
181
208
  specification_version: 4
182
209
  summary: Rails plugin to store your currency regularly