From c1e1644c52111e479b30e55a68052539c668a429 Mon Sep 17 00:00:00 2001 From: Hakan Ensari Date: Wed, 10 Oct 2018 13:39:25 +0100 Subject: [PATCH] Implement currencies endpoint --- Gemfile | 1 + Gemfile.lock | 8 +++++++- README.md | 6 ++++++ lib/currency_names.rb | 30 ++++++++++++++++++++++++++++++ lib/web/server.rb | 7 +++++++ spec/currency_names_spec.rb | 18 ++++++++++++++++++ spec/web/server_spec.rb | 25 +++++++++++++++---------- 7 files changed, 84 insertions(+), 11 deletions(-) create mode 100644 lib/currency_names.rb create mode 100644 spec/currency_names_spec.rb diff --git a/Gemfile b/Gemfile index ca5207e..eec928d 100644 --- a/Gemfile +++ b/Gemfile @@ -4,6 +4,7 @@ source 'http://rubygems.org' ruby '2.5.1' +gem 'money' gem 'oj' gem 'ox' gem 'rack-cors' diff --git a/Gemfile.lock b/Gemfile.lock index 44f7c50..1ae577c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,6 +6,7 @@ GEM ast (2.4.0) builder (3.2.3) coderay (1.1.2) + concurrent-ruby (1.0.5) crack (0.4.3) safe_yaml (~> 1.0.0) et-orbi (1.1.6) @@ -15,12 +16,16 @@ GEM et-orbi (~> 1.1, >= 1.1.6) raabro (~> 1.1) hashdiff (0.3.7) + i18n (1.1.0) + concurrent-ruby (~> 1.0) jaro_winkler (1.5.1) kgio (2.11.2) method_source (0.9.0) minitest (5.11.3) minitest-around (0.4.1) minitest (~> 5.0) + money (6.13.0) + i18n (>= 0.6.4, <= 2) mustermann (1.0.3) oj (3.6.11) ox (2.10.0) @@ -64,7 +69,7 @@ GEM sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - sequel (5.12.0) + sequel (5.13.0) sequel_pg (1.11.0) pg (>= 0.18.0) sequel (>= 4.38.0) @@ -97,6 +102,7 @@ PLATFORMS DEPENDENCIES minitest minitest-around + money oj ox pry diff --git a/README.md b/README.md index 4405fcb..6ded3db 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,12 @@ Get historical rates for a time period up to the present. GET /2010-01-01.. HTTP/1.1 ``` +Get a list of available currency symbols, along with their full names. + +```http +GET /currencies HTTP/1.1 +``` + Rates quote against the Euro by default. Quote against a different currency. ```http diff --git a/lib/currency_names.rb b/lib/currency_names.rb new file mode 100644 index 0000000..d5c7e9b --- /dev/null +++ b/lib/currency_names.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'currency' +require 'money/currency' + +class CurrencyNames + def cache_key + Digest::MD5.hexdigest(currencies.first.date.to_s) + end + + def formatted + iso_codes.each_with_object({}) do |iso_code, result| + result[iso_code] = Money::Currency.find(iso_code).name + end + end + + private + + def iso_codes + currencies.map(&:iso_code).append('EUR').sort + end + + def currencies + @currencies ||= find_currencies + end + + def find_currencies + Currency.latest.all + end +end diff --git a/lib/web/server.rb b/lib/web/server.rb index 60aa83a..fd27306 100644 --- a/lib/web/server.rb +++ b/lib/web/server.rb @@ -6,6 +6,7 @@ require 'redcarpet' require 'sass/plugin/rack' require 'sinatra' +require 'currency_names' require 'query' require 'quote' @@ -102,6 +103,12 @@ get '/(?\d{4}-\d{2}-\d{2})\.\.(?\d{4}-\d{2}-\d{2})?', json interval_quote.formatted end +get '/currencies' do + currency_names = CurrencyNames.new + etag currency_names.cache_key + json currency_names.formatted +end + not_found do halt 404 end diff --git a/spec/currency_names_spec.rb b/spec/currency_names_spec.rb new file mode 100644 index 0000000..5665dc3 --- /dev/null +++ b/spec/currency_names_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require_relative 'helper' +require 'currency_names' + +describe CurrencyNames do + let(:currency_names) do + CurrencyNames.new + end + + it 'returns currency codes and names' do + currency_names.formatted['USD'].must_equal 'United States Dollar' + end + + it 'has a cache key' do + currency_names.cache_key.wont_be :empty? + end +end diff --git a/spec/web/server_spec.rb b/spec/web/server_spec.rb index c13ce64..46105b7 100644 --- a/spec/web/server_spec.rb +++ b/spec/web/server_spec.rb @@ -16,25 +16,25 @@ describe 'the server' do last_response.must_be :ok? end - it 'returns current quotes' do - get '/current' + it 'returns latest quotes' do + get '/latest' last_response.must_be :ok? end it 'sets base currency' do - get '/current' + get '/latest' res = Oj.load(last_response.body) - get '/current?from=USD' + get '/latest?from=USD' json.wont_equal res end it 'sets base amount' do - get '/current?amount=10' + get '/latest?amount=10' json['rates']['USD'].must_be :>, 10 end it 'filters symbols' do - get '/current?to=USD' + get '/latest?to=USD' json['rates'].keys.must_equal %w[USD] end @@ -50,14 +50,14 @@ describe 'the server' do end it 'returns an ETag' do - %w[/current /2012-11-20].each do |path| + %w[/latest /2012-11-20].each do |path| get path headers['ETag'].wont_be_nil end end it 'allows cross-origin requests' do - %w[/ /current /2012-11-20].each do |path| + %w[/ /latest /2012-11-20].each do |path| header 'Origin', '*' get path assert headers.key?('Access-Control-Allow-Methods') @@ -65,7 +65,7 @@ describe 'the server' do end it 'responds to preflight requests' do - %w[/ /current /2012-11-20].each do |path| + %w[/ /latest /2012-11-20].each do |path| header 'Origin', '*' header 'Access-Control-Request-Method', 'GET' header 'Access-Control-Request-Headers', 'Content-Type' @@ -75,7 +75,7 @@ describe 'the server' do end it 'converts an amount' do - get '/current?from=GBP&to=USD&amount=100' + get '/latest?from=GBP&to=USD&amount=100' json['rates']['USD'].must_be :>, 100 end @@ -92,4 +92,9 @@ describe 'the server' do json['end_date'].wont_be :empty? json['rates'].wont_be :empty? end + + it 'returns currencies' do + get '/currencies' + json['USD'].must_equal 'United States Dollar' + end end