Module: Configurable
- Extended by:
- ModuleMethods
- Defined in:
- lib/configurable.rb,
lib/configurable/utils.rb,
lib/configurable/config.rb,
lib/configurable/version.rb,
lib/configurable/validation.rb,
lib/configurable/config_hash.rb,
lib/configurable/nest_config.rb,
lib/configurable/class_methods.rb,
lib/configurable/module_methods.rb,
lib/configurable/indifferent_access.rb,
lib/configurable/ordered_hash_patch.rb
Overview
Configurable enables the specification of configurations within a class definition.
class ConfigClass
include Configurable
config :one, 'one'
config :two, 'two'
config :three, 'three'
end
c = ConfigClass.new
c.config.class # => Configurable::ConfigHash
c.config # => {:one => 'one', :two => 'two', :three => 'three'}
Instances have a config object that acts like a forwarding hash; configuration keys delegate to accessors while undeclared key-value pairs are stored internally:
c.config[:one] = 'ONE'
c.one # => 'ONE'
c.one = 1
c.config # => {:one => 1, :two => 'two', :three => 'three'}
c.config[:undeclared] = 'value'
c.config.store # => {:undeclared => 'value'}
The writer for a configuration can be defined by providing a block to config.
The Validation module provides a number of common validation/transform blocks accessible through the class method ‘c’:
class ValidationClass
include Configurable
config(:one, 'one') {|v| v.upcase }
config :two, 2, &c.integer
end
c = ValidationClass.new
c.config # => {:one => 'ONE', :two => 2}
c.one = 'aNothER'
c.one # => 'ANOTHER'
c.two = -2
c.two # => -2
c.two = "3"
c.two # => 3
c.two = nil # !> ValidationError
c.two = 'str' # !> ValidationError
Note that config blocks are defined in class-context and will have access to variables outside the block (as you would expect). For instance, these are analagous declarations:
class ExampleClass
config :key, 'value' do |input|
input.upcase
end
end
class AnalagousClass
block = lambda {|input| input.upcase}
define_method(:key=) do |input|
@key = block.call(input)
end
end
To have the block literally define the writer, use the config_attr method. Blocks provided to config_attr will have instance context and must set the instance variable themselves.
class LiteralClass
config_attr :key, 'value' do |input|
@key = input.upcase
end
end
Configurations are inherited and may be overridden in subclasses. They may also be included from a module:
module A
include Configurable
config :a, 'a'
config :b, 'b'
end
class B
include A
end
class C < B
config :b, 'B'
config :c, 'C'
end
B.new.config.to_hash # => {:a => 'a', :b => 'b'}
C.new.config.to_hash # => {:a => 'a', :b => 'B', :c => 'C'}
Lastly, configurable classes may be nested through the nest method. Nesting creates a configurable class with the configs defined in the nest block; nested configs may be accessed by chaining method calls, or through nested calls to config.
class NestingClass
include Configurable
config :one, 'one'
nest :two do
config :three, 'three'
end
end
c = NestingClass.new
c.config.to_hash # => {:one => 'one', :two => {:three => 'three'}}
c.two.three = 'THREE'
c.config[:two][:three] # => 'THREE'
Attributes
Alternative reader and writer methods may be specified as config attributes. When alternate methods are specified, Configurable assumes the methods are declared elsewhere and will not define accessors.
class AlternativeClass
include Configurable
config_attr :sym, 'value', :reader => :get_sym, :writer => :set_sym
def get_sym
@sym
end
def set_sym(input)
@sym = input.to_sym
end
end
alt = AlternativeClass.new
alt.respond_to?(:sym) # => false
alt.respond_to?(:sym=) # => false
alt.config[:sym] = 'one'
alt.get_sym # => :one
alt.set_sym('two')
alt.config[:sym] # => :two
Idiosyncratically, true and false may also be provided as reader/writer values.
- true
-
Same as using the defaults, accessors are defined.
- false
-
Sets the default reader/writer but does not define the accessors (think ‘define reader/writer’ => false).
Nil is not allowed as a value.
Non-reader/writer attributes
Attributes provide metadata for how to use configurations in various contexts. In general, attributes can be used to set any metadata an application needs. A few attributes are used internally by Configurable.
- Attribute
- Use
- init
-
When set to false, the config will not initialize itself. Specify when you manually initialize a config.
- type
-
Specifies the type of option ConfigParser generates for this Config (ex: :switch, :flag, :list, :hidden)
- desc
-
The description string used in the ConfigParser help
- long
-
The long option (default: key)
- short
-
The short option.
Validation blocks have default attributes already assigned to them (ex type). In cases where a user-defined block gets used multiple times, it may be useful to register default attributes for that block. To do so, use this pattern:
class AttributesClass
include Configurable
block = c.register(:type => :upcase) {|v| v.upcase }
config :a, 'A', &block
config :b, 'B', &block
end
AttributesClass.configurations[:a][:type] # => :upcase
AttributesClass.configurations[:b][:type] # => :upcase
Defined Under Namespace
Modules: ClassMethods, IndifferentAccess, ModuleMethods, Utils, Validation Classes: Config, ConfigHash, NestConfig, OrderedHashPatch
Constant Summary collapse
- MAJOR =
0- MINOR =
7- TINY =
0- VERSION =
"#{MAJOR}.#{MINOR}.#{TINY}"- DEFAULT_ATTRIBUTES =
A hash of (block, default attributes) for config blocks. The attributes for nil will be merged with those for the block.
Hash.new({})
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
A ConfigHash bound to self.
Instance Method Summary collapse
-
#initialize(*args) ⇒ Object
Initializes config, if necessary, and then calls super.
-
#initialize_copy(orig) ⇒ Object
Reinitializes configurations in the copy such that the new object has it’s own set of configurations, separate from the original object.
-
#reconfigure(overrides = {}) ⇒ Object
Reconfigures self with the given overrides.
Methods included from ModuleMethods
Instance Attribute Details
#config ⇒ Object (readonly)
A ConfigHash bound to self. Accessing configurations through config is much slower (although sometimes more convenient) than through the config accessors.
197 198 199 |
# File 'lib/configurable.rb', line 197 def config @config end |
Instance Method Details
#initialize(*args) ⇒ Object
Initializes config, if necessary, and then calls super. If initialize is overridden without calling super, be sure to call initialize_config manually within the new initialize method.
202 203 204 205 |
# File 'lib/configurable.rb', line 202 def initialize(*args) initialize_config unless instance_variable_defined?(:@config) super end |
#initialize_copy(orig) ⇒ Object
Reinitializes configurations in the copy such that the new object has it’s own set of configurations, separate from the original object.
218 219 220 221 |
# File 'lib/configurable.rb', line 218 def initialize_copy(orig) super @config = ConfigHash.new(self, orig.config.store.dup, false) end |
#reconfigure(overrides = {}) ⇒ Object
Reconfigures self with the given overrides. Only the specified configs are modified.
Returns self.
211 212 213 214 |
# File 'lib/configurable.rb', line 211 def reconfigure(overrides={}) config.merge!(overrides) self end |