dsl_block 1.0.0 → 2.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.
- checksums.yaml +4 -4
- data/.gitignore +17 -17
- data/.rspec +2 -2
- data/Gemfile +4 -4
- data/LICENSE.txt +22 -22
- data/README.md +82 -82
- data/Rakefile +15 -15
- data/dsl_block.gemspec +29 -29
- data/lib/dsl_block.rb +168 -159
- data/lib/dsl_block/executor.rb +37 -37
- data/lib/dsl_block/version.rb +10 -10
- data/spec/lib/dsl_block/dsl_executor_spec.rb +60 -60
- data/spec/lib/dsl_block_spec.rb +251 -241
- data/spec/spec_helper.rb +114 -114
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc76bcc8987040d930830d224d9c95db5bd212ab
|
4
|
+
data.tar.gz: 03de7ce19db4372f7bf411488db80033ff4ae2a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1abb915845cd07c6384daf018d5bb7fe76515514d85dafd32b2fe7aba723adda356d3b8edca9b5478061c54db0d80cd9196e0879c94d09228f0224f7b8764ecb
|
7
|
+
data.tar.gz: acfbb43fe8257490e374801bf0ecf68237e1df6b37f1d4885147bf3dfe0a3ec15effce3f28bbe78264159c86f0fe7ab1b0b530c94088fee510284c8767918df6
|
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/.rspec
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
--colour
|
2
|
-
--format documentation
|
1
|
+
--colour
|
2
|
+
--format documentation
|
data/Gemfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in dsl_block.gemspec
|
4
|
-
gemspec
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in dsl_block.gemspec
|
4
|
+
gemspec
|
data/LICENSE.txt
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
Copyright (c) 2013 Frank Hall
|
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.
|
1
|
+
Copyright (c) 2013 Frank Hall
|
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
CHANGED
@@ -1,82 +1,82 @@
|
|
1
|
-
# DslBlock
|
2
|
-
|
3
|
-
DslBlock allows you to use classes to define blocks with commands for a Domain Specific Language. The commands are automatically relayed to your instance method.
|
4
|
-
|
5
|
-
## Installation
|
6
|
-
|
7
|
-
Add this line to your application's Gemfile:
|
8
|
-
|
9
|
-
gem 'dsl_block'
|
10
|
-
|
11
|
-
And then execute:
|
12
|
-
|
13
|
-
$ bundle
|
14
|
-
|
15
|
-
Or install it yourself as:
|
16
|
-
|
17
|
-
$ gem install dsl_block
|
18
|
-
|
19
|
-
## Usage
|
20
|
-
|
21
|
-
class Foo < DslBlock
|
22
|
-
commands :show_foo
|
23
|
-
def show_foo(x)
|
24
|
-
puts "Mr. T says you are a foo times #{x.to_i}"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class Bar < DslBlock
|
29
|
-
commands :show_bar
|
30
|
-
def show_bar(x)
|
31
|
-
puts "Ordering #{x.to_i} Shirley Temples from the bar"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class Baz < DslBlock
|
36
|
-
commands :show_baz
|
37
|
-
def show_baz(x)
|
38
|
-
puts "Baz spaz #{x.inspect}"
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
Baz.add_command_to(Bar)
|
43
|
-
Bar.add_command_to(Foo, true)
|
44
|
-
Foo.add_command_to(self)
|
45
|
-
|
46
|
-
|
47
|
-
foo do
|
48
|
-
puts self.inspect # => #<Foo:0x007f98f187e240 @block=#<Proc:0x...>, @parent=nil>
|
49
|
-
x = 10/10
|
50
|
-
show_foo x # => Mr. T says you are a foo times 1
|
51
|
-
|
52
|
-
bar do
|
53
|
-
x *= 2
|
54
|
-
show_bar x # => Ordering 2 Shirley Temples from the bar
|
55
|
-
x += 1
|
56
|
-
show_foo x # => Mr. T says you are a foo times 3
|
57
|
-
|
58
|
-
baz do
|
59
|
-
x *= 4
|
60
|
-
x /= 3
|
61
|
-
show_baz x # => Baz spaz 4
|
62
|
-
begin
|
63
|
-
x += 1
|
64
|
-
show_bar 5 # This will throw a NameError
|
65
|
-
rescue NameError
|
66
|
-
puts 'No bar for us'
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
|
76
|
-
## Contributing
|
77
|
-
|
78
|
-
1. Fork it
|
79
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
80
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
81
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
82
|
-
5. Create new Pull Request
|
1
|
+
# DslBlock
|
2
|
+
|
3
|
+
DslBlock allows you to use classes to define blocks with commands for a Domain Specific Language. The commands are automatically relayed to your instance method.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'dsl_block'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install dsl_block
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
class Foo < DslBlock
|
22
|
+
commands :show_foo
|
23
|
+
def show_foo(x)
|
24
|
+
puts "Mr. T says you are a foo times #{x.to_i}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Bar < DslBlock
|
29
|
+
commands :show_bar
|
30
|
+
def show_bar(x)
|
31
|
+
puts "Ordering #{x.to_i} Shirley Temples from the bar"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Baz < DslBlock
|
36
|
+
commands :show_baz
|
37
|
+
def show_baz(x)
|
38
|
+
puts "Baz spaz #{x.inspect}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
Baz.add_command_to(Bar)
|
43
|
+
Bar.add_command_to(Foo, true)
|
44
|
+
Foo.add_command_to(self)
|
45
|
+
|
46
|
+
|
47
|
+
foo do
|
48
|
+
puts self.inspect # => #<Foo:0x007f98f187e240 @block=#<Proc:0x...>, @parent=nil>
|
49
|
+
x = 10/10
|
50
|
+
show_foo x # => Mr. T says you are a foo times 1
|
51
|
+
|
52
|
+
bar do
|
53
|
+
x *= 2
|
54
|
+
show_bar x # => Ordering 2 Shirley Temples from the bar
|
55
|
+
x += 1
|
56
|
+
show_foo x # => Mr. T says you are a foo times 3
|
57
|
+
|
58
|
+
baz do
|
59
|
+
x *= 4
|
60
|
+
x /= 3
|
61
|
+
show_baz x # => Baz spaz 4
|
62
|
+
begin
|
63
|
+
x += 1
|
64
|
+
show_bar 5 # This will throw a NameError
|
65
|
+
rescue NameError
|
66
|
+
puts 'No bar for us'
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
## Contributing
|
77
|
+
|
78
|
+
1. Fork it
|
79
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
80
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
81
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
82
|
+
5. Create new Pull Request
|
data/Rakefile
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
-
require 'bundler/gem_tasks'
|
2
|
-
require 'rdoc/task'
|
3
|
-
require 'rspec/core/rake_task'
|
4
|
-
require 'rdoc/task'
|
5
|
-
|
6
|
-
RDoc::Task.new do |rdoc|
|
7
|
-
rdoc.rdoc_dir = 'doc'
|
8
|
-
rdoc.main = 'DslBlock.html'
|
9
|
-
rdoc.rdoc_files.include 'lib'
|
10
|
-
end
|
11
|
-
|
12
|
-
|
13
|
-
RSpec::Core::RakeTask.new
|
14
|
-
|
15
|
-
task :default => :spec
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rdoc/task'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
require 'rdoc/task'
|
5
|
+
|
6
|
+
RDoc::Task.new do |rdoc|
|
7
|
+
rdoc.rdoc_dir = 'doc'
|
8
|
+
rdoc.main = 'DslBlock.html'
|
9
|
+
rdoc.rdoc_files.include 'lib'
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
RSpec::Core::RakeTask.new
|
14
|
+
|
15
|
+
task :default => :spec
|
16
16
|
task :test => :spec
|
data/dsl_block.gemspec
CHANGED
@@ -1,29 +1,29 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'dsl_block/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = 'dsl_block'
|
8
|
-
spec.version = DslBlock::VERSION
|
9
|
-
spec.authors = ['Frank Hall']
|
10
|
-
spec.email = ['ChapterHouse.Dune@gmail.com']
|
11
|
-
spec.summary = %q{Quick and simple DSL creator.}
|
12
|
-
spec.description = %q{DslBlock is a quick and simple DSL creator.}
|
13
|
-
spec.homepage = 'http://chapterhouse.github.io/dsl_block'
|
14
|
-
spec.license = 'MIT'
|
15
|
-
|
16
|
-
spec.files = `git ls-files`.split($/)
|
17
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = ['lib']
|
20
|
-
|
21
|
-
spec.add_dependency 'activesupport', '~> 4.0'
|
22
|
-
|
23
|
-
spec.add_development_dependency 'bundler', '~> 1.3'
|
24
|
-
spec.add_development_dependency 'rake'
|
25
|
-
spec.add_development_dependency 'rspec', '~> 2.14.1'
|
26
|
-
spec.add_development_dependency 'simplecov', '~> 0.7.1'
|
27
|
-
spec.add_development_dependency 'rdoc', '~> 4.0.0'
|
28
|
-
|
29
|
-
end
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dsl_block/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'dsl_block'
|
8
|
+
spec.version = DslBlock::VERSION
|
9
|
+
spec.authors = ['Frank Hall']
|
10
|
+
spec.email = ['ChapterHouse.Dune@gmail.com']
|
11
|
+
spec.summary = %q{Quick and simple DSL creator.}
|
12
|
+
spec.description = %q{DslBlock is a quick and simple DSL creator.}
|
13
|
+
spec.homepage = 'http://chapterhouse.github.io/dsl_block'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'activesupport', '~> 4.0'
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 2.14.1'
|
26
|
+
spec.add_development_dependency 'simplecov', '~> 0.7.1'
|
27
|
+
spec.add_development_dependency 'rdoc', '~> 4.0.0'
|
28
|
+
|
29
|
+
end
|
data/lib/dsl_block.rb
CHANGED
@@ -1,159 +1,168 @@
|
|
1
|
-
require 'dsl_block/version'
|
2
|
-
require 'dsl_block/executor'
|
3
|
-
require 'active_support/core_ext/string/inflections'
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
# x
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
#
|
73
|
-
attr_accessor :
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
@commands
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
# +
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
#
|
115
|
-
#
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
end
|
1
|
+
require 'dsl_block/version'
|
2
|
+
require 'dsl_block/executor'
|
3
|
+
require 'active_support/core_ext/string/inflections'
|
4
|
+
require 'active_support/core_ext/array/extract_options'
|
5
|
+
|
6
|
+
|
7
|
+
# DslBlock is a base class for defining a Domain Specific Language. Subclasses of DslBlock define the desired dsl.
|
8
|
+
# These methods become available to ruby code running in the context of the subclass.
|
9
|
+
# The block execution is automatically isolated to prevent the called block from accessing instance methods unless
|
10
|
+
# specifically designated as callable. DslBlocks can be nested and parent blocks can allow their methods to be exposed to child block.
|
11
|
+
#
|
12
|
+
# ==== Example
|
13
|
+
# # Define three DslBlocks each with at least one command in each block
|
14
|
+
# class Foo < DslBlock
|
15
|
+
# commands :show_foo
|
16
|
+
# def show_foo(x)
|
17
|
+
# "Mr. T says you are a foo times #{x.to_i}"
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# class Bar < DslBlock
|
22
|
+
# commands :show_bar
|
23
|
+
# def show_bar(x)
|
24
|
+
# "Ordering #{x.to_i} Shirley Temples from the bar"
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# class Baz < DslBlock
|
29
|
+
# commands :show_baz
|
30
|
+
# def show_baz(x)
|
31
|
+
# "Baz spaz #{x.inspect}"
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# # Connect the blocks to each other so they can be easily nested
|
36
|
+
# Baz.add_command_to(Bar)
|
37
|
+
# Bar.add_command_to(Foo, :propagate => true) # Let Bar blocks also respond to foo methods
|
38
|
+
# Foo.add_command_to(self)
|
39
|
+
#
|
40
|
+
# # Use the new DSL
|
41
|
+
# foo do
|
42
|
+
# self.inspect # => #<Foo:0x007fdbd52b54e0 @block=#<Proc:0x007fdbd52b5530@/home/fhall/wonderland/alice.rb:29>, @parent=nil>
|
43
|
+
# x = 10/10
|
44
|
+
# show_foo x # => Mr. T says you are a foo times 1
|
45
|
+
#
|
46
|
+
# bar do
|
47
|
+
# x *= 2
|
48
|
+
# show_bar x # => Ordering 2 Shirley Temples from the bar
|
49
|
+
#
|
50
|
+
# x += 1
|
51
|
+
# show_foo x # => Mr. T says you are a foo times 3
|
52
|
+
#
|
53
|
+
# baz do
|
54
|
+
#
|
55
|
+
# x *= 4
|
56
|
+
# x /= 3
|
57
|
+
# show_baz x # => Baz spaz 4
|
58
|
+
#
|
59
|
+
# begin
|
60
|
+
# x += 1
|
61
|
+
# show_bar x # => NameError
|
62
|
+
# rescue NameError
|
63
|
+
# 'No bar for us'
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
class DslBlock
|
72
|
+
# Parent object providing additional commands to the block.
|
73
|
+
attr_accessor :parent
|
74
|
+
# Block of code that will be executed upon yield.
|
75
|
+
attr_accessor :block
|
76
|
+
|
77
|
+
# With no arguments, returns an array of command names that this DslBlock makes available to blocks either directly or indirectly.
|
78
|
+
# With arguments, adds new names to the array of command names, then returns the new array.
|
79
|
+
def self.commands(*args)
|
80
|
+
@commands ||= []
|
81
|
+
@commands = (@commands + args.map(&:to_sym)).uniq
|
82
|
+
@commands
|
83
|
+
end
|
84
|
+
|
85
|
+
# This is a convenience command that allows this DslBlock to inject itself as a method into another DslBlock or Object.
|
86
|
+
# If the parent is also a DslBlock, the new method will automatically be added to the available commands.
|
87
|
+
#
|
88
|
+
# Params:
|
89
|
+
# +destination+:: The object to receive the new method
|
90
|
+
# +options+:: A hash of options configuring the command
|
91
|
+
#
|
92
|
+
# Options:
|
93
|
+
# +:propagate+:: Allow methods in the destination to be called by the block. (default: false)
|
94
|
+
# +:command_name+:: The name of the method to be created or nil to use the default which is based off of the class name. (default: nil)
|
95
|
+
def self.add_command_to(destination, options={})
|
96
|
+
# Determine the name of the method to create
|
97
|
+
command_name = (options[:command_name] || name).to_s.underscore.to_sym
|
98
|
+
# Save a reference to our self so we will have something to call in a bit when self will refer to someone else.
|
99
|
+
this_class = self
|
100
|
+
# Define the command in the destination.
|
101
|
+
destination.send(:define_method, command_name) do |&block|
|
102
|
+
# Create a new instance of our self with the callers 'self' passed in as an optional parent.
|
103
|
+
# Immediately after initialization, yield the block.
|
104
|
+
this_class.new(:parent => options[:propagate] ? self : nil, &block).yield
|
105
|
+
end
|
106
|
+
# Add the new command to the parent if it is a DslBlock.
|
107
|
+
destination.commands << command_name if destination.is_a?(Class) && destination < DslBlock
|
108
|
+
end
|
109
|
+
|
110
|
+
# Create a new DslBlock instance.
|
111
|
+
# +block+:: Required block of code that will be executed when yield is called on the new DslBlock instance.
|
112
|
+
#
|
113
|
+
# Options:
|
114
|
+
# +:parent+:: Optional parent DslBlock or Object that is providing additional commands to the block. (default: nil)
|
115
|
+
# +:block+:: Optional method of passing in a block.
|
116
|
+
def initialize(*args, &block)
|
117
|
+
options = args.extract_options!
|
118
|
+
@block = block_given? ? block : options[:block]
|
119
|
+
raise ArgumentError, 'block must be provided' unless @block
|
120
|
+
@parent = options[:parent]
|
121
|
+
end
|
122
|
+
|
123
|
+
# This is the entire list of commands that this instance makes available to the block of code to be run.
|
124
|
+
# It is a combination of three distinct sources.
|
125
|
+
# 1. The class's declared commands
|
126
|
+
# 2. If there is a parent of this DslBock instance...
|
127
|
+
# * The parents declared commands if it is a DslBlock
|
128
|
+
# * The parents public_methods if it is any other type of object
|
129
|
+
# 3. Kernel.methods
|
130
|
+
#
|
131
|
+
# This method is prefixed with an underscore in an attempt to avoid collisions with commands in the given block.
|
132
|
+
def _commands
|
133
|
+
cmds = self.class.commands.dup
|
134
|
+
if @parent
|
135
|
+
if @parent.is_a?(DslBlock)
|
136
|
+
cmds += @parent._commands
|
137
|
+
else
|
138
|
+
cmds += @parent.public_methods
|
139
|
+
end
|
140
|
+
end
|
141
|
+
(cmds + Kernel.methods).uniq
|
142
|
+
end
|
143
|
+
|
144
|
+
# Yield the block given.
|
145
|
+
def yield
|
146
|
+
begin
|
147
|
+
# Evaluate the block in an executor to provide isolation
|
148
|
+
# and prevent accidental interference with ourselves.
|
149
|
+
Executor.new(self).instance_eval(&@block)
|
150
|
+
rescue Exception => e
|
151
|
+
e.set_backtrace(caller.select { |x| !x.include?(__FILE__)})
|
152
|
+
raise e
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# :nodoc:
|
157
|
+
def respond_to_missing?(method, include_all)
|
158
|
+
@parent && @parent.respond_to?(method, include_all) || super
|
159
|
+
end
|
160
|
+
|
161
|
+
def method_missing(name, *args, &block)
|
162
|
+
if @parent && @parent.respond_to?(name)
|
163
|
+
@parent.send(name, *args, &block)
|
164
|
+
else
|
165
|
+
super
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|