cascading-configuration-hash 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,138 @@
1
+ == Cascading Configuration
2
+
3
+ http://rubygems.org/gems/cascading-configuration-hash
4
+
5
+ == DESCRIPTION:
6
+
7
+ Adds methods for cascading configuration hashes. Support package for cascading-configuration.
8
+
9
+ == SUMMARY:
10
+
11
+ * :attr_configuration_hash
12
+
13
+ == INSTALL:
14
+
15
+ * sudo gem install cascading-configuration-hash
16
+
17
+ == EXAMPLE:
18
+
19
+ #############################################################################
20
+ ######################### attr_configuration_hash ###########################
21
+ #############################################################################
22
+
23
+ ##################
24
+ # first module #
25
+ ##################
26
+
27
+ module CascadingConfiguration::MockModule
28
+ attr_configuration_hash :some_hash_configuration
29
+ self.some_hash_configuration = { :some_value => :some_value }
30
+ # => some_hash_configuration.should == { :some_value => :some_value }
31
+ end
32
+
33
+ ########################
34
+ # including module 1 #
35
+ ########################
36
+
37
+ module CascadingConfiguration::MockModule2
38
+ # => some_hash_configuration.should == { :some_value => :some_value }
39
+ self.some_hash_configuration = { :module_value => :some_value }
40
+ # => some_hash_configuration.should == { :module_value => :some_value }
41
+ end
42
+
43
+ ########################
44
+ # including module 2 #
45
+ ########################
46
+
47
+ module CascadingConfiguration::MockModule3
48
+
49
+ end
50
+
51
+ ###############
52
+ # top class #
53
+ ###############
54
+
55
+ class CascadingConfiguration::MockClass
56
+ # => some_hash_configuration.should == { :module_value => :some_value }
57
+ self.some_hash_configuration = { :another_value => :some_value }
58
+ # => some_hash_configuration.should == { :another_value => :some_value }
59
+ end
60
+
61
+ ###########################
62
+ # instance of top class #
63
+ ###########################
64
+
65
+ object_instance_one = CascadingConfiguration::MockClass.new
66
+ # => object_instance_one.some_hash_configuration.should == { :another_value => :some_value }
67
+ object_instance_one.some_hash_configuration = { :yet_another_value => :some_value }
68
+ # => object_instance_one.some_hash_configuration.should == { :yet_another_value => :some_value }
69
+ # => CascadingConfiguration::MockClass.some_hash_configuration.should == { :another_value => :some_value }
70
+ # => CascadingConfiguration::MockModule.some_hash_configuration.should == { :some_value => :some_value }
71
+
72
+ ############################
73
+ # first inheriting class #
74
+ ############################
75
+
76
+ class CascadingConfiguration::MockClassSub1 < CascadingConfiguration::MockClass
77
+ # => some_hash_configuration.should == { :another_value => :some_value }
78
+ self.some_hash_configuration = { :a_value_not_yet_used => :some_value }
79
+ # => some_hash_configuration.should == { :a_value_not_yet_used => :some_value }
80
+ # => CascadingConfiguration::MockClass.some_hash_configuration.should == { :another_value => :some_value }
81
+ # => CascadingConfiguration::MockModule.some_hash_configuration.should == { :some_value => :some_value }
82
+ end
83
+
84
+ ########################################
85
+ # instance of first inheriting class #
86
+ ########################################
87
+
88
+ object_instance_two = CascadingConfiguration::MockClassSub1.new
89
+ # => object_instance_two.some_hash_configuration.should == { :a_value_not_yet_used => :some_value }
90
+ # => object_instance_one.some_hash_configuration.should == { :yet_another_value => :some_value }
91
+ # => CascadingConfiguration::MockClass.some_hash_configuration.should == { :another_value => :some_value }
92
+ # => CascadingConfiguration::MockModule.some_hash_configuration.should == { :some_value => :some_value }
93
+
94
+ #############################
95
+ # second inheriting class #
96
+ #############################
97
+
98
+ class CascadingConfiguration::MockClassSub2 < CascadingConfiguration::MockClassSub1
99
+ # => some_hash_configuration.should == { :a_value_not_yet_used => :some_value }
100
+ self.some_hash_configuration = { :another_value_not_yet_used => :some_value }
101
+ # => some_hash_configuration.should == { :another_value_not_yet_used => :some_value }
102
+ end
103
+
104
+ #########################################
105
+ # instance of second inheriting class #
106
+ #########################################
107
+
108
+ object_instance_three = CascadingConfiguration::MockClassSub2.new
109
+ # => object_instance_three.some_hash_configuration.should == { :another_value_not_yet_used => :some_value }
110
+ object_instance_three.some_hash_configuration = { :one_more_unused_value => :some_value }
111
+ # => object_instance_three.some_hash_configuration.should == { :one_more_unused_value => :some_value }
112
+
113
+ #############################################################################
114
+
115
+ == LICENSE:
116
+
117
+ (The MIT License)
118
+
119
+ Copyright (c) 2011 Asher
120
+
121
+ Permission is hereby granted, free of charge, to any person obtaining
122
+ a copy of this software and associated documentation files (the
123
+ 'Software'), to deal in the Software without restriction, including
124
+ without limitation the rights to use, copy, modify, merge, publish,
125
+ distribute, sublicense, and/or sell copies of the Software, and to
126
+ permit persons to whom the Software is furnished to do so, subject to
127
+ the following conditions:
128
+
129
+ The above copyright notice and this permission notice shall be
130
+ included in all copies or substantial portions of the Software.
131
+
132
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
133
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
134
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
135
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
136
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
137
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
138
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,35 @@
1
+
2
+ module CascadingConfiguration::CascadingCompositeHash::Instance
3
+
4
+ ###################
5
+ # self.included #
6
+ ###################
7
+
8
+ def self.included( class_or_module )
9
+ module_self = self
10
+ class_or_module.instance_eval do
11
+ extend module_self
12
+ end
13
+ end
14
+
15
+ ################################################
16
+ # composite_hash_for_cascading_configuration #
17
+ ################################################
18
+
19
+ def composite_hash_for_cascading_configuration( configuration_name )
20
+
21
+ # initialize composite hash if necessary or acquire it from object
22
+ composite_hash_variable = composite_hash_variable_name( configuration_name )
23
+ composite_hash = nil
24
+ if instance_variable_defined?( composite_hash_variable )
25
+ composite_hash = instance_variable_get( composite_hash_variable )
26
+ else
27
+ composite_hash = ::CascadingConfiguration::CascadingCompositeHash.new( configuration_name, self )
28
+ instance_variable_set( composite_hash_variable, composite_hash )
29
+ end
30
+
31
+ return composite_hash
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,16 @@
1
+
2
+ module CascadingConfiguration::CascadingCompositeHash::Instance
3
+
4
+ ###########################################################################################################
5
+ private ###############################################################################################
6
+ ###########################################################################################################
7
+
8
+ ##################################
9
+ # composite_hash_variable_name #
10
+ ##################################
11
+
12
+ def composite_hash_variable_name( configuration_name )
13
+ return ( cascading_variable_name( configuration_name ).to_s + '__' + 'composite_hash' ).to_sym
14
+ end
15
+
16
+ end
@@ -0,0 +1,133 @@
1
+
2
+ class CascadingConfiguration::CascadingCompositeHash < Hash
3
+
4
+ attr_accessor :working_instance, :local_cascading_hash
5
+
6
+ ################
7
+ # initialize #
8
+ ################
9
+
10
+ def initialize( cascading_name, working_instance )
11
+ @cascading_name = cascading_name
12
+ @cascading_variable = working_instance.cascading_variable_name( @cascading_name )
13
+ @working_instance = working_instance
14
+ # if first ancestor can have a composite array, register self with it in case it gets updated in the future
15
+ if ( first_ancestor = @working_instance.first_ancestor ).respond_to?( :composite_hash_for_cascading_configuration )
16
+ @parent_composite_hash = first_ancestor.composite_hash_for_cascading_configuration( @cascading_name )
17
+ @parent_composite_hash.register_child_composite_hash( self )
18
+ end
19
+ # get local cascading array (not included in parent composite)
20
+ @local_cascading_hash = ::CascadingConfiguration::ConfigurationHash.new
21
+ # we may later have our own child composites
22
+ @child_composite_hashes = Array.new
23
+ # initialize self status for parent and local
24
+ update_self_as_cascading_composite
25
+ end
26
+
27
+ ###################################
28
+ # register_child_composite_hash #
29
+ ###################################
30
+
31
+ def register_child_composite_hash( child_composite_hash )
32
+ @child_composite_hashes.push( child_composite_hash )
33
+ return self
34
+ end
35
+
36
+ #####################################
37
+ # unregister_child_composite_hash #
38
+ #####################################
39
+
40
+ def unregister_child_composite_hash( child_composite_hash )
41
+ @child_composite_hashes.delete( child_composite_hash )
42
+ return self
43
+ end
44
+
45
+ #########
46
+ # []= #
47
+ #########
48
+
49
+ def []=( key, value )
50
+ @local_cascading_hash[ key ] = value
51
+ update_adding_composite_elements( key => value )
52
+ end
53
+ alias_method :store, :[]=
54
+
55
+ ############
56
+ # delete #
57
+ ############
58
+
59
+ alias_method :super_delete, :delete
60
+ def delete( key )
61
+ value = self[ key ]
62
+ @local_cascading_hash.delete( key )
63
+ update_removing_composite_elements( key )
64
+ return value
65
+ end
66
+
67
+ ############
68
+ # merge! #
69
+ ############
70
+
71
+ alias_method :super_merge!, :merge!
72
+ def merge!( other_hash )
73
+ @local_cascading_hash.merge!( other_hash )
74
+ update_adding_composite_elements( other_hash )
75
+ return self
76
+ end
77
+
78
+ #############
79
+ # replace #
80
+ #############
81
+
82
+ def replace( other_hash )
83
+ # clear current values
84
+ clear
85
+ # merge replacement settings
86
+ merge!( other_hash )
87
+ return self
88
+ end
89
+
90
+ ###########
91
+ # shift #
92
+ ###########
93
+
94
+ def shift
95
+ element = super
96
+ key = element[ 0 ]
97
+ @local_cascading_hash.delete( key )
98
+ update_removing_composite_elements( key )
99
+ return element
100
+ end
101
+
102
+ ###########
103
+ # clear #
104
+ ###########
105
+
106
+ alias_method :super_clear, :clear
107
+ def clear
108
+ # add all existing values to exclude array
109
+ self.keys.each do |this_key|
110
+ delete( this_key )
111
+ end
112
+ update_removing_composite_elements( *self.keys )
113
+ return self
114
+ end
115
+
116
+ #############
117
+ # freeze! #
118
+ #############
119
+
120
+ # freezes configuration and prevents ancestors from changing this configuration in the future
121
+ def freeze!
122
+
123
+ # move current configuration into local configuration
124
+ @local_cascading_hash.replace( self )
125
+
126
+ # unregister with parent composite so we don't get future updates from it
127
+ @parent_composite_hash.unregister_child_composite_hash( self ) if @parent_composite_hash
128
+
129
+ return self
130
+
131
+ end
132
+
133
+ end
@@ -0,0 +1,83 @@
1
+
2
+ class CascadingConfiguration::ConfigurationHash < Hash
3
+
4
+ attr_accessor :exclude_array
5
+
6
+ ################
7
+ # initialize #
8
+ ################
9
+
10
+ def initialize()
11
+ @exclude_array = Array.new
12
+ end
13
+
14
+ #########
15
+ # []= #
16
+ #########
17
+
18
+ def []=( key, value )
19
+ super
20
+ remove_from_exclude_array( key )
21
+ end
22
+
23
+ ###########
24
+ # store #
25
+ ###########
26
+
27
+ def store( key, value )
28
+ self[ key ] = value
29
+ end
30
+
31
+ ############
32
+ # delete #
33
+ ############
34
+
35
+ def delete( key )
36
+ value = super
37
+ add_to_exclude_array( key )
38
+ return value
39
+ end
40
+
41
+ ############
42
+ # merge! #
43
+ ############
44
+
45
+ def merge!( other_hash )
46
+ super
47
+ remove_from_exclude_array( *other_hash.keys )
48
+ return self
49
+ end
50
+
51
+ #############
52
+ # replace #
53
+ #############
54
+
55
+ def replace( other_hash )
56
+ add_to_exclude_array( *self.keys )
57
+ super
58
+ end
59
+
60
+ ###########
61
+ # shift #
62
+ ###########
63
+
64
+ def shift
65
+ element = super
66
+ add_to_exclude_array( element )
67
+ return element
68
+ end
69
+
70
+ ###########
71
+ # clear #
72
+ ###########
73
+
74
+ def clear
75
+ # add all existing values to exclude array
76
+ self.each do |this_key, this_value|
77
+ delete( this_key )
78
+ end
79
+ # clear existing values
80
+ super
81
+ end
82
+
83
+ end
@@ -0,0 +1,35 @@
1
+
2
+ module CascadingConfiguration::ConfigurationSettingsHash::Accessors
3
+
4
+ ######################################
5
+ # define_configuration_hash_setter #
6
+ ######################################
7
+
8
+ def define_configuration_hash_setter( configuration_name )
9
+ [ self, eigenclass ].each do |klass_or_eigenclass|
10
+ klass_or_eigenclass.class_eval do
11
+ configuration_setter_name = ( configuration_name.to_s + '=' ).to_sym
12
+ define_method( configuration_setter_name ) do |hash|
13
+ # we want the hash to supplant existing config
14
+ return composite_hash_for_cascading_configuration( configuration_name ).replace( hash )
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ ######################################
21
+ # define_configuration_hash_getter #
22
+ ######################################
23
+
24
+ def define_configuration_hash_getter( configuration_name )
25
+ configuration_getter_name = configuration_name
26
+ [ self, eigenclass ].each do |klass_or_eigenclass|
27
+ klass_or_eigenclass.class_eval do
28
+ define_method( configuration_getter_name ) do
29
+ return composite_hash_for_cascading_configuration( configuration_name )
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,21 @@
1
+
2
+ module CascadingConfiguration::ConfigurationSettingsHash::ClassInstance
3
+
4
+ #############################
5
+ # attr_configuration_hash #
6
+ #############################
7
+
8
+ def attr_configuration_hash( *property_names )
9
+
10
+ property_names.each do |this_property_name|
11
+ # define configuration setter
12
+ define_configuration_hash_setter( this_property_name )
13
+ # define configuration getter
14
+ define_configuration_hash_getter( this_property_name )
15
+ end
16
+
17
+ return self
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,20 @@
1
+
2
+ module CascadingConfiguration::ConfigurationSettingsHash::ModuleInstance
3
+
4
+ ##############
5
+ # included #
6
+ ##############
7
+
8
+ def included( class_or_module )
9
+ self_module = self
10
+ class_or_module.instance_eval do
11
+ include CascadingConfiguration::ConfigurationSettingsHash
12
+ # when we extend a module (which has happened if we got here)
13
+ # then we need to make sure when the module we are extending is included
14
+ # * CascadingConfiguration is included
15
+ # * the module we extended is used to extend the class/module that included
16
+ extend self_module
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,21 @@
1
+
2
+ module CascadingConfiguration::ConfigurationSettingsHash
3
+
4
+ ###################
5
+ # self.included #
6
+ ###################
7
+
8
+ def self.included( class_or_module )
9
+ class_or_module.instance_eval do
10
+ include CascadingConfiguration::ConfigurationVariable
11
+ extend CascadingConfiguration::ConfigurationSettingsHash
12
+ extend CascadingConfiguration::ConfigurationSettingsHash::Accessors
13
+ extend CascadingConfiguration::ConfigurationSettingsHash::ClassInstance
14
+ include CascadingConfiguration::CascadingCompositeHash::Instance
15
+ unless class_or_module.is_a?( Class )
16
+ extend CascadingConfiguration::ConfigurationSettingsHash::ModuleInstance
17
+ end
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,60 @@
1
+
2
+ class CascadingConfiguration::CascadingCompositeHash < Hash
3
+
4
+ ###########################################################################################################
5
+ private ###############################################################################################
6
+ ###########################################################################################################
7
+
8
+ ########################################
9
+ # update_self_as_cascading_composite #
10
+ ########################################
11
+
12
+ def update_self_as_cascading_composite
13
+ # start fresh
14
+ super_clear
15
+ # add parent config
16
+ super_merge!( @parent_composite_hash ) if @parent_composite_hash
17
+ # add additional local config
18
+ super_merge!( @local_cascading_hash )
19
+ # remove local exclude
20
+ unless @local_cascading_hash.exclude_array.empty?
21
+ @local_cascading_hash.exclude_array.each do |this_excluded_element|
22
+ super_delete( this_excluded_element )
23
+ end
24
+ end
25
+ # notify children to update their composite status
26
+ update_child_composite_arrays
27
+ return self
28
+ end
29
+
30
+ ######################################
31
+ # update_adding_composite_elements #
32
+ ######################################
33
+
34
+ def update_adding_composite_elements( elements_to_cascade )
35
+ super_merge!( elements_to_cascade )
36
+ update_child_composite_arrays
37
+ end
38
+
39
+ ########################################
40
+ # update_removing_composite_elements #
41
+ ########################################
42
+
43
+ def update_removing_composite_elements( *elements_to_exclude )
44
+ elements_to_exclude.each do |this_key|
45
+ super_delete( this_key )
46
+ end
47
+ update_child_composite_arrays
48
+ end
49
+
50
+ ###################################
51
+ # update_child_composite_arrays #
52
+ ###################################
53
+
54
+ def update_child_composite_arrays
55
+ @child_composite_hashes.each do |this_composite_hash|
56
+ this_composite_hash.instance_eval { update_self_as_cascading_composite }
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,31 @@
1
+
2
+ class CascadingConfiguration::ConfigurationHash < Hash
3
+
4
+ ###########################################################################################################
5
+ private ###############################################################################################
6
+ ###########################################################################################################
7
+
8
+ ##########################
9
+ # add_to_exclude_array #
10
+ ##########################
11
+
12
+ def add_to_exclude_array( *elements )
13
+ @exclude_array ||= Array.new
14
+ @exclude_array += elements
15
+ @exclude_array.sort!.uniq!
16
+ end
17
+
18
+ ###############################
19
+ # remove_from_exclude_array #
20
+ ###############################
21
+
22
+ def remove_from_exclude_array( *elements )
23
+ if @exclude_array
24
+ @exclude_array -= elements
25
+ @exclude_array.sort!.uniq!
26
+ else
27
+ @exclude_array ||= Array.new
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,33 @@
1
+
2
+ require 'cascading-configuration-variable'
3
+ #require_relative '../../variable/lib/cascading-configuration-variable.rb'
4
+
5
+ module CascadingConfiguration
6
+ class CascadingCompositeHash < Hash
7
+ module Instance
8
+ end
9
+ end
10
+ class ConfigurationHash < Hash
11
+ end
12
+ module ConfigurationSettingsHash
13
+ module Accessors
14
+ end
15
+ module ClassInstance
16
+ end
17
+ module ObjectInstance
18
+ end
19
+ module ModuleInstance
20
+ end
21
+ end
22
+ end
23
+
24
+ require_relative 'cascading-configuration-hash/CascadingConfiguration/CascadingCompositeHash.rb'
25
+ require_relative 'cascading-configuration-hash/CascadingConfiguration/_private_/CascadingCompositeHash.rb'
26
+ require_relative 'cascading-configuration-hash/CascadingConfiguration/CascadingCompositeHash/Instance.rb'
27
+ require_relative 'cascading-configuration-hash/CascadingConfiguration/CascadingCompositeHash/_private_/Instance.rb'
28
+ require_relative 'cascading-configuration-hash/CascadingConfiguration/ConfigurationHash.rb'
29
+ require_relative 'cascading-configuration-hash/CascadingConfiguration/_private_/ConfigurationHash.rb'
30
+ require_relative 'cascading-configuration-hash/CascadingConfiguration/ConfigurationSettingsHash.rb'
31
+ require_relative 'cascading-configuration-hash/CascadingConfiguration/ConfigurationSettingsHash/Accessors.rb'
32
+ require_relative 'cascading-configuration-hash/CascadingConfiguration/ConfigurationSettingsHash/ClassInstance.rb'
33
+ require_relative 'cascading-configuration-hash/CascadingConfiguration/ConfigurationSettingsHash/ModuleInstance.rb'