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 +10 -0
- data/Gemfile.lock +29 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +64 -0
- data/Rakefile +45 -0
- data/TODO +0 -0
- data/VERSION +1 -0
- data/init.rb +1 -0
- data/lib/modalsettings.rb +1 -0
- data/lib/settings.rb +111 -0
- data/test/helper.rb +18 -0
- data/test/test_settings.rb +473 -0
- metadata +143 -0
data/Gemfile
ADDED
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: []
|