Last active
December 14, 2015 14:28
-
-
Save oz/5100368 to your computer and use it in GitHub Desktop.
I often need to convert currencies. This can be done from various search engines, but it's faster (for me) to just type a command in a term, and get results immediately. HTH.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# | |
# change.rb -- currency conversions on the CLI | |
# | |
# Requirements: | |
# | |
# gem install nas-yahoo_stock moneta slop | |
# | |
# Getting started: | |
# | |
# 1. Run change.rb --help | |
# 2. Format currencies using ISO 4217. | |
# 3. Stock are cached in ~/.change.cache for 24 hours | |
require 'pathname' | |
require 'fileutils' | |
require 'yahoo_stock' # nas-yahoo_stock | |
require 'moneta' | |
require 'slop' | |
module Currency | |
module Utils | |
module_function | |
# key/value store to cache stock values. | |
def store | |
return @store if @store | |
store_path = Pathname.new(ENV['HOME']) + '.change.cache' | |
@store = Moneta.new(:PStore, file: store_path.to_s, expires: expire) | |
end | |
# Rounding | |
def precision | |
3 | |
end | |
# Cache expiration | |
def expire | |
86400 | |
end | |
end | |
# Get currency conversions from Yahoo Finance API | |
class Stock | |
def initialize(options = {}) | |
@cache = options.fetch(:cache) { {} } | |
end | |
def get(name) | |
@cache.fetch(name) { fetch(name) } | |
@cache[name] | |
end | |
alias :[] :get | |
private | |
def fetch(name) | |
query = YahooStock::Quote.new(stock_symbols: [name]) | |
query.results(:to_array).output.each_with_index do |quote, i| | |
@cache[ name ] = quote[1].to_f | |
end | |
end | |
end | |
# Convert amounts between currencies. | |
Converter = Struct.new(:amount, :from, :to) do | |
include Utils | |
# @return [Float] | |
def convert | |
change = Stock.new(cache: store).get(stock_symbol) | |
(amount.to_f * change.to_f).round(precision) | |
end | |
def stock_symbol | |
"#{ from }#{ to }=X".upcase | |
end | |
end | |
end | |
opts = Slop.parse do | |
banner "Usage: change.rb -f <currency> -t <currency> -a <amount>" | |
on :f, :from=, 'Origin currency', argument: :optional | |
on :t, :to=, 'Target currency', argument: :optional | |
on :a, :amount=, 'Amount', argument: :optional | |
on :h, :help, 'Show help' | |
end | |
if opts.help? || !opts.from? || !opts.to? || !opts.amount? | |
puts opts | |
exit(1) | |
end | |
value = Currency::Converter.new(opts[:amount], opts[:from], opts[:to]).convert | |
puts "#{ opts[:amount] } #{ opts[:from] } = #{ value } #{ opts[:to] }" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment