configdsl 1.2.0 → 1.2.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f7a1fe10ca22b9a57f0864b3fc838877e8bd58a5
4
+ data.tar.gz: 3112cbc27003a4ea77bae907b339ccbfb3f999a8
5
+ SHA512:
6
+ metadata.gz: 9e49134ef6f2db5cb16f0df91efc3972a52e3ffd69db6082f48788aaf9cb281c2b94e041c8e577f6099e45de33bb9885b5605317a124fb1722c8dce62fb7240e
7
+ data.tar.gz: fc81060fce52ed8a8e9f0442370eaff61720c6937adfc567721dc7cdb23ea01f3288b4b083e6fc3174125af51a8d5ca0a7b02c66f3ed318fd287ec8815b60c47
data/.gitignore CHANGED
@@ -1,17 +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
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 CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in configdsl.gemspec
4
- gemspec
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in configdsl.gemspec
4
+ gemspec
data/LICENSE CHANGED
@@ -1,22 +1,22 @@
1
- Copyright (c) 2012 MOZGIII
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
1
+ Copyright (c) 2012 MOZGIII
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
22
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,247 +1,247 @@
1
- # ConfigDSL
2
-
3
- A tasty Ruby-based DSL for configuration files. Get rid of those silly YAML and JSON configs.
4
-
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- gem 'configdsl'
10
-
11
- And then execute:
12
-
13
- $ bundle
14
-
15
- Or install it yourself as:
16
-
17
- $ gem install configdsl
18
-
19
- ## Usage
20
-
21
- ### Standalone Usage
22
-
23
- #### To read a config file
24
-
25
- - in your app:
26
-
27
- ```ruby
28
- # Read external data
29
- ConfigDSL.read("test.cdsl.rb")
30
- ```
31
-
32
- - test.cdsl.rb
33
-
34
- ```ruby
35
- hi "User"
36
- # p hi # => "User"
37
-
38
- list do
39
- one "123"
40
- two "345"
41
- three do
42
- one "1"
43
- three_two one + " 2"
44
- three_three "three"
45
- end
46
- see "will_be_overwritten"
47
- end
48
-
49
- list 5 do |index|
50
- append "anything"
51
- second index + 1
52
- square index ** 2
53
-
54
- see "overwritten!"
55
- end
56
-
57
- starting_time Time.now
58
- ```
59
-
60
- will produce
61
-
62
- ```ruby
63
- pp ConfigDSL.data
64
-
65
- {:hi=>"User",
66
- :list=>
67
- {:one=>"123",
68
- :two=>"345",
69
- :three=>{:one=>"1", :three_two=>"1 2", :three_three=>"three"},
70
- :see=>"overwritten!",
71
- :append=>"anything",
72
- :second=>6,
73
- :square=>25},
74
- :starting_time=>2012-11-05 22:47:36 +0000}
75
- ```
76
-
77
- #### You can also load inline configs form your code
78
-
79
- ```ruby
80
- # Execute inline data
81
- ConfigDSL.execute do
82
- inline_loading_example "here goes"
83
- value "awesome"
84
- code "great"
85
- block_test "config option" do |preset|
86
- block_val preset
87
- end
88
- end
89
-
90
- # Another inline data
91
- ConfigDSL.execute do
92
- value "awesome"
93
- end
94
- ```
95
-
96
- gives
97
-
98
- ```ruby
99
- {:inline_loading_example=>"here goes",
100
- :value=>"awesome",
101
- :code=>"great",
102
- :block_test=>{:block_val=>"config option"}}
103
- ```
104
-
105
-
106
- #### You can combine theese two
107
-
108
- ```ruby
109
- # Read external data
110
- ConfigDSL.read("test.cdsl.rb")
111
-
112
- # Execute inline data
113
- ConfigDSL.execute do
114
- inline_loading_example "here goes"
115
- value "awesome"
116
- code "great"
117
- block_test "config option" do |preset|
118
- block_val preset
119
- end
120
- end
121
-
122
- # Another inline data
123
- ConfigDSL.execute do
124
- value "awesome"
125
- end
126
-
127
- require "pp" # for pretty print
128
- pp ConfigDSL.data
129
- ```
130
-
131
- is
132
-
133
- ```ruby
134
- {:hi=>"User",
135
- :list=>
136
- {:one=>"123",
137
- :two=>"345",
138
- :three=>{:one=>"1", :three_two=>"1 2", :three_three=>"three"},
139
- :see=>"overwritten!",
140
- :append=>"anything",
141
- :second=>6,
142
- :square=>25},
143
- :starting_time=>2012-11-05 22:48:40 +0000,
144
- :inline_loading_example=>"here goes",
145
- :value=>"awesome",
146
- :code=>"great",
147
- :block_test=>{:block_val=>"config option"}}
148
- ```
149
-
150
- #### You can coviniently access all the config values in your app
151
-
152
- ```ruby
153
- # Here is how you get all the config
154
- p ConfigDSL.data
155
-
156
- # To read data from your app you can do this:
157
-
158
- puts ; puts "Value of :value is: "
159
- p ConfigDSL.data[:value]
160
-
161
- # or this
162
-
163
- puts ; puts "Another way to get it is: "
164
- p ConfigDSL[:value]
165
-
166
- # Access block values
167
-
168
- puts "Block values: "
169
-
170
- puts ; puts "-- [:list][:one]"
171
- p ConfigDSL[:list][:one]
172
-
173
- puts ; puts "-- [:list][:two]"
174
- p ConfigDSL[:list][:two]
175
-
176
- puts ; puts "-- [:list][:three]"
177
- p ConfigDSL[:list][:three]
178
-
179
- puts ; puts "-- [:list][:three][:three_two]"
180
- p ConfigDSL[:list][:three][:three_two]
181
-
182
- # Get something complex
183
- puts ; puts "Program was stared at: "
184
- p ConfigDSL[:starting_time]
185
- ```
186
-
187
- #### Keys as methods
188
-
189
- You can access all config values using method chaining syntax instead of using the square brackets.
190
-
191
- ```ruby
192
- ConfigDSL[:list][:three][:three_two]
193
- ```
194
-
195
- is equal to
196
-
197
- ```ruby
198
- ConfigDSL.list.three.three_two
199
- ```
200
-
201
- However, there is a little problem with this approach.
202
- Data container objects do have their own methods besides the methods that they provide to get data values.
203
-
204
- Notice that `ConfigDSL.data` is also a reserved method (it returns internal first-level data container).
205
-
206
- #### Check out the example!
207
-
208
- There is an `examples` dir. Check it out to see how it works for yourself!
209
-
210
- ### Lazy Values
211
-
212
- You can have lazy values in your configuration code! By default, those values are evaluated when you call them for the first time.
213
- This can be very useful when you want to load config before everything else. Storing some config data in the database? This is for you.
214
-
215
- ```ruby
216
- ConfigDSL.execute do
217
- lazy_varaible lazy!{ Time.now }
218
- standart_variable Time.now
219
- end
220
-
221
- sleep 2
222
-
223
- ConfigDSL.standart_variable # => 2012-11-11 21:37:09 +0400
224
- ConfigDSL.lazy_varaible # => 2012-11-11 21:37:11 +0400
225
- ```
226
-
227
- Can be tricky! Make sure you understand what Lazy Values do and what they don't do!
228
-
229
- ### Use Hashie::Mash - Deprecated!
230
-
231
- Hashie::Mash can not be used as a layer-level storage anymore (because of lazy values implementation).
232
-
233
- ### Ruby on Rails
234
-
235
- To be implemented. For now you can use it like standalone as initializer.
236
-
237
- ### To-Do List
238
-
239
- - Ruby on Rails integration
240
-
241
- ## Contributing
242
-
243
- 1. Fork it
244
- 2. Create your feature branch (`git checkout -b my-new-feature`)
245
- 3. Commit your changes (`git commit -am 'Added some feature'`)
246
- 4. Push to the branch (`git push origin my-new-feature`)
247
- 5. Create new Pull Request
1
+ # ConfigDSL
2
+
3
+ A tasty Ruby-based DSL for configuration files. Get rid of those silly YAML and JSON configs.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'configdsl'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install configdsl
18
+
19
+ ## Usage
20
+
21
+ ### Standalone Usage
22
+
23
+ #### To read a config file
24
+
25
+ - in your app:
26
+
27
+ ```ruby
28
+ # Read external data
29
+ ConfigDSL.read("test.cdsl.rb")
30
+ ```
31
+
32
+ - test.cdsl.rb
33
+
34
+ ```ruby
35
+ hi "User"
36
+ # p hi # => "User"
37
+
38
+ list do
39
+ one "123"
40
+ two "345"
41
+ three do
42
+ one "1"
43
+ three_two one + " 2"
44
+ three_three "three"
45
+ end
46
+ see "will_be_overwritten"
47
+ end
48
+
49
+ list 5 do |index|
50
+ append "anything"
51
+ second index + 1
52
+ square index ** 2
53
+
54
+ see "overwritten!"
55
+ end
56
+
57
+ starting_time Time.now
58
+ ```
59
+
60
+ will produce
61
+
62
+ ```ruby
63
+ pp ConfigDSL.data
64
+
65
+ {:hi=>"User",
66
+ :list=>
67
+ {:one=>"123",
68
+ :two=>"345",
69
+ :three=>{:one=>"1", :three_two=>"1 2", :three_three=>"three"},
70
+ :see=>"overwritten!",
71
+ :append=>"anything",
72
+ :second=>6,
73
+ :square=>25},
74
+ :starting_time=>2012-11-05 22:47:36 +0000}
75
+ ```
76
+
77
+ #### You can also load inline configs form your code
78
+
79
+ ```ruby
80
+ # Execute inline data
81
+ ConfigDSL.execute do
82
+ inline_loading_example "here goes"
83
+ value "awesome"
84
+ code "great"
85
+ block_test "config option" do |preset|
86
+ block_val preset
87
+ end
88
+ end
89
+
90
+ # Another inline data
91
+ ConfigDSL.execute do
92
+ value "awesome"
93
+ end
94
+ ```
95
+
96
+ gives
97
+
98
+ ```ruby
99
+ {:inline_loading_example=>"here goes",
100
+ :value=>"awesome",
101
+ :code=>"great",
102
+ :block_test=>{:block_val=>"config option"}}
103
+ ```
104
+
105
+
106
+ #### You can combine theese two
107
+
108
+ ```ruby
109
+ # Read external data
110
+ ConfigDSL.read("test.cdsl.rb")
111
+
112
+ # Execute inline data
113
+ ConfigDSL.execute do
114
+ inline_loading_example "here goes"
115
+ value "awesome"
116
+ code "great"
117
+ block_test "config option" do |preset|
118
+ block_val preset
119
+ end
120
+ end
121
+
122
+ # Another inline data
123
+ ConfigDSL.execute do
124
+ value "awesome"
125
+ end
126
+
127
+ require "pp" # for pretty print
128
+ pp ConfigDSL.data
129
+ ```
130
+
131
+ is
132
+
133
+ ```ruby
134
+ {:hi=>"User",
135
+ :list=>
136
+ {:one=>"123",
137
+ :two=>"345",
138
+ :three=>{:one=>"1", :three_two=>"1 2", :three_three=>"three"},
139
+ :see=>"overwritten!",
140
+ :append=>"anything",
141
+ :second=>6,
142
+ :square=>25},
143
+ :starting_time=>2012-11-05 22:48:40 +0000,
144
+ :inline_loading_example=>"here goes",
145
+ :value=>"awesome",
146
+ :code=>"great",
147
+ :block_test=>{:block_val=>"config option"}}
148
+ ```
149
+
150
+ #### You can coviniently access all the config values in your app
151
+
152
+ ```ruby
153
+ # Here is how you get all the config
154
+ p ConfigDSL.data
155
+
156
+ # To read data from your app you can do this:
157
+
158
+ puts ; puts "Value of :value is: "
159
+ p ConfigDSL.data[:value]
160
+
161
+ # or this
162
+
163
+ puts ; puts "Another way to get it is: "
164
+ p ConfigDSL[:value]
165
+
166
+ # Access block values
167
+
168
+ puts "Block values: "
169
+
170
+ puts ; puts "-- [:list][:one]"
171
+ p ConfigDSL[:list][:one]
172
+
173
+ puts ; puts "-- [:list][:two]"
174
+ p ConfigDSL[:list][:two]
175
+
176
+ puts ; puts "-- [:list][:three]"
177
+ p ConfigDSL[:list][:three]
178
+
179
+ puts ; puts "-- [:list][:three][:three_two]"
180
+ p ConfigDSL[:list][:three][:three_two]
181
+
182
+ # Get something complex
183
+ puts ; puts "Program was stared at: "
184
+ p ConfigDSL[:starting_time]
185
+ ```
186
+
187
+ #### Keys as methods
188
+
189
+ You can access all config values using method chaining syntax instead of using the square brackets.
190
+
191
+ ```ruby
192
+ ConfigDSL[:list][:three][:three_two]
193
+ ```
194
+
195
+ is equal to
196
+
197
+ ```ruby
198
+ ConfigDSL.list.three.three_two
199
+ ```
200
+
201
+ However, there is a little problem with this approach.
202
+ Data container objects do have their own methods besides the methods that they provide to get data values.
203
+
204
+ Notice that `ConfigDSL.data` is also a reserved method (it returns internal first-level data container).
205
+
206
+ #### Check out the example!
207
+
208
+ There is an `examples` dir. Check it out to see how it works for yourself!
209
+
210
+ ### Lazy Values
211
+
212
+ You can have lazy values in your configuration code! By default, those values are evaluated when you call them for the first time.
213
+ This can be very useful when you want to load config before everything else. Storing some config data in the database? This is for you.
214
+
215
+ ```ruby
216
+ ConfigDSL.execute do
217
+ lazy_varaible lazy!{ Time.now }
218
+ standart_variable Time.now
219
+ end
220
+
221
+ sleep 2
222
+
223
+ ConfigDSL.standart_variable # => 2012-11-11 21:37:09 +0400
224
+ ConfigDSL.lazy_varaible # => 2012-11-11 21:37:11 +0400
225
+ ```
226
+
227
+ Can be tricky! Make sure you understand what Lazy Values do and what they don't do!
228
+
229
+ ### Use Hashie::Mash - Deprecated!
230
+
231
+ Hashie::Mash can not be used as a layer-level storage anymore (because of lazy values implementation).
232
+
233
+ ### Ruby on Rails
234
+
235
+ To be implemented. For now you can use it like standalone as initializer.
236
+
237
+ ### To-Do List
238
+
239
+ - Ruby on Rails integration
240
+
241
+ ## Contributing
242
+
243
+ 1. Fork it
244
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
245
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
246
+ 4. Push to the branch (`git push origin my-new-feature`)
247
+ 5. Create new Pull Request
data/Rakefile CHANGED
@@ -1,2 +1,2 @@
1
- #!/usr/bin/env rake
2
- require "bundler/gem_tasks"
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -1,19 +1,19 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/configdsl/version', __FILE__)
3
-
4
- Gem::Specification.new do |gem|
5
- gem.authors = ["MOZGIII"]
6
- gem.email = ["mike-n@narod.ru"]
7
- gem.description = %q{A convinient Ruby-based DSL for your app configuration!}
8
- gem.summary = %q{A convinient Ruby-based DSL for your app configuration!}
9
- gem.homepage = "http://github.com/MOZGIII/ConfigDSL"
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 = "configdsl"
15
- gem.require_paths = ["lib"]
16
- gem.version = ConfigDSL::VERSION
17
-
18
- gem.add_runtime_dependency "activesupport"
19
- end
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/configdsl/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["MOZGIII"]
6
+ gem.email = ["mike-n@narod.ru"]
7
+ gem.description = %q{A convinient Ruby-based DSL for your app configuration!}
8
+ gem.summary = %q{A convinient Ruby-based DSL for your app configuration!}
9
+ gem.homepage = "http://github.com/MOZGIII/ConfigDSL"
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 = "configdsl"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = ConfigDSL::VERSION
17
+
18
+ gem.add_runtime_dependency "activesupport", ">= 0.0.1"
19
+ end
@@ -1,255 +1,255 @@
1
- require "configdsl/version"
2
- require "active_support/concern"
3
- require "forwardable"
4
-
5
- module ConfigDSL
6
- module Memory
7
- class MemoryLayer < Hash
8
- def self.make_alias_method(meth)
9
- "original_#{meth}".to_sym
10
- end
11
-
12
- ALIASED_METHODS = [
13
- :[], :fetch
14
- ]
15
-
16
- ALIASED_METHODS.each do |meth|
17
- original_method = make_alias_method(meth)
18
-
19
- begin
20
- alias_method original_method, meth
21
-
22
- define_method meth do |*args, &block|
23
- lazy_value = __send__(original_method, *args, &block)
24
- lazy_value = lazy_value.value if lazy_value.kind_of?(LazyValue)
25
- lazy_value
26
- end
27
- rescue NameError
28
- end
29
- end
30
-
31
- # Give a more handy name
32
- alias_method :original_reader, make_alias_method(:[])
33
-
34
- # Allow methods invocation to read values
35
- def method_missing(meth, *args, &block)
36
- return self[meth] if has_key?(meth)
37
- super
38
- end
39
-
40
- # Allow methods invocation to read values, second part
41
- def respond_to?(meth)
42
- return true if has_key?(meth)
43
- super
44
- end
45
- end
46
-
47
- class << self
48
- # Creates a new layer-level storage element
49
- def layers_factory
50
- @factory_base_class ||= MemoryLayer
51
- @factory_base_class.new
52
- end
53
-
54
- # Main data container
55
- def data
56
- @data ||= layers_factory
57
- end
58
-
59
- # Stores a value in specified key for specified context
60
- def store(key, value, context = [])
61
- layer = expand_context(context)
62
- layer[key] = value
63
- end
64
-
65
- # Fetches a specified key for a specified context
66
- # Allows to provide a default value
67
- def fetch(key, defaul_value = nil, context = [])
68
- fetch!(key, context)
69
- rescue KeyError => e
70
- defaul_value
71
- end
72
-
73
- # Fetches a specified key for a specified context
74
- # Raises exception if something goes wrong
75
- def fetch!(key, context = [])
76
- layer = expand_context(context)
77
- raise KeyError, "In context #{context} key not found: #{key.inspect}" unless layer.has_key?(key)
78
- layer[key]
79
- end
80
-
81
- # Return a layer described by context or rises an exception
82
- # if any of parent layers is undefined
83
- def expand_context(context)
84
- context.inject(data) do |hash, level|
85
- hash[level]
86
- end
87
- end
88
-
89
- # Adds a new layer if it does not exist
90
- def add_layer(new_layer, context)
91
- current_layer = expand_context(context)
92
- current_layer[new_layer] ||= layers_factory
93
- end
94
- end
95
- end
96
-
97
- module DSL
98
- extend ActiveSupport::Concern
99
-
100
- def self.debug?
101
- @debug ||= false
102
- end
103
-
104
- def self.debug!(value = true)
105
- @debug = value
106
- end
107
-
108
- def context
109
- @@context ||= []
110
- end
111
-
112
- def debug(text)
113
- puts text if DSL.debug?
114
- end
115
-
116
- def lazy!(*args, &block)
117
- LazyValue.new(block, args)
118
- end
119
-
120
- def assign!(sym, value = nil, &block)
121
- return sym.each { |key, val| assign!(key, val) } if sym.kind_of? Hash
122
- varibales_hook(sym, value, &block)
123
- end
124
-
125
- def varibales_hook(meth, *args, &block)
126
- debug "Hooked #{meth}"
127
- debug "Context is #{context}"
128
- if block_given?
129
- # Add list
130
- debug "Adding list #{meth}"
131
- evaluate_within_layer(meth, block, args)
132
- else
133
- if args.empty?
134
- # Read variable
135
- debug "Reading variable #{meth}"
136
- Memory.fetch!(meth, context)
137
- else
138
- # Add variable
139
- debug "Adding variable #{meth}"
140
- value = args.size == 1 ? args.first : args.dup
141
- Memory.store(meth, value, context)
142
- end
143
- end
144
- end
145
-
146
- def evaluate_within_layer(new_layer, block, args = [])
147
- Memory.add_layer(new_layer, context)
148
- begin
149
- context.push new_layer
150
- block.call(*args)
151
- ensure
152
- context.pop
153
- end
154
- end
155
-
156
- def method_missing(meth, *args, &block)
157
- if respond_to?(meth)
158
- super
159
- else
160
- varibales_hook(meth, *args, &block)
161
- end
162
- end
163
-
164
- end
165
-
166
- module Processor
167
- class Sandbox
168
- include DSL
169
- end
170
-
171
- def self.process(filename)
172
- sandbox = Sandbox.new
173
- sandbox.instance_eval(File.read(filename), filename)
174
- sandbox
175
- end
176
-
177
- def self.execute(&block)
178
- sandbox = Sandbox.new
179
- sandbox.instance_eval(&block)
180
- sandbox
181
- end
182
-
183
- def self.add_module(module_const)
184
- Sandbox.extend module_const
185
- end
186
- end
187
-
188
- class << self
189
- def read(filename)
190
- Processor.process(filename)
191
- end
192
-
193
- def execute(&block)
194
- Processor.execute(&block)
195
- end
196
-
197
- def data
198
- Memory.data
199
- end
200
-
201
- def method_missing(meth, *args, &block)
202
- if data.respond_to?(meth)
203
- data.send(meth, *args, &block)
204
- else
205
- super
206
- end
207
- end
208
-
209
- def respond_to?(meth)
210
- super_value = super
211
- return super_value if super_value != false
212
- data.respond_to?(meth)
213
- end
214
- end
215
-
216
- class LazyValue
217
- def self.default_options
218
- {
219
- caching: true
220
- }
221
- end
222
-
223
- attr_reader :block, :args, :options
224
-
225
- def initialize(block, args = [], options = {})
226
- @block = block
227
- @args = args
228
- @options = self.class.default_options.merge(options)
229
- @cached = false
230
- end
231
-
232
- def value(new_args = nil)
233
- return @cache if caching? && cached?
234
- value = block.call(*(new_args ? new_args : args))
235
- if caching?
236
- @cache = value
237
- @cached = true
238
- end
239
- value
240
- end
241
-
242
- def caching?
243
- !!options[:caching]
244
- end
245
-
246
- def flush_cache!
247
- @cache = nil # clean pointer so that GC can do it's work immediately
248
- @cached = true
249
- end
250
-
251
- def cached?
252
- @cached
253
- end
254
- end
255
- end
1
+ require "configdsl/version"
2
+ require "active_support/concern"
3
+ require "forwardable"
4
+
5
+ module ConfigDSL
6
+ module Memory
7
+ class MemoryLayer < Hash
8
+ def self.make_alias_method(meth)
9
+ "original_#{meth}".to_sym
10
+ end
11
+
12
+ ALIASED_METHODS = [
13
+ :[], :fetch
14
+ ]
15
+
16
+ ALIASED_METHODS.each do |meth|
17
+ original_method = make_alias_method(meth)
18
+
19
+ begin
20
+ alias_method original_method, meth
21
+
22
+ define_method meth do |*args, &block|
23
+ lazy_value = __send__(original_method, *args, &block)
24
+ lazy_value = lazy_value.value if lazy_value.kind_of?(LazyValue)
25
+ lazy_value
26
+ end
27
+ rescue NameError
28
+ end
29
+ end
30
+
31
+ # Give a more handy name
32
+ alias_method :original_reader, make_alias_method(:[])
33
+
34
+ # Allow methods invocation to read values
35
+ def method_missing(meth, *args, &block)
36
+ return self[meth] if has_key?(meth)
37
+ super
38
+ end
39
+
40
+ # Allow methods invocation to read values, second part
41
+ def respond_to?(meth)
42
+ return true if has_key?(meth)
43
+ super
44
+ end
45
+ end
46
+
47
+ class << self
48
+ # Creates a new layer-level storage element
49
+ def layers_factory
50
+ @factory_base_class ||= MemoryLayer
51
+ @factory_base_class.new
52
+ end
53
+
54
+ # Main data container
55
+ def data
56
+ @data ||= layers_factory
57
+ end
58
+
59
+ # Stores a value in specified key for specified context
60
+ def store(key, value, context = [])
61
+ layer = expand_context(context)
62
+ layer[key] = value
63
+ end
64
+
65
+ # Fetches a specified key for a specified context
66
+ # Allows to provide a default value
67
+ def fetch(key, defaul_value = nil, context = [])
68
+ fetch!(key, context)
69
+ rescue KeyError => e
70
+ defaul_value
71
+ end
72
+
73
+ # Fetches a specified key for a specified context
74
+ # Raises exception if something goes wrong
75
+ def fetch!(key, context = [])
76
+ layer = expand_context(context)
77
+ raise KeyError, "In context #{context} key not found: #{key.inspect}" unless layer.has_key?(key)
78
+ layer[key]
79
+ end
80
+
81
+ # Return a layer described by context or rises an exception
82
+ # if any of parent layers is undefined
83
+ def expand_context(context)
84
+ context.inject(data) do |hash, level|
85
+ hash[level]
86
+ end
87
+ end
88
+
89
+ # Adds a new layer if it does not exist
90
+ def add_layer(new_layer, context)
91
+ current_layer = expand_context(context)
92
+ current_layer[new_layer] ||= layers_factory
93
+ end
94
+ end
95
+ end
96
+
97
+ module DSL
98
+ extend ActiveSupport::Concern
99
+
100
+ def self.debug?
101
+ @debug ||= false
102
+ end
103
+
104
+ def self.debug!(value = true)
105
+ @debug = value
106
+ end
107
+
108
+ def context
109
+ @@context ||= []
110
+ end
111
+
112
+ def debug(text)
113
+ puts text if DSL.debug?
114
+ end
115
+
116
+ def lazy!(*args, &block)
117
+ LazyValue.new(block, args)
118
+ end
119
+
120
+ def assign!(sym, value = nil, &block)
121
+ return sym.each { |key, val| assign!(key, val) } if sym.kind_of? Hash
122
+ varibales_hook(sym, value, &block)
123
+ end
124
+
125
+ def varibales_hook(meth, *args, &block)
126
+ debug "Hooked #{meth}"
127
+ debug "Context is #{context}"
128
+ if block_given?
129
+ # Add list
130
+ debug "Adding list #{meth}"
131
+ evaluate_within_layer(meth, block, args)
132
+ else
133
+ if args.empty?
134
+ # Read variable
135
+ debug "Reading variable #{meth}"
136
+ Memory.fetch!(meth, context)
137
+ else
138
+ # Add variable
139
+ debug "Adding variable #{meth}"
140
+ value = args.size == 1 ? args.first : args.dup
141
+ Memory.store(meth, value, context)
142
+ end
143
+ end
144
+ end
145
+
146
+ def evaluate_within_layer(new_layer, block, args = [])
147
+ Memory.add_layer(new_layer, context)
148
+ begin
149
+ context.push new_layer
150
+ block.call(*args)
151
+ ensure
152
+ context.pop
153
+ end
154
+ end
155
+
156
+ def method_missing(meth, *args, &block)
157
+ if respond_to?(meth)
158
+ super
159
+ else
160
+ varibales_hook(meth, *args, &block)
161
+ end
162
+ end
163
+
164
+ end
165
+
166
+ module Processor
167
+ class Sandbox
168
+ include DSL
169
+ end
170
+
171
+ def self.process(filename)
172
+ sandbox = Sandbox.new
173
+ sandbox.instance_eval(File.read(filename), filename)
174
+ sandbox
175
+ end
176
+
177
+ def self.execute(&block)
178
+ sandbox = Sandbox.new
179
+ sandbox.instance_eval(&block)
180
+ sandbox
181
+ end
182
+
183
+ def self.add_module(module_const)
184
+ Sandbox.extend module_const
185
+ end
186
+ end
187
+
188
+ class << self
189
+ def read(filename)
190
+ Processor.process(filename)
191
+ end
192
+
193
+ def execute(&block)
194
+ Processor.execute(&block)
195
+ end
196
+
197
+ def data
198
+ Memory.data
199
+ end
200
+
201
+ def method_missing(meth, *args, &block)
202
+ if data.respond_to?(meth)
203
+ data.send(meth, *args, &block)
204
+ else
205
+ super
206
+ end
207
+ end
208
+
209
+ def respond_to?(meth)
210
+ super_value = super
211
+ return super_value if super_value != false
212
+ data.respond_to?(meth)
213
+ end
214
+ end
215
+
216
+ class LazyValue
217
+ def self.default_options
218
+ {
219
+ caching: true
220
+ }
221
+ end
222
+
223
+ attr_reader :block, :args, :options
224
+
225
+ def initialize(block, args = [], options = {})
226
+ @block = block
227
+ @args = args
228
+ @options = self.class.default_options.merge(options)
229
+ @cached = false
230
+ end
231
+
232
+ def value(new_args = nil)
233
+ return @cache if caching? && cached?
234
+ value = block.call(*(new_args ? new_args : args))
235
+ if caching?
236
+ @cache = value
237
+ @cached = true
238
+ end
239
+ value
240
+ end
241
+
242
+ def caching?
243
+ !!options[:caching]
244
+ end
245
+
246
+ def flush_cache!
247
+ @cache = nil # clean pointer so that GC can do it's work immediately
248
+ @cached = true
249
+ end
250
+
251
+ def cached?
252
+ @cached
253
+ end
254
+ end
255
+ end
@@ -1,3 +1,3 @@
1
- module ConfigDSL
2
- VERSION = "1.2.0"
3
- end
1
+ module ConfigDSL
2
+ VERSION = "1.2.1"
3
+ end
metadata CHANGED
@@ -1,32 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configdsl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
5
- prerelease:
4
+ version: 1.2.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - MOZGIII
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-06-15 00:00:00.000000000 Z
11
+ date: 2013-11-18 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: activesupport
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
- version: '0'
19
+ version: 0.0.1
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
- version: '0'
26
+ version: 0.0.1
30
27
  description: A convinient Ruby-based DSL for your app configuration!
31
28
  email:
32
29
  - mike-n@narod.ru
@@ -47,27 +44,25 @@ files:
47
44
  - lib/configdsl/version.rb
48
45
  homepage: http://github.com/MOZGIII/ConfigDSL
49
46
  licenses: []
47
+ metadata: {}
50
48
  post_install_message:
51
49
  rdoc_options: []
52
50
  require_paths:
53
51
  - lib
54
52
  required_ruby_version: !ruby/object:Gem::Requirement
55
- none: false
56
53
  requirements:
57
- - - ! '>='
54
+ - - '>='
58
55
  - !ruby/object:Gem::Version
59
56
  version: '0'
60
57
  required_rubygems_version: !ruby/object:Gem::Requirement
61
- none: false
62
58
  requirements:
63
- - - ! '>='
59
+ - - '>='
64
60
  - !ruby/object:Gem::Version
65
61
  version: '0'
66
62
  requirements: []
67
63
  rubyforge_project:
68
- rubygems_version: 1.8.24
64
+ rubygems_version: 2.1.10
69
65
  signing_key:
70
- specification_version: 3
66
+ specification_version: 4
71
67
  summary: A convinient Ruby-based DSL for your app configuration!
72
68
  test_files: []
73
- has_rdoc: