exchange 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +17 -8
- data/Gemfile.lock +12 -6
- data/LICENSE.txt +1 -1
- data/README.rdoc +15 -12
- data/VERSION +1 -1
- data/exchange.gemspec +13 -23
- data/lib/core_extensions/conversability.rb +5 -4
- data/lib/exchange.rb +6 -11
- data/lib/exchange/base.rb +19 -0
- data/lib/exchange/cache/base.rb +57 -32
- data/lib/exchange/cache/file.rb +41 -45
- data/lib/exchange/cache/memcached.rb +28 -29
- data/lib/exchange/cache/no_cache.rb +4 -24
- data/lib/exchange/cache/rails.rb +26 -26
- data/lib/exchange/cache/redis.rb +30 -33
- data/lib/exchange/configuration.rb +167 -73
- data/lib/exchange/currency.rb +61 -30
- data/lib/exchange/external_api.rb +2 -0
- data/lib/exchange/external_api/base.rb +11 -5
- data/lib/exchange/external_api/call.rb +10 -7
- data/lib/exchange/external_api/currency_bot.rb +9 -5
- data/lib/exchange/external_api/ecb.rb +29 -13
- data/lib/exchange/external_api/json.rb +22 -0
- data/lib/exchange/external_api/xavier_media.rb +6 -5
- data/lib/exchange/external_api/xml.rb +22 -0
- data/lib/exchange/gem_loader.rb +35 -0
- data/lib/exchange/helper.rb +22 -15
- data/lib/exchange/iso_4217.rb +55 -44
- data/spec/core_extensions/conversability_spec.rb +2 -2
- data/spec/exchange/cache/base_spec.rb +7 -7
- data/spec/exchange/cache/file_spec.rb +19 -18
- data/spec/exchange/cache/memcached_spec.rb +29 -26
- data/spec/exchange/cache/no_cache_spec.rb +12 -6
- data/spec/exchange/cache/rails_spec.rb +13 -9
- data/spec/exchange/cache/redis_spec.rb +24 -24
- data/spec/exchange/configuration_spec.rb +38 -30
- data/spec/exchange/currency_spec.rb +33 -21
- data/spec/exchange/external_api/base_spec.rb +3 -1
- data/spec/exchange/external_api/call_spec.rb +5 -1
- data/spec/exchange/external_api/currency_bot_spec.rb +5 -1
- data/spec/exchange/external_api/ecb_spec.rb +9 -5
- data/spec/exchange/external_api/xavier_media_spec.rb +5 -1
- data/spec/exchange/gem_loader_spec.rb +29 -0
- data/spec/spec_helper.rb +1 -1
- metadata +12 -87
@@ -11,42 +11,41 @@ module Exchange
|
|
11
11
|
# c.cache_host = 'Your memcached host'
|
12
12
|
# c.cache_port = 'Your memcached port'
|
13
13
|
# end
|
14
|
+
#
|
14
15
|
class Memcached < Base
|
15
|
-
class << self
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
17
|
+
# instantiates a memcached client and memoizes it in a class variable.
|
18
|
+
# Use this client to access memcached data. For further explanation of use visit the memcached gem documentation
|
19
|
+
# @example
|
20
|
+
# Exchange::Cache::Memcached.client.set('FOO', 'BAR')
|
21
|
+
# @return [Dalli::Client] an instance of the dalli gem client class
|
22
|
+
#
|
23
|
+
def client
|
24
|
+
Exchange::GemLoader.new('dalli').try_load unless defined?(::Dalli)
|
25
|
+
@client ||= Dalli::Client.new("#{Exchange.configuration.cache.host}:#{Exchange.configuration.cache.port}")
|
26
|
+
end
|
27
|
+
|
28
|
+
# returns either cached data from the memcached client or calls the block and caches it in memcached.
|
29
|
+
# This method has to be the same in all the cache classes in order for the configuration binding to work
|
30
|
+
# @param [Exchange::ExternalAPI::Subclass] api The API class the data has to be stored for
|
31
|
+
# @param [Hash] opts the options to cache with
|
32
|
+
# @option opts [Time] :at the historic time of the exchange rates to be cached
|
33
|
+
# @yield [] This method takes a mandatory block with an arity of 0 and calls it if no cached result is available
|
34
|
+
# @raise [CachingWithoutBlockError] an Argument Error when no mandatory block has been given
|
35
|
+
|
36
|
+
def cached api, opts={}, &block
|
37
|
+
result = opts[:plain] ? client.get(key(api, opts)).to_s.gsub(/["\s+]/, '') : JSON.load(client.get(key(api, opts)))
|
26
38
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
# @option opts [Time] :at the historic time of the exchange rates to be cached
|
32
|
-
# @yield [] This method takes a mandatory block with an arity of 0 and calls it if no cached result is available
|
33
|
-
# @raise [CachingWithoutBlockError] an Argument Error when no mandatory block has been given
|
34
|
-
|
35
|
-
def cached api, opts={}, &block
|
36
|
-
raise CachingWithoutBlockError.new('Caching needs a block') unless block_given?
|
37
|
-
begin
|
38
|
-
result = opts[:plain] ? client.get(key(api, opts)).gsub(/["\s+]/, '') : JSON.load(client.get(key(api, opts)))
|
39
|
-
rescue ::Memcached::NotFound
|
40
|
-
result = block.call
|
41
|
-
if result && !result.to_s.empty?
|
42
|
-
client.set key(api, opts), result.to_json, Configuration.update == :daily ? 86400 : 3600
|
43
|
-
end
|
39
|
+
unless result
|
40
|
+
result = super
|
41
|
+
if result && !result.to_s.empty?
|
42
|
+
client.set key(api, opts), result.to_json, Exchange.configuration.cache.expire == :daily ? 86400 : 3600
|
44
43
|
end
|
45
|
-
|
46
|
-
result
|
47
44
|
end
|
48
45
|
|
46
|
+
result
|
49
47
|
end
|
48
|
+
|
50
49
|
end
|
51
50
|
end
|
52
51
|
end
|
@@ -2,32 +2,12 @@ module Exchange
|
|
2
2
|
module Cache
|
3
3
|
|
4
4
|
# @author Beat Richartz
|
5
|
-
# A class
|
6
|
-
# It just may be necessary to cache large files somewhere, this class allows you to do that
|
5
|
+
# A class to set caching to false
|
7
6
|
#
|
8
|
-
# @version 0.
|
7
|
+
# @version 0.6
|
9
8
|
# @since 0.3
|
9
|
+
#
|
10
|
+
NoCache = Class.new Base
|
10
11
|
|
11
|
-
class NoCache < Base
|
12
|
-
class << self
|
13
|
-
|
14
|
-
# returns either cached data from a stored file or stores a file.
|
15
|
-
# This method has to be the same in all the cache classes in order for the configuration binding to work
|
16
|
-
# @param [Exchange::ExternalAPI::Subclass] api The API class the data has to be stored for
|
17
|
-
# @param [Hash] opts the options to cache with
|
18
|
-
# @option opts [Time] :at IS IGNORED FOR FILECACHE
|
19
|
-
# @option opts [Symbol] :cache_period The period to cache the file for
|
20
|
-
# @yield [] This method takes a mandatory block with an arity of 0 and calls it if no cached result is available
|
21
|
-
# @raise [CachingWithoutBlockError] an Argument Error when no mandatory block has been given
|
22
|
-
|
23
|
-
def cached api, opts={}, &block
|
24
|
-
raise CachingWithoutBlockError.new('Caching needs a block') unless block_given?
|
25
|
-
|
26
|
-
block.call
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
32
12
|
end
|
33
13
|
end
|
data/lib/exchange/cache/rails.rb
CHANGED
@@ -9,37 +9,37 @@ module Exchange
|
|
9
9
|
# Exchange::Configuration.define do |c|
|
10
10
|
# c.cache = :rails
|
11
11
|
# end
|
12
|
+
#
|
12
13
|
class Rails < Base
|
13
|
-
class << self
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
15
|
+
# returns a Rails cache client. This has not to be stored since rails already memoizes it.
|
16
|
+
# Use this client to access rails cache data. For further explanation of use visit the rails documentation
|
17
|
+
# @example
|
18
|
+
# Exchange::Cache::Rails.client.set('FOO', 'BAR')
|
19
|
+
# @return [ActiveSupport::Cache::Subclass] an instance of the rails cache class (presumably a subclass of ActiveSupport::Cache)
|
20
|
+
#
|
21
|
+
def client
|
22
|
+
Exchange::GemLoader.new('rails').try_load unless defined?(::Rails)
|
23
|
+
::Rails.cache
|
24
|
+
end
|
25
|
+
|
26
|
+
# returns either cached data from the memcached client or calls the block and caches it in rails cache.
|
27
|
+
# This method has to be the same in all the cache classes in order for the configuration binding to work
|
28
|
+
# @param [Exchange::ExternalAPI::Subclass] api The API class the data has to be stored for
|
29
|
+
# @param [Hash] opts the options to cache with
|
30
|
+
# @option opts [Time] :at the historic time of the exchange rates to be cached
|
31
|
+
# @yield [] This method takes a mandatory block with an arity of 0 and calls it if no cached result is available
|
32
|
+
# @raise [CachingWithoutBlockError] an Argument Error when no mandatory block has been given
|
33
|
+
#
|
34
|
+
def cached api, opts={}, &block
|
35
|
+
raise CachingWithoutBlockError.new('Caching needs a block') unless block_given?
|
32
36
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
result = client.fetch key(api, opts), :expires_in => Configuration.update == :daily ? 86400 : 3600, &block
|
37
|
-
client.delete(key(api, opts)) unless result && !result.to_s.empty?
|
38
|
-
|
39
|
-
result
|
40
|
-
end
|
37
|
+
result = client.fetch key(api, opts), :expires_in => Exchange.configuration.cache.expire == :daily ? 86400 : 3600, &block
|
38
|
+
client.delete(key(api, opts)) unless result && !result.to_s.empty?
|
41
39
|
|
40
|
+
result
|
42
41
|
end
|
42
|
+
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
data/lib/exchange/cache/redis.rb
CHANGED
@@ -12,43 +12,40 @@ module Exchange
|
|
12
12
|
# c.cache_port = 'Your redis port (an Integer)'
|
13
13
|
# end
|
14
14
|
class Redis < Base
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
client.set key(api, opts), result.to_json
|
44
|
-
client.expire key(api, opts), Configuration.update == :daily ? 86400 : 3600
|
45
|
-
end
|
15
|
+
|
16
|
+
# instantiates a redis client and memoizes it in a class variable.
|
17
|
+
# Use this client to access redis data. For further explanation of use visit the redis gem documentation
|
18
|
+
# @example
|
19
|
+
# Exchange::Cache::Redis.client.set('FOO', 'BAR')
|
20
|
+
# @return [::Redis] an instance of the redis client gem class
|
21
|
+
#
|
22
|
+
def client
|
23
|
+
Exchange::GemLoader.new('redis').try_load unless defined?(::Redis)
|
24
|
+
@client ||= ::Redis.new(:host => Exchange.configuration.cache.host, :port => Exchange.configuration.cache.port)
|
25
|
+
end
|
26
|
+
|
27
|
+
# returns either cached data from the redis client or calls the block and caches it in redis.
|
28
|
+
# This method has to be the same in all the cache classes in order for the configuration binding to work
|
29
|
+
# @param [Exchange::ExternalAPI::Subclass] api The API class the data has to be stored for
|
30
|
+
# @param [Hash] opts the options to cache with
|
31
|
+
# @option opts [Time] :at the historic time of the exchange rates to be cached
|
32
|
+
# @yield [] This method takes a mandatory block with an arity of 0 and calls it if no cached result is available
|
33
|
+
# @raise [CachingWithoutBlockError] an Argument Error when no mandatory block has been given
|
34
|
+
#
|
35
|
+
def cached api, opts={}, &block
|
36
|
+
if result = client.get(key(api, opts))
|
37
|
+
result = opts[:plain] ? result.gsub(/["\s+]/, '') : JSON.load(result)
|
38
|
+
else
|
39
|
+
result = super
|
40
|
+
if result && !result.to_s.empty?
|
41
|
+
client.set key(api, opts), result.to_json
|
42
|
+
client.expire key(api, opts), Exchange.configuration.cache.expire == :daily ? 86400 : 3600
|
46
43
|
end
|
47
|
-
|
48
|
-
result
|
49
44
|
end
|
50
45
|
|
46
|
+
result
|
51
47
|
end
|
48
|
+
|
52
49
|
end
|
53
50
|
end
|
54
51
|
end
|
@@ -1,88 +1,182 @@
|
|
1
1
|
module Exchange
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
# A configuration setter for the Exchange gem. This comes in handy if you want to have backup or test setting
|
6
|
+
# @param [Exchange::Configuration] configuration the configuration to install
|
7
|
+
# @raise [ArgumentError] if fed with anything else than an Exchange::Configuration
|
8
|
+
# @return [Exchange::Configuration] The configuration installed
|
9
|
+
#
|
10
|
+
def configuration= configuration
|
11
|
+
if configuration.is_a? Exchange::Configuration
|
12
|
+
@configuration = configuration
|
13
|
+
else
|
14
|
+
raise ArgumentError.new("The configuration needs to be an instance of Exchange::Configuration")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# A getter for the configuration, returns the currently installed configuration or a default configuration
|
19
|
+
# if no configuration is installed
|
20
|
+
# @return [Exchange::Configuration] The currently installed / the default configuration
|
21
|
+
#
|
22
|
+
def configuration
|
23
|
+
@configuration ||= Configuration.new
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
2
27
|
# @author Beat Richartz
|
3
28
|
# A configuration class that stores the configuration of the gem. It allows to set the api from which the data gets retrieved,
|
4
29
|
# the cache in which the data gets cached, the regularity of updates for the currency rates, how many times the api calls should be
|
5
30
|
# retried on failure, and wether operations mixing currencies should raise errors or not
|
6
|
-
# @version 0.
|
31
|
+
# @version 0.6
|
7
32
|
# @since 0.1
|
8
|
-
|
33
|
+
#
|
34
|
+
class Configuration
|
35
|
+
|
9
36
|
class << self
|
10
|
-
@@config ||= {:api => :xavier_media, :retries => 5, :filestore_path => File.expand_path('exchange_filestore'), :allow_mixed_operations => true, :cache => :memcached, :cache_host => 'localhost', :cache_port => 11211, :update => :daily}
|
11
|
-
|
12
|
-
# A configuration method that stores the configuration of the gem. It allows to set the api from which the data gets retrieved,
|
13
|
-
# the cache in which the data gets cached, the regularity of updates for the currency rates, how many times the api calls should be
|
14
|
-
# retried on failure, and wether operations mixing currencies should raise errors or not
|
15
|
-
# @version 0.1
|
16
|
-
# @since 0.1
|
17
|
-
# @example Set a configuration by passing a block to the configuration
|
18
|
-
# Exchange::Configuration.define do |c|
|
19
|
-
# c.cache = :redis
|
20
|
-
# c.cache_host = '127.0.0.1'
|
21
|
-
# c.cache_port = 6547
|
22
|
-
# c.api = :currency_bot
|
23
|
-
# c.retries = 1
|
24
|
-
# c.allow_mixed_operations = false
|
25
|
-
# c.update = :hourly
|
26
|
-
# end
|
27
|
-
# @yield [Exchange::Configuration] yields a the configuration class
|
28
|
-
# @yieldparam [optional, Symbol] cache The cache type to use. Possible Values: :redis, :memcached or :rails or false to disable caching. Defaults to :memcached
|
29
|
-
# @yieldparam [optional, String] cache_host A string with the hostname or IP to set the cache host to. Does not have to be set for Rails cache
|
30
|
-
# @yieldparam [optional, Integer] cache_port An integer for the cache port. Does not have to be set for Rails cache
|
31
|
-
# @yieldparam [optional, Symbol] api The API to use. Possible Values: :currency_bot (Open Source currency bot API) or :xavier_media (Xavier Media API). Defaults to :currency_bot
|
32
|
-
# @yieldparam [optional, Integer] retries The number of times the gem should retry to connect to the api host. Defaults to 5.
|
33
|
-
# @yieldparam [optional, Boolean] If set to false, Operations with with different currencies raise errors. Defaults to true.
|
34
|
-
# @yieldparam [optional, Symbol] The regularity of updates for the API. Possible values: :daily, :hourly. Defaults to :daily.
|
35
|
-
# @yieldparam [optional, String] The path where files can be stored for the gem (used for large files from ECB). Make sure ruby has write access.
|
36
|
-
# @example Set configuration values directly to the class
|
37
|
-
# Exchange::Configuration.cache = :redis
|
38
|
-
# Exchange::Configuration.api = :xavier_media
|
39
37
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
@@config.merge! m => data
|
38
|
+
private
|
39
|
+
|
40
|
+
# @private
|
41
|
+
# @macro [setter] install_setter
|
42
|
+
#
|
43
|
+
def install_setter key
|
44
|
+
define_method :"#{key}=" do |data|
|
45
|
+
@config[key] = DEFAULTS[key].merge(data)
|
46
|
+
end
|
50
47
|
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# The instantiated api class according to the configuration
|
54
|
-
# @example
|
55
|
-
# Exchange::Configuration.api = :currency_bot
|
56
|
-
# Exchange::Configuration.api_class #=> Exchange::ExternalAPI::CurrencyBot
|
57
|
-
# @param [Hash] options A hash of Options
|
58
|
-
# @option options [Class] :api A api to return instead of the api class (use for fallback)
|
59
|
-
# @return [Exchange::ExternalAPI::Subclass] A subclass of Exchange::ExternalAPI
|
60
|
-
|
61
|
-
def api_class(options={})
|
62
|
-
@api_class ||= {}
|
63
|
-
return @api_class[options[:api] || self.api] if @api_class[options[:api] || self.api]
|
64
48
|
|
65
|
-
@api_class[options[:api] || self.api] = ExternalAPI.const_get((options[:api] || self.api).to_s.gsub(/(?:^|_)(.)/) { $1.upcase })
|
66
|
-
end
|
67
|
-
|
68
|
-
# The instantiated cache class according to the configuration
|
69
|
-
# @example
|
70
|
-
# Exchange::Configuration.cache = :redis
|
71
|
-
# Exchange::Configuration.cache_class #=> Exchange::ExternalAPI::Redis
|
72
|
-
# @param [Hash] options A hash of Options
|
73
|
-
# @option options [Class] :api A api to return instead of the api class (use for fallback)
|
74
|
-
# @return [Exchange::Cache::Subclass] A subclass of Exchange::Cache (or nil if caching has been set to false)
|
75
|
-
|
76
|
-
def cache_class(options={})
|
77
|
-
@cache_class ||= {}
|
78
|
-
return @cache_class[options[:cache] || self.cache] if @cache_class[options[:cache] || self.cache]
|
79
49
|
|
80
|
-
@
|
81
|
-
|
82
|
-
|
83
|
-
|
50
|
+
# @private
|
51
|
+
# @macro [getter] install_getter
|
52
|
+
#
|
53
|
+
def install_getter key, parent_module
|
54
|
+
define_method key do
|
55
|
+
@config[key] = OpenStruct.new(@config[key]) unless @config[key].is_a?(OpenStruct)
|
56
|
+
@config[key].subclass = parent_module.const_get camelize(@config[key].subclass) unless @config[key].subclass.is_a?(Class)
|
57
|
+
@config[key]
|
58
|
+
end
|
84
59
|
end
|
85
|
-
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
# The configuration defaults
|
64
|
+
# @version 0.6
|
65
|
+
# @since 0.6
|
66
|
+
#
|
67
|
+
DEFAULTS = {
|
68
|
+
:api => {
|
69
|
+
:subclass => ExternalAPI::XavierMedia,
|
70
|
+
:retries => 5
|
71
|
+
},
|
72
|
+
:cache => {
|
73
|
+
:subclass => Cache::Memcached,
|
74
|
+
:host => 'localhost',
|
75
|
+
:port => 11211,
|
76
|
+
:expire => :daily
|
77
|
+
},
|
78
|
+
:allow_mixed_operations => true
|
79
|
+
}
|
80
|
+
|
81
|
+
# Initialize a new configuration. Takes a hash and/or a block. Lets you easily set the configuration the way you want it to be
|
82
|
+
# @version 0.6
|
83
|
+
# @since 0.6
|
84
|
+
# @param [Hash] configuration The configuration as a hash
|
85
|
+
# @param [Proc] block A block to yield the configuration with
|
86
|
+
# @example Define the configuration with a hash
|
87
|
+
# Exchange::Configuration.new(:allow_mixed_operations => false, :api => {:subclass => :currency_bot, :retries => 2})
|
88
|
+
# @example Define the configuration with a block
|
89
|
+
# Exchange::Configuration.new do |c|
|
90
|
+
# c.allow_mixed_operations = false
|
91
|
+
# c.cache = {
|
92
|
+
# :subclass => Cache::Redis,
|
93
|
+
# :expire => :hourly
|
94
|
+
# }
|
95
|
+
#
|
96
|
+
# @yield [Exchange::Configuration] yields an instance of the configuration class
|
97
|
+
# @yieldparam [optional, Symbol] cache The cache type to use. Possible Values: :redis, :memcached or :rails or false to disable caching. Defaults to :memcached
|
98
|
+
# @yieldparam [optional, String] cache_host A string with the hostname or IP to set the cache host to. Does not have to be set for Rails cache
|
99
|
+
# @yieldparam [optional, Integer] cache_port An integer for the cache port. Does not have to be set for Rails cache
|
100
|
+
# @yieldparam [optional, Symbol] api The API to use. Possible Values: :currency_bot (Open Source currency bot API) or :xavier_media (Xavier Media API). Defaults to :currency_bot
|
101
|
+
# @yieldparam [optional, Integer] retries The number of times the gem should retry to connect to the api host. Defaults to 5.
|
102
|
+
# @yieldparam [optional, Boolean] If set to false, Operations with with different currencies raise errors. Defaults to true.
|
103
|
+
# @yieldparam [optional, Symbol] The regularity of updates for the API. Possible values: :daily, :hourly. Defaults to :daily.
|
104
|
+
# @yieldparam [optional, String] The path where files can be stored for the gem (used for large files from ECB). Make sure ruby has write access.
|
105
|
+
#
|
106
|
+
def initialize configuration={}, &block
|
107
|
+
@config = DEFAULTS.merge(configuration)
|
108
|
+
self.instance_eval(&block) if block_given?
|
109
|
+
super()
|
86
110
|
end
|
111
|
+
|
112
|
+
# Getter for the mixed operations configuration. If set to true, operations with mixed currencies will not raise errors
|
113
|
+
# If set to false, mixed operations will raise errors
|
114
|
+
# @since 0.6
|
115
|
+
# @version 0.6
|
116
|
+
# @return [Boolean] True if mixed operations are allowed, false if not
|
117
|
+
#
|
118
|
+
def allow_mixed_operations
|
119
|
+
@config[:allow_mixed_operations]
|
120
|
+
end
|
121
|
+
|
122
|
+
# Setter for the mixed operations configuration. If set to true, operations with mixed currencies will not raise errors
|
123
|
+
# If set to false, mixed operations will raise errors
|
124
|
+
# @since 0.6
|
125
|
+
# @version 0.6
|
126
|
+
# @param [Boolean] data The configuration to set
|
127
|
+
# @return [Boolean] The configuration set
|
128
|
+
#
|
129
|
+
def allow_mixed_operations= data
|
130
|
+
@config[:allow_mixed_operations] = data
|
131
|
+
end
|
132
|
+
|
133
|
+
# Setter for the api configuration.
|
134
|
+
# @since 0.6
|
135
|
+
# @version 0.6
|
136
|
+
# @param [Hash] The hash to set the configuration to
|
137
|
+
# @option [Symbol] :subclass The API subclass to use as a underscored symbol (will be camelized and constantized)
|
138
|
+
# @option [Integer] :retries The amount of retries on connection failure
|
139
|
+
# @example set the api to be ecb with a maximum of 8 retries on connection failure
|
140
|
+
# configuration.api = { :subclass => :ecb, :retries => 8 }
|
141
|
+
#
|
142
|
+
install_setter :api
|
143
|
+
|
144
|
+
# Setter for the cache configuration.
|
145
|
+
# @since 0.6
|
146
|
+
# @version 0.6
|
147
|
+
# @param [Hash] The hash to set the configuration to
|
148
|
+
# @option [Symbol] :subclass The Cache subclass to use as a underscored symbol (will be camelized and constantized)
|
149
|
+
# @option [String] :host The cache connection host
|
150
|
+
# @option [Integer] :port The cache connection port
|
151
|
+
# @option [Symbol] :expire The expiration period for the cache, can be :daily or :hourly, defaults to daily
|
152
|
+
# @example set the cache to be redis on localhost:6578 with hourly expiration
|
153
|
+
# configuration.cache = { :subclass => :redis, :host => 'localhost', :port => 6578, :expire => :hourly }
|
154
|
+
#
|
155
|
+
install_setter :cache
|
156
|
+
|
157
|
+
# Getter for the api configuration. Instantiates the configuration as an open struct, if called for the first time.
|
158
|
+
# Also camelizes and constantizes the api subclass, if used for the first time.
|
159
|
+
# @return [OpenStruct] an openstruct with the complete api configuration
|
160
|
+
#
|
161
|
+
install_getter :api, ExternalAPI
|
162
|
+
|
163
|
+
# Getter for the cache configuration. Instantiates the configuration as an open struct, if called for the first time.
|
164
|
+
# Also camelizes and constantizes the cache subclass, if used for the first time.
|
165
|
+
# @return [OpenStruct] an openstruct with the complete cache configuration
|
166
|
+
#
|
167
|
+
install_getter :cache, Cache
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
# Camelize a string or a symbol
|
172
|
+
# @param [String, Symbol] s The string to camelize
|
173
|
+
# @return [String] a camelized string
|
174
|
+
# @example Camelize an underscored symbol
|
175
|
+
# camelize(:some_thing) #=> "SomeThing"
|
176
|
+
#
|
177
|
+
def camelize s
|
178
|
+
s = s.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }
|
179
|
+
end
|
180
|
+
|
87
181
|
end
|
88
182
|
end
|