configdsl 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: