exchange 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|