active_currency 1.0.1 → 1.3.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
- 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