modalsettings 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'modalsupport', '>= 0.8.1'
4
+
5
+ group :development do
6
+ gem "shoulda", ">= 0"
7
+ gem "rdoc", "~> 3.12"
8
+ gem "bundler", "~> 1"
9
+ gem "jeweler", "~> 1.8.3"
10
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,29 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.8.3)
6
+ bundler (~> 1.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ rdoc
10
+ json (1.6.6)
11
+ modalsupport (0.8.3)
12
+ rake (0.9.2.2)
13
+ rdoc (3.12)
14
+ json (~> 1.4)
15
+ shoulda (3.0.1)
16
+ shoulda-context (~> 1.0.0)
17
+ shoulda-matchers (~> 1.0.0)
18
+ shoulda-context (1.0.0)
19
+ shoulda-matchers (1.0.0)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ bundler (~> 1)
26
+ jeweler (~> 1.8.3)
27
+ modalsupport (>= 0.8.1)
28
+ rdoc (~> 3.12)
29
+ shoulda
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Javier Goizueta
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,64 @@
1
+ = ModalSettings
2
+
3
+ Settings container, supporting nested settings.
4
+
5
+ Properties can be set from a hash with either String or Symbol keys.
6
+
7
+ s = Settings[:a=>1, 'b'=>2]
8
+
9
+ Properties can be accessed as attributes or as indices (String or Symbol).
10
+
11
+ puts s.a
12
+ puts s[:a]
13
+ puts s['a']
14
+
15
+ Properties are writable
16
+
17
+ s.a = 100
18
+ s[:a] = 100
19
+ s['a'] = 100
20
+
21
+ Nested hashes are accessed as Settings too.
22
+
23
+ s = Setings[:a=>1, :email=>{:from=>'a', :to=>'b'}]
24
+ puts s.email.a
25
+
26
+ Can be converted to a Hash
27
+
28
+ puts s.to_h.inspect
29
+
30
+ Converts to YAML as a Hash
31
+
32
+ puts s.to_yaml
33
+
34
+ Undefined parameters can be read (and return nil)
35
+
36
+ puts s.x
37
+
38
+ Settings can be merged
39
+
40
+ s2 = s.merge(:z=>100)
41
+
42
+ Note that properties with names corresponding to Object methods cannot be accessed with the s.x syntax:
43
+
44
+ s = Settings[:object_id=>100]
45
+ puts s.object_id # this is not the setting!
46
+ puts s[:object_id] # => 100
47
+ s.object_id = 200 # this changes the setting
48
+ puts s[:object_id] # => 200
49
+
50
+ To know which current settings need s[] syntax use the collisions method:
51
+
52
+ s = Settings[:object_id=>1]
53
+ s.collisions # [:object_id]
54
+
55
+ To check for collisions recursively:
56
+
57
+ s = Settings[:object_id=>{:to_h=>1, :x=>2}]
58
+ s.collisions(true) # [:object_id, [:object_id, :to_h]]
59
+
60
+ == Copyright
61
+
62
+ Copyright (c) 2012 Javier Goizueta. See LICENSE.txt for
63
+ further details.
64
+
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "modalsettings"
18
+ gem.homepage = "http://github.com/jgoizueta/modalsettings"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Settings container}
21
+ gem.description = %Q{Settings container, supporting nested settings}
22
+ gem.email = "jgoizueta@gmail.com"
23
+ gem.authors = ["Javier Goizueta"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ task :default => :test
36
+
37
+ require 'rdoc/task'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "modalsettings #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/TODO ADDED
File without changes
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'settings.rb'
@@ -0,0 +1 @@
1
+ require 'settings'
data/lib/settings.rb ADDED
@@ -0,0 +1,111 @@
1
+ require 'rubygems'
2
+ require 'modalsupport' # requires modalsupport >= 0.8.1
3
+ require 'yaml'
4
+ require 'ostruct'
5
+ require 'erb'
6
+
7
+ # Settings container, supporting nested settings.
8
+ class Settings < OpenStruct
9
+
10
+ # This uses implementation details of OpenStruct (the @table instance variable) that could change
11
+ # in future releases of Ruby.
12
+
13
+ class << self
14
+ # Settings constructor. A hash is passed to define properties
15
+ #
16
+ # s = Settings[:x=>100, :y=>200]
17
+ #
18
+ def [](settings={})
19
+ ModalSupport.recursive_map(settings){|v| v.kind_of?(Hash) ? Settings.new(v) : v}
20
+ end
21
+
22
+ # Build a Settings from a YAML file defining a properties Hash. The YAML can include ERB macros.
23
+ # An optional second argument defines the name of an attribute to be merge into the top level.
24
+ def load(settings_filename, merge_key=nil)
25
+ properties = File.exists?(settings_filename) ? YAML.load(ERB.new(File.read(settings_filename)).result(binding)) : {}
26
+ s = Settings[properties]
27
+ if merge_key
28
+ merge_settings = s[merge_key]
29
+ s.merge! merge_settings if merge_settings && merge_settings.kind_of?(Settings)
30
+ end
31
+ s
32
+ end
33
+ end
34
+
35
+ # Read a property with Hash syntax (with either a String or Symbol property name)
36
+ def [](k)
37
+ @table[k.to_sym]
38
+ end
39
+
40
+ # Write a property with Hash syntax (with either a String or Symbol property name)
41
+ def []=(k,v)
42
+ @table[k.to_sym] = Settings[v]
43
+ end
44
+
45
+ def method_missing(mth, *args)
46
+ # property assignments convert Hashes to Settings
47
+ args = Settings[args] if mth.to_s[-1,1]=='='
48
+ super mth, *args
49
+ end
50
+
51
+ # Convert to a hash of properties indexed by symbolic property names. Nested Settings objects are also
52
+ # converted to hash.
53
+ def to_h
54
+ ModalSupport.recursive_map(self){|s| s.kind_of?(Settings) ? s.instance_variable_get(:@table) : s}
55
+ end
56
+
57
+ # A Settings object converts to YAML as a Hash.
58
+ def to_yaml
59
+ to_h.to_yaml
60
+ end
61
+
62
+ # Iterator of key-value pairs.
63
+ def each(&blk)
64
+ @table.each(&blk)
65
+ end
66
+
67
+ # Merge with another Settings or Hash object (deeply).
68
+ def merge(other)
69
+ dup.merge!(other)
70
+ end
71
+
72
+ # Merge with another Settings or Hash object mutator (deeply).
73
+ def merge!(other)
74
+ other.each do |k,v|
75
+ if self[k].kind_of?(Settings) && (v.kind_of?(Settings) || v.kind_of?(Hash))
76
+ self[k].merge! v
77
+ else
78
+ self[k] = v
79
+ end
80
+ end
81
+ self
82
+ end
83
+
84
+ # Deep copy (in relation to nested Settings; other non-inmediate values (e.g. arrays) are to cloned)
85
+ def dup
86
+ copy = super
87
+ copy.each do |k, v|
88
+ copy[k] = v.dup if v.kind_of?(Settings)
89
+ end
90
+ copy
91
+ end
92
+
93
+ # Keys that need [] syntax for access (because of collision with defined methods)
94
+ def collisions(recursive=false)
95
+ unless defined?(@@predefined_keys)
96
+ empty = Settings.new
97
+ # note that private & protected methods do not collide
98
+ @@predefined_keys = (empty.methods).map{|k| k.to_sym}
99
+ end
100
+ keys = @table.keys & @@predefined_keys
101
+ if recursive
102
+ @table.each_pair do |key, value|
103
+ if value.kind_of?(Settings)
104
+ keys += value.collisions(recursive).map{|k| k.kind_of?(Array) ? [key]+k : [key, k]}
105
+ end
106
+ end
107
+ end
108
+ keys
109
+ end
110
+
111
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'modalsettings'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,473 @@
1
+ require 'helper'
2
+
3
+ class SettingsTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @tmp_dir = File.join(File.dirname(__FILE__), "tmp")
7
+ FileUtils.mkdir_p @tmp_dir
8
+ end
9
+
10
+
11
+ def test_simple_settings
12
+ s = Settings[:a=>1, 'b'=>2, :x=>'xyz', :y=>[1,2,3]]
13
+ assert_equal 1, s.a
14
+ assert_equal 1, s[:a]
15
+ assert_equal 1, s['a']
16
+ assert_equal 2, s.b
17
+ assert_equal 2, s[:b]
18
+ assert_equal 2, s['b']
19
+ assert_equal 'xyz', s.x
20
+ assert_equal 'xyz', s[:x]
21
+ assert_equal 'xyz', s['x']
22
+ assert_equal [1,2,3], s.y
23
+ assert_equal [1,2,3], s[:y]
24
+ assert_equal [1,2,3], s['y']
25
+ assert_nil s.z
26
+ assert_nil s[:z]
27
+ assert_nil s['z']
28
+
29
+ s.a = 10
30
+ assert_equal 10, s.a
31
+ assert_equal 10, s[:a]
32
+ assert_equal 10, s['a']
33
+
34
+ end
35
+
36
+ def test_nested_settings
37
+ s = Settings[
38
+ :a=>1, 'b'=>2, :x=>'xyz', :y=>[1,2,3],
39
+ :z=>{
40
+ :a=>10, 'b'=>20, :x=>'rst', :y=>[10,20,30], :w=>{:a=>1000}
41
+ }
42
+ ]
43
+ assert_equal 1, s.a
44
+ assert_equal 1, s[:a]
45
+ assert_equal 1, s['a']
46
+ assert_equal 2, s.b
47
+ assert_equal 2, s[:b]
48
+ assert_equal 2, s['b']
49
+ assert_equal 'xyz', s.x
50
+ assert_equal 'xyz', s[:x]
51
+ assert_equal 'xyz', s['x']
52
+ assert_equal [1,2,3], s.y
53
+ assert_equal [1,2,3], s[:y]
54
+ assert_equal [1,2,3], s['y']
55
+
56
+ assert_equal 10, s.z.a
57
+ assert_equal 10, s[:z].a
58
+ assert_equal 10, s['z'].a
59
+ assert_equal 10, s.z[:a]
60
+ assert_equal 10, s[:z][:a]
61
+ assert_equal 10, s['z'][:a]
62
+ assert_equal 10, s.z['a']
63
+ assert_equal 10, s[:z]['a']
64
+ assert_equal 10, s['z']['a']
65
+ assert_equal 20, s.z.b
66
+ assert_equal 20, s.z[:b]
67
+ assert_equal 20, s.z['b']
68
+ assert_equal 'rst', s.z.x
69
+ assert_equal 'rst', s.z[:x]
70
+ assert_equal 'rst', s.z['x']
71
+ assert_equal [10,20,30], s.z.y
72
+ assert_equal [10,20,30], s.z[:y]
73
+ assert_equal [10,20,30], s.z['y']
74
+ assert_nil s.z.z
75
+ assert_nil s.z[:z]
76
+ assert_nil s.z['z']
77
+ assert_equal 1000, s.z.w.a
78
+ assert_equal 1000, s[:z].w.a
79
+ assert_equal 1000, s['z'].w.a
80
+ assert_equal 1000, s.z[:w].a
81
+ assert_equal 1000, s.z['w'].a
82
+ end
83
+
84
+ def test_assignment
85
+ s = Settings[:a=>1, 'b'=>2, :x=>'xyz', :y=>[1,2,3], :z=>{:a=>100, :b=>200}]
86
+ assert_equal 1, s.a
87
+ assert_equal 1, s[:a]
88
+ assert_equal 1, s['a']
89
+ assert_equal 100, s.z.a
90
+ assert_equal 100, s.z[:a]
91
+ assert_equal 100, s.z['a']
92
+ s.a = 10
93
+ assert_equal 10, s.a
94
+ assert_equal 10, s[:a]
95
+ assert_equal 10, s['a']
96
+ s[:a] = 11
97
+ assert_equal 11, s.a
98
+ assert_equal 11, s[:a]
99
+ assert_equal 11, s['a']
100
+ s['a'] = 12
101
+ assert_equal 12, s.a
102
+ assert_equal 12, s[:a]
103
+ assert_equal 12, s['a']
104
+ s.z.a = 101
105
+ assert_equal 101, s.z.a
106
+ assert_equal 101, s.z[:a]
107
+ assert_equal 101, s.z['a']
108
+ s.z[:a] = 102
109
+ assert_equal 102, s.z.a
110
+ assert_equal 102, s.z[:a]
111
+ assert_equal 102, s.z['a']
112
+ s.z['a'] = 103
113
+ assert_equal 103, s.z.a
114
+ assert_equal 103, s.z[:a]
115
+ assert_equal 103, s.z['a']
116
+ end
117
+
118
+ def test_settings_merge
119
+ s = Settings[:a=>1, 'b'=>2, :x=>'xyz', :y=>[1,2,3]]
120
+ s.merge! :a=>10, :z=>100
121
+ assert_equal 10, s.a
122
+ assert_equal 2, s.b
123
+ assert_equal 100, s.z
124
+
125
+ s = Settings[:a=>1, 'b'=>2, :x=>'xyz', :y=>[1,2,3]]
126
+ s.merge! Settings[:a=>10, :z=>100]
127
+ assert_equal 10, s.a
128
+ assert_equal 2, s.b
129
+ assert_equal 100, s.z
130
+ end
131
+
132
+ def test_yaml_load
133
+ File.open(fn=File.join(@tmp_dir, 'settings_test.yml'), 'w') do |file|
134
+ file.write({:a=>1, 'b'=>2, :x=>'xyz', :y=>[1,2,3]}.to_yaml)
135
+ end
136
+ s = Settings.load(fn)
137
+ assert_equal 1, s.a
138
+ assert_equal 1, s[:a]
139
+ assert_equal 1, s['a']
140
+ assert_equal 2, s.b
141
+ assert_equal 2, s[:b]
142
+ assert_equal 2, s['b']
143
+ assert_equal 'xyz', s.x
144
+ assert_equal 'xyz', s[:x]
145
+ assert_equal 'xyz', s['x']
146
+ assert_equal [1,2,3], s.y
147
+ assert_equal [1,2,3], s[:y]
148
+ assert_equal [1,2,3], s['y']
149
+ assert_nil s.z
150
+ assert_nil s[:z]
151
+ assert_nil s['z']
152
+ end
153
+
154
+ def test_yaml_erb_load
155
+ yml = %{
156
+ :a: <%= 30/3 %>
157
+ b: <%= 1+1 %>
158
+ :x: xyz
159
+ :y: <%= (1..3).to_a.inspect %>
160
+ }
161
+ File.open(fn=File.join(@tmp_dir, 'settings_test.yml'), 'w') do |file|
162
+ file.write yml
163
+ end
164
+ s = Settings.load(fn)
165
+ assert_equal 10, s.a
166
+ assert_equal 10, s[:a]
167
+ assert_equal 10, s['a']
168
+ assert_equal 2, s.b
169
+ assert_equal 2, s[:b]
170
+ assert_equal 2, s['b']
171
+ assert_equal 'xyz', s.x
172
+ assert_equal 'xyz', s[:x]
173
+ assert_equal 'xyz', s['x']
174
+ assert_equal [1,2,3], s.y
175
+ assert_equal [1,2,3], s[:y]
176
+ assert_equal [1,2,3], s['y']
177
+ assert_nil s.z
178
+ assert_nil s[:z]
179
+ assert_nil s['z']
180
+ end
181
+
182
+ def test_rails_env_merge
183
+ yml = %{
184
+ :a: <%= 30/3 %>
185
+ b: <%= 1+1 %>
186
+ :x: xyz
187
+ :y: <%= (1..3).to_a.inspect %>
188
+ test:
189
+ a: 100
190
+ z: 200
191
+ }
192
+ File.open(fn=File.join(@tmp_dir, 'settings_test.yml'), 'w') do |file|
193
+ file.write yml
194
+ end
195
+ s = Settings.load(fn, 'test')
196
+ assert_equal 100, s.a
197
+ assert_equal 100, s[:a]
198
+ assert_equal 100, s['a']
199
+ assert_equal 2, s.b
200
+ assert_equal 2, s[:b]
201
+ assert_equal 2, s['b']
202
+ assert_equal 'xyz', s.x
203
+ assert_equal 'xyz', s[:x]
204
+ assert_equal 'xyz', s['x']
205
+ assert_equal [1,2,3], s.y
206
+ assert_equal [1,2,3], s[:y]
207
+ assert_equal [1,2,3], s['y']
208
+ assert_equal 200, s.z
209
+ assert_equal 200, s[:z]
210
+ assert_equal 200, s['z']
211
+ end
212
+
213
+ def test_to_hash
214
+ s = Settings[:a=>1, 'b'=>2]
215
+ h = s.to_h
216
+ assert h.kind_of?(Hash)
217
+ assert_equal 1, h[:a]
218
+ assert_equal 2, h[:b]
219
+ assert_equal [:a,:b], h.keys.sort_by(&:to_s)
220
+ end
221
+
222
+ def test_to_yaml
223
+ s = Settings[:a=>1, 'b'=>2]
224
+ h = YAML.load(s.to_yaml)
225
+ assert h.kind_of?(Hash)
226
+ assert_equal 1, h[:a]
227
+ assert_equal 2, h[:b]
228
+ assert_equal [:a,:b], h.keys.sort_by(&:to_s)
229
+ end
230
+
231
+ def test_assign_hash
232
+ s = Settings[
233
+ :a=>1, 'b'=>2, :x=>'xyz', :y=>[1,2,3],
234
+ ]
235
+ s.z = { :a=>10, 'b'=>20, :x=>'rst', :y=>[10,20,30], :w=>{:a=>1000} }
236
+
237
+ assert_equal 1, s.a
238
+ assert_equal 1, s[:a]
239
+ assert_equal 1, s['a']
240
+ assert_equal 2, s.b
241
+ assert_equal 2, s[:b]
242
+ assert_equal 2, s['b']
243
+ assert_equal 'xyz', s.x
244
+ assert_equal 'xyz', s[:x]
245
+ assert_equal 'xyz', s['x']
246
+ assert_equal [1,2,3], s.y
247
+ assert_equal [1,2,3], s[:y]
248
+ assert_equal [1,2,3], s['y']
249
+
250
+ assert_equal 10, s.z.a
251
+ assert_equal 10, s[:z].a
252
+ assert_equal 10, s['z'].a
253
+ assert_equal 10, s.z[:a]
254
+ assert_equal 10, s[:z][:a]
255
+ assert_equal 10, s['z'][:a]
256
+ assert_equal 10, s.z['a']
257
+ assert_equal 10, s[:z]['a']
258
+ assert_equal 10, s['z']['a']
259
+ assert_equal 20, s.z.b
260
+ assert_equal 20, s.z[:b]
261
+ assert_equal 20, s.z['b']
262
+ assert_equal 'rst', s.z.x
263
+ assert_equal 'rst', s.z[:x]
264
+ assert_equal 'rst', s.z['x']
265
+ assert_equal [10,20,30], s.z.y
266
+ assert_equal [10,20,30], s.z[:y]
267
+ assert_equal [10,20,30], s.z['y']
268
+ assert_nil s.z.z
269
+ assert_nil s.z[:z]
270
+ assert_nil s.z['z']
271
+ assert_equal 1000, s.z.w.a
272
+ assert_equal 1000, s[:z].w.a
273
+ assert_equal 1000, s['z'].w.a
274
+ assert_equal 1000, s.z[:w].a
275
+ assert_equal 1000, s.z['w'].a
276
+
277
+ s = Settings[
278
+ :a=>1, 'b'=>2, :x=>'xyz', :y=>[1,2,3],
279
+ ]
280
+ s['z'] = { :a=>10, 'b'=>20, :x=>'rst', :y=>[10,20,30], :w=>{:a=>1000} }
281
+
282
+ assert_equal 1, s.a
283
+ assert_equal 1, s[:a]
284
+ assert_equal 1, s['a']
285
+ assert_equal 2, s.b
286
+ assert_equal 2, s[:b]
287
+ assert_equal 2, s['b']
288
+ assert_equal 'xyz', s.x
289
+ assert_equal 'xyz', s[:x]
290
+ assert_equal 'xyz', s['x']
291
+ assert_equal [1,2,3], s.y
292
+ assert_equal [1,2,3], s[:y]
293
+ assert_equal [1,2,3], s['y']
294
+
295
+ assert_equal 10, s.z.a
296
+ assert_equal 10, s[:z].a
297
+ assert_equal 10, s['z'].a
298
+ assert_equal 10, s.z[:a]
299
+ assert_equal 10, s[:z][:a]
300
+ assert_equal 10, s['z'][:a]
301
+ assert_equal 10, s.z['a']
302
+ assert_equal 10, s[:z]['a']
303
+ assert_equal 10, s['z']['a']
304
+ assert_equal 20, s.z.b
305
+ assert_equal 20, s.z[:b]
306
+ assert_equal 20, s.z['b']
307
+ assert_equal 'rst', s.z.x
308
+ assert_equal 'rst', s.z[:x]
309
+ assert_equal 'rst', s.z['x']
310
+ assert_equal [10,20,30], s.z.y
311
+ assert_equal [10,20,30], s.z[:y]
312
+ assert_equal [10,20,30], s.z['y']
313
+ assert_nil s.z.z
314
+ assert_nil s.z[:z]
315
+ assert_nil s.z['z']
316
+ assert_equal 1000, s.z.w.a
317
+ assert_equal 1000, s[:z].w.a
318
+ assert_equal 1000, s['z'].w.a
319
+ assert_equal 1000, s.z[:w].a
320
+ assert_equal 1000, s.z['w'].a
321
+
322
+ s = Settings[
323
+ :a=>1, 'b'=>2, :x=>'xyz', :y=>[1,2,3],
324
+ ]
325
+ s[:z] = { :a=>10, 'b'=>20, :x=>'rst', :y=>[10,20,30], :w=>{:a=>1000} }
326
+
327
+ assert_equal 1, s.a
328
+ assert_equal 1, s[:a]
329
+ assert_equal 1, s['a']
330
+ assert_equal 2, s.b
331
+ assert_equal 2, s[:b]
332
+ assert_equal 2, s['b']
333
+ assert_equal 'xyz', s.x
334
+ assert_equal 'xyz', s[:x]
335
+ assert_equal 'xyz', s['x']
336
+ assert_equal [1,2,3], s.y
337
+ assert_equal [1,2,3], s[:y]
338
+ assert_equal [1,2,3], s['y']
339
+
340
+ assert_equal 10, s.z.a
341
+ assert_equal 10, s[:z].a
342
+ assert_equal 10, s['z'].a
343
+ assert_equal 10, s.z[:a]
344
+ assert_equal 10, s[:z][:a]
345
+ assert_equal 10, s['z'][:a]
346
+ assert_equal 10, s.z['a']
347
+ assert_equal 10, s[:z]['a']
348
+ assert_equal 10, s['z']['a']
349
+ assert_equal 20, s.z.b
350
+ assert_equal 20, s.z[:b]
351
+ assert_equal 20, s.z['b']
352
+ assert_equal 'rst', s.z.x
353
+ assert_equal 'rst', s.z[:x]
354
+ assert_equal 'rst', s.z['x']
355
+ assert_equal [10,20,30], s.z.y
356
+ assert_equal [10,20,30], s.z[:y]
357
+ assert_equal [10,20,30], s.z['y']
358
+ assert_nil s.z.z
359
+ assert_nil s.z[:z]
360
+ assert_nil s.z['z']
361
+ assert_equal 1000, s.z.w.a
362
+ assert_equal 1000, s[:z].w.a
363
+ assert_equal 1000, s['z'].w.a
364
+ assert_equal 1000, s.z[:w].a
365
+ assert_equal 1000, s.z['w'].a
366
+ end
367
+
368
+ def test_collisions
369
+ s = Settings[:a => 10, :merge => 100]
370
+ assert_equal [:merge], s.collisions
371
+ assert_equal 100, s[:merge]
372
+ s[:merge] = 200
373
+ assert_equal 200, s['merge']
374
+ end
375
+
376
+ def test_recursive_collisions
377
+ s = Settings[
378
+ :a => 10, :merge => 100,
379
+ :x=>{:a=>100, :b=>1},
380
+ :y=>{:a=>100, :to_h=>200},
381
+ :z=>{:a=>200, :w=>{:b=>1, :to_yaml=>300}}
382
+ ]
383
+ assert_equal [:merge], s.collisions
384
+ assert_equal [:merge, [:y, :to_h], [:z, :w, :to_yaml]], s.collisions(true).sort_by{|k| Array(k).size}
385
+ s = Settings[
386
+ :a => 10, :merge => {:to_h=>200}
387
+ ]
388
+ assert_equal [:merge, [:merge, :to_h]], s.collisions(true).sort_by{|k| Array(k).size}
389
+ end
390
+
391
+ def test_deep_copy
392
+ s = Settings[
393
+ :a=>10,
394
+ :b=>{
395
+ :c=>20,
396
+ :d=>{
397
+ :e=>30,
398
+ :f=> {
399
+ :g=>40
400
+ }
401
+ }
402
+ }
403
+ ]
404
+ d = s.dup
405
+ assert_equal 10, d.a
406
+ assert_equal 20, d.b.c
407
+ assert_equal 30, d.b.d.e
408
+ assert_equal 40, d.b.d.f.g
409
+ s.a = 20
410
+ s.b.c = 30
411
+ s.b.d.e = 40
412
+ s.b.d.f.g = 50
413
+ assert_equal 20, s.a
414
+ assert_equal 30, s.b.c
415
+ assert_equal 40, s.b.d.e
416
+ assert_equal 50, s.b.d.f.g
417
+ assert_equal 10, d.a
418
+ assert_equal 20, d.b.c
419
+ assert_equal 30, d.b.d.e
420
+ assert_equal 40, d.b.d.f.g
421
+ end
422
+
423
+ def test_deep_merge
424
+ s = Settings[
425
+ :a=>10,
426
+ :b=>{
427
+ :c=>20,
428
+ :d=>{
429
+ :e=>30,
430
+ :f=> {
431
+ :g=>40
432
+ }
433
+ }
434
+ }
435
+ ]
436
+ s.merge! :b=>{:cc=>21, :d=>{:ee=>31, :f=>{:g=>400}}}
437
+ assert_equal 10, s.a
438
+ assert_equal 20, s.b.c
439
+ assert_equal 21, s.b.cc
440
+ assert_equal 30, s.b.d.e
441
+ assert_equal 31, s.b.d.ee
442
+ assert_equal 400, s.b.d.f.g
443
+ end
444
+
445
+ def test_deep_merge_and_copy
446
+ s = Settings[
447
+ :a=>10,
448
+ :b=>{
449
+ :c=>20,
450
+ :d=>{
451
+ :e=>30,
452
+ :f=> {
453
+ :g=>40
454
+ }
455
+ }
456
+ }
457
+ ]
458
+ d = s.merge :b=>{:cc=>21, :d=>{:ee=>31, :f=>{:g=>400}}}
459
+ assert_equal 10, d.a
460
+ assert_equal 20, d.b.c
461
+ assert_equal 21, d.b.cc
462
+ assert_equal 30, d.b.d.e
463
+ assert_equal 31, d.b.d.ee
464
+ assert_equal 400, d.b.d.f.g
465
+ assert_equal 10, s.a
466
+ assert_equal 20, s.b.c
467
+ assert_equal 30, s.b.d.e
468
+ assert_equal 40, s.b.d.f.g
469
+ assert_nil s.b.cc
470
+ assert_nil s.b.d.ee
471
+ end
472
+
473
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: modalsettings
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Javier Goizueta
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: modalsupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.8.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.8.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: shoulda
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rdoc
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '3.12'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '3.12'
62
+ - !ruby/object:Gem::Dependency
63
+ name: bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '1'
78
+ - !ruby/object:Gem::Dependency
79
+ name: jeweler
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 1.8.3
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 1.8.3
94
+ description: Settings container, supporting nested settings
95
+ email: jgoizueta@gmail.com
96
+ executables: []
97
+ extensions: []
98
+ extra_rdoc_files:
99
+ - LICENSE.txt
100
+ - README.rdoc
101
+ - TODO
102
+ files:
103
+ - Gemfile
104
+ - Gemfile.lock
105
+ - LICENSE.txt
106
+ - README.rdoc
107
+ - Rakefile
108
+ - TODO
109
+ - VERSION
110
+ - init.rb
111
+ - lib/modalsettings.rb
112
+ - lib/settings.rb
113
+ - test/helper.rb
114
+ - test/test_settings.rb
115
+ homepage: http://github.com/jgoizueta/modalsettings
116
+ licenses:
117
+ - MIT
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ segments:
129
+ - 0
130
+ hash: 2355315678743574084
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ! '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 1.8.21
140
+ signing_key:
141
+ specification_version: 3
142
+ summary: Settings container
143
+ test_files: []