cascading_configuration 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +40 -0
- data/README.md +211 -0
- data/lib/cascading_configuration/array/sorted/unique.rb +110 -0
- data/lib/cascading_configuration/array/sorted.rb +106 -0
- data/lib/cascading_configuration/array/unique.rb +106 -0
- data/lib/cascading_configuration/array.rb +103 -0
- data/lib/cascading_configuration/core/enable_instance_support.rb +22 -0
- data/lib/cascading_configuration/core/enable_module_support.rb +24 -0
- data/lib/cascading_configuration/core/encapsulation.rb +343 -0
- data/lib/cascading_configuration/core/instance_controller/extension_module.rb +38 -0
- data/lib/cascading_configuration/core/instance_controller/support_module/instance_support_module.rb +21 -0
- data/lib/cascading_configuration/core/instance_controller/support_module/singleton_support_module.rb +21 -0
- data/lib/cascading_configuration/core/instance_controller/support_module.rb +253 -0
- data/lib/cascading_configuration/core/instance_controller.rb +840 -0
- data/lib/cascading_configuration/core/module/block_configurations/cascading_variables.rb +129 -0
- data/lib/cascading_configuration/core/module/block_configurations.rb +15 -0
- data/lib/cascading_configuration/core/module/extended_configurations/compositing_objects.rb +173 -0
- data/lib/cascading_configuration/core/module/extended_configurations.rb +65 -0
- data/lib/cascading_configuration/core/module/inheriting_values.rb +64 -0
- data/lib/cascading_configuration/core/module.rb +284 -0
- data/lib/cascading_configuration/core.rb +23 -0
- data/lib/cascading_configuration/hash.rb +103 -0
- data/lib/cascading_configuration/setting.rb +87 -0
- data/lib/cascading_configuration.rb +47 -0
- data/lib/namespaces.rb +9 -0
- data/lib/requires.rb +46 -0
- data/spec/cascading_configuration/array/sorted/unique_spec.rb +742 -0
- data/spec/cascading_configuration/array/sorted_spec.rb +741 -0
- data/spec/cascading_configuration/array/unique_spec.rb +746 -0
- data/spec/cascading_configuration/array_spec.rb +768 -0
- data/spec/cascading_configuration/core/encapsulation_spec.rb +208 -0
- data/spec/cascading_configuration/core/instance_controller/extension_module_spec.rb +26 -0
- data/spec/cascading_configuration/core/instance_controller/support_module_spec.rb +269 -0
- data/spec/cascading_configuration/core/instance_controller_spec.rb +273 -0
- data/spec/cascading_configuration/core/module/block_configurations/cascading_variables_spec.rb +17 -0
- data/spec/cascading_configuration/core/module/extended_configurations/compositing_objects_spec.rb +127 -0
- data/spec/cascading_configuration/core/module/extended_configurations_spec.rb +37 -0
- data/spec/cascading_configuration/core/module/inheriting_values_spec.rb +87 -0
- data/spec/cascading_configuration/core/module_spec.rb +491 -0
- data/spec/cascading_configuration/hash_spec.rb +826 -0
- data/spec/cascading_configuration/setting_spec.rb +687 -0
- data/spec/cascading_configuration_spec.rb +58 -0
- metadata +185 -0
@@ -0,0 +1,129 @@
|
|
1
|
+
|
2
|
+
class ::CascadingConfiguration::Core::Module::BlockConfigurations::CascadingVariables <
|
3
|
+
::CascadingConfiguration::Core::Module::BlockConfigurations
|
4
|
+
|
5
|
+
##########################
|
6
|
+
# create_configuration #
|
7
|
+
##########################
|
8
|
+
|
9
|
+
# Pending.
|
10
|
+
def create_configuration( encapsulation, instance, name )
|
11
|
+
|
12
|
+
unless compositing_object = encapsulation.get_configuration( instance, name )
|
13
|
+
|
14
|
+
super
|
15
|
+
|
16
|
+
# initialize without initializing for parents
|
17
|
+
# we will initialize for parents after initializing all instances for inheritance
|
18
|
+
compositing_object = @compositing_object_class.new( nil, instance )
|
19
|
+
|
20
|
+
instance_controller = ::CascadingConfiguration::Core::InstanceController.nearest_instance_controller( encapsulation,
|
21
|
+
instance,
|
22
|
+
name )
|
23
|
+
|
24
|
+
extension_modules = instance_controller.extension_modules_upward( name, encapsulation )
|
25
|
+
|
26
|
+
unless extension_modules.empty?
|
27
|
+
# Modules are gathered from lowest ancestor upward. This means that they are already
|
28
|
+
# in the proper order for include/extend (which usually we would have to reverse).
|
29
|
+
compositing_object.extend( *extension_modules )
|
30
|
+
end
|
31
|
+
|
32
|
+
encapsulation.set_configuration( instance, name, compositing_object )
|
33
|
+
|
34
|
+
initialize_compositing_configuration_for_parent( encapsulation, instance, name )
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
return compositing_object
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
############
|
43
|
+
# setter #
|
44
|
+
############
|
45
|
+
|
46
|
+
# Pending.
|
47
|
+
def setter( encapsulation, instance, name, value )
|
48
|
+
|
49
|
+
return encapsulation.set_configuration( instance, name, value )
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
############
|
54
|
+
# getter #
|
55
|
+
############
|
56
|
+
|
57
|
+
# Pending.
|
58
|
+
def getter( encapsulation, instance, name )
|
59
|
+
|
60
|
+
return encapsulation.get_configuration( instance, name )
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
#####################
|
65
|
+
# instance_setter #
|
66
|
+
#####################
|
67
|
+
|
68
|
+
# Pending.
|
69
|
+
def instance_setter( encapsulation, instance, name, value )
|
70
|
+
|
71
|
+
# ensure our compositing object already exists
|
72
|
+
instance_getter( encapsulation, instance, name, value )
|
73
|
+
|
74
|
+
# now we can set normally
|
75
|
+
return setter( encapsulation, instance, name, value )
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
#####################
|
80
|
+
# instance_getter #
|
81
|
+
#####################
|
82
|
+
|
83
|
+
# Pending.
|
84
|
+
def instance_getter( encapsulation, instance, name )
|
85
|
+
|
86
|
+
cascading_value = nil
|
87
|
+
|
88
|
+
if encapsulation.has_configuration_value?( instance, name )
|
89
|
+
cascading_value = encapsulation.get_configuration( instance, name )
|
90
|
+
else
|
91
|
+
cascading_value = initialize_configuration_for_parent( encapsulation, instance, configuration_name )
|
92
|
+
end
|
93
|
+
|
94
|
+
return cascading_value
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
#####################################################
|
99
|
+
# initialize_compositing_configuration_for_parent #
|
100
|
+
#####################################################
|
101
|
+
|
102
|
+
# Pending.
|
103
|
+
def initialize_compositing_configuration_for_parent( encapsulation, instance, configuration_name )
|
104
|
+
|
105
|
+
unless compositing_object = encapsulation.get_configuration( instance, configuration_name )
|
106
|
+
compositing_object = create_configuration( encapsulation, instance, configuration_name )
|
107
|
+
end
|
108
|
+
|
109
|
+
# if instance has a parent
|
110
|
+
if parent = encapsulation.parent_for_configuration( instance, configuration_name )
|
111
|
+
|
112
|
+
# if first parent for configuration isn't initialized yet, initialize it
|
113
|
+
unless parent_composite_object = encapsulation.get_configuration( parent, configuration_name )
|
114
|
+
parent_composite_object = initialize_compositing_configuration_for_parent( encapsulation,
|
115
|
+
parent,
|
116
|
+
configuration_name )
|
117
|
+
end
|
118
|
+
|
119
|
+
unless compositing_object.parent_composite_object == parent_composite_object
|
120
|
+
compositing_object.initialize_for_parent( parent_composite_object )
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
return compositing_object
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
class ::CascadingConfiguration::Core::Module::BlockConfigurations < ::CascadingConfiguration::Core::Module
|
3
|
+
|
4
|
+
###########################
|
5
|
+
# define_configurations #
|
6
|
+
###########################
|
7
|
+
|
8
|
+
# Pending.
|
9
|
+
def define_configurations( instance_controller, encapsulation, method_types, *names, & definer_block )
|
10
|
+
|
11
|
+
super
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
|
2
|
+
class ::CascadingConfiguration::Core::Module::ExtendedConfigurations::CompositingObjects <
|
3
|
+
::CascadingConfiguration::Core::Module::ExtendedConfigurations
|
4
|
+
|
5
|
+
################
|
6
|
+
# initialize #
|
7
|
+
################
|
8
|
+
|
9
|
+
def initialize( ccm_name,
|
10
|
+
compositing_object_class = nil,
|
11
|
+
default_encapsulation_or_encapsulation_name = ::CascadingConfiguration::Core::
|
12
|
+
Module::DefaultEncapsulation,
|
13
|
+
*ccm_aliases )
|
14
|
+
|
15
|
+
super( ccm_name, default_encapsulation_or_encapsulation_name, *ccm_aliases )
|
16
|
+
|
17
|
+
@compositing_object_class = compositing_object_class
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
##########################
|
22
|
+
# create_configuration #
|
23
|
+
##########################
|
24
|
+
|
25
|
+
def create_configuration( encapsulation, instance, name )
|
26
|
+
|
27
|
+
unless compositing_object = encapsulation.get_configuration( instance, name )
|
28
|
+
|
29
|
+
super
|
30
|
+
|
31
|
+
# initialize without initializing for parents
|
32
|
+
# we will initialize for parents after initializing all instances for inheritance
|
33
|
+
compositing_object = @compositing_object_class.new( nil, instance )
|
34
|
+
|
35
|
+
instance_controller = ::CascadingConfiguration::Core::
|
36
|
+
InstanceController.nearest_instance_controller( encapsulation, instance, name )
|
37
|
+
|
38
|
+
if instance_controller
|
39
|
+
|
40
|
+
extension_modules = instance_controller.extension_modules_upward( name, encapsulation )
|
41
|
+
|
42
|
+
unless extension_modules.empty?
|
43
|
+
# Modules are gathered from lowest ancestor upward. This means that they are already
|
44
|
+
# in the proper order for include/extend (which usually we would have to reverse).
|
45
|
+
compositing_object.extend( *extension_modules )
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
encapsulation.set_configuration( instance, name, compositing_object )
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
return compositing_object
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
##############################
|
59
|
+
# initialize_configuration #
|
60
|
+
##############################
|
61
|
+
|
62
|
+
def initialize_configuration( encapsulation, instance, name )
|
63
|
+
|
64
|
+
initialize_compositing_configuration_for_parent( encapsulation, instance, name )
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
##############################
|
69
|
+
# compositing_object_class #
|
70
|
+
##############################
|
71
|
+
|
72
|
+
attr_reader :compositing_object_class
|
73
|
+
|
74
|
+
############
|
75
|
+
# setter #
|
76
|
+
############
|
77
|
+
|
78
|
+
def setter( encapsulation, instance, name, value )
|
79
|
+
|
80
|
+
compositing_object = encapsulation.get_configuration( instance, name )
|
81
|
+
|
82
|
+
compositing_object.replace( value )
|
83
|
+
|
84
|
+
return compositing_object
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
#####################
|
89
|
+
# instance_setter #
|
90
|
+
#####################
|
91
|
+
|
92
|
+
def instance_setter( encapsulation, instance, name, value )
|
93
|
+
|
94
|
+
# ensure our compositing object already exists
|
95
|
+
instance_getter( encapsulation, instance, name )
|
96
|
+
|
97
|
+
# now we can set normally
|
98
|
+
return setter( encapsulation, instance, name, value )
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
############
|
103
|
+
# getter #
|
104
|
+
############
|
105
|
+
|
106
|
+
def getter( encapsulation, instance, name )
|
107
|
+
|
108
|
+
return encapsulation.get_configuration( instance, name )
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
#####################
|
113
|
+
# instance_getter #
|
114
|
+
#####################
|
115
|
+
|
116
|
+
def instance_getter( encapsulation, instance, name )
|
117
|
+
|
118
|
+
compositing_object = nil
|
119
|
+
|
120
|
+
unless compositing_object = encapsulation.get_configuration( instance, name )
|
121
|
+
compositing_object = initialize_compositing_configuration_for_parent( encapsulation, instance, name )
|
122
|
+
end
|
123
|
+
|
124
|
+
return compositing_object
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
#####################################################
|
129
|
+
# initialize_compositing_configuration_for_parent #
|
130
|
+
#####################################################
|
131
|
+
|
132
|
+
def initialize_compositing_configuration_for_parent( encapsulation, instance, configuration_name )
|
133
|
+
|
134
|
+
unless compositing_object = encapsulation.get_configuration( instance, configuration_name )
|
135
|
+
compositing_object = create_configuration( encapsulation, instance, configuration_name )
|
136
|
+
end
|
137
|
+
|
138
|
+
# if instance has a parent
|
139
|
+
if parent = encapsulation.parent_for_configuration( instance, configuration_name )
|
140
|
+
|
141
|
+
# We are initializing for existing ancestors, but they may not have initialized yet -
|
142
|
+
# so we need to make sure they did before we initialize for instance.
|
143
|
+
|
144
|
+
# As long as our ancestor has an ancestor make sure that it has initialized for its parent.
|
145
|
+
# We can break at the first ancestor that we hit that has initialized for parent
|
146
|
+
# or if we run out of ancestors.
|
147
|
+
|
148
|
+
parent_composite_object = encapsulation.get_configuration( parent, configuration_name )
|
149
|
+
parent_composite_object2 = nil
|
150
|
+
if parent2 = encapsulation.parent_for_configuration( parent, configuration_name )
|
151
|
+
parent_composite_object2 = encapsulation.get_configuration( parent2, configuration_name )
|
152
|
+
end
|
153
|
+
|
154
|
+
# if first parent for configuration isn't initialized yet, initialize it
|
155
|
+
unless parent_composite_object and
|
156
|
+
parent_composite_object.parent_composite_object.equal?( parent_composite_object2 )
|
157
|
+
|
158
|
+
parent_composite_object = initialize_compositing_configuration_for_parent( encapsulation,
|
159
|
+
parent,
|
160
|
+
configuration_name )
|
161
|
+
end
|
162
|
+
|
163
|
+
unless compositing_object.parent_composite_object.equal?( parent_composite_object )
|
164
|
+
compositing_object.initialize_for_parent( parent_composite_object )
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
return compositing_object
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
class ::CascadingConfiguration::Core::Module::ExtendedConfigurations < ::CascadingConfiguration::Core::Module
|
3
|
+
|
4
|
+
##################################
|
5
|
+
# self.parse_extension_modules #
|
6
|
+
##################################
|
7
|
+
|
8
|
+
def self.parse_extension_modules( instance_controller, encapsulation, *names_modules )
|
9
|
+
|
10
|
+
# We can have configuration names or modules - we need to separate them.
|
11
|
+
names = [ ]
|
12
|
+
modules = [ ]
|
13
|
+
|
14
|
+
names_modules.each do |this_name_or_module|
|
15
|
+
|
16
|
+
case this_name_or_module
|
17
|
+
|
18
|
+
when ::Class
|
19
|
+
|
20
|
+
raise ArgumentError, 'Module expected (received Class).'
|
21
|
+
|
22
|
+
when ::Module
|
23
|
+
|
24
|
+
modules.push( this_name_or_module )
|
25
|
+
|
26
|
+
else
|
27
|
+
|
28
|
+
names.push( this_name_or_module )
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
names_modules_hash = { }
|
35
|
+
|
36
|
+
# if we have a block to define extensions to the compositing object:
|
37
|
+
|
38
|
+
names.each do |this_name|
|
39
|
+
names_modules_hash[ this_name ] = modules
|
40
|
+
end
|
41
|
+
|
42
|
+
return names_modules_hash
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
###########################
|
47
|
+
# define_configurations #
|
48
|
+
###########################
|
49
|
+
|
50
|
+
def define_configurations( instance_controller, encapsulation, method_types, *names_modules, & definer_block )
|
51
|
+
|
52
|
+
# Ask MethodModule to parse extension modules for these declarations on instance.
|
53
|
+
names_modules_hash = self.class.parse_extension_modules( instance_controller, encapsulation, *names_modules )
|
54
|
+
|
55
|
+
names_modules_hash.each do |this_name, these_modules|
|
56
|
+
instance_controller.add_extension_modules( this_name, encapsulation, *these_modules, & definer_block )
|
57
|
+
end
|
58
|
+
|
59
|
+
names = names_modules_hash.keys
|
60
|
+
|
61
|
+
super( instance_controller, encapsulation, method_types, *names, & definer_block )
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
class ::CascadingConfiguration::Core::Module::InheritingValues < ::CascadingConfiguration::Core::Module
|
3
|
+
|
4
|
+
############
|
5
|
+
# setter #
|
6
|
+
############
|
7
|
+
|
8
|
+
def setter( encapsulation, instance, name, value )
|
9
|
+
|
10
|
+
return encapsulation.set_configuration( instance, name, value )
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
############
|
15
|
+
# getter #
|
16
|
+
############
|
17
|
+
|
18
|
+
def getter( encapsulation, instance, name )
|
19
|
+
|
20
|
+
return get_configuration_searching_upward( encapsulation, instance, name )
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
#####################
|
25
|
+
# instance_getter #
|
26
|
+
#####################
|
27
|
+
|
28
|
+
alias_method( :instance_getter, :getter )
|
29
|
+
|
30
|
+
#####################
|
31
|
+
# instance_setter #
|
32
|
+
#####################
|
33
|
+
|
34
|
+
alias_method( :instance_setter, :setter )
|
35
|
+
|
36
|
+
########################################
|
37
|
+
# get_configuration_searching_upward #
|
38
|
+
########################################
|
39
|
+
|
40
|
+
def get_configuration_searching_upward( encapsulation, instance, configuration_name )
|
41
|
+
|
42
|
+
configuration_value = nil
|
43
|
+
|
44
|
+
matching_ancestor = nil
|
45
|
+
|
46
|
+
did_match_ancestor = false
|
47
|
+
|
48
|
+
matching_ancestor = encapsulation.match_parent( instance, configuration_name ) do |this_ancestor|
|
49
|
+
if encapsulation.has_configuration_value?( this_ancestor, configuration_name )
|
50
|
+
did_match_ancestor = true
|
51
|
+
else
|
52
|
+
false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
if did_match_ancestor
|
57
|
+
configuration_value = encapsulation.get_configuration( matching_ancestor, configuration_name )
|
58
|
+
end
|
59
|
+
|
60
|
+
return configuration_value
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|