Refactor snapshot

This commit is contained in:
Hakan Ensari 2012-11-23 14:13:49 +00:00
parent cfea8e71ad
commit 631d42207b
7 changed files with 97 additions and 88 deletions

View File

@ -5,7 +5,8 @@ gem 'pg'
gem 'sequel'
gem 'sinatra-jsonp'
gem 'unicorn'
gem 'yajl-ruby', require: 'yajl'
gem 'virtus'
gem 'yajl-ruby'
group :development do
gem 'minitest'

View File

@ -1,6 +1,7 @@
GEM
remote: http://rubygems.org/
specs:
backports (2.6.5)
fixer (0.5.0)
nokogiri (~> 1.5)
kgio (2.7.4)
@ -29,6 +30,8 @@ GEM
kgio (~> 2.6)
rack
raindrops (~> 0.7)
virtus (0.5.2)
backports (~> 2.6.1)
yajl-ruby (1.1.0)
PLATFORMS
@ -43,4 +46,5 @@ DEPENDENCIES
shotgun
sinatra-jsonp
unicorn
virtus
yajl-ruby

View File

@ -6,8 +6,10 @@ require 'yajl'
set :root, File.expand_path('..', File.dirname(__FILE__))
helpers do
def base
params[:base] || Snapshot::DEFAULT_BASE
def snapshot
Snapshot
.new(params)
.quote
end
end
@ -16,15 +18,13 @@ get '/' do
end
get '/latest' do
jsonp Snapshot
.last
.with_base(base)
.to_hash
jsonp snapshot
end
get '/:date' do
jsonp Snapshot
.new(params[:date])
.with_base(base)
.to_hash
jsonp snapshot
end
error do
"Something is rotten in the state of Denmark."
end

View File

@ -1,59 +1,49 @@
require_relative 'db'
require 'virtus'
class Snapshot
DEFAULT_BASE = 'EUR'
include Virtus
def self.last
new Currency.last_date
end
attribute :base, String, default: 'EUR'
attribute :date, Date, default: proc { Currency.last_date }
def initialize(date)
@date = date
@base = DEFAULT_BASE
end
# Ugly as fuck.
def to_hash
rebased_rates = rates
unless @base == DEFAULT_BASE
base_rate = rebased_rates
.update('EUR' => 1.0)
.delete @base
rebased_rates.each do |iso_code, rate|
new_rate = rate / base_rate
rebased_rates[iso_code] =
case new_rate
when new_rate > 100
new_rate.round 2
when new_rate > 10
new_rate.round 3
else
new_rate.round 4
end
end
end
{
base: @base,
date: @date,
rates: rebased_rates
}
end
def with_base(base)
@base = base
self
def quote
attributes.merge rates: rebase(rates)
end
private
def rates
Currency
.where(date: @date)
.reduce({}) { |hsh, currency|
hsh.update currency.to_hash
}
.where(date: date)
.reduce({}) do |rates, currency|
rates.update currency.to_hash
end
end
# Ugly as fuck.
def rebase(rates)
if base.upcase! != 'EUR'
denominator = rates
.update('EUR' => 1.0)
.delete base
rates.each do |iso_code, rate|
rates[iso_code] = round(rate / denominator)
end
end
rates
end
def round(rate)
case rate
when rate > 100
rate.round 2
when rate > 10
rate.round 3
else
rate.round 4
end
end
end

View File

@ -7,6 +7,7 @@ describe 'the application' do
let(:app) { Sinatra::Application }
let(:json) { Yajl::Parser.new.parse last_response.body }
let(:status) { last_response.status }
it 'returns latest snapshot' do
get '/latest'

View File

@ -1,31 +0,0 @@
require_relative 'helper'
require 'snapshot'
describe 'when rebased to a new base' do
let(:new_base) { 'USD' }
let(:snapshot) { Snapshot.new 'a date' }
let(:rates) { { new_base => 1.2781 } }
let(:rebased_hash) do
snapshot.stub :rates, rates do
snapshot
.with_base(new_base)
.to_hash
end
end
it 'resets base' do
rebased_hash[:base].must_equal new_base
end
it 'adds former base to rates' do
rebased_hash[:rates].keys.must_include Snapshot::DEFAULT_BASE
end
it 'removes new base from rates' do
rebased_hash[:rates].keys.wont_include new_base
end
it 'rebases rates' do
rebased_hash[:rates][Snapshot::DEFAULT_BASE].must_equal 0.7824
end
end

44
spec/snapshot_spec.rb Normal file
View File

@ -0,0 +1,44 @@
require_relative 'helper'
require 'snapshot'
describe Snapshot do
let(:snapshot) { Snapshot.new }
def stub_rates(rates = {})
snapshot.stub :rates, rates do
yield snapshot.quote[:rates]
end
end
describe 'by default' do
it 'quotes rates against the euro' do
stub_rates 'USD' => 1.25 do |quotes|
quotes['USD'].must_equal 1.25
end
end
it 'does not quote the euro' do
stub_rates do |quotes|
quotes.keys.wont_include 'EUR'
end
end
end
describe 'when base is set to a non-euro currency' do
before do
snapshot.base = 'USD'
end
it 'quotes rates against that currency' do
stub_rates 'USD' => 1.25 do |quotes|
quotes['EUR'].must_equal 0.8
end
end
it 'does not quote the base currency' do
stub_rates 'USD' => 1.25 do |quotes|
quotes.keys.wont_include 'USD'
end
end
end
end