iron-dsl 1.0.0

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: 58e6a28f277a7fb6305e7ffb268f26d2f737c0e2
4
+ data.tar.gz: 2e08931bde299f5ac6f84f93f924b3e4beecf85f
5
+ SHA512:
6
+ metadata.gz: 51b0a8cea42976e123c25471d8558cdea7e4f53ecd8d47de187d9551f87ec4f55429087fd9826f893ce18e729cfb3baffe344b6f942772f2d8fe28b8a0748bb4
7
+ data.tar.gz: 55e093337f7a637640d4d99acb6b4880be3515aabc0f949c23fb8ceaf5ea7a043dbdb62bc4a46145d1e8b4691a3c7e71fd02507da0ce5aea39384abb1c2ba352
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require <%= File.join(File.expand_path(File.dirname(__FILE__)), 'spec', 'spec_helper.rb') %>
@@ -0,0 +1,5 @@
1
+ == 1.0.0 / 2015-01-26
2
+
3
+ * Broke out iron-dsl from older iron-extensions gem
4
+ * Improved documentation a bit
5
+ * Updated dsl_accessor to capture blocks
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Irongaze Consulting LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,149 @@
1
+ = GEM: iron-dsl
2
+
3
+ Written by Rob Morris @ Irongaze Consulting LLC (http://irongaze.com)
4
+
5
+ == DESCRIPTION
6
+
7
+ The iron-dsl gem provides a set of powerful tools for building "domain-specific languages"
8
+ in Ruby. Ruby's natural DSL construction capabilities (through, e.g. instance_eval) are
9
+ very solid, but to make truly clean DSLs requires additional magic. This gem provides
10
+ that magic in a nice self-contained package.
11
+
12
+ == USAGE
13
+
14
+ There are 3 main pieces to this gem: DslBuilder, a set of accessor helpers, and DslProxy.
15
+
16
+ DslBuilder is simply an empty class, suitable for use as a base class for your DSL receiver class.
17
+ It is similar to BasicObject in the standard library, but has methods such as #respond_to?
18
+ and #send that are required for any real DSL building effort.
19
+
20
+ You can use DslBuilder, or any other class, as the basis for your DSL system. In any case,
21
+ you want a clean way to set attributes on an instance of that class. For that, we have
22
+ two class-level methods: #dsl_accessor and #dsl_flag
23
+
24
+ The first, #dsl_accessor, is a helpful method for defining accessors on DSL builder-style classes:
25
+
26
+ require 'iron/dsl'
27
+
28
+ class MyBuilder < DslBuilder
29
+ # Declare an accessor on this receiver class, just like you'd use attr_accessor
30
+ dsl_accessor :name
31
+ end
32
+
33
+ # When you create an instance, you have a set of behavior for the #name accessor you declared
34
+ builder = MyBuilder.new
35
+
36
+ # You can set a value by calling #name as a setter, and get the value by using #name as a getter
37
+ builder.name = 'ProjectX'
38
+ builder.name # => 'ProjectX'
39
+
40
+ # But you can also set the value by simply calling #name with the value to set:
41
+ builder.name 'ProjectY'
42
+ builder.name # => 'ProjectY'
43
+
44
+ # This makes for a cleaner syntax when using your DSL with DslProxy#exec below..
45
+ DslProxy.exec(builder) do
46
+ name 'Project Omega'
47
+ end
48
+ builder.name # => 'Project Omega'
49
+
50
+ # You can also capture blocks this way, which is often useful in DSL creation for values
51
+ # that need to be dynamically calculated at run-time
52
+ builder.name do
53
+ "Project " + Date.today
54
+ end
55
+
56
+ The second accessor helper is #dsl_flag, which is the same as #dsl_accessor, but designed for
57
+ boolean values.
58
+
59
+ class AnotherBuilder < DslBuilder
60
+ dsl_flag :awesome
61
+ end
62
+
63
+ builder = AnotherBuilder
64
+ builder.awesome? # => false on uninitialized value
65
+ builder.awesome! # => sets @awesome to true
66
+ # dsl_flags can still be set normally
67
+ builder.awesome true
68
+ builder.awesome false
69
+
70
+ Bringing it all together, and the key to the whole system, is DslProxy. DslProxy is a more powerful version of
71
+ #instance_exec that handles instance variable propagation and other nifty tricks like nesting and propagating
72
+ method references and constant lookups to the calling scope. That all sounds like gibberish, so here's a few
73
+ hopefully illustrative examples.
74
+
75
+ @name = 'Bob'
76
+
77
+ # First, how you would traditionally do it:
78
+ instance_exec(some_receiver) do
79
+ # This fails - the instance var from the calling context is not defined. Sucks if you're in Rails
80
+ # and trying to define something in a controller or view, where all the state is typically in
81
+ # instance vars!
82
+ self.name = @name
83
+ end
84
+
85
+ # This, however, totally works
86
+ DslProxy.exec(some_receiver) do
87
+ # @name has bubbled into our block and can be referenced!
88
+ self.name = @name
89
+ # But of course, we'd use a dsl_accessor so we could lose the 'self.' and the '='
90
+ name @name
91
+
92
+ # Having nested DSLs is also supported, all instance vars are available at all levels
93
+ sub_define do
94
+ page_title @name + ' Likes Bees'
95
+ end
96
+ end
97
+
98
+ In summary, making DSLs is a bit of an art, and what this gem attempts to do is make pretty DSLs like this
99
+ easier to build:
100
+
101
+ grid = Grid.define do
102
+ url '/orders/grid'
103
+ souce Order.by_date
104
+
105
+ columns do
106
+ column :id
107
+ column :customer do
108
+ no_wrap!
109
+ column :total do
110
+ render_as :currency
111
+ end
112
+ end
113
+
114
+ pagination do
115
+ default 40
116
+ allow_custom!
117
+ end
118
+ end
119
+
120
+ Using code to configure complex systems (rather than hashes of hashes, or manually constructed settings objects)
121
+ allows for a much more expressive codebase. At Irongaze, we use this type of builder for grid controls, pagination,
122
+ filters, forms, fields, and so forth. Places where the MVC system breaks down, and complexity that bridges
123
+ controller and view needs to be managed.
124
+
125
+ == SYNOPSIS
126
+
127
+ To use:
128
+
129
+ require 'iron/dsl'
130
+
131
+ After that, simply write code to make use of the new extensions and helper classes.
132
+
133
+ == REQUIREMENTS
134
+
135
+ * Ruby 1.9.2 or later
136
+
137
+ == INSTALL
138
+
139
+ To install, simply run:
140
+
141
+ sudo gem install iron-dsl
142
+
143
+ RVM users should drop the 'sudo':
144
+
145
+ gem install iron-dsl
146
+
147
+ Then simply require the library:
148
+
149
+ require 'iron/dsl'
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,5 @@
1
+ # Requires all classes
2
+ search_path = File.join(File.expand_path(File.dirname(__FILE__)), '*', '*.rb')
3
+ Dir.glob(search_path) do |path|
4
+ require path
5
+ end
@@ -0,0 +1,46 @@
1
+ class Class
2
+
3
+ # Provides a DSL-friendly way to set values. Similar to attr_accessor, but
4
+ # supports setting values like so:
5
+ #
6
+ # class Widget
7
+ # dsl_accessor :size
8
+ # end
9
+ # @w = Widget.new
10
+ # @w.size = 5 # normal setter, same as...
11
+ # @w.size 5 # note the lack of explicit = sign
12
+ # puts @w.size # still get reader access
13
+ #
14
+ # Useful in DslProxy blocks:
15
+ #
16
+ # DslProxy.exec(Widget.new) do
17
+ # size 10 # sets size to 10, as expected
18
+ # size = 10 # fails, creates local variable 'size' instead of invoking Widget#size
19
+ # end
20
+ #
21
+ def dsl_accessor(*keys)
22
+ keys.each do |key|
23
+ class_eval "def #{key}(val = :__UNDEFINED, &block); if val != :__UNDEFINED ; @#{key} = val ; elsif block ; @#{key} = block ; end ; @#{key}; end"
24
+ class_eval "def #{key}=(val); @#{key} = val; end"
25
+ end
26
+ end
27
+
28
+ # Like #dsl_accessor, but adds imperative and query versions of the keys as well to set the
29
+ # flag to true and to query the true-ness of the flag.
30
+ #
31
+ # class Widget
32
+ # dsl_flag :heavy
33
+ # end
34
+ # @w = Widget.new
35
+ # @w.heavy? # => false
36
+ # @w.heavy! # now is true
37
+ #
38
+ def dsl_flag(*keys)
39
+ dsl_accessor(*keys)
40
+ keys.each do |key|
41
+ class_eval "def #{key}!; @#{key} = true; end"
42
+ class_eval "def #{key}?; @#{key} === true; end"
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,14 @@
1
+ # Provides a base class for building DSL (domain specific language) builder
2
+ # classes, ie classes that define a minimal subset of methods and act as aggregators
3
+ # of settings or functionality. Similar to BasicObject in the standard library, but
4
+ # has methods such as respond_to? and send that are required for any real DSL building
5
+ # effort.
6
+ class DslBuilder < Object
7
+
8
+ # Remove all methods not explicitly desired
9
+ instance_methods.each do |m|
10
+ keepers = [:inspect, :send]
11
+ undef_method m if m =~ /^[a-z]+[0-9]?$/ && !keepers.include?(m)
12
+ end
13
+
14
+ end
@@ -0,0 +1,176 @@
1
+ # Specialty helper class for building elegant DSLs (domain-specific languages)
2
+ # The purpose of the class is to allow seamless DSL's by allowing execution
3
+ # of blocks with the instance variables of the calling context preserved, but
4
+ # all method calls proxied to a given receiver. This sounds pretty abstract,
5
+ # so here's an example:
6
+ #
7
+ # class ControlBuilder
8
+ # def initialize; @controls = []; end
9
+ # def control_list; @controls; end
10
+ # def knob; @controls << :knob; end
11
+ # def button; @controls << :button; end
12
+ # def switch; @controls << :switch; end
13
+ # def self.define(&block)
14
+ # @builder = self.new
15
+ # DslProxy.exec(@builder, &block)
16
+ # # Do something here with the builder's list of controls
17
+ # @builder.control_list
18
+ # end
19
+ # end
20
+ #
21
+ # @knob_count = 5
22
+ # new_list = ControlBuilder.define do
23
+ # switch
24
+ # @knob_count.times { knob }
25
+ # button
26
+ # end
27
+ #
28
+ # Notice the lack of explicit builder receiver to the calls to #switch, #knob and #button.
29
+ # Those calls are automatically proxied to the receiver we passed to the DslProxy.
30
+ #
31
+ # In quick and dirty DSLs, like Rails' migrations, you end up with a lot of
32
+ # pointless receiver declarations for each method call, like so:
33
+ #
34
+ # def change
35
+ # create_table do |t|
36
+ # t.integer :counter
37
+ # t.text :title
38
+ # t.text :desc
39
+ # # ... tired of typing "t." yet? ...
40
+ # end
41
+ # end
42
+ #
43
+ # This is not a big deal if you're using a simple DSL, but when you have multiple nested
44
+ # builders going on at once, it is ugly, pointless, and can cause bugs when
45
+ # the throwaway arg names you choose (eg 't' above) overlap in scope.
46
+ #
47
+ # In addition, simply using a yield statment loses the instance variables set in the calling
48
+ # context. This is a major pain in eg Rails views, where most of the interesting
49
+ # data resides in instance variables. You can get around this when #yield-ing by
50
+ # explicitly creating a local variable to be picked up by the closure created in the
51
+ # block, but it kind of sucks.
52
+ #
53
+ # In summary, DslProxy allows you to keep all the local and instance variable context
54
+ # from your block declarations, while proxying all method calls to a given
55
+ # receiver. If you're not building DSLs, this class is not for you, but if you are,
56
+ # I hope it helps!
57
+ class DslProxy < BasicObject
58
+
59
+ # Pass in a builder-style class, or other receiver you want set as "self" within the
60
+ # block, and off you go. The passed block will be executed with all
61
+ # block-context local and instance variables available, but with all
62
+ # method calls sent to the receiver you pass in. The block's result will
63
+ # be returned.
64
+ #
65
+ # If the receiver doesn't respond_to? a method, any missing methods
66
+ # will be proxied to the enclosing context.
67
+ def self.exec(receiver, *to_yield, &block) # :yields: receiver
68
+ # Find the context within which the block was defined
69
+ context = ::Kernel.eval('self', block.binding)
70
+
71
+ # Create or re-use our proxy object
72
+ if context.respond_to?(:_to_dsl_proxy)
73
+ # If we're nested, we don't want/need a new dsl proxy, just re-use the existing one
74
+ proxy = context._to_dsl_proxy
75
+ else
76
+ # Not nested, create a new proxy for our use
77
+ proxy = DslProxy.new(context)
78
+ end
79
+
80
+ # Exec the block and return the result
81
+ proxy._proxy(receiver, *to_yield, &block)
82
+ end
83
+
84
+ # Simple state setup
85
+ def initialize(context)
86
+ @_receivers = []
87
+ @_instance_original_values = {}
88
+ @_context = context
89
+ end
90
+
91
+ def _proxy(receiver, *to_yield, &block) # :yields: receiver
92
+ # Sanity!
93
+ raise 'Cannot proxy with a DslProxy as receiver!' if receiver.respond_to?(:_to_dsl_proxy)
94
+
95
+ if @_receivers.empty?
96
+ # On first proxy call, run each context instance variable,
97
+ # and set it to ourselves so we can proxy it
98
+ @_context.instance_variables.each do |var|
99
+ unless var[0...2] == '@_'
100
+ value = @_context.instance_variable_get(var.to_s)
101
+ @_instance_original_values[var] = value
102
+ instance_eval "#{var} = value"
103
+ end
104
+ end
105
+ end
106
+
107
+ # Save the dsl target as our receiver for proxying
108
+ _push_receiver(receiver)
109
+
110
+ # Run the block with ourselves as the new "self", passing the given yieldable(s) or
111
+ # the receiver in case the code wants to disambiguate for some reason
112
+ to_yield = [receiver] if to_yield.empty?
113
+ to_yield = to_yield.first(block.arity)
114
+ result = instance_exec(*to_yield, &block)
115
+
116
+ # Pop the last receiver off the stack
117
+ _pop_receiver
118
+
119
+ if @_receivers.empty?
120
+ # Run each local instance variable and re-set it back to the context if it has changed during execution
121
+ #instance_variables.each do |var|
122
+ @_context.instance_variables.each do |var|
123
+ unless var[0...2] == '@_'
124
+ value = instance_eval("#{var}")
125
+ if @_instance_original_values[var] != value
126
+ @_context.instance_variable_set(var.to_s, value)
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ return result
133
+ end
134
+
135
+ # For nesting multiple proxies
136
+ def _to_dsl_proxy
137
+ self
138
+ end
139
+
140
+ # Set the currently active receiver
141
+ def _push_receiver(receiver)
142
+ @_receivers.push receiver
143
+ end
144
+
145
+ # Remove the currently active receiver, restore old receiver if nested
146
+ def _pop_receiver
147
+ @_receivers.pop
148
+ end
149
+
150
+ # Proxies all calls to our receiver, or to the block's context
151
+ # if the receiver doesn't respond_to? it.
152
+ def method_missing(method, *args, &block)
153
+ #$stderr.puts "Method missing: #{method}"
154
+ if @_receivers.last.respond_to?(method)
155
+ #$stderr.puts "Proxy [#{method}] to receiver"
156
+ @_receivers.last.__send__(method, *args, &block)
157
+ else
158
+ #$stderr.puts "Proxy [#{method}] to context"
159
+ @_context.__send__(method, *args, &block)
160
+ end
161
+ end
162
+
163
+ # Let anyone who's interested know what our proxied objects will accept
164
+ def respond_to?(method, include_private = false)
165
+ return true if method == :_to_dsl_proxy
166
+ @_receivers.last.respond_to?(method, include_private) || @_context.respond_to?(method, include_private)
167
+ end
168
+
169
+ # Proxies searching for constants to the context, so that eg Kernel::foo can actually
170
+ # find Kernel - BasicObject does not partake in the global scope!
171
+ def self.const_missing(name)
172
+ #$stderr.puts "Constant missing: #{name} - proxy to context"
173
+ @_context.class.const_get(name)
174
+ end
175
+
176
+ end
@@ -0,0 +1,33 @@
1
+ describe Class do
2
+
3
+ context 'when using dsl_accessor' do
4
+ class MyBuilder < DslBuilder
5
+ dsl_accessor :process
6
+ end
7
+
8
+ before do
9
+ @builder = MyBuilder.new
10
+ end
11
+
12
+ it 'should set via =' do
13
+ @builder.process.should be_nil
14
+ @builder.process = 5
15
+ @builder.process.should == 5
16
+ end
17
+
18
+ it 'should set via call' do
19
+ @builder.process.should be_nil
20
+ @builder.process 5
21
+ @builder.process.should == 5
22
+ end
23
+
24
+ it 'should capture blocks' do
25
+ @builder.process do
26
+ puts 'foo'
27
+ end
28
+ @builder.process.should be_a Proc
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,29 @@
1
+ describe DslBuilder do
2
+
3
+ # TODO: break this out a bit...
4
+ it 'should allow using DSL-style accessors' do
5
+ class MyBuilder < DslBuilder
6
+ dsl_accessor :name
7
+ dsl_flag :flagged
8
+ end
9
+ builder = MyBuilder.new
10
+
11
+ # Test standalone
12
+ builder.name 'ProjectX'
13
+ builder.name.should == 'ProjectX'
14
+
15
+ builder.flagged?.should be_false
16
+ builder.flagged = true
17
+ builder.flagged?.should be_true
18
+ builder.flagged = false
19
+
20
+ # Test as part of DslProxy usage (common case)
21
+ DslProxy.exec(builder) do
22
+ name 'Project Omega'
23
+ flagged!
24
+ end
25
+ builder.name.should == 'Project Omega'
26
+ builder.flagged?.should be_true
27
+ end
28
+
29
+ end
@@ -0,0 +1,110 @@
1
+ describe DslProxy do
2
+
3
+ # Sample DSL builder class for use in testing
4
+ class ControlBuilder
5
+ def initialize; @controls = []; end
6
+ def controls; @controls; end
7
+ def knob; @controls << :knob; end
8
+ def button; @controls << :button; end
9
+ def switch; @controls << :switch; end
10
+
11
+ def self.define(&block)
12
+ @builder = self.new
13
+ DslProxy.exec(@builder, &block)
14
+ @builder.controls
15
+ end
16
+ end
17
+
18
+ it 'should proxy calls to the receiver' do
19
+ receiver = Object.new
20
+ DslProxy.exec(receiver) do
21
+ self.class.name.should == 'Object'
22
+ end
23
+ end
24
+
25
+ it 'should proxy respond_to? to the receiver' do
26
+ receiver = ControlBuilder.new
27
+ DslProxy.exec(receiver) do
28
+ respond_to?(:garbaz).should == false
29
+ respond_to?(:button).should == true
30
+ end
31
+ end
32
+
33
+ it 'should proxy local variables from the binding context' do
34
+ @foo = 'bar'
35
+ DslProxy.exec(Object.new) do
36
+ @foo.should == 'bar'
37
+ end
38
+ end
39
+
40
+ it 'should propagate local variable changes back to the binding context' do
41
+ @foo = 'bar'
42
+ DslProxy.exec(Object.new) do
43
+ @foo = 'no bar!'
44
+ end
45
+ @foo.should == 'no bar!'
46
+ end
47
+
48
+ it 'should proxy missing methods on the receiver to the calling context' do
49
+ class TestContext
50
+ def bar
51
+ 'something'
52
+ end
53
+
54
+ def test
55
+ DslProxy.exec(Object.new) do
56
+ bar
57
+ end
58
+ end
59
+ end
60
+
61
+ TestContext.new.test.should == 'something'
62
+ end
63
+
64
+ it 'should return the result of the block' do
65
+ res = DslProxy.exec(Object.new) do
66
+ 'foo'
67
+ end
68
+ res.should == 'foo'
69
+ end
70
+
71
+ it 'should allow access to global constants' do
72
+ DslProxy.exec(self) do # Use self here, so #be_a is defined. :-)
73
+ Object.new.should be_a(Object)
74
+ end
75
+ end
76
+
77
+ it 'should proxy correctly even when nested' do
78
+ def outerfunc
79
+ 5
80
+ end
81
+ @instance_var = nil
82
+ local_var = nil
83
+ DslProxy.exec(self) do
84
+ DslProxy.exec(Object.new) do
85
+ outerfunc.should == 5
86
+ @instance_var.should be_nil
87
+ local_var.should be_nil
88
+ @instance_var = 10
89
+ local_var = 11
90
+ end
91
+ end
92
+ @instance_var.should == 10
93
+ local_var.should == 11
94
+ end
95
+
96
+ it 'should pass additional args to block as argument' do
97
+ l = lambda {|arg1, arg2| arg1 + arg2}
98
+ DslProxy.exec(Object.new, 5, 1, &l).should == 6
99
+ end
100
+
101
+ it 'should put it all together' do
102
+ @knob_count = 5
103
+ controls = ControlBuilder.define do
104
+ switch
105
+ @knob_count.times { knob }
106
+ end
107
+ controls.count.should == 6
108
+ end
109
+
110
+ end
@@ -0,0 +1,11 @@
1
+ # Require our library
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'iron', 'dsl'))
3
+
4
+ # Config RSpec options
5
+ RSpec.configure do |config|
6
+ config.color = true
7
+ config.add_formatter 'documentation'
8
+ config.backtrace_clean_patterns = [/rspec/]
9
+ end
10
+
11
+
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: iron-dsl
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Rob Morris
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.6'
27
+ description: Provides the DslProxy and DslBuilder classes plus DSL-friendly accessor
28
+ and flag support
29
+ email:
30
+ - rob@irongaze.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".rspec"
36
+ - History.txt
37
+ - LICENSE
38
+ - README.rdoc
39
+ - Version.txt
40
+ - lib/iron/dsl.rb
41
+ - lib/iron/dsl/class.rb
42
+ - lib/iron/dsl/dsl_builder.rb
43
+ - lib/iron/dsl/dsl_proxy.rb
44
+ - spec/dsl/class_spec.rb
45
+ - spec/dsl/dsl_builder_spec.rb
46
+ - spec/dsl/dsl_proxy_spec.rb
47
+ - spec/spec_helper.rb
48
+ homepage: https://github.com/irongaze/iron-dsl
49
+ licenses:
50
+ - MIT
51
+ metadata: {}
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.9.2
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 2.4.3
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Powerful and concise construction helpers for Domain Specific Languages
72
+ test_files: []