cascading-configuration-array-unique 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # Cascading Configuration Array #
2
+
3
+ http://rubygems.org/gems/cascading-configuration-array
4
+
5
+ # Description #
6
+
7
+ Adds methods for cascading configuration arrays. Support package for cascading-configuration.
8
+
9
+ # Summary #
10
+
11
+ Cascading configuration methods for arrays, which returns the appropriate lowest accumulated value. Configuration inheritance can cascade through modules, classes, and to instances.
12
+
13
+ This means that we can create configuration modules, optionally setting configuration defaults, and include those configuration modules in other modules or classes.
14
+
15
+ # Install #
16
+
17
+ * sudo gem install cascading-configuration
18
+
19
+ # Usage #
20
+
21
+ Including the module will enable support for singleton and for instances.
22
+
23
+ ```ruby
24
+ module AnyModuleOrClass
25
+ include CascadingConfiguration
26
+ end
27
+ ```
28
+
29
+ Extending the module will enable support for singleton only.
30
+
31
+ ```ruby
32
+ module AnyModuleOrClass
33
+ extend CascadingConfiguration
34
+ end
35
+ ```
36
+
37
+ Including or extending CascadingConfiguration includes or extends:
38
+
39
+ * CascadingConfiguration::Variable
40
+
41
+ ## :attr_configuration_unique_array ##
42
+
43
+ :attr_configuration_unique_array provides inheritable array configurations that cascade downward. A composite sorted and unique array will be returned (merging downward from most distant ancestor to self).
44
+
45
+ An internal cache is kept, and any configuration updates that occur to higher-level ancestors cascade immediately downward.
46
+
47
+ The array maintained by :attr_configuration_unique_array is kept unique.
48
+
49
+ Define initial configuration in a module or class:
50
+
51
+ ```ruby
52
+ module SomeModule
53
+
54
+ include CascadingConfiguration::Array
55
+
56
+ attr_array_configuration :some_array_setting
57
+
58
+ some_array_setting # => nil
59
+
60
+ some_array_setting.push( :some_value )
61
+
62
+ some_array_setting # => [ :some_value ]
63
+
64
+ end
65
+ ```
66
+
67
+ Include initial module in a module or class:
68
+
69
+ ```ruby
70
+ class SomeClass
71
+
72
+ include SomeModule
73
+
74
+ some_array_setting # => [ :some_value ]
75
+
76
+ self.some_array_setting = [ :some_other_value ]
77
+
78
+ some_array_setting # => [ :some_other_value ]
79
+
80
+ some_array_setting.push( :another_value ) # => [ :another_value, :some_other_value ]
81
+
82
+ SomeModule.some_array_setting # => [ :some_value ]
83
+
84
+ end
85
+ ```
86
+
87
+ And it cascades to instances:
88
+
89
+ ```ruby
90
+ instance = SomeClass.new
91
+
92
+ instance.some_array_setting.should == [ :another_value, :some_other_value ]
93
+
94
+ instance.some_array_setting.delete( :some_other_value )
95
+
96
+ instance.some_array_setting.should == [ :another_value ]
97
+ ```
98
+
99
+ ### :attr_module_configuration_unique_array, :attr_class_configuration_unique_array ###
100
+
101
+ :attr_class_configuration_unique_array works like :attr_configuration_unique_array but does not cascade to instances.
102
+
103
+ ```ruby
104
+ module SomeModule
105
+
106
+ include CascadingConfiguration::Array
107
+
108
+ attr_array_configuration :some_array_setting
109
+
110
+ some_array_setting # => nil
111
+
112
+ some_array_setting.push( :some_value )
113
+
114
+ some_array_setting # => [ :some_value ]
115
+
116
+ end
117
+ ```
118
+
119
+ Include initial module in a module or class:
120
+
121
+ ```ruby
122
+ class SomeClass
123
+
124
+ include SomeModule
125
+
126
+ some_array_setting # => [ :some_value ]
127
+
128
+ self.some_array_setting = [ :some_other_value ]
129
+
130
+ some_array_setting # => [ :some_other_value ]
131
+
132
+ some_array_setting.push( :another_value ) # => [ :another_value, :some_other_value ]
133
+
134
+ SomeModule.some_array_setting # => [ :some_value ]
135
+
136
+ end
137
+ ```
138
+
139
+ And it does not cascade to instances:
140
+
141
+ ```ruby
142
+ instance = SomeClass.new
143
+
144
+ instance.respond_to?( :some_array_setting ).should == false
145
+ ```
146
+
147
+ ### :attr_local_configuration_unique_array ###
148
+
149
+ :attr_local_configuration_unique_array works like :attr_configuration_unique_array but does not cascade. This is primarily useful for creating local configurations maintained in parallel with cascading configurations (for instance, with the same variable prefixes), for overriding the local configuration method, and for hiding the configuration variable (coming soon).
150
+
151
+ ```ruby
152
+ module SomeModule
153
+
154
+ include CascadingConfiguration::Array
155
+
156
+ attr_array_configuration :some_array_setting
157
+
158
+ some_array_setting # => nil
159
+
160
+ some_array_setting.push( :some_value )
161
+
162
+ some_array_setting # => [ :some_value ]
163
+
164
+ end
165
+ ```
166
+
167
+ Include initial module in a module or class:
168
+
169
+ ```ruby
170
+ class SomeClass
171
+
172
+ include SomeModule
173
+
174
+ respond_to?( :some_array_setting ).should == false
175
+
176
+ end
177
+ ```
178
+
179
+ ## Additional Functionality ##
180
+
181
+ Cascading-configuration also provides several other convenience functions.
182
+
183
+ ### Method Redefinition ###
184
+
185
+ Any declared configuration is defined in order to support locally redefining the method and accessing the original by calling super.
186
+
187
+ ```ruby
188
+ module SomeModule
189
+
190
+ include CascadingConfiguration
191
+
192
+ attr_configuration :some_array_setting
193
+
194
+ def some_array_setting=( value )
195
+ puts 'Replacing configuration array!'
196
+ super
197
+ end
198
+
199
+ end
200
+ ```
201
+
202
+ # License #
203
+
204
+ (The MIT License)
205
+
206
+ Copyright (c) 2011 Asher
207
+
208
+ Permission is hereby granted, free of charge, to any person obtaining
209
+ a copy of this software and associated documentation files (the
210
+ 'Software'), to deal in the Software without restriction, including
211
+ without limitation the rights to use, copy, modify, merge, publish,
212
+ distribute, sublicense, and/or sell copies of the Software, and to
213
+ permit persons to whom the Software is furnished to do so, subject to
214
+ the following conditions:
215
+
216
+ The above copyright notice and this permission notice shall be
217
+ included in all copies or substantial portions of the Software.
218
+
219
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
220
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
221
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
222
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
223
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
224
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
225
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,58 @@
1
+ == Cascading Configuration
2
+
3
+ http://rubygems.org/gems/cascading-configuration-array
4
+
5
+ == Description
6
+
7
+ Adds methods for cascading configuration arrays. Support package for cascading-configuration.
8
+
9
+ == Summary
10
+
11
+ Cascading configuration methods for arrays, which returns the appropriate lowest accumulated value. Configuration inheritance can cascade through modules, classes, and to instances.
12
+
13
+ This means that we can create configuration modules, optionally setting configuration defaults, and include those configuration modules in other modules or classes.
14
+
15
+ == :attr_configuration_unique_array
16
+
17
+ :attr_configuration_unique_array provides inheritable array configurations that cascade downward. A composite sorted and unique array will be returned (merging downward from most distant ancestor to self).
18
+
19
+ An internal cache is kept, and any configuration updates that occur to higher-level ancestors cascade immediately downward.
20
+
21
+ The array maintained by :attr_configuration_unique_array is kept unique.
22
+
23
+ :attr_class_configuration_unique_array works like :attr_configuration_unique_array but does not cascade to instances.
24
+
25
+ :attr_local_configuration_unique_array works like :attr_configuration_unique_array but does not cascade. This is primarily useful for creating local configurations maintained in parallel with cascading configurations (for instance, with the same variable prefixes), for overriding the local configuration method, and for hiding the configuration variable (coming soon).
26
+
27
+ == Install
28
+
29
+ * sudo gem install cascading-configuration
30
+
31
+ == Usage
32
+
33
+ See README.md
34
+
35
+ == License
36
+
37
+ (The MIT License)
38
+
39
+ Copyright (c) 2011 Asher
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining
42
+ a copy of this software and associated documentation files (the
43
+ 'Software'), to deal in the Software without restriction, including
44
+ without limitation the rights to use, copy, modify, merge, publish,
45
+ distribute, sublicense, and/or sell copies of the Software, and to
46
+ permit persons to whom the Software is furnished to do so, subject to
47
+ the following conditions:
48
+
49
+ The above copyright notice and this permission notice shall be
50
+ included in all copies or substantial portions of the Software.
51
+
52
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
53
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
54
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
55
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
56
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
57
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
58
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,28 @@
1
+
2
+ if $__cascading_configuration__spec__development
3
+ require_relative '../../settings-array/lib/cascading-configuration-array.rb'
4
+ else
5
+ require 'cascading-configuration-variable'
6
+ end
7
+
8
+ module CascadingConfiguration
9
+ module Array
10
+ module Unique
11
+ class CompositingArray < ::CascadingConfiguration::Array::CompositingArray
12
+ end
13
+ module ModuleSupportMethods
14
+ end
15
+ module Interface
16
+ module GettersSetters
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ require_relative 'cascading-configuration-array-unique/_private_/CascadingConfiguration/Array/Unique/CompositingArray.rb'
24
+ require_relative 'cascading-configuration-array-unique/_private_/CascadingConfiguration/Array/Unique/Interface/GettersSetters.rb'
25
+ require_relative 'cascading-configuration-array-unique/_private_/CascadingConfiguration/Array/Unique/ModuleSupportMethods.rb'
26
+
27
+ require_relative 'cascading-configuration-array-unique/CascadingConfiguration/Array/Unique/Interface.rb'
28
+ require_relative 'cascading-configuration-array-unique/CascadingConfiguration/Array/Unique.rb'
@@ -0,0 +1,12 @@
1
+
2
+ module ::CascadingConfiguration::Array::Unique
3
+
4
+ # Configuration modules for storage of settings arrays
5
+ include ::CascadingConfiguration::Variable
6
+
7
+ # Interface to declare configuration settings arrays
8
+ include ::CascadingConfiguration::Array::Unique::Interface
9
+
10
+ extend ::CascadingConfiguration::Array::Unique::ModuleSupportMethods
11
+
12
+ end
@@ -0,0 +1,107 @@
1
+
2
+ module ::CascadingConfiguration::Array::Unique::Interface
3
+
4
+ # Support methods that define configuration settings array methods
5
+ include ::CascadingConfiguration::Array::Unique::Interface::GettersSetters
6
+
7
+ #####################################
8
+ # attr_configuration_unique_array #
9
+ #####################################
10
+
11
+ # defines configuration in class or module
12
+ # configuration cascades downward to instance including all classes or modules in-between
13
+ def attr_configuration_unique_array( *configuration_names )
14
+
15
+ configuration_names.each do |this_configuration_name|
16
+ # define configuration setter
17
+ define_cascading_unique_array_setter( this_configuration_name )
18
+ # define configuration getter
19
+ define_cascading_unique_array_getter( this_configuration_name )
20
+ end
21
+
22
+ return self
23
+
24
+ end
25
+
26
+ ############################################
27
+ # attr_module_configuration_unique_array #
28
+ ############################################
29
+
30
+ # defines configuration in class or module
31
+ # configuration cascades downward to last class or module
32
+ def attr_module_configuration_unique_array( *configuration_names )
33
+
34
+ configuration_names.each do |this_configuration_name|
35
+ # define configuration setter
36
+ define_class_configuration_unique_array_setter( this_configuration_name )
37
+ # define configuration getter
38
+ define_class_configuration_unique_array_getter( this_configuration_name )
39
+ end
40
+
41
+ return self
42
+
43
+ end
44
+ alias_method :attr_class_configuration_unique_array, :attr_module_configuration_unique_array
45
+
46
+ ###########################################
47
+ # attr_local_configuration_unique_array #
48
+ ###########################################
49
+
50
+ # defines configuration in present class or module context
51
+ # configuration does not cascade
52
+ def attr_local_configuration_unique_array( *configuration_names )
53
+
54
+ ::CascadingConfiguration::Variable.create_local_instance_configuration_support_module( self )
55
+
56
+ configuration_names.each do |this_configuration_name|
57
+ # define configuration setter
58
+ define_local_configuration_unique_array_setter( this_configuration_name )
59
+ # define configuration getter
60
+ define_local_configuration_unique_array_getter( this_configuration_name )
61
+ end
62
+
63
+ return self
64
+
65
+ end
66
+
67
+ ############################################
68
+ # attr_object_configuration_unique_array #
69
+ ############################################
70
+
71
+ # defines configuration in present instance
72
+ # configuration does not cascade
73
+ def attr_object_configuration_unique_array( *configuration_names )
74
+
75
+ ::CascadingConfiguration::Variable.create_local_instance_configuration_support_module( self )
76
+
77
+ configuration_names.each do |this_configuration_name|
78
+ # define configuration setter
79
+ define_object_configuration_unique_array_setter( this_configuration_name )
80
+ # define configuration getter
81
+ define_object_configuration_unique_array_getter( this_configuration_name )
82
+ end
83
+
84
+ return self
85
+
86
+ end
87
+
88
+ ##############################################
89
+ # attr_instance_configuration_unique_array #
90
+ ##############################################
91
+
92
+ # defines configuration in present class or module context
93
+ # configuration does not cascade
94
+ def attr_instance_configuration_unique_array( *configuration_names )
95
+
96
+ configuration_names.each do |this_configuration_name|
97
+ # define configuration setter
98
+ define_instance_configuration_unique_array_setter( this_configuration_name )
99
+ # define configuration getter
100
+ define_instance_configuration_unique_array_getter( this_configuration_name )
101
+ end
102
+
103
+ return self
104
+
105
+ end
106
+
107
+ end
@@ -0,0 +1,166 @@
1
+
2
+ class ::CascadingConfiguration::Array::Unique::CompositingArray <
3
+ ::CascadingConfiguration::Array::CompositingArray
4
+
5
+ ################
6
+ # initialize #
7
+ ################
8
+
9
+ def initialize( configuration_instance, configuration_name )
10
+
11
+ @unique_keys = { }
12
+
13
+ super
14
+
15
+ end
16
+
17
+ ##################################### Self Management ##########################################
18
+
19
+ #########
20
+ # []= #
21
+ #########
22
+
23
+ def []=( index, object )
24
+
25
+ # we only set if we don't already have the object being inserted
26
+ # for this reason we return nil if no insert occurred
27
+
28
+ return_value = nil
29
+
30
+ # make sure that set is unique
31
+ unless @unique_keys.has_key?( object )
32
+
33
+ @unique_keys[ object ] = true
34
+
35
+ return_value = super
36
+
37
+ end
38
+
39
+ return return_value
40
+
41
+ end
42
+
43
+ ############
44
+ # insert #
45
+ ############
46
+
47
+ def insert( index, *objects )
48
+
49
+ # we only insert if we don't already have the object being inserted
50
+ # for this reason we return nil if no insert occurred
51
+
52
+ # if we have less elements in self than the index we are inserting at
53
+ # we need to make sure the nils inserted cascade
54
+ if index > count
55
+ if @unique_keys.has_key?( nil )
56
+ index -= ( index - count + 1 )
57
+ else
58
+ objects.unshift( nil )
59
+ index -= ( index - count )
60
+ end
61
+ end
62
+
63
+ # get rid of objects already inserted
64
+ indexes_to_delete = [ ]
65
+ objects.each_with_index do |this_object, index|
66
+ if @unique_keys.has_key?( this_object )
67
+ indexes_to_delete.push( index )
68
+ else
69
+ @unique_keys[ this_object ] = true
70
+ end
71
+ end
72
+ indexes_to_delete.sort.reverse.each do |this_index|
73
+ objects.delete_at( this_index )
74
+ end
75
+
76
+ return nil if objects.empty?
77
+
78
+ return super
79
+
80
+ end
81
+
82
+ ##############
83
+ # collect! #
84
+ # map! #
85
+ ##############
86
+
87
+ def collect!
88
+
89
+ return to_enum unless block_given?
90
+
91
+ delete_indexes = [ ]
92
+ self.each_with_index do |this_object, index|
93
+ replacement_object = yield( this_object )
94
+ if @unique_keys.has_key?( replacement_object ) and replacement_object != this_object
95
+ delete_indexes.push( index )
96
+ else
97
+ self[ index ] = replacement_object
98
+ end
99
+ end
100
+
101
+ delete_indexes.sort.reverse.each do |this_index|
102
+ delete_at( this_index )
103
+ end
104
+
105
+ return self
106
+
107
+ end
108
+ alias_method :map!, :collect!
109
+
110
+ ##################################################################################################
111
+ private ######################################################################################
112
+ ##################################################################################################
113
+
114
+ #############################
115
+ # non_cascading_delete_at #
116
+ #############################
117
+
118
+ def non_cascading_delete_at( index )
119
+
120
+ object = super
121
+
122
+ @unique_keys.delete( object )
123
+
124
+ return object
125
+
126
+ end
127
+
128
+ ######################### Self-as-Sub Management for Parent Updates ############################
129
+
130
+ ########################################
131
+ # update_as_sub_array_for_parent_set #
132
+ ########################################
133
+
134
+ def update_as_sub_array_for_parent_set( index, object )
135
+
136
+ super unless @unique_keys.has_key?( object )
137
+
138
+ end
139
+
140
+ ###########################################
141
+ # update_as_sub_array_for_parent_insert #
142
+ ###########################################
143
+
144
+ def update_as_sub_array_for_parent_insert( index, *objects )
145
+
146
+ # new parent indexes have been inserted at index in parent
147
+
148
+ # get rid of objects already inserted
149
+ indexes_to_delete = [ ]
150
+ objects.each_with_index do |this_object, index|
151
+ if @unique_keys.has_key?( this_object )
152
+ indexes_to_delete.push( index )
153
+ else
154
+ @unique_keys[ this_object ] = true
155
+ end
156
+ end
157
+ indexes_to_delete.sort.reverse.each do |this_index|
158
+ objects.delete_at( this_index )
159
+ end
160
+ return false if objects.empty?
161
+
162
+ super
163
+
164
+ end
165
+
166
+ end