super_stack 0.2.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f195f8d4912d140d7a3932c3d24d1a2ed4489452
4
- data.tar.gz: 8eded758dd34c83dd1ded7cbf7209919d372a8ec
3
+ metadata.gz: 54cbe4ddd3ce5e7164c09042f75841a327cd1a1c
4
+ data.tar.gz: a01f72c6e8ab135e13cf12d0f9662e1bfa6c75fc
5
5
  SHA512:
6
- metadata.gz: f6edf0b4ccdabef1b6cddf821f5db017bdb52e306cde0f01e5c88d5f2799b5f8ce40743aa8ecdda4375b24a1095c03519f1415332a345d8cbcede947fcd2c141
7
- data.tar.gz: 75881f18d92264c18dc6f6396ec703fb7a2289cd866f220bb39c013b141024acfed260890eb59c752144218ed9212065fa59cca3dea2d6196f27f2b9f0add0a5
6
+ metadata.gz: 771fcfb537611679e55a5fc36c14755ee276f71f3261190245b9299e54ec1f7fa460676f1e5a80056aa673ae9fcc9e9ab438850dd8a02c88bd3fc3aa4f64a83f
7
+ data.tar.gz: b9a855e2c8e20d9e15181ceb843da436c6b70175f96ed1deb8c0c088a67a65b6024e943e7eb265a96055ec86601195893bb262c13c68a0d81a7f5b1b66a7b64a
data/README.md CHANGED
@@ -63,11 +63,11 @@ the name conflicts with another layer already handled by the manager**.
63
63
  You can notice by the way that it gives a third way to create a layer from a hash, as when adding a hash to a manager,
64
64
  it automatically adds the `SuperStack::LayerWrapper` module to the hash.
65
65
 
66
- Layers can be populated from a file anytime using the `load` method:
66
+ Layers can be populated from a yaml file anytime using the `load` method:
67
67
 
68
68
  ```ruby
69
69
  layer = SuperStack::Layer.new.load 'a_file_somewhere'
70
- # Once loaded you can get the file name used to load the layed anytime
70
+ # Once loaded you can get the file name used to load the layer anytime
71
71
  puts layer.file_name
72
72
  # And you can load or reload the layer
73
73
  layer.has_file? # => true
@@ -89,6 +89,13 @@ manager << layer2
89
89
  manager.reload_layers
90
90
  ```
91
91
 
92
+ Layers can of course be:
93
+ * removed (using the manager's `remove_layer(layer_or_layer_name)` method).
94
+ * Enabled or disabled (using the manager's `disable_layer(layer_or_layer_name)` and `enable_layer(layer_or_layer_name)`
95
+ methods).
96
+
97
+ Of course these methods have an impact on the `write_layer` if applied to it. Check tests (run `rspec -f d`) for
98
+ more info.
92
99
 
93
100
  ### Merge policies
94
101
 
@@ -8,7 +8,8 @@ module SuperStack
8
8
 
9
9
  DEFAULT_LAYER_NAME = 'Unknown layer'
10
10
 
11
- attr_reader :file_name, :priority, :manager
11
+ attr_reader :file_name, :priority, :manager, :disabled
12
+ alias_method :disabled?, :disabled
12
13
 
13
14
  def priority=(priority)
14
15
  raise 'invalid priority' unless priority.is_a? Numeric
@@ -16,14 +16,10 @@ module SuperStack
16
16
  end
17
17
 
18
18
  def write_layer=(layer_or_layer_name)
19
- if layer_or_layer_name.is_a?(String) || layer_or_layer_name.is_a?(Symbol)
20
- layer_name = layer_or_layer_name.to_s
21
- raise 'Invalid write layer' unless layers.keys.include? layer_name
22
- layer_or_layer_name = layers[layer_name]
23
- end
24
- # At that point layer_or_layer_name can only contain a layer object
25
- raise 'Invalid write layer' unless layers.values.include? layer_or_layer_name
26
- @write_layer = layer_or_layer_name
19
+ layer = get_existing_layer layer_or_layer_name, 'Invalid write layer specified'
20
+ raise 'Cannot use a disabled layer as write layer' if layer.disabled?
21
+ @previous_write_layer = nil
22
+ @write_layer = layer
27
23
  end
28
24
 
29
25
  def []=(key,value)
@@ -37,8 +33,12 @@ module SuperStack
37
33
  return layers[0] if layers.count == 1
38
34
  first_layer = layers.shift
39
35
  res = layers.inject(first_layer) do |stack, layer|
40
- policy_to_apply = layer.merge_policy.nil? ? default_merge_policy : layer.merge_policy
41
- policy_to_apply.merge stack, layer
36
+ if layer.disabled?
37
+ stack
38
+ else
39
+ policy_to_apply = layer.merge_policy.nil? ? default_merge_policy : layer.merge_policy
40
+ policy_to_apply.merge stack, layer
41
+ end
42
42
  end
43
43
  if filter.nil?
44
44
  # Trick to return a bare hash
@@ -62,11 +62,35 @@ module SuperStack
62
62
  end
63
63
  set_valid_name_for layer if layers.keys.include? layer.name
64
64
  layer.priority = get_unused_priority if layer.priority.nil?
65
+ raise 'This layer already belongs to a manager' unless layer.manager.nil?
65
66
  layers[layer.name] = layer
66
67
  layer.instance_variable_set :@manager, self
67
68
  layer.managed if layer.respond_to? :managed
68
69
  end
69
70
 
71
+ def remove_layer(layer_or_layer_name)
72
+ layer = get_existing_layer layer_or_layer_name, 'Cannot remove unmanaged layer'
73
+ layer_name = layer.name
74
+ @write_layer = nil if layer == write_layer
75
+ layer.instance_variable_set :@manager, nil
76
+ layers.delete layer_name
77
+ end
78
+
79
+ def disable_layer(layer_or_layer_name)
80
+ layer = get_existing_layer layer_or_layer_name, 'Cannot disable unmanaged layer'
81
+ if layer == write_layer
82
+ @previous_write_layer = write_layer
83
+ @write_layer = nil
84
+ end
85
+ layer.instance_variable_set :@disabled, true
86
+ end
87
+
88
+ def enable_layer(layer_or_layer_name)
89
+ layer = get_existing_layer layer_or_layer_name, 'Cannot enable unmanaged layer'
90
+ layer.instance_variable_set :@disabled, false
91
+ @write_layer = @previous_write_layer if layer == @previous_write_layer
92
+ end
93
+
70
94
  def <<(layer)
71
95
  add_layer layer
72
96
  end
@@ -77,6 +101,15 @@ module SuperStack
77
101
 
78
102
  private
79
103
 
104
+ def get_existing_layer(layer_or_layer_name, error_message)
105
+ layer_name = layer_or_layer_name.to_s if layer_or_layer_name.is_a? Symbol
106
+ layer_name = layer_or_layer_name if layer_or_layer_name.is_a? String
107
+ layer = layers[layer_name] unless layer_name.nil?
108
+ layer = layer_or_layer_name if layer_or_layer_name.class.included_modules.include? SuperStack::LayerWrapper
109
+ raise error_message if layer.nil?
110
+ layer
111
+ end
112
+
80
113
  def get_unused_priority
81
114
  ordered = self.to_a
82
115
  return DEFAULT_PRIORITY_INTERVAL if ordered.empty?
@@ -85,6 +118,7 @@ module SuperStack
85
118
 
86
119
  def set_valid_name_for(layer)
87
120
  name_pattern = /^(?<layer_name>.+) #(?<number>\d+)\s*$/
121
+
88
122
  while layers.keys.include? layer.name
89
123
  layer.name = "#{layer.name} #1" unless layer.name =~ name_pattern
90
124
  layer.name.match(name_pattern) do |md|
@@ -1,3 +1,3 @@
1
1
  module SuperStack
2
- VERSION = '0.2.5'
2
+ VERSION = '0.3.0'
3
3
  end
data/spec/manager_spec.rb CHANGED
@@ -13,6 +13,11 @@ describe SuperStack::Manager do
13
13
  layer
14
14
  }
15
15
  end
16
+ let(:override) {
17
+ override = SuperStack::Layer.new
18
+ override.name = :override
19
+ override
20
+ }
16
21
 
17
22
 
18
23
  it 'should contain layers' do
@@ -71,16 +76,6 @@ describe SuperStack::Manager do
71
76
  expect(subject.layers.keys[1] == "#{SuperStack::Layer::DEFAULT_LAYER_NAME} #2").to be_truthy
72
77
  end
73
78
 
74
- it 'should allow the same layer to be added multiple times, automatically changing names' do
75
- expect {subject.add_layer(layer1) }.not_to raise_error
76
- expect {subject.add_layer(layer1) }.not_to raise_error
77
- expect {subject.add_layer(layer1) }.not_to raise_error
78
- expect(subject.layers.keys.count == 3).to be_truthy
79
- expect(subject.layers.keys[0] == 'layer1').to be_truthy
80
- expect(subject.layers.keys[1] == 'layer1 #2').to be_truthy
81
- expect(subject.layers.keys[2] == 'layer1 #3').to be_truthy
82
- end
83
-
84
79
  it 'should allow to reload all layers at once' do
85
80
  subject.add_layer layer1
86
81
  subject << {bar: :foo}
@@ -95,47 +90,53 @@ describe SuperStack::Manager do
95
90
  expect(subject[:bar] == :foo).to be_truthy
96
91
  end
97
92
 
98
- it 'should be possible to specify a write layer using its name or itself' do
99
- override = SuperStack::Layer.new
100
- override.name = :override
101
- subject << override
102
- subject << layer1
103
- expect {subject.write_layer = :override}.not_to raise_error
104
- expect {subject.write_layer = 'override'}.not_to raise_error
105
- expect {subject.write_layer = override}.not_to raise_error
106
- end
107
-
108
- it 'should not be possible to modify if no write layer has been specified' do
93
+ it 'should not be possible to modify the manager if no write layer has been specified' do
109
94
  subject << layer1
110
95
  subject << layer2
111
96
  expect {subject[:foo] = :bar}.to raise_error
112
97
  end
113
98
 
114
- it 'should push all modifications to the write layer' do
115
- override = SuperStack::Layer.new
116
- override.name = :override
117
- subject << override
118
- subject << layer1
119
- subject.write_layer = override
120
- expect {subject[:foo] = :bar}.not_to raise_error
121
- expect(subject.layers['override'][:foo] == :bar).to be_truthy
122
- expect(subject[:foo] == :bar).to be_truthy
123
- end
99
+ context 'when specifying a write layer' do
124
100
 
101
+ it 'should be possible using its name or itself' do
102
+ subject << override
103
+ subject << layer1
104
+ expect {subject.write_layer = :override}.not_to raise_error
105
+ expect {subject.write_layer = 'override'}.not_to raise_error
106
+ expect {subject.write_layer = override}.not_to raise_error
107
+ end
108
+
109
+ it 'should push all modifications to the write layer' do
110
+ subject << override
111
+ subject << layer1
112
+ subject.write_layer = override
113
+ expect {subject[:foo] = :bar}.not_to raise_error
114
+ expect(subject.layers['override'][:foo] == :bar).to be_truthy
115
+ expect(subject[:foo] == :bar).to be_truthy
116
+ end
117
+
118
+
119
+ it 'should be possible to clear modifications' do
120
+ subject << layer1
121
+ subject << override
122
+ subject.write_layer = override
123
+ subject[:something_modified] = :modified
124
+ expect(subject[:something_modified]).not_to be_nil
125
+ subject.reset
126
+ expect(subject[:something_modified]).to be_nil
127
+ end
128
+
129
+ it 'should not be possible to specify a disabled layer' do
130
+ subject << override
131
+ subject.write_layer = override
132
+ subject.disable_layer override
133
+ expect {subject.write_layer = override}.to raise_error
134
+ end
125
135
 
126
- it 'should be possible to clear modifications' do
127
- subject << layer1
128
- override = SuperStack::Layer.new
129
- override.name = :override
130
- subject << override
131
- subject.write_layer = override
132
- subject[:something_modified] = :modified
133
- expect(subject[:something_modified]).not_to be_nil
134
- subject.reset
135
- expect(subject[:something_modified]).to be_nil
136
136
  end
137
137
 
138
138
 
139
+
139
140
  SuperStack::MergePolicies.list.each do |policy|
140
141
  it "should provide a merged view of the layers according to the merge policy: #{policy}" do
141
142
  subject.add_layer layer1
@@ -164,4 +165,114 @@ describe SuperStack::Manager do
164
165
 
165
166
  end
166
167
 
168
+ context 'when removing a layer' do
169
+
170
+ subject {
171
+ s = SuperStack::Manager.new
172
+ s.add_layer layer1
173
+ s.add_layer layer2
174
+ s.add_layer layer3
175
+ s.add_layer layer4
176
+ s
177
+ }
178
+
179
+
180
+ it 'should not accept an incorrect layer' do
181
+ expect {subject.remove_layer :layer12}.to raise_error
182
+ expect {subject.remove_layer nil}.to raise_error
183
+ end
184
+
185
+ it 'should accept a symbol' do
186
+ expect {subject.remove_layer :layer3}.not_to raise_error
187
+ end
188
+ it 'should accept a string' do
189
+ expect {subject.remove_layer 'layer3'}.not_to raise_error
190
+ end
191
+ it 'should accept a layer itself' do
192
+ expect {subject.remove_layer layer3}.not_to raise_error
193
+ end
194
+ it 'should not manage the layer anymore' do
195
+ subject.remove_layer :layer3
196
+ expect(layer3.manager).to be_nil
197
+ end
198
+
199
+ it 'should remain consistent in terms of merged view' do
200
+ subject.remove_layer :layer3
201
+ expect(subject[:from_layer_3]).to be_nil
202
+ expect(subject[:from_layer_1]).not_to be_nil
203
+ expect(subject[:from_layer_2]).not_to be_nil
204
+ expect(subject[:from_layer_4]).not_to be_nil
205
+ end
206
+
207
+ it 'should remain consistent regarding the write level' do
208
+ subject.write_layer = :layer3
209
+ expect(subject.write_layer == layer3).to be_truthy
210
+ subject[:foo] = :bar
211
+ expect(layer3[:foo] == :bar).to be_truthy
212
+ subject.remove_layer :layer3
213
+ expect(subject[:foo] == :bar).to be_falsey
214
+ expect(subject.write_layer).to be_nil
215
+ end
216
+
217
+ end
218
+
219
+ context 'when disabling a layer' do
220
+
221
+ subject {
222
+ s = SuperStack::Manager.new
223
+ s.add_layer layer1
224
+ s.add_layer layer2
225
+ s.add_layer layer3
226
+ s.add_layer layer4
227
+ s
228
+ }
229
+
230
+ it 'should not been taken in account in the merge' do
231
+ subject.disable_layer :layer3
232
+ expect(subject[:from_layer_3]).to be_nil
233
+ expect(subject[:from_layer_1]).not_to be_nil
234
+ expect(subject[:from_layer_2]).not_to be_nil
235
+ expect(subject[:from_layer_4]).not_to be_nil
236
+ end
237
+
238
+ it 'could be reactivated' do
239
+ subject.disable_layer :layer3
240
+ subject.enable_layer :layer3
241
+ expect(subject[:from_layer_3]).not_to be_nil
242
+ expect(subject[:from_layer_1]).not_to be_nil
243
+ expect(subject[:from_layer_2]).not_to be_nil
244
+ expect(subject[:from_layer_4]).not_to be_nil
245
+ end
246
+
247
+ context 'when enabling/disabling a layer which is the write layer' do
248
+ subject {
249
+ s = SuperStack::Manager.new
250
+ s.add_layer layer1
251
+ s.add_layer layer2
252
+ s.add_layer layer3
253
+ s.add_layer layer4
254
+ s.write_layer = :layer3
255
+ s
256
+ }
257
+ it 'should restore it as the write layer if re-enabled' do
258
+ subject.disable_layer :layer3
259
+ expect(subject.write_layer).to be_nil
260
+ subject.enable_layer :layer3
261
+ expect(subject.write_layer).to be layer3
262
+ expect {subject[:foo] = :bar}.not_to raise_error
263
+ end
264
+
265
+ it 'should not restore it as the write layer if another write layer has been set in between' do
266
+ subject.disable_layer :layer3
267
+ expect(subject.write_layer).to be_nil
268
+ subject.write_layer = :layer2
269
+ subject.enable_layer :layer3
270
+ expect(subject.write_layer).to be layer2
271
+ expect {subject[:foo] = :bar}.not_to raise_error
272
+ end
273
+ end
274
+
275
+
276
+ end
277
+
167
278
  end
data/super_stack.gemspec CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency 'pry'
26
26
  spec.add_development_dependency 'rspec', '~> 3.0'
27
27
 
28
- spec.add_dependency 'deep_merge'
28
+ spec.add_dependency 'deep_merge', '~> 1.0'
29
29
 
30
30
 
31
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: super_stack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Laurent B.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-24 00:00:00.000000000 Z
11
+ date: 2015-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: deep_merge
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ~>
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '1.0'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ~>
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '1.0'
83
83
  description: The purpose of this gem is to provide a simple way to manage the merge
84
84
  of different hashes (layers) according to priority and several merge policies.
85
85
  email: