ecb_exchange_rates_api 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6da5762fe7f7e48e41dd1b0e9f9acc87cce3eec9
4
+ data.tar.gz: a3446ca9eecdf2fac5f78ea861cad9001ee6805c
5
+ SHA512:
6
+ metadata.gz: 7ef18ee9cd2a3c4770bd57e1aa6f5eb7bad22e1f3fb891b9754f7582e6e57a486a875b057adb1fb81812c368b68f60c7394b578ecbe64808dd630a131e99cb04
7
+ data.tar.gz: dec49c2eeee01340ba59d41c272c1fafd99491ca92876bd75e5ec6d9d6a40907d8b24187cb267c95d4e8c6006d3ff4db5b1a28b01e24b63ca603342ef2e2afd9
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ /.idea
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,17 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+
4
+ Metrics/BlockLength:
5
+ Exclude:
6
+ - 'spec/**/*'
7
+ - 'ecb_exchange_rates_api.gemspec'
8
+
9
+ Style/Documentation:
10
+ Exclude:
11
+ - 'spec/**/*'
12
+
13
+ Style/StringLiterals:
14
+ EnforcedStyle: double_quotes
15
+
16
+ Layout/LineLength:
17
+ Max: 120
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.5.3
6
+ before_install: gem install bundler -v 2.1.2
7
+ script:
8
+ - bundle exec rspec
9
+ - bundle exec rubocop
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in ecb_exchange_rates_api.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,118 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ecb_exchange_rates_api (0.1.0)
5
+ activesupport
6
+ httparty
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (5.2.4.1)
12
+ concurrent-ruby (~> 1.0, >= 1.0.2)
13
+ i18n (>= 0.7, < 2)
14
+ minitest (~> 5.1)
15
+ tzinfo (~> 1.1)
16
+ addressable (2.7.0)
17
+ public_suffix (>= 2.0.2, < 5.0)
18
+ ast (2.4.0)
19
+ coderay (1.1.2)
20
+ concurrent-ruby (1.1.5)
21
+ crack (0.4.3)
22
+ safe_yaml (~> 1.0.0)
23
+ diff-lcs (1.3)
24
+ ffi (1.11.3)
25
+ formatador (0.2.5)
26
+ guard (2.16.1)
27
+ formatador (>= 0.2.4)
28
+ listen (>= 2.7, < 4.0)
29
+ lumberjack (>= 1.0.12, < 2.0)
30
+ nenv (~> 0.1)
31
+ notiffany (~> 0.0)
32
+ pry (>= 0.9.12)
33
+ shellany (~> 0.0)
34
+ thor (>= 0.18.1)
35
+ guard-compat (1.2.1)
36
+ guard-rspec (4.7.3)
37
+ guard (~> 2.1)
38
+ guard-compat (~> 1.1)
39
+ rspec (>= 2.99.0, < 4.0)
40
+ hashdiff (1.0.0)
41
+ httparty (0.17.3)
42
+ mime-types (~> 3.0)
43
+ multi_xml (>= 0.5.2)
44
+ i18n (1.8.1)
45
+ concurrent-ruby (~> 1.0)
46
+ jaro_winkler (1.5.4)
47
+ listen (3.2.1)
48
+ rb-fsevent (~> 0.10, >= 0.10.3)
49
+ rb-inotify (~> 0.9, >= 0.9.10)
50
+ lumberjack (1.1.1)
51
+ method_source (0.9.2)
52
+ mime-types (3.3.1)
53
+ mime-types-data (~> 3.2015)
54
+ mime-types-data (3.2019.1009)
55
+ minitest (5.13.0)
56
+ multi_xml (0.6.0)
57
+ nenv (0.3.0)
58
+ notiffany (0.1.3)
59
+ nenv (~> 0.1)
60
+ shellany (~> 0.0)
61
+ parallel (1.19.1)
62
+ parser (2.7.0.2)
63
+ ast (~> 2.4.0)
64
+ pry (0.12.2)
65
+ coderay (~> 1.1.0)
66
+ method_source (~> 0.9.0)
67
+ public_suffix (4.0.3)
68
+ rainbow (3.0.0)
69
+ rb-fsevent (0.10.3)
70
+ rb-inotify (0.10.1)
71
+ ffi (~> 1.0)
72
+ rspec (3.9.0)
73
+ rspec-core (~> 3.9.0)
74
+ rspec-expectations (~> 3.9.0)
75
+ rspec-mocks (~> 3.9.0)
76
+ rspec-core (3.9.1)
77
+ rspec-support (~> 3.9.1)
78
+ rspec-expectations (3.9.0)
79
+ diff-lcs (>= 1.2.0, < 2.0)
80
+ rspec-support (~> 3.9.0)
81
+ rspec-mocks (3.9.1)
82
+ diff-lcs (>= 1.2.0, < 2.0)
83
+ rspec-support (~> 3.9.0)
84
+ rspec-support (3.9.2)
85
+ rubocop (0.79.0)
86
+ jaro_winkler (~> 1.5.1)
87
+ parallel (~> 1.10)
88
+ parser (>= 2.7.0.1)
89
+ rainbow (>= 2.2.2, < 4.0)
90
+ ruby-progressbar (~> 1.7)
91
+ unicode-display_width (>= 1.4.0, < 1.7)
92
+ ruby-progressbar (1.10.1)
93
+ safe_yaml (1.0.5)
94
+ shellany (0.0.1)
95
+ thor (1.0.1)
96
+ thread_safe (0.3.6)
97
+ tzinfo (1.2.6)
98
+ thread_safe (~> 0.1)
99
+ unicode-display_width (1.6.0)
100
+ vcr (5.0.0)
101
+ webmock (3.7.6)
102
+ addressable (>= 2.3.6)
103
+ crack (>= 0.3.2)
104
+ hashdiff (>= 0.4.0, < 2.0.0)
105
+
106
+ PLATFORMS
107
+ ruby
108
+
109
+ DEPENDENCIES
110
+ ecb_exchange_rates_api!
111
+ guard-rspec
112
+ rspec
113
+ rubocop
114
+ vcr
115
+ webmock
116
+
117
+ BUNDLED WITH
118
+ 2.0.2
data/Guardfile ADDED
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A sample Guardfile
4
+ # More info at https://github.com/guard/guard#readme
5
+
6
+ ## Uncomment and set this to only include directories you want to watch
7
+ # directories %w(app lib config test spec features) \
8
+ # .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")}
9
+
10
+ ## Note: if you are using the `directories` clause above and you are not
11
+ ## watching the project directory ('.'), then you will want to move
12
+ ## the Guardfile to a watched dir and symlink it back, e.g.
13
+ #
14
+ # $ mkdir config
15
+ # $ mv Guardfile config/
16
+ # $ ln -s config/Guardfile .
17
+ #
18
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
19
+
20
+ # Note: The cmd option is now required due to the increasing number of ways
21
+ # rspec may be run, below are examples of the most common uses.
22
+ # * bundler: 'bundle exec rspec'
23
+ # * bundler binstubs: 'bin/rspec'
24
+ # * spring: 'bin/rspec' (This will use spring if running and you have
25
+ # installed the spring binstubs per the docs)
26
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
27
+ # * 'just' rspec: 'rspec'
28
+ #
29
+ guard :rspec, cmd: "rspec" do
30
+ watch(%r{^spec/.+_spec\.rb$})
31
+ watch(%r{^spec/*/.+_spec\.rb$})
32
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
33
+ watch("spec/spec_helper.rb") { "spec" }
34
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Roman Ovcharov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,111 @@
1
+ # ECBExchangeRatesApi
2
+
3
+ This is an unofficial wrapper for the awesome, free ExchangeRatesAPI, which provides exchange rate lookups courtesy of the European Central Bank.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'ecb_exchange_rates_api'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install ecb_exchange_rates_api
20
+
21
+ ## Getting Started
22
+
23
+ Since the CurrencyExchangeAPI does not require API keys or authentication in order to access and interrogate its API, getting started with this library is easy. The following examples show how to achieve various functions using the library.
24
+
25
+ ### Basic usage:
26
+
27
+ Fetch the latest exchange rates from the European Central Bank:
28
+
29
+ ```ruby
30
+ query = ECBExchangeRatesApi::Client.new
31
+ query.fetch
32
+ ```
33
+
34
+ ###Historical data:
35
+
36
+ Get historical rates for any day since 1999:
37
+
38
+ ```ruby
39
+ query.at("2010-09-21").fetch
40
+ ```
41
+
42
+ or specify some date range:
43
+
44
+ ```ruby
45
+ query.from("2010-09-21").to("2010-10-21").fetch
46
+ ```
47
+
48
+ ### Set the base currency:
49
+
50
+ By default, the base currency is set to Euro (EUR), but it can be changed:
51
+
52
+ ```ruby
53
+ query.with_base("USD").fetch
54
+ ```
55
+
56
+ currency code should be passed as an ISO 4217 code.
57
+
58
+ ### Fetch specific rates:
59
+ If you do not want all current rates, it's possible to specify only the currencies you want using `for_rate(symbol)` or `for_rates(array_of_symbols)`. The following code fetches only the exchange rate between GBP and EUR:
60
+
61
+ ```ruby
62
+ query.with_base("GBP").for_rate("EUR").fetch
63
+ ```
64
+
65
+ Please refer to the [API website](https://exchangeratesapi.io/) for further information and full API docs.
66
+
67
+ ### Supported Currencies:
68
+
69
+ The library supports any currency currently available on the European Central Bank's web service, which at the time of the latest release are as follows:
70
+
71
+ ![](https://www.ecb.europa.eu/shared/img/flags/AUD.gif) Australian Dollar (AUD)<br />
72
+ ![](https://www.ecb.europa.eu/shared/img/flags/BRL.gif) Brazilian Real (BRL)<br />
73
+ ![](https://www.ecb.europa.eu/shared/img/flags/GBP.gif) British Pound Sterline (GBP)<br />
74
+ ![](https://www.ecb.europa.eu/shared/img/flags/BGN.gif) Bulgarian Lev (BGN)<br />
75
+ ![](https://www.ecb.europa.eu/shared/img/flags/CAD.gif) Canadian Dollar (CAD)<br />
76
+ ![](https://www.ecb.europa.eu/shared/img/flags/CNY.gif) Chinese Yuan Renminbi (CNY)<br />
77
+ ![](https://www.ecb.europa.eu/shared/img/flags/HRK.gif) Croatian Kuna (HRK)<br />
78
+ ![](https://www.ecb.europa.eu/shared/img/flags/CZK.gif) Czech Koruna (CZK)<br />
79
+ ![](https://www.ecb.europa.eu/shared/img/flags/DKK.gif) Danish Krone (DKK)<br />
80
+ ![](https://www.ecb.europa.eu/shared/img/flags/EUR.gif) Euro (EUR)<br />
81
+ ![](https://www.ecb.europa.eu/shared/img/flags/HKD.gif) Hong Kong Dollar (HKD)<br />
82
+ ![](https://www.ecb.europa.eu/shared/img/flags/HUF.gif) Hungarian Forint (HUF)<br />
83
+ ![](https://www.ecb.europa.eu/shared/img/flags/ISK.gif) Icelandic Krona (ISK)<br />
84
+ ![](https://www.ecb.europa.eu/shared/img/flags/IDR.gif) Indonesian Rupiah (IDR)<br />
85
+ ![](https://www.ecb.europa.eu/shared/img/flags/INR.gif) Indian Rupee (INR)<br />
86
+ ![](https://www.ecb.europa.eu/shared/img/flags/ILS.gif) Israeli Shekel (ILS)<br />
87
+ ![](https://www.ecb.europa.eu/shared/img/flags/JPY.gif) Japanese Yen (JPY)<br />
88
+ ![](https://www.ecb.europa.eu/shared/img/flags/MYR.gif) Malaysian Ringgit (MYR)<br />
89
+ ![](https://www.ecb.europa.eu/shared/img/flags/MXN.gif) Mexican Peso (MXN)<br />
90
+ ![](https://www.ecb.europa.eu/shared/img/flags/NZD.gif) New Zealand Dollar (NZD)<br />
91
+ ![](https://www.ecb.europa.eu/shared/img/flags/NOK.gif) Norwegian Krone (NOK)<br />
92
+ ![](https://www.ecb.europa.eu/shared/img/flags/PHP.gif) Philippine Peso (PHP)<br />
93
+ ![](https://www.ecb.europa.eu/shared/img/flags/PLN.gif) Polish Zloty (PLN)<br />
94
+ ![](https://www.ecb.europa.eu/shared/img/flags/RON.gif) Romanian Leu (RON)<br />
95
+ ![](https://www.ecb.europa.eu/shared/img/flags/RUB.gif) Russian Rouble (RUB)<br />
96
+ ![](https://www.ecb.europa.eu/shared/img/flags/SGD.gif) Singapore Dollar (SGD)<br />
97
+ ![](https://www.ecb.europa.eu/shared/img/flags/ZAR.gif) South African Rand (ZAR)<br />
98
+ ![](https://www.ecb.europa.eu/shared/img/flags/KRW.gif) South Korean Won (KRW)<br />
99
+ ![](https://www.ecb.europa.eu/shared/img/flags/SEK.gif) Swedish Krona (SEK)<br />
100
+ ![](https://www.ecb.europa.eu/shared/img/flags/CHF.gif) Swiss Franc (CHF)<br />
101
+ ![](https://www.ecb.europa.eu/shared/img/flags/THB.gif) Thai Baht (THB)<br />
102
+ ![](https://www.ecb.europa.eu/shared/img/flags/TRY.gif) Turkish Lira (TRY)<br />
103
+ ![](https://www.ecb.europa.eu/shared/img/flags/USD.gif) US Dollar (USD)<br />
104
+
105
+ ## Contributing
106
+
107
+ Bug reports and pull requests are welcome on GitHub at https://github.com/overchind/ECBExchangeRatesApi. This project is intended to be a safe, welcoming space for collaboration.
108
+
109
+ ## License
110
+
111
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "ecb_exchange_rates_api"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/ecb_exchange_rates_api/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "ecb_exchange_rates_api"
7
+ spec.version = ECBExchangeRatesApi::VERSION
8
+ spec.authors = ["Roman Ovcharov"]
9
+ spec.email = ["overchind@gmail.com"]
10
+
11
+ spec.summary = "Client library for ExchangeRates API"
12
+ spec.description = <<-DESCRIPTION
13
+ This is an unofficial wrapper for the awesome, free ExchangeRatesAPI,
14
+ which provides exchange rate lookups courtesy of the Central European Bank."
15
+ DESCRIPTION
16
+ spec.homepage = "https://github.com/overchind/ExchangeRatesAPI"
17
+ spec.license = "MIT"
18
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
19
+
20
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
21
+
22
+ spec.metadata["homepage_uri"] = spec.homepage
23
+
24
+ # Specify which files should be added to the gem when it is released.
25
+ # The `git ls-files -z`
26
+ # loads the files in the RubyGem that have been added into git.
27
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
28
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
29
+ end
30
+ spec.bindir = "exe"
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ["lib"]
33
+
34
+ spec.add_dependency "activesupport"
35
+ spec.add_dependency "httparty"
36
+
37
+ spec.add_development_dependency "guard-rspec"
38
+ spec.add_development_dependency "rspec"
39
+ spec.add_development_dependency "rubocop"
40
+ spec.add_development_dependency "vcr"
41
+ spec.add_development_dependency "webmock"
42
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ecb_exchange_rates_api/options"
4
+ require "ecb_exchange_rates_api/shared_methods"
5
+ require "forwardable"
6
+ require "httparty"
7
+
8
+ module ECBExchangeRatesApi
9
+ # Client. Provides ways for different configurations.
10
+ class Client
11
+ include SharedMethods
12
+ include ::HTTParty
13
+
14
+ extend Forwardable
15
+
16
+ def_delegators :@options, :start_at, :end_at, :specific_date, :base, :symbols
17
+
18
+ base_uri "https://api.exchangeratesapi.io"
19
+ format :json
20
+
21
+ def initialize
22
+ @options = ECBExchangeRatesApi::Options.new
23
+ yield self if block_given?
24
+ end
25
+
26
+ def fetch
27
+ response = self.class.get(path, query: options.to_params)
28
+ ECBExchangeRatesApi::Result.new(response.parsed_response, status: response.code)
29
+ end
30
+
31
+ def from(date)
32
+ @options.start_at = date
33
+ self
34
+ end
35
+
36
+ def to(date)
37
+ @options.end_at = date
38
+ self
39
+ end
40
+
41
+ def at(date)
42
+ @options.specific_date = date
43
+ self
44
+ end
45
+
46
+ def with_base(code)
47
+ @options.base = code
48
+ self
49
+ end
50
+
51
+ def for_rates(codes)
52
+ codes.each(&method(:for_rate))
53
+ self
54
+ end
55
+
56
+ def for_rate(code)
57
+ @options.append_symbol(code)
58
+ self
59
+ end
60
+
61
+ def currency_is_supported?(code)
62
+ supported_currency?(validated_currency_code(code))
63
+ end
64
+
65
+ def supported_currencies
66
+ CURRENCIES
67
+ end
68
+
69
+ private
70
+
71
+ attr_reader :options
72
+
73
+ def path
74
+ return "/#{specific_date}" if specific_date
75
+
76
+ return "/history" if start_at && end_at
77
+
78
+ "/latest"
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ECBExchangeRatesApi
4
+ module Constants
5
+ CURRENCIES = %w[USD GBP EUR JPY BGN CZK DKK HUF PLN RON
6
+ SEK CHF ISK NOK HRK RUB TRY AUD BRL CAD
7
+ CNY HKD IDR ILS INR KRW MXN MYR NZD PHP
8
+ SGD THB ZAR].freeze
9
+
10
+ CURRENCY_REGEXP = /^[A-Z]{3}$/.freeze
11
+
12
+ # rubocop:disable Metrics/LineLength
13
+ DATE_REGEXP = /^[0-9]{4}-((([13578]|0[13578]|(10|12))-([1-9]|0[1-9]|[1-2][0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|(([469]|0[469]|11)-([1-9]|0[1-9]|[1-2][0-9]|30)))$/.freeze
14
+ # rubocop:enable Metrics/LineLength
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ECBExchangeRatesApi
4
+ InvalidCurrencyCodeError = Class.new(StandardError)
5
+ InvalidDateFormatError = Class.new(StandardError)
6
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ecb_exchange_rates_api/shared_methods"
4
+
5
+ module ECBExchangeRatesApi
6
+ # Presents API params
7
+ class Options
8
+ include SharedMethods
9
+
10
+ attr_reader :start_at, :end_at, :specific_date, :base, :symbols
11
+ date_attr_writer :start_at, :end_at, :specific_date
12
+ code_attr_writer :base
13
+
14
+ def initialize
15
+ @start_at = nil
16
+ @end_at = nil
17
+ @specific_date = nil
18
+ @base = nil
19
+ @symbols = []
20
+ end
21
+
22
+ def append_symbol(code)
23
+ @symbols << validated_currency_code(code)
24
+ end
25
+
26
+ def to_params
27
+ options_params.reject { |_, val| val.nil? || val.empty? }
28
+ end
29
+
30
+ private
31
+
32
+ def options_params
33
+ instance_variables.each_with_object({}) do |var, hash|
34
+ key = var.to_s[1..-1].to_sym
35
+ variable = instance_variable_get(var)
36
+ value = key == :symbols ? variable&.join(",") : variable
37
+ hash[key] = value
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash"
4
+
5
+ module ECBExchangeRatesApi
6
+ # Wrapper for HTTParty response object
7
+ class Result
8
+ attr_reader :data, :status
9
+
10
+ def initialize(data, status: 200)
11
+ data = {} unless data.is_a?(Hash)
12
+
13
+ @status = status
14
+ @data = OpenStruct.new(data.with_indifferent_access)
15
+ end
16
+
17
+ def success?
18
+ status == 200
19
+ end
20
+
21
+ def error?
22
+ !success?
23
+ end
24
+
25
+ private
26
+
27
+ def method_missing(method_name, *arguments, &block)
28
+ if @data.respond_to?(method_name)
29
+ @data.send(method_name, *arguments, &block)
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ def respond_to_missing?(method_name, include_private = false)
36
+ @data.respond_to?(method_name) || super
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ECBExchangeRatesApi
4
+ # Presents API params
5
+ module SharedMethods
6
+ # ::nodoc::
7
+ module Attributes
8
+ private
9
+
10
+ def date_attr_writer(*attr_names)
11
+ attr_names.each do |attr_name|
12
+ define_method("#{attr_name}=") do |date|
13
+ instance_variable_set("@#{attr_name}", represent_date(date))
14
+ end
15
+ end
16
+ end
17
+
18
+ def code_attr_writer(*attr_names)
19
+ attr_names.each do |attr_name|
20
+ define_method("#{attr_name}=") do |code|
21
+ instance_variable_set("@#{attr_name}", validated_currency_code(code))
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ecb_exchange_rates_api/shared_methods/attributes"
4
+ require "ecb_exchange_rates_api/constants"
5
+ require "ecb_exchange_rates_api/errors"
6
+
7
+ module ECBExchangeRatesApi
8
+ # ::nodoc::
9
+ module SharedMethods
10
+ extend SharedMethods::Attributes
11
+
12
+ def self.included(base)
13
+ base.send :extend, SharedMethods::Attributes
14
+ end
15
+
16
+ private
17
+
18
+ def represent_date(date)
19
+ return date.strftime("%Y-%m-%d") if time_or_date_instance?(date)
20
+
21
+ return date if date.is_a?(String) && date =~ ECBExchangeRatesApi::Constants::DATE_REGEXP
22
+
23
+ raise InvalidDateFormatError, date
24
+ end
25
+
26
+ def time_or_date_instance?(instance)
27
+ instance.is_a?(Date) || instance.is_a?(Time)
28
+ end
29
+
30
+ def validated_currency_code(code)
31
+ currency = sanitize_currency_code(code)
32
+ raise InvalidCurrencyCodeError, "Ivalid code format #{code}" unless valid_currency_code_format?(currency)
33
+
34
+ raise InvalidCurrencyCodeError, "Unsupported currency #{code}" unless supported_currency?(currency)
35
+
36
+ currency
37
+ end
38
+
39
+ def supported_currency?(currency)
40
+ ECBExchangeRatesApi::Constants::CURRENCIES.include?(currency)
41
+ end
42
+
43
+ def valid_currency_code_format?(currency_code)
44
+ !currency_code.nil? && currency_code =~ ECBExchangeRatesApi::Constants::CURRENCY_REGEXP
45
+ end
46
+
47
+ def sanitize_currency_code(code)
48
+ code&.strip&.upcase
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ECBExchangeRatesApi
4
+ VERSION = "0.1.1"
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ecb_exchange_rates_api/version"
4
+ require "ecb_exchange_rates_api/result"
5
+ require "ecb_exchange_rates_api/client"
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ecb_exchange_rates_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Roman Ovcharov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-01-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: httparty
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: guard-rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
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
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
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'
83
+ - !ruby/object:Gem::Dependency
84
+ name: vcr
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: |2
112
+ This is an unofficial wrapper for the awesome, free ExchangeRatesAPI,
113
+ which provides exchange rate lookups courtesy of the Central European Bank."
114
+ email:
115
+ - overchind@gmail.com
116
+ executables: []
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - ".gitignore"
121
+ - ".rspec"
122
+ - ".rubocop.yml"
123
+ - ".travis.yml"
124
+ - Gemfile
125
+ - Gemfile.lock
126
+ - Guardfile
127
+ - LICENSE.txt
128
+ - README.md
129
+ - Rakefile
130
+ - bin/console
131
+ - bin/setup
132
+ - ecb_exchange_rates_api.gemspec
133
+ - lib/ecb_exchange_rates_api.rb
134
+ - lib/ecb_exchange_rates_api/client.rb
135
+ - lib/ecb_exchange_rates_api/constants.rb
136
+ - lib/ecb_exchange_rates_api/errors.rb
137
+ - lib/ecb_exchange_rates_api/options.rb
138
+ - lib/ecb_exchange_rates_api/result.rb
139
+ - lib/ecb_exchange_rates_api/shared_methods.rb
140
+ - lib/ecb_exchange_rates_api/shared_methods/attributes.rb
141
+ - lib/ecb_exchange_rates_api/version.rb
142
+ homepage: https://github.com/overchind/ExchangeRatesAPI
143
+ licenses:
144
+ - MIT
145
+ metadata:
146
+ allowed_push_host: https://rubygems.org
147
+ homepage_uri: https://github.com/overchind/ExchangeRatesAPI
148
+ post_install_message:
149
+ rdoc_options: []
150
+ require_paths:
151
+ - lib
152
+ required_ruby_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: 2.3.0
157
+ required_rubygems_version: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ requirements: []
163
+ rubyforge_project:
164
+ rubygems_version: 2.5.1
165
+ signing_key:
166
+ specification_version: 4
167
+ summary: Client library for ExchangeRates API
168
+ test_files: []