fixer_io 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 638eb554517ad5a34cbaa79d5a4ee8d4632d5aa9eeb2a9c4cd3b132d8e3f66f6
4
+ data.tar.gz: 8a5f11f86462910a7ceb9b3712becc9b742136358234c39893d254d5d8113115
5
+ SHA512:
6
+ metadata.gz: 4bac9a44d08045feae0726d683c1b02055cc2085c6d7eededacc6d9153f1eb0e82e932e52c4fa1e27cca0114f4a1dfd9ff5bd19d87ebc2da867bf1ca4287d8ed
7
+ data.tar.gz: 8c5f064458e211f496da86ca419b8a4e7b32fea4204240df7679b141132f993f057f6c46c18dfb4f97cb14aedd3a49e85a65efbe8b6193f4bd1bdf0694c564b6
@@ -0,0 +1,8 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = space
5
+ indent_size = 2
6
+ charset = utf-8
7
+ trim_trailing_whitespace = true
8
+ insert_final_newline = true
@@ -0,0 +1,208 @@
1
+
2
+ # Created by https://www.gitignore.io/api/vim,ruby,macos,linux,emacs,windows,visualstudiocode
3
+
4
+ ### Emacs ###
5
+ # -*- mode: gitignore; -*-
6
+ *~
7
+ \#*\#
8
+ /.emacs.desktop
9
+ /.emacs.desktop.lock
10
+ *.elc
11
+ auto-save-list
12
+ tramp
13
+ .\#*
14
+
15
+ # Org-mode
16
+ .org-id-locations
17
+ *_archive
18
+
19
+ # flymake-mode
20
+ *_flymake.*
21
+
22
+ # eshell files
23
+ /eshell/history
24
+ /eshell/lastdir
25
+
26
+ # elpa packages
27
+ /elpa/
28
+
29
+ # reftex files
30
+ *.rel
31
+
32
+ # AUCTeX auto folder
33
+ /auto/
34
+
35
+ # cask packages
36
+ .cask/
37
+ dist/
38
+
39
+ # Flycheck
40
+ flycheck_*.el
41
+
42
+ # server auth directory
43
+ /server/
44
+
45
+ # projectiles files
46
+ .projectile
47
+ projectile-bookmarks.eld
48
+
49
+ # directory configuration
50
+ .dir-locals.el
51
+
52
+ # saveplace
53
+ places
54
+
55
+ # url cache
56
+ url/cache/
57
+
58
+ # cedet
59
+ ede-projects.el
60
+
61
+ # smex
62
+ smex-items
63
+
64
+ # company-statistics
65
+ company-statistics-cache.el
66
+
67
+ # anaconda-mode
68
+ anaconda-mode/
69
+
70
+ ### Linux ###
71
+
72
+ # temporary files which can be created if a process still has a handle open of a deleted file
73
+ .fuse_hidden*
74
+
75
+ # KDE directory preferences
76
+ .directory
77
+
78
+ # Linux trash folder which might appear on any partition or disk
79
+ .Trash-*
80
+
81
+ # .nfs files are created when an open file is removed but is still being accessed
82
+ .nfs*
83
+
84
+ ### macOS ###
85
+ *.DS_Store
86
+ .AppleDouble
87
+ .LSOverride
88
+
89
+ # Icon must end with two \r
90
+ Icon
91
+
92
+ # Thumbnails
93
+ ._*
94
+
95
+ # Files that might appear in the root of a volume
96
+ .DocumentRevisions-V100
97
+ .fseventsd
98
+ .Spotlight-V100
99
+ .TemporaryItems
100
+ .Trashes
101
+ .VolumeIcon.icns
102
+ .com.apple.timemachine.donotpresent
103
+
104
+ # Directories potentially created on remote AFP share
105
+ .AppleDB
106
+ .AppleDesktop
107
+ Network Trash Folder
108
+ Temporary Items
109
+ .apdisk
110
+
111
+ ### Ruby ###
112
+ *.gem
113
+ *.rbc
114
+ /.config
115
+ /coverage/
116
+ /InstalledFiles
117
+ /pkg/
118
+ /spec/reports/
119
+ /spec/examples.txt
120
+ /test/tmp/
121
+ /test/version_tmp/
122
+ /tmp/
123
+
124
+ # Used by dotenv library to load environment variables.
125
+ # .env
126
+
127
+ ## Specific to RubyMotion:
128
+ .dat*
129
+ .repl_history
130
+ build/
131
+ *.bridgesupport
132
+ build-iPhoneOS/
133
+ build-iPhoneSimulator/
134
+
135
+ ## Specific to RubyMotion (use of CocoaPods):
136
+ #
137
+ # We recommend against adding the Pods directory to your .gitignore. However
138
+ # you should judge for yourself, the pros and cons are mentioned at:
139
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
140
+ #
141
+ # vendor/Pods/
142
+
143
+ ## Documentation cache and generated files:
144
+ /.yardoc/
145
+ /_yardoc/
146
+ /doc/
147
+ /rdoc/
148
+
149
+ ## Environment normalization:
150
+ /.bundle/
151
+ /vendor/bundle
152
+ /lib/bundler/man/
153
+
154
+ # for a library or gem, you might want to ignore these files since the code is
155
+ # intended to run in multiple environments; otherwise, check them in:
156
+ Gemfile.lock
157
+ .ruby-version
158
+ # .ruby-gemset
159
+
160
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
161
+ .rvmrc
162
+
163
+ ### Vim ###
164
+ # swap
165
+ .sw[a-p]
166
+ .*.sw[a-p]
167
+ # session
168
+ Session.vim
169
+ # temporary
170
+ .netrwhist
171
+ # auto-generated tag files
172
+ tags
173
+
174
+ ### VisualStudioCode ###
175
+ .vscode/*
176
+ !.vscode/settings.json
177
+ !.vscode/tasks.json
178
+ !.vscode/launch.json
179
+ !.vscode/extensions.json
180
+ .history
181
+
182
+ ### Windows ###
183
+ # Windows thumbnail cache files
184
+ Thumbs.db
185
+ ehthumbs.db
186
+ ehthumbs_vista.db
187
+
188
+ # Folder config file
189
+ Desktop.ini
190
+
191
+ # Recycle Bin used on file shares
192
+ $RECYCLE.BIN/
193
+
194
+ # Windows Installer files
195
+ *.cab
196
+ *.msi
197
+ *.msm
198
+ *.msp
199
+
200
+ # Windows shortcuts
201
+ *.lnk
202
+
203
+
204
+ # End of https://www.gitignore.io/api/vim,ruby,macos,linux,emacs,windows,visualstudiocode
205
+
206
+ # rspec failure tracking
207
+ .rspec_status
208
+ .env
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.2
5
+ before_install: gem install bundler -v 1.16.0
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at janlindblom@fastmail.fm. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ group :deployment do
6
+ gem 'curb', '~> 0.9'
7
+ end
8
+
9
+ # Specify your gem's dependencies in fixer_io.gemspec
10
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Jan Lindblom
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.
@@ -0,0 +1,120 @@
1
+ # FixerIo
2
+
3
+ ![Amazon CodeBuild](https://codebuild.us-east-1.amazonaws.com/badges?uuid=eyJlbmNyeXB0ZWREYXRhIjoiUDl6UGFwN3A5dUZmdE5PTkJsNk5KQ0V6UXlCT2ZaWkJxMld0enBCVC92dGxEOC9iM1F2cEtNVW5ua0JaTGl0N0VobjNsbGI2WEZ3eEJaOFduV3BUSkdRPSIsIml2UGFyYW1ldGVyU3BlYyI6IkdhQXplZytUYWx6U0lrQkciLCJtYXRlcmlhbFNldFNlcmlhbCI6MX0%3D&branch=master)
4
+ [![Bitbucket Pipelines](https://img.shields.io/bitbucket/pipelines/janlindblom/ruby-fixer.png)](https://bitbucket.org/janlindblom/ruby-fixer/addon/pipelines/home)
5
+
6
+ Interface to the fixer.io API. See [fixer.io](https://fixer.io/) for details on
7
+ getting an API key.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'fixer_io'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install fixer_io
24
+
25
+ ## Usage
26
+
27
+ Before using the library, you need to configure it with your API key. See
28
+ https://fixer.io/product for information on getting a key.
29
+
30
+ ```ruby
31
+ FixerIo.configure do |config|
32
+ config.api_key = "YOUR_API_KEY"
33
+ end
34
+ ```
35
+
36
+ #### Latest Rates
37
+
38
+ ```ruby
39
+ # Get the latest rates for all currencies like so:
40
+ FixerIo.latest_rates => #<FixerIo::Response::LatestRates:0x00007fd11c0d39d8
41
+ @base=:eur,
42
+ @rates=
43
+ {:aed=>4.54192,
44
+ :afn=>86.44557,
45
+ :all=>128.678993,
46
+ ...,
47
+ :zmk=>11131.842267,
48
+ :zmw=>11.724245,
49
+ :zwl=>398.657538},
50
+ @timestamp=2018-04-18 13:19:03 +0300>
51
+
52
+ # Get the latest rates for only a selected number of currencies like so:
53
+ FixerIo.latest_rates(symbols: 'SEK,USD,GBP') => #<FixerIo::Response::LatestRates:0x00007fd11ca46bf0
54
+ @base=:eur,
55
+ @rates={:sek=>10.405956, :usd=>1.236703, :gbp=>0.870949},
56
+ @timestamp=2018-04-18 13:19:03 +0300>
57
+ ```
58
+
59
+ #### Historical Rates
60
+
61
+ ```ruby
62
+ # Get historical rates for all currencies like so:
63
+ FixerIo.historical_rates('2018-01-01') => #<FixerIo::Response::HistoricalRates:0x00007fd11d10eff0
64
+ @base=:eur,
65
+ @date=#<Date: 2018-01-01 ((2458120j,0s,0n),+0s,2299161j)>,
66
+ @historical=true,
67
+ @rates=
68
+ {:aed=>4.412975,
69
+ :afn=>83.395841,
70
+ :all=>132.765995,
71
+ ...,
72
+ :zmk=>10814.90303,
73
+ :zmw=>11.979648,
74
+ :zwl=>387.308253},
75
+ @timestamp=2018-01-02 01:59:59 +0200>
76
+
77
+ # Get historical rates for only a selected number of currencies like so:
78
+ FixerIo.historical_rates('2018-01-01', symbols: 'SEK,USD,GBP') => #<FixerIo::Response::HistoricalRates:0x00007fd11c16b3c8
79
+ @base=:eur,
80
+ @date=#<Date: 2018-01-01 ((2458120j,0s,0n),+0s,2299161j)>,
81
+ @historical=true,
82
+ @rates={:sek=>9.823708, :usd=>1.201496, :gbp=>0.889131},
83
+ @timestamp=2018-01-02 01:59:59 +0200>
84
+ ```
85
+
86
+ ## Limitations
87
+
88
+ The first release of the gem will only work with the resources available to
89
+ free accounts on [fixer.io](https://fixer.io/).
90
+
91
+ ## Development
92
+
93
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
94
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
95
+ prompt that will allow you to experiment.
96
+
97
+ To install this gem onto your local machine, run `bundle exec rake install`. To
98
+ release a new version, update the version number in `version.rb`, and then run
99
+ `bundle exec rake release`, which will create a git tag for the version, push
100
+ git commits and tags, and push the `.gem` file to
101
+ [rubygems.org](https://rubygems.org).
102
+
103
+ ## Contributing
104
+
105
+ Bug reports and pull requests are welcome on Bitbucket at
106
+ https://bitbucket.org/janlindblom/ruby-fixer. This project is intended to be a
107
+ safe, welcoming space for collaboration, and contributors are expected to
108
+ adhere to the [Contributor Covenant](http://contributor-covenant.org) code of
109
+ conduct.
110
+
111
+ ## License
112
+
113
+ The gem is available as open source under the terms of the
114
+ [MIT License](https://opensource.org/licenses/MIT).
115
+
116
+ ## Code of Conduct
117
+
118
+ Everyone interacting in the FixerIo project’s codebases, issue trackers, chat
119
+ rooms and mailing lists is expected to follow the
120
+ [code of conduct](https://bitbucket.org/janlindblom/ruby-fixer/src/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,39 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
4
+ require 'yard'
5
+ require 'yard/rake/yardoc_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ RuboCop::RakeTask.new(:rubocop) do |task|
10
+ task.patterns = ['lib/**/*.rb']
11
+ # only show the files with failures
12
+ # task.formatters = ['worst']
13
+ # don't abort rake on failure
14
+ task.fail_on_error = false
15
+ end
16
+
17
+ YARD::Rake::YardocTask.new do |t|
18
+ t.files = ['lib/**/*.rb']
19
+ t.stats_options = ['--list-undoc']
20
+ end
21
+
22
+ task deploy: :build do
23
+ require 'curb'
24
+ require 'dotenv'
25
+ Dotenv.load
26
+ pkg_path=File.expand_path('pkg', __dir__)
27
+ artifacts = File.join(Dir.glob(File.join(pkg_path, '*.gem')))
28
+ puts "Deploying artifact: #{artifacts}..."
29
+ auth_string = ENV.fetch 'BB_AUTH_STRING'
30
+ repo_owner = ENV.fetch 'BITBUCKET_REPO_OWNER'
31
+ repo_slug = ENV.fetch 'BITBUCKET_REPO_SLUG'
32
+ resource = "https://#{auth_string}@api.bitbucket.org/2.0/repositories/#{repo_owner}/#{repo_slug}/downloads"
33
+ puts "Posting to #{resource}..."
34
+ c = Curl::Easy.new(resource)
35
+ c.multipart_form_post = true
36
+ c.http_post(Curl::PostField.file('files', artifacts))
37
+ end
38
+
39
+ task default: :spec
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'dotenv'
5
+ Dotenv.load
6
+ require 'fixer_io'
7
+
8
+ FixerIo.configure do |config|
9
+ config.api_key = ENV.fetch 'FIXER_IO_API_KEY'
10
+ end
11
+
12
+ require 'pry'
13
+ Pry.start
@@ -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,73 @@
1
+ image: ruby:2.4
2
+
3
+ pipelines:
4
+ default:
5
+ - step:
6
+ name: Generate documentation
7
+ caches:
8
+ - bundler
9
+ script:
10
+ - bundle install --path ./vendor --without deployment
11
+ - bundle exec rake yard
12
+ - step:
13
+ name: Rubocop
14
+ caches:
15
+ - bundler
16
+ script:
17
+ - bundle install --path ./vendor --without deployment
18
+ - bundle exec rake rubocop
19
+ - step:
20
+ name: Run tests
21
+ deployment: test
22
+ caches:
23
+ - bundler
24
+ script:
25
+ - bundle install --path ./vendor --without deployment
26
+ - bundle exec rake spec
27
+ - step:
28
+ name: Deploy to stage
29
+ deployment: staging
30
+ caches:
31
+ - bundler
32
+ script:
33
+ - bundle install --path ./vendor
34
+ - bundle exec rake build
35
+ - bundle exec rake deploy
36
+ branches:
37
+ master:
38
+ - step:
39
+ name: Generate documentation
40
+ caches:
41
+ - bundler
42
+ script:
43
+ - bundle install --path ./vendor --without deployment
44
+ - bundle exec rake yard
45
+ - step:
46
+ name: Rubocop
47
+ caches:
48
+ - bundler
49
+ script:
50
+ - ruby --version
51
+ - bundle install --path ./vendor --without deployment
52
+ - bundle exec rake rubocop
53
+ - step:
54
+ name: Run tests
55
+ deployment: test
56
+ caches:
57
+ - bundler
58
+ script:
59
+ - bundle install --path ./vendor --without deployment
60
+ - bundle exec rake spec
61
+ - step:
62
+ name: Deploy to production
63
+ deployment: production
64
+ caches:
65
+ - bundler
66
+ script:
67
+ - bundle install --path ./vendor
68
+ - bundle exec rake build
69
+ - bundle exec rake deploy
70
+
71
+ definitions:
72
+ caches:
73
+ bundler: ./vendor
@@ -0,0 +1,21 @@
1
+ version: 0.2
2
+
3
+ phases:
4
+ install:
5
+ commands:
6
+ - gem install bundler
7
+ pre_build:
8
+ commands:
9
+ - bundle install
10
+ build:
11
+ commands:
12
+ - bundle exec rake yard
13
+ - bundle exec rake rubocop
14
+ - bundle exec rake spec
15
+ - bundle exec rake build
16
+
17
+ artifacts:
18
+ files:
19
+ - pkg/*.gem
20
+ discard-paths: yes
21
+ #base-directory: location
@@ -0,0 +1,34 @@
1
+
2
+ lib = File.expand_path('lib', __dir__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fixer_io/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'fixer_io'
8
+ spec.version = FixerIo::VERSION
9
+ spec.authors = ['Jan Lindblom']
10
+ spec.email = ['janlindblom@fastmail.fm']
11
+
12
+ spec.summary = 'Get exchange rates from fixer.io.'
13
+ spec.homepage = 'https://bitbucket.org/janlindblom/ruby-fixer'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = 'exe'
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.16'
24
+ spec.add_development_dependency 'dotenv', '~> 2.2'
25
+ spec.add_development_dependency 'pry', '~> 0.11'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'rspec', '~> 3.0'
28
+ spec.add_development_dependency 'rubocop', '~> 0.55'
29
+ spec.add_development_dependency 'simplecov', '~> 0.16'
30
+ spec.add_development_dependency 'simplecov-rcov', '~> 0.2'
31
+ spec.add_development_dependency 'solargraph', '~> 0.19'
32
+ spec.add_development_dependency 'yard', '~> 0.9'
33
+ spec.add_runtime_dependency 'rest-client', '~> 2.0'
34
+ end
@@ -0,0 +1,151 @@
1
+ require 'json'
2
+ require 'rest-client'
3
+ require 'fixer_io/version'
4
+ require 'fixer_io/configuration'
5
+ require 'fixer_io/api_server_error'
6
+ require 'fixer_io/missing_api_key_error'
7
+ require 'fixer_io/invalid_api_key_error'
8
+ require 'fixer_io/base_currency_access_restricted_error'
9
+ require 'fixer_io/response'
10
+
11
+ # Interface to the fixer.io API.
12
+ #
13
+ # @author Jan Lindblom <janlindblom@fastmail.fm>
14
+ module FixerIo
15
+ class << self
16
+ # Module configuration.
17
+ # @return [Configuration]
18
+ attr_accessor :configuration
19
+
20
+ private
21
+
22
+ def query_api(request)
23
+ perform_request(request[:function], request[:params])
24
+ end
25
+
26
+ def build_request(which_request, args = {})
27
+ {
28
+ function: which_request,
29
+ params: args.merge(access_key: FixerIo.configuration.api_key)
30
+ }
31
+ end
32
+
33
+ def perform_request(req, params)
34
+ request = Configuration::API_ENDPOINT + req
35
+ response = RestClient.get(request, params: params, accept: :json)
36
+ case response.code
37
+ when 200
38
+ return process_response(response.body)
39
+ when 500
40
+ raise ApiServerError, 'A server-side error occured.'
41
+ end
42
+ nil
43
+ end
44
+
45
+ def process_response(body)
46
+ parsed = JSON.parse(body)
47
+
48
+ return parsed if parsed.key?('success') && parsed['success']
49
+
50
+ handle_error(parsed['error']) unless parsed['success']
51
+ end
52
+
53
+ def handle_error(error)
54
+ error_type = error['type'] if error.key? 'type'
55
+ error_info = error['info'] if error.key? 'info'
56
+ raise_errors(error_type, error_info)
57
+ end
58
+
59
+ def raise_errors(error_type, error_info)
60
+ raise MissingApiKeyError, error_info if error_type == 'missing_access_key'
61
+ if error_type == 'base_currency_access_restricted'
62
+ raise BaseCurrencyAccessRestrictedError,
63
+ 'Base currency access is restricted for this API key.'
64
+ end
65
+ raise InvalidApiKeyError, error_info if error_type == 'invalid_access_key'
66
+ raise StandardError,
67
+ "#{error_type}: #{error_info ? error_info : 'Unknown error'}"
68
+ end
69
+ end
70
+
71
+ # Modify the current configuration.
72
+ #
73
+ # @example Set your API key
74
+ # FixerIo.configure do |config|
75
+ # config.api_key = "YOUR_API_KEY"
76
+ # end
77
+ #
78
+ # @yieldparam [Configuration] config current configuration
79
+ def self.configure
80
+ self.configuration ||= Configuration.new
81
+ yield self.configuration
82
+ end
83
+
84
+ # Get historical rates for a given date.
85
+ #
86
+ # @example Get historical rates for a given date and all currencies
87
+ # FixerIo.historical_rates '2018-01-01'
88
+ #
89
+ # @example Historical rates for a given date and selected currencies
90
+ # FixerIo.historical_rates '2018-01-01', symbols: 'SEK,USD,GBP'
91
+ #
92
+ # @param [String] date the date to fetch rates for.
93
+ # @param [Hash] args optional arguments.
94
+ # @option args [String] :base base currency.
95
+ # @option args [String] :symbols comma separated list of currency symbols.
96
+ # @return [Response::HistoricalRates] historical rates for the given date.
97
+ def self.historical_rates(date, args = {})
98
+ response = query_api(build_request(date, args))
99
+ Response::HistoricalRates.new base: response['base'],
100
+ rates: response['rates'],
101
+ timestamp: response['timestamp'],
102
+ historical: response['historical'],
103
+ date: response['date']
104
+ end
105
+
106
+ # Get historical rates for a given date.
107
+ #
108
+ # Shorthand for {FixerIo#historical_rates}.
109
+ #
110
+ # @see FixerIo#historical_rates
111
+ # @param [String] date the date to fetch rates for.
112
+ # @param [Hash] args optional arguments.
113
+ # @option args [String] :base base currency.
114
+ # @option args [String] :symbols comma separated list of currency symbols.
115
+ # @return [Response::HistoricalRates] historical rates for the given date.
116
+ def self.historical(date, args = {})
117
+ historical_rates(date, args)
118
+ end
119
+
120
+ # Get latest rates.
121
+ #
122
+ # @example Latest rates for all available currencies
123
+ # FixerIo.latest_rates
124
+ #
125
+ # @example Latest rates for selected currencies only
126
+ # FixerIo.latest_rates symbols: 'SEK,USD,GBP'
127
+ #
128
+ # @param [Hash] args optional arguments.
129
+ # @option args [String] :base base currency.
130
+ # @option args [String] :symbols comma separated list of currency symbols.
131
+ # @return [Response::LatestRates] historical rates for the given date.
132
+ def self.latest_rates(args = {})
133
+ response = query_api(build_request('latest', args))
134
+ Response::LatestRates.new timestamp: response['timestamp'],
135
+ base: response['base'],
136
+ rates: response['rates']
137
+ end
138
+
139
+ # Get latest rates.
140
+ #
141
+ # Shorthand for {FixerIo#latest_rates}.
142
+ #
143
+ # @see FixerIo#latest_rates
144
+ # @param [Hash] args optional arguments.
145
+ # @option args [String] :base base currency.
146
+ # @option args [String] :symbols comma separated list of currency symbols.
147
+ # @return [Response::LatestRates] historical rates for the given date.
148
+ def self.latest(args = {})
149
+ latest_rates(args)
150
+ end
151
+ end
@@ -0,0 +1,5 @@
1
+ module FixerIo
2
+ # API Server Error.
3
+ class ApiServerError < StandardError
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ module FixerIo
2
+ # Base Currency Access Restricted Error.
3
+ #
4
+ # This occurs whenever a request contains a +:base+ option and the API key
5
+ # is on the wrong access tier.
6
+ class BaseCurrencyAccessRestrictedError < StandardError
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ module FixerIo
2
+ # Holds configuration of the module required for it to work.
3
+ class Configuration
4
+ # Sets the fixer.io API key.
5
+ # @return [String]
6
+ attr_accessor :api_key
7
+
8
+ # API Endpoint.
9
+ # @return [String]
10
+ API_ENDPOINT = 'http://data.fixer.io/api/'.freeze
11
+
12
+ def initialize
13
+ @api_key = ''
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ module FixerIo
2
+ # Invalid API Key Error.
3
+ class InvalidApiKeyError < StandardError
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module FixerIo
2
+ # Missing API Key Error.
3
+ class MissingApiKeyError < StandardError
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+ require 'fixer_io/response/latest_rates'
2
+ require 'fixer_io/response/historical_rates'
3
+
4
+ module FixerIo
5
+ # API Responses.
6
+ module Response
7
+ class << self
8
+ # Make String Hash keys into Symbols.
9
+ #
10
+ # @api private
11
+ # @param [Hash<String, Object>] hash
12
+ # @return [Hash<Symbol, Object>]
13
+ def symbolize_hash_keys(hash)
14
+ hash.keys.each do |key|
15
+ hash[(begin
16
+ key.downcase.to_sym
17
+ rescue StandardError
18
+ key
19
+ end) || key] = hash.delete(key)
20
+ end
21
+ hash
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,50 @@
1
+ require 'date'
2
+ require 'time'
3
+
4
+ module FixerIo
5
+ module Response
6
+ # Historical Rates response.
7
+ class HistoricalRates
8
+ # The exact date and time the given rates were collected.
9
+ # @return [Time]
10
+ attr_reader :timestamp
11
+
12
+ # The three-letter currency code of the base currency used for this
13
+ # request.
14
+ # @return [Symbol]
15
+ attr_reader :base
16
+
17
+ # Exchange rate data for the currencies you have requested.
18
+ # @return [Hash<Symbol, Numeric>]
19
+ attr_reader :rates
20
+
21
+ # Returns +true+ if a request for historical exchange rates was made.
22
+ # @return [Boolean]
23
+ attr_reader :historical
24
+
25
+ # The date for which historical rates were requested.
26
+ # @return [Date]
27
+ attr_reader :date
28
+
29
+ # Create a new instance.
30
+ #
31
+ # @param [Hash] args arguments used to create the object.
32
+ # @option args [Integer] :timestamp the exact date and time the given
33
+ # rates were collected.
34
+ # @option args [String] :base the three-letter currency code of the base
35
+ # currency used for this request.
36
+ # @option args [Hash] :rates exchange rate data for the currencies.
37
+ # @option args [Boolean] :historical +true+ if a request for historical
38
+ # exchange rates was made.
39
+ # @option args [String] :date the date for which historical rates were
40
+ # requested.
41
+ def initialize(args)
42
+ @timestamp = Time.at args[:timestamp].to_i
43
+ @base = args[:base].downcase.to_sym
44
+ @rates = Response.symbolize_hash_keys args[:rates]
45
+ @date = Date.parse args[:date]
46
+ @historical = args[:historical]
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,35 @@
1
+ require 'time'
2
+
3
+ module FixerIo
4
+ module Response
5
+ # Latest Rates response.
6
+ class LatestRates
7
+ # The exact date and time the given rates were collected.
8
+ # @return [Time]
9
+ attr_reader :timestamp
10
+
11
+ # The three-letter currency code of the base currency used for this
12
+ # request.
13
+ # @return [Symbol]
14
+ attr_reader :base
15
+
16
+ # Exchange rate data for the currencies you have requested.
17
+ # @return [Hash<Symbol, Numeric>]
18
+ attr_reader :rates
19
+
20
+ # Create a new instance.
21
+ #
22
+ # @param [Hash] args arguments used to create the object.
23
+ # @option args [Integer] :timestamp the exact date and time the given
24
+ # rates were collected.
25
+ # @option args [String] :base the three-letter currency code of the base
26
+ # currency used for this request.
27
+ # @option args [Hash] :rates exchange rate data for the currencies.
28
+ def initialize(args)
29
+ @timestamp = Time.at args[:timestamp].to_i
30
+ @base = args[:base].downcase.to_sym
31
+ @rates = Response.symbolize_hash_keys args[:rates]
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,4 @@
1
+ module FixerIo
2
+ # Current version.
3
+ VERSION = '0.1.0'.freeze
4
+ end
metadata ADDED
@@ -0,0 +1,222 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fixer_io
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jan Lindblom
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-04-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: dotenv
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.11'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.11'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.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: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.55'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.55'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.16'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.16'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov-rcov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.2'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.2'
125
+ - !ruby/object:Gem::Dependency
126
+ name: solargraph
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.19'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.19'
139
+ - !ruby/object:Gem::Dependency
140
+ name: yard
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.9'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.9'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rest-client
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '2.0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '2.0'
167
+ description:
168
+ email:
169
+ - janlindblom@fastmail.fm
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - ".editorconfig"
175
+ - ".gitignore"
176
+ - ".rspec"
177
+ - ".travis.yml"
178
+ - CODE_OF_CONDUCT.md
179
+ - Gemfile
180
+ - LICENSE.txt
181
+ - README.md
182
+ - Rakefile
183
+ - bin/console
184
+ - bin/setup
185
+ - bitbucket-pipelines.yml
186
+ - buildspec.yml
187
+ - fixer_io.gemspec
188
+ - lib/fixer_io.rb
189
+ - lib/fixer_io/api_server_error.rb
190
+ - lib/fixer_io/base_currency_access_restricted_error.rb
191
+ - lib/fixer_io/configuration.rb
192
+ - lib/fixer_io/invalid_api_key_error.rb
193
+ - lib/fixer_io/missing_api_key_error.rb
194
+ - lib/fixer_io/response.rb
195
+ - lib/fixer_io/response/historical_rates.rb
196
+ - lib/fixer_io/response/latest_rates.rb
197
+ - lib/fixer_io/version.rb
198
+ homepage: https://bitbucket.org/janlindblom/ruby-fixer
199
+ licenses:
200
+ - MIT
201
+ metadata: {}
202
+ post_install_message:
203
+ rdoc_options: []
204
+ require_paths:
205
+ - lib
206
+ required_ruby_version: !ruby/object:Gem::Requirement
207
+ requirements:
208
+ - - ">="
209
+ - !ruby/object:Gem::Version
210
+ version: '0'
211
+ required_rubygems_version: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ requirements: []
217
+ rubyforge_project:
218
+ rubygems_version: 2.7.3
219
+ signing_key:
220
+ specification_version: 4
221
+ summary: Get exchange rates from fixer.io.
222
+ test_files: []