├── .gemtest ├── .github └── workflows │ └── ruby.yml ├── .gitignore ├── AUTHORS ├── CHANGELOG.md ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── google_currency.gemspec ├── lib └── money │ ├── bank │ └── google_currency.rb │ └── rates_store │ └── rate_removal_support.rb └── spec ├── google_currency_with_json_spec.rb ├── rates ├── captcha.html ├── error.html ├── sgd_to_usd.html └── vnd_to_usd.html └── spec_helper.rb /.gemtest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RubyMoney/google_currency/6a650d61f7b5d22ad194da997c43ca69ff03b41c/.gemtest -------------------------------------------------------------------------------- /.github/workflows/ruby.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake 6 | # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby 7 | 8 | name: Ruby 9 | 10 | on: 11 | push: 12 | branches: [ master ] 13 | pull_request: 14 | branches: [ master ] 15 | 16 | jobs: 17 | test: 18 | 19 | runs-on: ubuntu-latest 20 | strategy: 21 | matrix: 22 | ruby-version: ['2.6', '2.7', '3.0'] 23 | 24 | steps: 25 | - uses: actions/checkout@v2 26 | - name: Set up Ruby 27 | # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, 28 | # change this to (see https://github.com/ruby/setup-ruby#versioning): 29 | uses: ruby/setup-ruby@v1 30 | with: 31 | ruby-version: ${{ matrix.ruby-version }} 32 | bundler-cache: true # runs 'bundle install' and caches installed gems automatically 33 | - name: Run tests 34 | run: bundle exec rspec spec 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## MAC OS 2 | .DS_Store 3 | 4 | ## TEXTMATE 5 | *.tmproj 6 | tmtags 7 | 8 | ## EMACS 9 | *~ 10 | \#* 11 | .\#* 12 | 13 | ## VIM 14 | *.swp 15 | 16 | ## PROJECT::GENERAL 17 | pkg 18 | doc 19 | .yardoc 20 | *.gem 21 | Gemfile.lock 22 | .bundle 23 | vendor/ruby 24 | 25 | ## PROJECT::SPECIFIC 26 | .rbenv-version 27 | .rbx 28 | .ruby-version 29 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | andersonbrandon 2 | cover 3 | Donald Ball 4 | Daniel Doubrovkine 5 | James Chen 6 | Jérémy Lecour 7 | Lars Pind 8 | Shane Emmons 9 | sowenjub 10 | yinquanteo 11 | Tarang Patel -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 3.4.1 2 | ===== 3 | 4 | - Fix the deprecated URL 5 | 6 | 3.4.0 7 | ===== 8 | 9 | - Add captcha response detection 10 | - Use finance.google.com for reliability across different regions 11 | 12 | 3.3.0 13 | ===== 14 | 15 | - Update Money gem dep 16 | 17 | 3.2.1 18 | ===== 19 | - Increase precision of rates by using inverse reciprocals for certain currencyes 20 | 21 | 3.0.0 22 | ===== 23 | 24 | - Google closed ig/calculator, so we're now using finance/calculator 25 | - fix incorrect parsing of complex rates 26 | 27 | Google Currency 2.2.0 28 | ===================== 29 | 30 | - Update money dependency to ~> 5.1.0 31 | 32 | Google Currency 2.1.0 33 | ===================== 34 | 35 | - Update money dependency to ~> 5.0.0 36 | 37 | Google Currency 2.0.2 38 | ===================== 39 | 40 | Bugfixes 41 | -------- 42 | - Fix encoding issue 43 | 44 | Google Currency 2.0.1 45 | ===================== 46 | 47 | Features 48 | -------- 49 | - Handles funky exchange rates (Arnaud Joubay) 50 | 51 | Bugfixes 52 | -------- 53 | - Fix for running under 1.9.2 in TextMate (larspind) 54 | 55 | Google Currency 2.0.0 56 | ===================== 57 | 58 | Features 59 | -------- 60 | - Added multi_json to allow users to select their own JSON parsing engine. 61 | - Removed deprecated method #get_google_rate. 62 | 63 | Bugfixes 64 | -------- 65 | - Updated deprecated rake tasks 66 | 67 | Google Currency 1.1.1 68 | ===================== 69 | 70 | Bugfixes 71 | -------- 72 | - Built gem using Ruby 1.8.7 to bypass a known error with RubyGems 1.5.0 and 73 | Ruby 1.9.2 74 | 75 | Google Currency 1.1.0 76 | ===================== 77 | 78 | Features 79 | -------- 80 | - Deprecated #get_google_rate, use #get_rate (thanks RMU Alumni) 81 | 82 | Bugfixes 83 | --------- 84 | - Fixed an issue when rates over 1000 did not parse correctly (thanks Brandon 85 | Anderson) 86 | 87 | Google Currency 1.0.3 88 | ===================== 89 | 90 | Features 91 | -------- 92 | - Update `money` requirement to `~> 3.5` 93 | 94 | Google Currency 1.0.2 95 | ===================== 96 | 97 | Features 98 | -------- 99 | - Replace `eval` with `JSON.parse` 100 | - Use BigDecimal instead of Float 101 | 102 | Bugfixes 103 | -------- 104 | - Quell parenthetical warnings in specs 105 | 106 | Google Currency 1.0.1 107 | ===================== 108 | 109 | Features 110 | -------- 111 | - Update `money` requirement to `~> 3.1.5` 112 | 113 | Google Currency 1.0.0 114 | ===================== 115 | 116 | Features 117 | -------- 118 | - Updated `money` requirement to `~> 3.1.0` 119 | 120 | Google Currency 0.1.1 121 | ===================== 122 | 123 | Features 124 | -------- 125 | - Added #flush_rates 126 | - Added #flush_rate 127 | 128 | Google Currency 0.1.0 129 | ===================== 130 | 131 | Features 132 | -------- 133 | - Initial release 134 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec 4 | 5 | group :development do 6 | gem 'rake' 7 | end 8 | 9 | group :test do 10 | gem 'timecop' 11 | end 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Shane Emmons 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ARCHIVED 2 | ======== 3 | 4 | Google's Finance Converter is no more. This exists only for historical purposes. Please see below for alternatives. 5 | 6 | 7 | Google Currency 8 | =============== 9 | 10 | [![Build Status](https://secure.travis-ci.org/RubyMoney/google_currency.png)](http://travis-ci.org/RubyMoney/google_currency) 11 | 12 | This gem extends Money::Bank::VariableExchange with Money::Bank::GoogleCurrency 13 | and gives you access to the current Google Currency exchange rates. 14 | 15 | Warning 16 | ------- 17 | 18 | This gem relies on Google's Finance Converter, which is getting deprecated without a known replacement. The network failures you might be getting are most likely the result of the deprecation. **Use at your own risk!** 19 | 20 | Here's a list of alternative currency converters that you might wanna use instead — https://github.com/RubyMoney/money#implementations. 21 | 22 | Usage 23 | ----- 24 | 25 | ```ruby 26 | 27 | require 'money' 28 | require 'money/bank/google_currency' 29 | 30 | # (optional) 31 | # set the seconds after than the current rates are automatically expired 32 | # by default, they never expire 33 | Money::Bank::GoogleCurrency.ttl_in_seconds = 86400 34 | 35 | # set default bank to instance of GoogleCurrency 36 | Money.default_bank = Money::Bank::GoogleCurrency.new 37 | 38 | # create a new money object, and use the standard #exchange_to method 39 | money = Money.new(1_00, "USD") # amount is in cents 40 | money.exchange_to(:EUR) 41 | 42 | # or install and use the 'monetize' gem 43 | require 'monetize' 44 | money = 1.to_money(:USD) 45 | money.exchange_to(:EUR) 46 | 47 | ``` 48 | 49 | An `UnknownRate` will be thrown if `#exchange_to` is called with a `Currency` 50 | that `Money` knows, but Google does not. 51 | 52 | An `UnknownCurrency` will be thrown if `#exchange_to` is called with a 53 | `Currency` that `Money` does not know. 54 | 55 | A `GoogleCurrencyCaptchaError` will be thrown if the Google Finance Converter API page responds with a Captcha instead of a rate (#52). 56 | 57 | A `GoogleCurrencyFetchError` will be thrown if there is an unknown issue with the Google Finance Converter API. 58 | 59 | Caveats 60 | ------- 61 | 62 | This gem uses [Google Finance Converter](https://finance.google.com/finance/converter) under the hood. 63 | 64 | Exchange rates are, 65 | 66 | 1. Based on 1 unit of the original currency. 67 | 1. Have a precision of 4 decimal places. 68 | 69 | What this means is that if the JPY to USD exchange rate is 0.0083660, 70 | Google will report the JPY to USD exchange rate as 0.0084. 71 | As a result, a larger JPY to USD conversion such as 10000 JPY to USD would yield 84 USD instead of 83.66 USD. 72 | 73 | Consequently, this means that small exchange rates will be imprecise. 74 | For example, if the IDR to USD exchange rate were 0.00007761, Google will report it as 0.0001. 75 | This means 100000 IDR would exchange to 10 USD instead of 7.76 USD. 76 | 77 | To accommodate for this, the reverse rate will be obtained if the rate is small 78 | (below 0.1) and the reciprocal of this reverse rate is used. 79 | 80 | Copyright 81 | --------- 82 | 83 | Copyright (c) 2011 Shane Emmons. See [LICENSE](LICENSE) for details. 84 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'rake/clean' 3 | 4 | CLOBBER.include('.yardoc', 'doc') 5 | 6 | def gemspec 7 | @gemspec ||= begin 8 | file = File.expand_path("../google_currency.gemspec", __FILE__) 9 | eval(File.read(file), binding, file) 10 | end 11 | end 12 | 13 | begin 14 | require 'rspec/core/rake_task' 15 | RSpec::Core::RakeTask.new 16 | rescue LoadError 17 | task(:spec){abort "`gem install rspec` to run specs"} 18 | end 19 | task :default => :spec 20 | task :test => :spec 21 | 22 | begin 23 | require 'yard' 24 | YARD::Rake::YardocTask.new do |t| 25 | t.options << "--files" << "CHANGELOG.md,LICENSE" 26 | end 27 | rescue LoadError 28 | task(:yard){abort "`gem install yard` to generate documentation"} 29 | end 30 | 31 | begin 32 | require 'rubygems/package_task' 33 | Gem::PackageTask.new(gemspec) do |pkg| 34 | pkg.gem_spec = gemspec 35 | end 36 | task :gem => :gemspec 37 | rescue LoadError 38 | task(:gem){abort "`gem install rake` to package gems"} 39 | end 40 | 41 | desc "Install the gem locally" 42 | task :install => :gem do 43 | sh "gem install pkg/#{gemspec.full_name}.gem" 44 | end 45 | 46 | desc "Validate the gemspec" 47 | task :gemspec do 48 | gemspec.validate 49 | end 50 | -------------------------------------------------------------------------------- /google_currency.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = "google_currency" 3 | s.version = "3.4.1" 4 | s.platform = Gem::Platform::RUBY 5 | s.authors = ["Shane Emmons"] 6 | s.email = ["semmons99@gmail.com"] 7 | s.homepage = "http://rubymoney.github.com/google_currency" 8 | s.summary = "Access the Google Currency exchange rate data." 9 | s.description = "GoogleCurrency extends Money::Bank::Base and gives you access to the current Google Currency exchange rates." 10 | s.license = 'MIT' 11 | 12 | s.add_development_dependency "rspec", ">= 3.0.0" 13 | s.add_development_dependency "yard", ">= 0.5.8" 14 | s.add_development_dependency "ffi" 15 | 16 | s.add_dependency "money", "~> 6.7" 17 | 18 | s.files = Dir.glob("{lib,spec}/**/*") 19 | s.files += %w(LICENSE README.md CHANGELOG.md AUTHORS) 20 | s.files += %w(Rakefile .gemtest google_currency.gemspec) 21 | 22 | s.require_path = "lib" 23 | end 24 | -------------------------------------------------------------------------------- /lib/money/bank/google_currency.rb: -------------------------------------------------------------------------------- 1 | require 'money' 2 | require 'money/rates_store/rate_removal_support' 3 | require 'open-uri' 4 | 5 | class Money 6 | module Bank 7 | # Raised when there is an unexpected error in extracting exchange rates 8 | # from Google Finance Calculator 9 | class GoogleCurrencyFetchError < Error 10 | end 11 | # Raised when there is a captcha form request in extracting exchange rates 12 | # from Google Finance Calculator 13 | class GoogleCurrencyCaptchaError < Error 14 | end 15 | 16 | class GoogleCurrency < Money::Bank::VariableExchange 17 | 18 | 19 | SERVICE_HOST = "finance.google.com" 20 | SERVICE_PATH = "/bctzjpnsun/converter" 21 | 22 | 23 | # @return [Hash] Stores the currently known rates. 24 | attr_reader :rates 25 | 26 | 27 | class << self 28 | # @return [Integer] Returns the Time To Live (TTL) in seconds. 29 | attr_reader :ttl_in_seconds 30 | 31 | # @return [Time] Returns the time when the rates expire. 32 | attr_reader :rates_expiration 33 | 34 | ## 35 | # Set the Time To Live (TTL) in seconds. 36 | # 37 | # @param [Integer] the seconds between an expiration and another. 38 | def ttl_in_seconds=(value) 39 | @ttl_in_seconds = value 40 | refresh_rates_expiration! if ttl_in_seconds 41 | end 42 | 43 | ## 44 | # Set the rates expiration TTL seconds from the current time. 45 | # 46 | # @return [Time] The next expiration. 47 | def refresh_rates_expiration! 48 | @rates_expiration = Time.now + ttl_in_seconds 49 | end 50 | end 51 | 52 | def initialize(*) 53 | super 54 | @store.extend Money::RatesStore::RateRemovalSupport 55 | end 56 | 57 | ## 58 | # Clears all rates stored in @rates 59 | # 60 | # @return [Hash] The empty @rates Hash. 61 | # 62 | # @example 63 | # @bank = GoogleCurrency.new #=> 64 | # @bank.get_rate(:USD, :EUR) #=> 0.776337241 65 | # @bank.flush_rates #=> {} 66 | def flush_rates 67 | store.clear_rates 68 | end 69 | 70 | ## 71 | # Clears the specified rate stored in @rates. 72 | # 73 | # @param [String, Symbol, Currency] from Currency to convert from (used 74 | # for key into @rates). 75 | # @param [String, Symbol, Currency] to Currency to convert to (used for 76 | # key into @rates). 77 | # 78 | # @return [Float] The flushed rate. 79 | # 80 | # @example 81 | # @bank = GoogleCurrency.new #=> 82 | # @bank.get_rate(:USD, :EUR) #=> 0.776337241 83 | # @bank.flush_rate(:USD, :EUR) #=> 0.776337241 84 | def flush_rate(from, to) 85 | store.remove_rate(from, to) 86 | end 87 | 88 | ## 89 | # Returns the requested rate. 90 | # 91 | # It also flushes all the rates when and if they are expired. 92 | # 93 | # @param [String, Symbol, Currency] from Currency to convert from 94 | # @param [String, Symbol, Currency] to Currency to convert to 95 | # 96 | # @return [Float] The requested rate. 97 | # 98 | # @example 99 | # @bank = GoogleCurrency.new #=> 100 | # @bank.get_rate(:USD, :EUR) #=> 0.776337241 101 | def get_rate(from, to) 102 | expire_rates 103 | store.get_rate(from, to) || store.add_rate(from, to, fetch_rate(from, to)) 104 | end 105 | 106 | ## 107 | # Flushes all the rates if they are expired. 108 | # 109 | # @return [Boolean] 110 | def expire_rates 111 | if self.class.ttl_in_seconds && self.class.rates_expiration <= Time.now 112 | flush_rates 113 | self.class.refresh_rates_expiration! 114 | true 115 | else 116 | false 117 | end 118 | end 119 | 120 | private 121 | 122 | ## 123 | # Queries for the requested rate and returns it. 124 | # 125 | # @param [String, Symbol, Currency] from Currency to convert from 126 | # @param [String, Symbol, Currency] to Currency to convert to 127 | # 128 | # @return [BigDecimal] The requested rate. 129 | def fetch_rate(from, to) 130 | 131 | from, to = Currency.wrap(from), Currency.wrap(to) 132 | 133 | data = build_uri(from, to).read 134 | rate = extract_rate(data); 135 | 136 | if (rate < 0.1) 137 | rate = 1/extract_rate(build_uri(to, from).read) 138 | end 139 | 140 | rate 141 | 142 | end 143 | 144 | ## 145 | # Build a URI for the given arguments. 146 | # 147 | # @param [Currency] from The currency to convert from. 148 | # @param [Currency] to The currency to convert to. 149 | # 150 | # @return [URI::HTTP] 151 | def build_uri(from, to) 152 | uri = URI::HTTP.build( 153 | :host => SERVICE_HOST, 154 | :path => SERVICE_PATH, 155 | :query => "a=1&from=#{from.iso_code}&to=#{to.iso_code}" 156 | ) 157 | end 158 | 159 | ## 160 | # Takes the response from Google and extract the rate. 161 | # 162 | # @param [String] data The google rate string to decode. 163 | # 164 | # @return [BigDecimal] 165 | def extract_rate(data) 166 | case data 167 | when /(\d+\.?\d*) [A-Z]{3}<\/span>/ 168 | BigDecimal($1) 169 | when /Could not convert\./ 170 | raise UnknownRate 171 | when /captcha-form/ 172 | raise GoogleCurrencyCaptchaError 173 | else 174 | raise GoogleCurrencyFetchError 175 | end 176 | end 177 | end 178 | end 179 | end 180 | -------------------------------------------------------------------------------- /lib/money/rates_store/rate_removal_support.rb: -------------------------------------------------------------------------------- 1 | module Money::RatesStore 2 | module RateRemovalSupport 3 | # Remove a conversion rate and returns it. Uses +Mutex+ to synchronize data access. 4 | # 5 | # @param [String] currency_iso_from Currency to exchange from. 6 | # @param [String] currency_iso_to Currency to exchange to. 7 | # 8 | # @return [Numeric] 9 | # 10 | # @example 11 | # store = Money::RatesStore::Memory.new 12 | # store.remove_rate("USD", "CAD") 13 | # store.remove_rate("CAD", "USD") 14 | def remove_rate(currency_iso_from, currency_iso_to) 15 | transaction { index.delete rate_key_for(currency_iso_from, currency_iso_to) } 16 | end 17 | 18 | # Clears all conversion rates. Uses +Mutex+ to synchronize data access. 19 | # 20 | # @example 21 | # store = Money::RatesStore::Memory.new 22 | # store.clear_rates 23 | def clear_rates 24 | transaction { @index = {} } 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/google_currency_with_json_spec.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/spec_helper') 2 | 3 | require 'money' 4 | require 'money/bank/google_currency' 5 | 6 | describe "GoogleCurrency" do 7 | before :each do 8 | @bank = Money::Bank::GoogleCurrency.new 9 | end 10 | 11 | it "should accept a ttl_in_seconds option" do 12 | Money::Bank::GoogleCurrency.ttl_in_seconds = 86400 13 | expect(Money::Bank::GoogleCurrency.ttl_in_seconds).to eq(86400) 14 | end 15 | 16 | describe ".refresh_rates_expiration!" do 17 | it "set the #rates_expiration using the TTL and the current time" do 18 | Money::Bank::GoogleCurrency.ttl_in_seconds = 86400 19 | new_time = Time.now 20 | Timecop.freeze(new_time) 21 | Money::Bank::GoogleCurrency.refresh_rates_expiration! 22 | expect(Money::Bank::GoogleCurrency.rates_expiration).to eq(new_time + 86400) 23 | end 24 | end 25 | 26 | describe "#get_rate" do 27 | it "should try to expire the rates" do 28 | expect(@bank).to receive(:expire_rates).once 29 | @bank.get_rate('USD', 'USD') 30 | end 31 | 32 | it "should use #fetch_rate when rate is unknown" do 33 | expect(@bank).to receive(:fetch_rate).once 34 | @bank.get_rate('USD', 'USD') 35 | end 36 | 37 | it "should not use #fetch_rate when rate is known" do 38 | @bank.get_rate('USD', 'USD') 39 | expect(@bank).to_not receive(:fetch_rate) 40 | @bank.get_rate('USD', 'USD') 41 | end 42 | 43 | it "should return the correct rate" do 44 | expect(@bank.get_rate('USD', 'USD')).to eq(1.0) 45 | end 46 | 47 | it "should store the rate for faster retreival" do 48 | @bank.get_rate('USD', 'EUR') 49 | expect(@bank.store.instance_variable_get("@index")).to include('USD_TO_EUR') 50 | end 51 | 52 | context "handles" do 53 | before :each do 54 | @uri = double('uri') 55 | allow(@bank).to receive(:build_uri){ |from,to| @uri } 56 | end 57 | 58 | it "should return rate when it is known" do 59 | allow(@uri).to receive(:read) { load_rate_http_response("sgd_to_usd") } 60 | expect(@bank.get_rate('SGD', 'USD')).to eq(BigDecimal("0.8066")) 61 | end 62 | 63 | it "should raise UnknownRate error when rate is not known" do 64 | allow(@uri).to receive(:read) { load_rate_http_response("vnd_to_usd") } 65 | expect { 66 | @bank.get_rate('VND', 'USD') 67 | }.to raise_error(Money::Bank::UnknownRate) 68 | end 69 | 70 | it "should raise GoogleCurrencyFetchError there is an unknown issue with extracting the exchange rate" do 71 | allow(@uri).to receive(:read) { load_rate_http_response("error") } 72 | expect { 73 | @bank.get_rate('VND', 'USD') 74 | }.to raise_error(Money::Bank::GoogleCurrencyFetchError) 75 | end 76 | 77 | it "should raise GoogleCurrencyCaptchaError when the page sends a Captcha form" do 78 | allow(@uri).to receive(:read) { load_rate_http_response("captcha") } 79 | expect { 80 | @bank.get_rate('VND', 'USD') 81 | }.to raise_error(Money::Bank::GoogleCurrencyCaptchaError) 82 | end 83 | end 84 | end 85 | 86 | describe "#flush_rates" do 87 | it "should empty @rates" do 88 | @bank.get_rate('USD', 'EUR') 89 | @bank.flush_rates 90 | expect(@bank.store.instance_variable_get("@index")).to eq({}) 91 | end 92 | end 93 | 94 | describe "#flush_rate" do 95 | it "should remove a specific rate from @rates" do 96 | @bank.get_rate('USD', 'EUR') 97 | @bank.get_rate('USD', 'JPY') 98 | @bank.flush_rate('USD', 'EUR') 99 | expect(@bank.store.instance_variable_get("@index")).to include('USD_TO_JPY') 100 | expect(@bank.store.instance_variable_get("@index")).to_not include('USD_TO_EUR') 101 | end 102 | end 103 | 104 | describe "#expire_rates" do 105 | before do 106 | Money::Bank::GoogleCurrency.ttl_in_seconds = 1000 107 | end 108 | 109 | context "when the ttl has expired" do 110 | before do 111 | new_time = Time.now + 1001 112 | Timecop.freeze(new_time) 113 | end 114 | 115 | it "should flush all rates" do 116 | expect(@bank).to receive(:flush_rates) 117 | @bank.expire_rates 118 | end 119 | 120 | it "updates the next expiration time" do 121 | exp_time = Time.now + 1000 122 | 123 | @bank.expire_rates 124 | expect(Money::Bank::GoogleCurrency.rates_expiration).to eq(exp_time) 125 | end 126 | end 127 | 128 | context "when the ttl has not expired" do 129 | it "not should flush all rates" do 130 | expect(@bank).to_not receive(:flush_rates) 131 | @bank.expire_rates 132 | end 133 | end 134 | end 135 | end 136 | -------------------------------------------------------------------------------- /spec/rates/captcha.html: -------------------------------------------------------------------------------- 1 | - Google Finance Search

Recent Quotes (30 days)

You have no recent quotes
chg | %
36 |
37 | 38 | 39 | 40 | 41 | 44 | 45 | 46 | 49 | 50 | 51 | 55 | 56 | 57 | 62 | 63 | 64 |
To continue your request, type the numbers you see 42 | in the picture below: 43 |
47 | 48 |
52 | 54 |
58 | 59 |     60 | 61 |
65 |
66 |
84 | 87 |
88 | -------------------------------------------------------------------------------- /spec/rates/error.html: -------------------------------------------------------------------------------- 1 | Something went wrong. 2 | -------------------------------------------------------------------------------- /spec/rates/sgd_to_usd.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RubyMoney/google_currency/6a650d61f7b5d22ad194da997c43ca69ff03b41c/spec/rates/sgd_to_usd.html -------------------------------------------------------------------------------- /spec/rates/vnd_to_usd.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RubyMoney/google_currency/6a650d61f7b5d22ad194da997c43ca69ff03b41c/spec/rates/vnd_to_usd.html -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'timecop' 2 | 3 | RSpec.configure do |config| 4 | end 5 | 6 | def load_rate_http_response(name) 7 | f = File.expand_path("../rates/#{name}.html", __FILE__) 8 | File.read(f, :encoding => 'iso-8859-1') 9 | end 10 | --------------------------------------------------------------------------------