Class: Currency::Exchange::Rate::Source::Xe
- Defined in:
- lib/currency/exchange/rate/source/xe.rb
Overview
Connects to xe.com and parses “XE.com Quick Cross Rates” from home page HTML.
Constant Summary collapse
- PIVOT_CURRENCY =
Defines the pivot currency for xe.com/.
:USD
Instance Attribute Summary
Attributes inherited from Provider
Attributes inherited from Base
#pivot_currency, #time_quantitizer, #verbose
Instance Method Summary collapse
- #clear_rates ⇒ Object
- #eat_lines_until(rx) ⇒ Object
-
#initialize(*opt) ⇒ Xe
constructor
A new instance of Xe.
-
#load_rates(time = nil) ⇒ Object
Return a list of known base rates.
-
#name ⇒ Object
Returns ‘xe.com’.
-
#parse_page_rates(data = nil) ⇒ Object
Parses xe.com homepage HTML for quick rates of 10 currencies.
-
#raw_rates ⇒ Object
Returns a cached Hash of rates:.
Methods inherited from Provider
#available?, #date_DD, #date_MM, #date_YYYY, #get_page_content, #get_rate, #get_uri, #rates
Methods inherited from Base
#__subclass_responsibility, #clear_rate, #convert, #currencies, #get_rate, #get_rate_base, #get_rates, #new_rate, #normalize_time, #rate, #rates, #to_s
Constructor Details
#initialize(*opt) ⇒ Xe
Returns a new instance of Xe.
19 20 21 22 23 24 |
# File 'lib/currency/exchange/rate/source/xe.rb', line 19 def initialize(*opt) self.uri = 'http://xe.com/' self.pivot_currency = PIVOT_CURRENCY @raw_rates = nil super(*opt) end |
Instance Method Details
#clear_rates ⇒ Object
33 34 35 36 |
# File 'lib/currency/exchange/rate/source/xe.rb', line 33 def clear_rates @raw_rates = nil super end |
#eat_lines_until(rx) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/currency/exchange/rate/source/xe.rb', line 124 def eat_lines_until(rx) until @lines.empty? @line = @lines.shift if md = rx.match(@line) $stderr.puts "\nMATCHED #{@line.inspect} WITH #{rx.inspect} AT LINES:\n#{@lines[0..4].inspect}" if @verbose return md end yield @line if block_given? end raise ParserError, [ 'eat_lines_until failed', :rx, rx ] false end |
#load_rates(time = nil) ⇒ Object
Return a list of known base rates.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/currency/exchange/rate/source/xe.rb', line 141 def load_rates(time = nil) if time $stderr.puts "#{self}: WARNING CANNOT SUPPLY HISTORICAL RATES" unless @time_warning @time_warning = true end rates = raw_rates # Load rates rates_pivot = rates[PIVOT_CURRENCY] raise ::Currency::Exception::UnknownRate, [ "Cannot get base rate #{PIVOT_CURRENCY.inspect}", :pivot_currency, PIVOT_CURRENCY, ] unless rates_pivot result = rates_pivot.keys.collect do | c2 | new_rate(PIVOT_CURRENCY, c2, rates_pivot[c2], @rate_timestamp) end result end |
#name ⇒ Object
Returns ‘xe.com’.
28 29 30 |
# File 'lib/currency/exchange/rate/source/xe.rb', line 28 def name 'xe.com' end |
#parse_page_rates(data = nil) ⇒ Object
Parses xe.com homepage HTML for quick rates of 10 currencies.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/currency/exchange/rate/source/xe.rb', line 52 def parse_page_rates(data = nil) data = get_page_content unless data @lines = data = data.split(/\n/); # xe.com no longer gives date/time. # Remove usecs. time = Time.at(Time.new.to_i).getutc @rate_timestamp = time eat_lines_until /More currencies\.\.\.<\/a>/i eat_lines_until /^\s*<tr>/i eat_lines_until /^\s*<tr>/i # Read first table row to get position for each currency currency = [ ] eat_lines_until /^\s*<\/tr>/i do if md = /<td[^>]+?>.*?\/> ([A-Z][A-Z][A-Z])<\/td>/.match(@line) cur = md[1].intern cur_i = currency.size currency.push(cur) $stderr.puts "Found currency header: #{cur.inspect} at #{cur_i}" if @verbose end end raise ParserError, "Currencies header not found" if currency.empty? # Skip until "1 USD =" eat_lines_until /^\s*<td[^>]+?> 1 +USD =/ # Read first row of 1 USD = ... rate = { } cur_i = -1 eat_lines_until /^\s*<\/tr>/i do # Grok: # # <td align="center" class="cur2 currencyA">114.676</td>\n # # AND # # <td align="center" class="cur2 currencyA"><div id="positionImage">0.9502\n # if md = /<td[^>]+?>\s*(<div[^>]+?>\s*)?(\d+\.\d+)\s*(<\/td>)?/i.match(@line) usd_to_cur = md[2].to_f cur_i = cur_i + 1 cur = currency[cur_i] raise ParserError, "Currency not found at column #{cur_i}" unless cur next if cur.to_s == PIVOT_CURRENCY.to_s (rate[PIVOT_CURRENCY] ||= {})[cur] = usd_to_cur (rate[cur] ||= { })[PIVOT_CURRENCY] ||= 1.0 / usd_to_cur $stderr.puts "#{cur.inspect} => #{usd_to_cur}" if @verbose end end raise ::Currency::Exception::UnavailableRates, "No rates found in #{get_uri.inspect}" if rate.keys.empty? raise ParserError, [ "Not all currencies found", :expected_currences, currency, :found_currencies, rate.keys, :missing_currencies, currency - rate.keys, ] if rate.keys.size != currency.size @lines = @line = nil raise ParserError, "Rate date not found" unless @rate_timestamp rate end |
#raw_rates ⇒ Object
Returns a cached Hash of rates:
xe.raw_rates[:USD][:CAD] => 1.0134
43 44 45 46 |
# File 'lib/currency/exchange/rate/source/xe.rb', line 43 def raw_rates # Force load of rates @raw_rates ||= parse_page_rates end |