« 25 Days of Ruby Gems - Ruby Advent Calendar 2020, December 1st - December 25th

Day 13 - lumione Gem - Money. Money. Money. Convert NZD ($) to USD ($) or EUR (€) to JPY (¥) in Your Terminal using the European Central Bank (ECB) Reference Exchange Rates. No API Key Required. Yes, Works Offline

Written by ledestin Dmitry Maksyoma

A Ruby / Rails freelancer from Auckland, New Zealand. Can’t quit Vim. Into JavaScript and meditation. Tech blog at Ruby Clarity and personal at A Journey to Find Motivation.

How to use Lumione

Lumione, convert 13 New Zealand Dollar (NZD) to US Dollar (USD):

$ lumione 13 nzd usd
$13.00 NZD ($9.22 USD) (rates updated 3 days ago)

Lumione, how many Japanese Yen (JPY) for one Euro (EUR):

$ lumione 1 eur jpy
€1.00 EUR (¥126 JPY) (rates updated 3 days ago)

Lumione, convert 12 Swiss Franc (CHF) to Chinese Yuan Renminbi (CNY):

$ lumione 12 chf cny
CHF12.00 CHF (¥88.32 CNY) (rates updated 3 days ago)

Install with gem install lumione.

What’s unique about Lumione? There are lots of command line currency converters, but…

Lumione doesn’t use an API. No API - no token setup needed and no limits on usage. Also:

Some caveats about rates:

Inside the Lumione back office trading room - The money (and eu_central_bank) gems

To speed up development I use the money gem. I could have used an API to get exchange rates, and then write code to convert between currencies. There are issues though, like the Japanese Yen being all “cents”, with no concept similar to 100 cents is 1 dollar. Japanese Yen are always “cents”, be it 1000 Yen or 10000 Yen. I’d have to take that into consideration, while writing conversion code.

Thankfully, the money gem takes care of that. With the money gem, currency conversion is easy. The main issue is to have exchange rates available. I get rates via the eu_central_bank gem. Tip: When used without caching, the eu_central_bank gem is easy to use. Example:

require "lumione/initializer"

def convert(amount, from_currency, to_currency)
  @original_money = Money.from_amount(amount, from_currency)
  @converted_money = @original_money.exchange_to(to_currency)
end

Money.default_bank.update_rates
convert 1, "nzd", "usd"
puts @converted_money.format(with_currency: true)

lumione/initializer sets up the money gem and EuCentralBank as default_bank.

You can use Money.from_amount 100, "jpy" and Money.from_amount 100, "usd", and it’ll take care of the currency differences. And #exchange_to converts to the target currency.

#update_rates loads exchange rates from European Central Bank (ECB) website.

However, caching rates complicates things quite a bit.

Off the Rails - The actionview gem

To speed up development, I use a Rails ActionView helper. I was after using #distance_of_time_in_words_to_now. You could see it in action earlier, when you saw “(rates updated 3 days ago)”. “3 days” was generated by #distance_of_time_in_words_to_now.

Many people suggest reimplementing things, rather than adding dependencies, but I don’t believe in that. I’d rather save time and use somebody else’s code. Of course, dependencies should be chosen carefully.

To use #distance_of_time_in_words_to_now outside Rails is easy:

require "active_support/core_ext/numeric/time"
require "action_view"

class Foo
  include ActionView::Helpers::DateHelper

  def foo
    distance_of_time_in_words_to_now 3.minutes.ago
  end
end

puts Foo.new.foo # => "3 minutes"

Start your command line scripts off right - The optparse-plus Gem

To speed up development, I use the optparse-plus gem. Handling command line arguments and options can be annoying and require effort, but not so with optparse-plus.

For example, command line arguments are defined like this:

arg :amount
arg :original_currency
arg :converted_to_currency

And, when I run lumione, I get this:

Usage: lumione [options] amount original_currency converted_to_currency

Convert money in one currency into another

v0.1.0

Options:
    -h, --help                       Show command line help
        --version                    Show help/version info
        --log-level LEVEL            Set the logging level
                                     (debug|info|warn|error|fatal)
                                     (Default: info)

All automatic! And it’ll tell user if an arument is missing.

And, optparse-plus generates ./bin/lumione and ./lib, and a gemspec, so it’s really worth using it.

Find Out More

References

Built with Ruby (running Jekyll) on 2021-03-12 22:04:06 +0000 in 0.371 seconds.
Hosted on GitHub Pages. </> Source on GitHub. (0) Dedicated to the public domain.