class ExchangeRate
Constants
- CURRY_LENGTH_CONST
A constant value which defines the length of the standard currency abbreviation.
- FAR_BACK_DATE
- FUTURE_DATE
- INVALID_DATE
- NO_CURRY_FOR_DATE
- NO_ERR
Error message constants for the error_msg_map
- NULL_CURRY
- NULL_DATE
Public Class Methods
# File lib/ExchangeRate.rb, line 29 def initialize @date_hash = Hash.new @curry_list = Array.new @error_msg_map = Hash.new read_from_file fill_error_msg_map end
Public Instance Methods
Calculate exchange rate
# File lib/ExchangeRate.rb, line 134 def at(date, from_curry, to_curry) # Validate input date = date.to_s if chk_valid_input(date, from_curry) != NO_ERR error_msg_id = chk_valid_input(date, from_curry) return @error_msg_map[error_msg_id] elsif chk_valid_input(date, to_curry) != NO_ERR error_msg_id = chk_valid_input(date, to_curry) return @error_msg_map[error_msg_id] else rate_from_curry = curry_rate(date, from_curry) rate_to_curry = curry_rate(date, to_curry) return rate_to_curry/rate_from_curry end end
Check if the date read from the XML has a valid date format.
# File lib/ExchangeRate.rb, line 101 def chk_valid_date(date) Date.parse(date) rescue ArgumentError return false end
Check if the input parameters are valid.
# File lib/ExchangeRate.rb, line 108 def chk_valid_input(date, currency) if date == nil || date == '' return NULL_DATE elsif Date.today - Date.parse(date) < 0 return FUTURE_DATE elsif Date.today - Date.parse(date) > 90 return FAR_BACK_DATE elsif currency == nil || currency == '' return NULL_CURRY elsif @date_hash[date] == nil return INVALID_DATE elsif @date_hash[date][currency] == nil return NO_CURRY_FOR_DATE else return NO_ERR end end
Check if the currency read from the XML has a valid format.
# File lib/ExchangeRate.rb, line 94 def chk_valid_read(currency, rate) begin return currency.upcase.length == CURRY_LENGTH_CONST && rate.is_a?(Float) end end
Return a currency item from the list
# File lib/ExchangeRate.rb, line 157 def curry_item(index) # Keep unique currency entries only. @curry_list = @curry_list.uniq return @curry_list[index] end
Find currency rate for given date
# File lib/ExchangeRate.rb, line 129 def curry_rate(date, currency) return @date_hash[date][currency] end
# File lib/ExchangeRate.rb, line 83 def fill_error_msg_map @error_msg_map[0] = "Date is null." @error_msg_map[1] = "Date cannot be in the future." @error_msg_map[2] = "Date must be within the last 90 days." @error_msg_map[3] = "Currency is null." @error_msg_map[4] = "No data for this date." @error_msg_map[5] = "Currency details do not exist for the given date." end
Assuming that the XML file is downloaded using cron once a day, we access the file and then all currency data are stored into hash tables. We could read directly from the URL, or ideally we could create a configuration file with the path or the URL in order to make it easier for parameterisation, but we can keep it simple for that case. The path where the XML file can be found is defined in the gemspeck.
# File lib/ExchangeRate.rb, line 44 def read_from_file xml_path = File.expand_path("../ExchangeRate/eurofxref-hist-90d.xml", __FILE__) xml_source = File.new(xml_path) xml_doc = Document.new(xml_source) # This will split based upon different dates. xml_doc.elements.each('gesmes:Envelope/Cube/Cube'){ |date| curry_hash = Hash.new # This will split based upon each currency for the specific date. date.elements.each('Cube'){ |currency| # If XML data are correct then write in the tables. if chk_valid_read(currency.attributes["currency"].to_s, currency.attributes["rate"].to_f) @curry_list.push(currency.attributes["currency"].to_s) curry_hash[currency.attributes["currency"].to_s] = currency.attributes["rate"].to_f else # Else, omit this row. puts "Incorrect currency format. Line was omited." end } # Euro is also added in the map and the list curry_hash["EUR"] = 1.00 @curry_list.push("EUR") # If date format is correct then write in the table. if chk_valid_date(date.attributes["time"].to_s) @date_hash[date.attributes["time"].to_s] = curry_hash else # Else, omit this row. puts "Incorrect date format. Row was omited." end } end