Cascading Configuration
http://rubygems.org/gems/cascading_configuration
Summary
Provides inheritable values across Ruby inheritance hierarchy or across arbitrary declared inheritance relations.
Description
Inheritable Objects and Downward-Compositing Hashes and Arrays; Downward-Transforming Values coming soon.
Install
- sudo gem install cascading_configuration
Usage
Since CascadingConfiguration produces configurations for both singletons and instances, include or extend of a CascadingConfiguration module (for instance CascadingConfiguration::Setting) also causes the including instance to be extended by module::ClassInstance (ie CascadingConfiguration::Setting::ClassInstance).
The result is that extending will enable only the singleton, whereas including will enable both singleton and instances.
Each module supports the same pattern for naming methods it provides.
The module has a name, which is used in each of the method types:
:setting # => :attr_setting
:hash # => :attr_hash
:array # => :attr_array
:unique_array # => :attr_unique_array
:sorted_array # => :attr_sorted_array
:sorted_unique_array # => :attr_sorted_unique_array
For backwards compatibility, these methods are also available:
:attr_configuration
:attr_configuration_hash
:attr_configuration_array
:attr_configuration_unique_array
:attr_configuration_sorted_array
:attr_configuration_sorted_unique_array
Base Method Naming Pattern
There are 5 types of base methods:
:attr_[module_name]
Cascading methods, which will affect instances according to include/extend pattern used.
:attr_module_[module_name] and attr_class_[module_name]
Cascading module/class methods, which will affect all module singletons according to include/extend pattern used.
:attr_instance_[module_name]
Cascading instance methods, which will affect instances of including modules according to include/extend pattern used.
:attr_local_[module_name]
Non-cascading methods that will affect the instance declared on as well as instances of that instance, if applicable.
:attr_object_[module_name]
Non-cascading methods that will affect only the instance declared on.
Inheritable Objects
Inheritable Objects are values received from an ancestor:
module ModuleA
include CascadingConfiguration::Setting
attr_setting :some_setting
self.some_setting = :some_value
end
class ClassA
include ModuleA
self.some_setting = :some_other_value
end
class ClassB < ClassA
some_setting == :some_other_value
self.some_setting = :another_value
end
class ClassC < ClassB
some_setting == :another_value
end
Simply put, the instance asked for the value will look up its ancestor chain until it finds an explicitly assigned value, which it returns.
This is provided by:
- CascadingConfiguration::Setting
Downward-Compositing Hashes and Arrays
Whether Hashes or Arrays, the idea is the same. We call the Compositing Objects. They all work the same way (automatically):
- The compositing object is initialized with a reference to the configuration instance it is attached to.
- The compositing object is initialized (separately) for its immediate parent object.
- Whenever an update occurs, the compositing object updates its registered child object with the update.
This way the lower objects are kept in sync with parent elements. Overriding hooked methods (provided by Array::Hooked from the array-hooked gem) provides a great deal of flexible functionality, permitting elements to be transformed as they are passed down the ancestor hierarchy.
Right now there are 5 types of Compositing Objects:
- CascadingConfiguration::Hash
- CascadingConfiguration::Array
- CascadingConfiguration::Array::Unique
- CascadingConfiguration::Array::Sorted
- CascadingConfiguration::Array::Sorted::Unique
All work the same with the exception of differing compositing object types. All declarations of compositing object configurations also accept extension modules and/or a block that will be used to create an extension module. Extension modules will be used to extend the compositing object; extension modules automatically cascade along the ancestor hierarchy for a given configuration.
module ModuleA
include CascadingConfiguration::Array
attr_array :some_array
some_array == [ ]
some_array.push( :some_value )
some_array == [ :some_value ]
end
class ClassA
include ModuleA
some_array == [ :some_value ]
end
class ClassB < ClassA
some_array == [ :some_value ]
some_array.push( :another_value )
some_array == [ :some_value, :another_value ]
end
class ClassC < ClassB
some_setting == :another_value
some_array.delete( :some_value )
some_array == [ :another_value ]
end
The end result:
ModuleA.some_array == [ :some_value ]
ClassA.some_array == [ :some_value ]
ClassB.some_array == [ :some_value, :another_value ]
ClassA.some_array == [ :another_value ]
Downward-Transforming Values
Downward-Transforming Values are not yet 100% implemented, but the remainder is minimal and will be coming soon.
Each time a child is registered, Downward-Transforming Values are processed via a block to produce the new value that the inheriting instance will receive.
Final details still being determined.
Configuration Modules
Including or extending CascadingConfiguration includes or extends all of its configuration modules:
- CascadingConfiguration::Setting
- CascadingConfiguration::Hash
- CascadingConfiguration::Array
- CascadingConfiguration::Array::Unique
- CascadingConfiguration::Array::Sorted
- CascadingConfiguration::Array::Sorted::Unique
These modules can also be used individually in the same way (simply include or extend).
Check Out the Code
CascadingConfiguration is, in my opinion, a strong showing of what one can do with Ruby. Of particular interest is its demonstrated use of the parallel-ancestry gem. More very real world examples coming soon.
License
(The MIT License)
Copyright (c) Asher
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.