zen_config 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in zen_config.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Gauthier Delacroix
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,116 @@
1
+ # ZenConfig
2
+
3
+ ZenConfig is an attempt to rewrite Zend Framework's Zend_Config for Ruby.
4
+
5
+ It allows easy management of configuration objects and files.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'zen_config'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install zen_config
20
+
21
+ ## Usage
22
+
23
+ Instantiate ZenConfig with a configuration hash :
24
+
25
+ config_hash = { :foo => "foo value" }
26
+ MyConfig = ZenConfig.new config_hash
27
+ MyConfig.foo
28
+ => "foo value"
29
+
30
+ By default, ZenConfig is read only :
31
+
32
+ MyConfig.foo = "bar value"
33
+ NoMethodError: undefined method `foo=' for #<ZenConfig:0x00000002ee52f8>
34
+
35
+ But changes can be allowed on build time :
36
+
37
+ MyConfig = ZenConfig.new config_hash, true
38
+ MyConfig.foo = "bar value"
39
+ => "bar value"
40
+ MyConfig.foo
41
+ => "bar value"
42
+
43
+ Then the object can be locked to read only again :
44
+
45
+ MyConfig.read_only
46
+ MyConfig.read_only?
47
+ => true
48
+ MyConfig.foo = "foo value"
49
+ NoMethodError: undefined method `foo=' for #<ZenConfig:0x00000002ee52f8>
50
+
51
+ And there's no way to unlock write.
52
+ This guarantees that ZenConfig data hasn't been altered since read-only lock has been set.
53
+ You should not use unlocked ZenConfig in your application code, since you don't know when and where it has been modified.
54
+ Dynamic persistent writes functions will come in future versions.
55
+
56
+ Sub configurations can be nested (if ZenConfig object is not locked) :
57
+
58
+ MyConfig.new :bar
59
+ MyConfig.bar.baz = "baz value"
60
+
61
+ Nested configurations are ZenConfigs. This allow accessing configuration on a specific context :
62
+
63
+ MyBarConfig = MyConfig.bar
64
+ MyBarConfig.class
65
+ => ZenConfig
66
+ MyBarConfig.baz
67
+ => "baz value"
68
+
69
+ Nested ZenConfigs can access their parent :
70
+
71
+ MyBarConfig.parent.foo
72
+ => "bar value"
73
+
74
+ Of course, root ZenConfig has no parent :
75
+
76
+ MyConfig.parent
77
+ => nil
78
+
79
+ You can check if a config key exists :
80
+
81
+ MyConfig.foo_exists?
82
+ => true
83
+
84
+ Count keys :
85
+
86
+ MyConfig.count
87
+ => 2
88
+ MyConfig.bar.count
89
+ => 1
90
+
91
+ ZenConfigs can be converted to hashs :
92
+
93
+ MyConfig.to_hash
94
+ => {:foo=>"bar value", :bar=>{:baz=>"baz value"}}
95
+
96
+ And finally, config keys can be deleted (if ZenConfig is unlocked) :
97
+
98
+ MyConfig.delete :foo
99
+ MyConfig.to_hash
100
+ => {:bar=>{:baz=>"baz value"}}
101
+
102
+ Note : ZenConfig methods are reserved words that can not be used as config keys.
103
+ They'll probably be renamed with a leading underscore in future versions.
104
+
105
+ ## Goals
106
+
107
+ - Provide hierarchical configuration objects => Done!
108
+ - Bring a read-only lock mode to guarantee config values haven't been modified => Done!
109
+ - Allow config file loading.
110
+ - Allow config file writing.
111
+ - Provide full unit tests.
112
+
113
+ ## Known bugs
114
+
115
+ - Nested hashs raise an error on init
116
+ - Merging doesn't always work
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ class ZenConfig
2
+ VERSION = "0.0.1"
3
+ end
data/lib/zen_config.rb ADDED
@@ -0,0 +1,193 @@
1
+ require 'zen_config/version'
2
+ require 'forwardable'
3
+
4
+ class ZenConfig
5
+ include Enumerable
6
+ extend Forwardable
7
+
8
+ def_delegators :@data, :each, :<<
9
+
10
+ def initialize hash, allow_modifications = false
11
+ @allow_modifications = !!allow_modifications
12
+ @loaded_section = nil
13
+ @index = 0
14
+ @data = {}
15
+
16
+ hash.each do |key, value|
17
+ key = key.to_sym
18
+
19
+ if value.is_a? Hash
20
+ @data[key] = self.new value, @allow_modifications
21
+ else
22
+ @data[key] = value
23
+ end
24
+
25
+ set_key_parent key
26
+ end
27
+
28
+ update_count
29
+ end
30
+
31
+ # Accessors
32
+
33
+ def get name, default = nil
34
+ result = default
35
+
36
+ if @data.has_key? name
37
+ result = @data[name]
38
+ end
39
+
40
+ return result
41
+ end
42
+
43
+ def set key, value
44
+ if @allow_modifications
45
+ if value.is_a? Hash
46
+ @data[key] = self.new value, true
47
+ else
48
+ @data[key] = value
49
+ end
50
+
51
+ set_key_parent key
52
+ update_count
53
+
54
+ return value
55
+ end
56
+ end
57
+
58
+ # Data
59
+
60
+ def count
61
+ @count
62
+ end
63
+
64
+ def delete key
65
+ if @allow_modifications
66
+ backup = @data[key]
67
+ @data.delete key
68
+ update_count
69
+ return backup
70
+ end
71
+ end
72
+
73
+ def exists? key
74
+ @data.has_key? key
75
+ end
76
+
77
+ def new key, force = false
78
+ key = key.to_sym
79
+
80
+ if @allow_modifications
81
+ if (!exists? key) || force
82
+ @data[key] = ZenConfig.new({}, true)
83
+ set_key_parent key
84
+ else
85
+ raise "'#{key}' key already exists."
86
+ end
87
+ end
88
+ end
89
+
90
+ #Global
91
+
92
+ def merge merge
93
+ raise "Merged configuration must be a ZenConfig" unless merge.kind_of? ZenConfig
94
+
95
+ merge.each do |key, value|
96
+ if @data.has_key? key
97
+ if (value.kind_of? ZenConfig) && (@data[key].kind_of? ZenConfig)
98
+ @data[key] = @data[key].merge(ZenConfig.new value.to_hash, !read_only?)
99
+ else
100
+ @data[key] = value
101
+ end
102
+ else
103
+ if value.kind_of? ZenConfig
104
+ @data[key] = ZenConfig.new value.to_hash, read_only?
105
+ else
106
+ @data[key] = value
107
+ end
108
+ end
109
+
110
+ set_key_parent key
111
+ end
112
+
113
+ return self
114
+ end
115
+
116
+ def method_missing method, *args
117
+ value = args.first
118
+
119
+ # Checks if a key exists
120
+ if /\A(.*)_exists\?\Z/.match method
121
+ exists? $1
122
+
123
+ # Delete a key
124
+ elsif /\Adelete_(.*)\Z/.match method
125
+ delete $1 if exists? $1
126
+
127
+ # Writes a key value
128
+ elsif (method[-1] == '=') && @allow_modifications
129
+ key = method[0..-2].to_sym
130
+ set key, value
131
+
132
+ # Reads a key value
133
+ elsif (args.count == 0)
134
+ get method
135
+
136
+ # Unknown method
137
+ else
138
+ super
139
+ end
140
+ end
141
+
142
+ def read_only
143
+ @allow_modifications = false
144
+ @data.each do |key, value|
145
+ if value.kind_of? ZenConfig
146
+ value.read_only
147
+ end
148
+ end
149
+ end
150
+
151
+ def read_only?
152
+ !@allow_modifications
153
+ end
154
+
155
+ def to_hash
156
+ hash = {}
157
+ @data.each do |key, value|
158
+ if value.kind_of? ZenConfig
159
+ hash[key] = value.to_hash
160
+ else
161
+ hash[key] = value
162
+ end
163
+ end
164
+
165
+ return hash
166
+ end
167
+
168
+ # Parent
169
+
170
+ def parent
171
+ return @parent
172
+ end
173
+
174
+ def set_key_parent key
175
+ if @data[key].kind_of? ZenConfig
176
+ @data[key].set_parent self
177
+ end
178
+ end
179
+
180
+ def set_parent parent
181
+ if parent.kind_of? ZenConfig
182
+ @parent = parent
183
+ else
184
+ raise "Parent must be a ZenConfig"
185
+ end
186
+ end
187
+
188
+ private
189
+
190
+ def update_count
191
+ @count = @data.count
192
+ end
193
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+
3
+ require 'zen_config'
4
+
5
+ RSpec.configure do |config|
6
+
7
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe ZenConfig do
4
+
5
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/zen_config/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Gauthier Delacroix"]
6
+ gem.email = ["gauthier.delacroix@gmail.com"]
7
+ gem.description = "Zend_Config translated into Ruby"
8
+ gem.summary = "Brings Ruby config objects as with Zend Framework's Zend_Config"
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "zen_config"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = ZenConfig::VERSION
17
+
18
+ gem.add_development_dependency "rspec"
19
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zen_config
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gauthier Delacroix
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: Zend_Config translated into Ruby
31
+ email:
32
+ - gauthier.delacroix@gmail.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - .gitignore
38
+ - Gemfile
39
+ - LICENSE
40
+ - README.md
41
+ - Rakefile
42
+ - lib/zen_config.rb
43
+ - lib/zen_config/version.rb
44
+ - spec/spec_helper.rb
45
+ - spec/zen_config_spec.rb
46
+ - zen_config.gemspec
47
+ homepage: ''
48
+ licenses: []
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 1.8.21
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Brings Ruby config objects as with Zend Framework's Zend_Config
71
+ test_files:
72
+ - spec/spec_helper.rb
73
+ - spec/zen_config_spec.rb