Skip to content

Commit aef39e1

Browse files
committed
Cleanup implementation with the help of recent upstream changes
1 parent b952710 commit aef39e1

File tree

7 files changed

+96
-144
lines changed

7 files changed

+96
-144
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ You can use a configuration file (`-c /path/to/config.yml`) instead of providing
4343
options through the command line:
4444

4545
```yaml
46+
rate_store:
47+
name: File
48+
options:
49+
filepath: ~/.cache/fx-calculator/currency-rates.json
50+
ttl: 15 minutes
51+
4652
rate_provider:
4753
name: Compound
4854
options:
@@ -52,7 +58,6 @@ rate_provider:
5258
options:
5359
api_key: your-api-key
5460

55-
currency_rates_ttl: 15 minutes
5661
currency: EUR
5762
```
5863

shard.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ shards:
1010

1111
money:
1212
git: https://github.com/crystal-money/money.git
13-
version: 2.0.0-dev+git.commit.f8ec13ccb04e52f0448ba9338f48defb8bf14274
13+
version: 2.0.0-dev+git.commit.e1fe8d48fed75eed8389b2b53f27bd9b2ee27b05
1414

src/cli.cr

Lines changed: 39 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,23 @@ require "option_parser"
33
require "colorize"
44
require "./fx-calculator"
55

6+
DEFAULT_CONFIG_PATH =
7+
Path["~", ".config", "fx-calculator", "config.yml"].expand(home: true)
8+
69
Log.setup_from_env
710

811
clear_currency_rates_cache = false
912
config_path =
10-
if File.exists?(FXCalculator::Config::DEFAULT_CONFIG_PATH)
11-
FXCalculator::Config::DEFAULT_CONFIG_PATH
13+
if File.exists?(DEFAULT_CONFIG_PATH)
14+
DEFAULT_CONFIG_PATH
1215
end
1316

1417
currency_code = ENV["FX_CALCULATOR_CURRENCY"]?.presence
1518
currency_rates_ttl = ENV["FX_CALCULATOR_CURRENCY_RATES_TTL"]?.presence
1619

20+
rate_store_name = ENV["FX_CALCULATOR_RATE_STORE"]?.presence
21+
rate_store_opts = ENV["FX_CALCULATOR_RATE_STORE_OPTIONS"]?.presence
22+
1723
rate_provider_name = ENV["FX_CALCULATOR_RATE_PROVIDER"]?.presence
1824
rate_provider_opts = ENV["FX_CALCULATOR_RATE_PROVIDER_OPTIONS"]?.presence
1925

@@ -26,19 +32,25 @@ option_parser = OptionParser.new do |parser|
2632
clear_currency_rates_cache = true
2733
end
2834
parser.on("-c PATH", "--config=PATH", "Path to configuration file") do |path|
29-
config_path = Path[path] if path.presence
35+
config_path = Path[path].expand(home: true) if path.presence
3036
end
3137
parser.on("-C CURRENCY", "--currency=CODE", "Default target currency") do |code|
32-
currency_code = code.presence
38+
currency_code = code if code.presence
3339
end
3440
parser.on("-t TTL", "--currency-rates-ttl=TIME_SPAN", "Currency rates TTL") do |ttl|
35-
currency_rates_ttl = ttl.presence
41+
currency_rates_ttl = ttl if ttl.presence
42+
end
43+
parser.on("-s RATE_STORE", "--store=NAME", "Currency store to use") do |name|
44+
rate_store_name = name if name.presence
45+
end
46+
parser.on("-S RATE_STORE_OPTIONS", "--store-options=JSON", "Currency store options") do |opts|
47+
rate_store_opts = opts if opts.presence
3648
end
3749
parser.on("-p RATE_PROVIDER", "--provider=NAME", "Currency provider to use") do |name|
38-
rate_provider_name = name.presence
50+
rate_provider_name = name if name.presence
3951
end
40-
parser.on("-o RATE_PROVIDER_OPTIONS", "--provider-options=JSON", "Currency provider options") do |opts|
41-
rate_provider_opts = opts.presence
52+
parser.on("-P RATE_PROVIDER_OPTIONS", "--provider-options=JSON", "Currency provider options") do |opts|
53+
rate_provider_opts = opts if opts.presence
4254
end
4355
parser.on("-v", "--version", "Print version") do
4456
puts FXCalculator::VERSION
@@ -48,63 +60,35 @@ option_parser = OptionParser.new do |parser|
4860
puts parser
4961
exit(0)
5062
end
51-
parser.unknown_args do |args|
52-
values.concat(args)
53-
end
5463
parser.invalid_option do |flag|
5564
STDERR.puts "ERROR: #{flag} is not a valid option".colorize(:red)
5665
STDERR.puts parser
5766
exit(1)
5867
end
68+
parser.unknown_args do |args|
69+
values.concat(args)
70+
end
5971
end
6072

6173
option_parser.parse
6274

63-
begin
64-
if clear_currency_rates_cache
65-
FXCalculator::Config.clear_currency_rates_cache!
66-
end
67-
68-
if values.empty?
69-
if clear_currency_rates_cache
70-
exit(0)
71-
else
72-
STDERR.puts option_parser
73-
exit(1)
74-
end
75-
end
76-
77-
config =
78-
if path = config_path
79-
File.open(path) do |file|
80-
FXCalculator::Config.from_yaml(file)
81-
end
82-
else
83-
FXCalculator::Config.from_yaml("{}")
84-
end
85-
86-
if code = currency_code
87-
config.currency = Money::Currency.find(code)
88-
end
89-
90-
if name = rate_provider_name
91-
config.rate_provider = begin
92-
klass = Money::Currency::RateProvider.find(name)
93-
94-
if opts = rate_provider_opts
95-
klass.from_json(opts)
96-
else
97-
klass.from_json("{}")
98-
end
99-
end
100-
end
75+
if values.empty?
76+
abort option_parser
77+
end
10178

102-
if ttl = currency_rates_ttl
103-
config.currency_rates_ttl = Time::Span.parse(ttl)
104-
end
79+
begin
80+
config = FXCalculator::Utils.config_from_opts(
81+
config_path,
82+
rate_store_name,
83+
rate_store_opts,
84+
rate_provider_name,
85+
rate_provider_opts,
86+
currency_code,
87+
currency_rates_ttl,
88+
)
10589

106-
unless config.rate_provider?
107-
raise ArgumentError.new("Currency rate provider is required")
90+
if clear_currency_rates_cache
91+
config.rate_store.clear
10892
end
10993

11094
Money.configure do |context|
@@ -120,6 +104,5 @@ begin
120104
renderer = FXCalculator::Renderer.new
121105
renderer.render(moneys)
122106
rescue ex
123-
STDERR.puts "ERROR: #{ex.message}".colorize(:red)
124-
exit(1)
107+
abort "ERROR: #{ex.message}".colorize(:red)
125108
end

src/core_ext/time/span.cr

Lines changed: 0 additions & 49 deletions
This file was deleted.

src/fx-calculator.cr

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
require "yaml"
22
require "money"
33

4-
require "./core_ext/**"
54
require "./fx-calculator/**"

src/fx-calculator/config.cr

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,15 @@ module FXCalculator
22
class Config
33
include YAML::Serializable
44

5-
# Default configuration file path.
6-
DEFAULT_CONFIG_PATH =
7-
Path["~", ".config", "fx-calculator", "config.yml"].expand(home: true)
8-
9-
# Filepath to currency rates cache.
10-
CURRENCY_RATES_FILEPATH =
11-
Path[Dir.tempdir] / "fx-calculator" / ".cache" / "currency_rates.json"
12-
13-
# Initializes currency rates cache.
14-
def self.init_currency_rates_cache! : Nil
15-
Dir.mkdir_p(CURRENCY_RATES_FILEPATH.dirname)
16-
end
17-
18-
# Clears currency rates cache.
19-
def self.clear_currency_rates_cache! : Bool
20-
File.delete?(CURRENCY_RATES_FILEPATH)
21-
end
22-
235
# Currency rate store to use.
24-
@[YAML::Field(ignore: true)]
256
property rate_store : Money::Currency::RateStore do
26-
if ttl = currency_rates_ttl
27-
Money::Currency::RateStore::File.new(
28-
filepath: CURRENCY_RATES_FILEPATH,
29-
ttl: ttl,
30-
)
31-
else
32-
Money::Currency::RateStore::Memory.new
33-
end
7+
Money.default_rate_store
348
end
359

3610
# Rate provider used for currency exchange.
37-
@[YAML::Field(converter: Money::Currency::RateProvider::Converter)]
3811
property! rate_provider : Money::Currency::RateProvider
3912

40-
# Time to live (TTL) for currency rates, `nil` means no persistence.
41-
@[YAML::Field(converter: Time::Span::Converter)]
42-
property currency_rates_ttl : Time::Span?
43-
4413
# Target currency.
4514
property currency : Money::Currency?
46-
47-
private def after_initialize
48-
Config.init_currency_rates_cache!
49-
end
5015
end
5116
end

src/fx-calculator/utils.cr

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,55 @@ module FXCalculator
22
module Utils
33
extend self
44

5+
def config_from_opts(
6+
config_path : Path | String?,
7+
rate_store_name : String?,
8+
rate_store_opts : String?,
9+
rate_provider_name : String?,
10+
rate_provider_opts : String?,
11+
currency_code : String?,
12+
currency_rates_ttl : String?,
13+
)
14+
config =
15+
if config_path
16+
File.open(config_path) do |file|
17+
FXCalculator::Config.from_yaml(file)
18+
end
19+
else
20+
FXCalculator::Config.from_yaml("{}")
21+
end
22+
23+
if rate_store_name
24+
config.rate_store = begin
25+
klass = Money::Currency::RateStore.find(rate_store_name)
26+
klass.from_json(rate_store_opts || "{}")
27+
end
28+
end
29+
30+
if rate_provider_name
31+
config.rate_provider = begin
32+
klass = Money::Currency::RateProvider.find(rate_provider_name)
33+
klass.from_json(rate_provider_opts || "{}")
34+
end
35+
end
36+
37+
if currency_code
38+
config.currency =
39+
Money::Currency.find(currency_code)
40+
end
41+
42+
if currency_rates_ttl
43+
config.rate_store.ttl =
44+
Time::Span::StringConverter.parse(currency_rates_ttl)
45+
end
46+
47+
unless config.rate_provider?
48+
raise ArgumentError.new("Currency rate provider is required")
49+
end
50+
51+
config
52+
end
53+
554
# Parses a string representing a money value along with target currency,
655
# if present, and returns it as a tuple of `Money` and `Money::Currency`.
756
def parse_money_with_currency(str : String) : {Money, Money::Currency}

0 commit comments

Comments
 (0)