dsl_compose 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +300 -3
- data/lib/dsl_compose/composer.rb +74 -0
- data/lib/dsl_compose/dsl/arguments/argument/equal_to_validation.rb +25 -0
- data/lib/dsl_compose/dsl/arguments/argument/format_validation.rb +25 -0
- data/lib/dsl_compose/dsl/arguments/argument/greater_than_or_equal_to_validation.rb +35 -0
- data/lib/dsl_compose/dsl/arguments/argument/greater_than_validation.rb +35 -0
- data/lib/dsl_compose/dsl/arguments/argument/in_validation.rb +35 -0
- data/lib/dsl_compose/dsl/arguments/argument/interpreter.rb +86 -0
- data/lib/dsl_compose/dsl/arguments/argument/length_validation.rb +42 -0
- data/lib/dsl_compose/dsl/arguments/argument/less_than_or_equal_to_validation.rb +35 -0
- data/lib/dsl_compose/dsl/arguments/argument/less_than_validation.rb +35 -0
- data/lib/dsl_compose/dsl/arguments/argument/not_in_validation.rb +35 -0
- data/lib/dsl_compose/dsl/arguments/argument.rb +299 -0
- data/lib/dsl_compose/dsl/arguments.rb +113 -0
- data/lib/dsl_compose/dsl/dsl_method/interpreter.rb +57 -0
- data/lib/dsl_compose/dsl/dsl_method.rb +143 -0
- data/lib/dsl_compose/dsl/interpreter.rb +72 -0
- data/lib/dsl_compose/dsl.rb +152 -0
- data/lib/dsl_compose/dsls.rb +80 -0
- data/lib/dsl_compose/interpreter/execution/arguments.rb +145 -0
- data/lib/dsl_compose/interpreter/execution/method_calls/method_call.rb +53 -0
- data/lib/dsl_compose/interpreter/execution/method_calls.rb +25 -0
- data/lib/dsl_compose/interpreter/execution.rb +64 -0
- data/lib/dsl_compose/interpreter.rb +50 -0
- data/lib/dsl_compose/version.rb +2 -2
- data/lib/dsl_compose.rb +35 -4
- metadata +26 -3
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class Arguments
|
6
|
+
class Argument
|
7
|
+
class LengthValidation
|
8
|
+
class ValidationFailedError < StandardError
|
9
|
+
def message
|
10
|
+
"The argument is invalid"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize maximum: nil, minimum: nil, is: nil
|
15
|
+
@maximum = maximum
|
16
|
+
@minimum = minimum
|
17
|
+
@is = is
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate! value
|
21
|
+
maximum = @maximum
|
22
|
+
unless maximum.nil?
|
23
|
+
raise ValidationFailedError if value.length > maximum
|
24
|
+
end
|
25
|
+
|
26
|
+
minimum = @minimum
|
27
|
+
unless minimum.nil?
|
28
|
+
raise ValidationFailedError if value.length < minimum
|
29
|
+
end
|
30
|
+
|
31
|
+
is = @is
|
32
|
+
unless is.nil?
|
33
|
+
raise ValidationFailedError if value.length != is
|
34
|
+
end
|
35
|
+
|
36
|
+
true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class Arguments
|
6
|
+
class Argument
|
7
|
+
class LessThanOrEqualToValidation
|
8
|
+
class InvalidValueError < StandardError
|
9
|
+
def message
|
10
|
+
"The value provided to validate_greater_than must be a number"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ValidationFailedError < StandardError
|
15
|
+
def message
|
16
|
+
"The argument is invalid"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize value
|
21
|
+
unless value.is_a?(Numeric)
|
22
|
+
raise InvalidValueError
|
23
|
+
end
|
24
|
+
|
25
|
+
@value = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate! value
|
29
|
+
raise ValidationFailedError unless value <= @value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class Arguments
|
6
|
+
class Argument
|
7
|
+
class LessThanValidation
|
8
|
+
class InvalidValueError < StandardError
|
9
|
+
def message
|
10
|
+
"The value provided to validate_greater_than must be a number"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ValidationFailedError < StandardError
|
15
|
+
def message
|
16
|
+
"The argument is invalid"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize value
|
21
|
+
unless value.is_a?(Numeric)
|
22
|
+
raise InvalidValueError
|
23
|
+
end
|
24
|
+
|
25
|
+
@value = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate! value
|
29
|
+
raise ValidationFailedError unless value < @value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class Arguments
|
6
|
+
class Argument
|
7
|
+
class NotInValidation
|
8
|
+
class InvalidValueError < StandardError
|
9
|
+
def message
|
10
|
+
"The value provided to validate_greater_than must be a number"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ValidationFailedError < StandardError
|
15
|
+
def message
|
16
|
+
"The argument is invalid"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize values
|
21
|
+
unless values.is_a?(Array)
|
22
|
+
raise InvalidValueError
|
23
|
+
end
|
24
|
+
|
25
|
+
@values = values
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate! value
|
29
|
+
raise ValidationFailedError if @values.include?(value)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,299 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class Arguments
|
6
|
+
class Argument
|
7
|
+
class ValidationIncompatibleError < StandardError
|
8
|
+
def message
|
9
|
+
"The validation is not compatible with this argument type"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class ValidationAlreadyExistsError < StandardError
|
14
|
+
def message
|
15
|
+
"This validation has already been applied to this method option."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class InvalidTypeError < StandardError
|
20
|
+
def message
|
21
|
+
"Argument type must be one of :integer, :boolean, :float, :string or :symbol"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class InvalidNameError < StandardError
|
26
|
+
def message
|
27
|
+
"The option name is invalid, it must be of type symbol."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class InvalidDescriptionError < StandardError
|
32
|
+
def message
|
33
|
+
"The option description is invalid, it must be of type string and have length greater than 0."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class DescriptionAlreadyExistsError < StandardError
|
38
|
+
def message
|
39
|
+
"The description has already been set"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# The name of this Argument.
|
44
|
+
attr_reader :name
|
45
|
+
# An arguments type. This determines what kind of value can be passed when calling the
|
46
|
+
# associated DSLMethod.
|
47
|
+
# `type` should be set to either :integer, :boolean, :float, :string or :symbol
|
48
|
+
attr_reader :type
|
49
|
+
# if required, then this Argument must be provided when calling its associated DSLMethod.
|
50
|
+
attr_reader :required
|
51
|
+
# An otional description of this Attribute, if provided then it must be a string.
|
52
|
+
# The description accepts markdown and is used when generating documentation.
|
53
|
+
attr_reader :description
|
54
|
+
# Optional validations that have been applied to this Argument. When the DSL is used
|
55
|
+
# each of these validations will be checked against the value provided to
|
56
|
+
# this Argument.
|
57
|
+
attr_reader :greater_than_validation
|
58
|
+
attr_reader :greater_than_or_equal_to_validation
|
59
|
+
attr_reader :less_than_validation
|
60
|
+
attr_reader :less_than_or_equal_to_validation
|
61
|
+
attr_reader :format_validation
|
62
|
+
attr_reader :equal_to_validation
|
63
|
+
attr_reader :in_validation
|
64
|
+
attr_reader :not_in_validation
|
65
|
+
attr_reader :length_validation
|
66
|
+
|
67
|
+
# Create a new Attribute object.
|
68
|
+
#
|
69
|
+
# `name` must be a symbol.
|
70
|
+
# `required` is a boolean which determines if this Attribute must be provided when
|
71
|
+
# calling its associated DSLMethod.
|
72
|
+
# `type` can be either :integer, :boolean, :float, :string or :symbol
|
73
|
+
# `block` contains the instructions to further configure this Attribute
|
74
|
+
def initialize name, required, type, &block
|
75
|
+
if name.is_a? Symbol
|
76
|
+
@name = name
|
77
|
+
else
|
78
|
+
raise InvalidNameError
|
79
|
+
end
|
80
|
+
|
81
|
+
if type == :integer || type == :boolean || type == :float || type == :string || type == :symbol
|
82
|
+
@type = type
|
83
|
+
else
|
84
|
+
raise InvalidTypeError
|
85
|
+
end
|
86
|
+
|
87
|
+
@required = required ? true : false
|
88
|
+
|
89
|
+
# If a block was provided, then we evaluate it using a seperate
|
90
|
+
# interpreter class. We do this because the interpreter class contains
|
91
|
+
# no other methods or variables, if it was evaluated in the context of
|
92
|
+
# this class then the block would have access to all of the methods defined
|
93
|
+
# in here.
|
94
|
+
if block
|
95
|
+
Interpreter.new(self).instance_eval(&block)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Set the description for this Argument to the provided value.
|
100
|
+
#
|
101
|
+
# `description` must be a string with a length greater than 0.
|
102
|
+
# The `description` can only be set once per Argument
|
103
|
+
def set_description description
|
104
|
+
unless description.is_a?(String) && description.length > 0
|
105
|
+
raise InvalidDescriptionError
|
106
|
+
end
|
107
|
+
|
108
|
+
if has_description?
|
109
|
+
raise DescriptionAlreadyExistsError
|
110
|
+
end
|
111
|
+
|
112
|
+
@description = description
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns `true` if this DSL has a description, else false.
|
116
|
+
def has_description?
|
117
|
+
@description.nil? == false
|
118
|
+
end
|
119
|
+
|
120
|
+
# returns true if this DSLMethod is flagged as required, otherwise returns false.
|
121
|
+
def required?
|
122
|
+
@required == true
|
123
|
+
end
|
124
|
+
|
125
|
+
# returns true if this DSLMethod is flagged as optional, otherwise returns false.
|
126
|
+
def optional?
|
127
|
+
@required == false
|
128
|
+
end
|
129
|
+
|
130
|
+
def validate_greater_than value
|
131
|
+
if @greater_than_validation
|
132
|
+
raise ValidationAlreadyExistsError
|
133
|
+
end
|
134
|
+
|
135
|
+
unless @type == :integer || @type == :float
|
136
|
+
raise ValidationIncompatibleError
|
137
|
+
end
|
138
|
+
|
139
|
+
@greater_than_validation = GreaterThanValidation.new value
|
140
|
+
end
|
141
|
+
|
142
|
+
def validate_greater_than_or_equal_to value
|
143
|
+
if @greater_than_or_equal_to_validation
|
144
|
+
raise ValidationAlreadyExistsError
|
145
|
+
end
|
146
|
+
|
147
|
+
unless value.is_a?(Numeric)
|
148
|
+
raise ValidationInvalidArgumentError
|
149
|
+
end
|
150
|
+
|
151
|
+
unless @type == :integer || @type == :float
|
152
|
+
raise ValidationIncompatibleError
|
153
|
+
end
|
154
|
+
|
155
|
+
@greater_than_or_equal_to_validation = GreaterThanOrEqualToValidation.new value
|
156
|
+
end
|
157
|
+
|
158
|
+
def validate_less_than value
|
159
|
+
if @less_than_validation
|
160
|
+
raise ValidationAlreadyExistsError
|
161
|
+
end
|
162
|
+
|
163
|
+
unless value.is_a?(Numeric)
|
164
|
+
raise ValidationInvalidArgumentError
|
165
|
+
end
|
166
|
+
|
167
|
+
unless @type == :integer || @type == :float
|
168
|
+
raise ValidationIncompatibleError
|
169
|
+
end
|
170
|
+
|
171
|
+
@less_than_validation = LessThanValidation.new value
|
172
|
+
end
|
173
|
+
|
174
|
+
def validate_less_than_or_equal_to value
|
175
|
+
if @less_than_or_equal_to_validation
|
176
|
+
raise ValidationAlreadyExistsError
|
177
|
+
end
|
178
|
+
|
179
|
+
unless value.is_a?(Numeric)
|
180
|
+
raise ValidationInvalidArgumentError
|
181
|
+
end
|
182
|
+
|
183
|
+
unless @type == :integer || @type == :float
|
184
|
+
raise ValidationIncompatibleError
|
185
|
+
end
|
186
|
+
|
187
|
+
@less_than_or_equal_to_validation = LessThanOrEqualToValidation.new value
|
188
|
+
end
|
189
|
+
|
190
|
+
def validate_format regexp
|
191
|
+
if @format_validation
|
192
|
+
raise ValidationAlreadyExistsError
|
193
|
+
end
|
194
|
+
|
195
|
+
unless regexp.is_a? Regexp
|
196
|
+
raise ValidationInvalidArgumentError
|
197
|
+
end
|
198
|
+
|
199
|
+
unless @type == :string || @type == :symbol
|
200
|
+
raise ValidationIncompatibleError
|
201
|
+
end
|
202
|
+
@format_validation = FormatValidation.new regexp
|
203
|
+
end
|
204
|
+
|
205
|
+
def validate_equal_to value
|
206
|
+
if @equal_to_validation
|
207
|
+
raise ValidationAlreadyExistsError
|
208
|
+
end
|
209
|
+
|
210
|
+
unless @type == :integer || @type == :float || @type == :string || @type == :symbol || @type == :boolean
|
211
|
+
raise ValidationIncompatibleError
|
212
|
+
end
|
213
|
+
|
214
|
+
@equal_to_validation = EqualToValidation.new value
|
215
|
+
end
|
216
|
+
|
217
|
+
def validate_in values
|
218
|
+
if @in_validation
|
219
|
+
raise ValidationAlreadyExistsError
|
220
|
+
end
|
221
|
+
|
222
|
+
unless values.is_a? Array
|
223
|
+
raise ValidationInvalidArgumentError
|
224
|
+
end
|
225
|
+
|
226
|
+
unless @type == :integer || @type == :float || @type == :string || @type == :symbol
|
227
|
+
raise ValidationIncompatibleError
|
228
|
+
end
|
229
|
+
|
230
|
+
@in_validation = InValidation.new values
|
231
|
+
end
|
232
|
+
|
233
|
+
def validate_not_in values
|
234
|
+
if @not_in_validation
|
235
|
+
raise ValidationAlreadyExistsError
|
236
|
+
end
|
237
|
+
|
238
|
+
unless values.is_a? Array
|
239
|
+
raise ValidationInvalidArgumentError
|
240
|
+
end
|
241
|
+
|
242
|
+
unless @type == :integer || @type == :float || @type == :string || @type == :symbol
|
243
|
+
raise ValidationIncompatibleError
|
244
|
+
end
|
245
|
+
|
246
|
+
@not_in_validation = NotInValidation.new values
|
247
|
+
end
|
248
|
+
|
249
|
+
def validate_length maximum: nil, minimum: nil, is: nil
|
250
|
+
if @length_validation
|
251
|
+
raise ValidationAlreadyExistsError
|
252
|
+
end
|
253
|
+
|
254
|
+
unless @type == :string || @type == :symbol
|
255
|
+
raise ValidationIncompatibleError
|
256
|
+
end
|
257
|
+
|
258
|
+
@length_validation = LengthValidation.new(maximum: maximum, minimum: minimum, is: is)
|
259
|
+
end
|
260
|
+
|
261
|
+
# returns true if every provided integer validation also returns true
|
262
|
+
def validate_integer! value
|
263
|
+
(greater_than_validation.nil? || greater_than_validation.validate!(value)) &&
|
264
|
+
(greater_than_or_equal_to_validation.nil? || greater_than_or_equal_to_validation.validate!(value)) &&
|
265
|
+
(less_than_validation.nil? || less_than_validation.validate!(value)) &&
|
266
|
+
(less_than_or_equal_to_validation.nil? || less_than_or_equal_to_validation.validate!(value)) &&
|
267
|
+
(format_validation.nil? || format_validation.validate!(value)) &&
|
268
|
+
(equal_to_validation.nil? || equal_to_validation.validate!(value)) &&
|
269
|
+
(in_validation.nil? || in_validation.validate!(value)) &&
|
270
|
+
(not_in_validation.nil? || not_in_validation.validate!(value)) &&
|
271
|
+
(length_validation.nil? || length_validation.validate!(value))
|
272
|
+
end
|
273
|
+
|
274
|
+
# returns true if every provided symbol validation also returns true
|
275
|
+
def validate_symbol! value
|
276
|
+
(format_validation.nil? || format_validation.validate!(value)) &&
|
277
|
+
(equal_to_validation.nil? || equal_to_validation.validate!(value)) &&
|
278
|
+
(in_validation.nil? || in_validation.validate!(value)) &&
|
279
|
+
(not_in_validation.nil? || not_in_validation.validate!(value)) &&
|
280
|
+
(length_validation.nil? || length_validation.validate!(value))
|
281
|
+
end
|
282
|
+
|
283
|
+
# returns true if every provided string validation also returns true
|
284
|
+
def validate_string! value
|
285
|
+
(format_validation.nil? || format_validation.validate!(value)) &&
|
286
|
+
(equal_to_validation.nil? || equal_to_validation.validate!(value)) &&
|
287
|
+
(in_validation.nil? || in_validation.validate!(value)) &&
|
288
|
+
(not_in_validation.nil? || not_in_validation.validate!(value)) &&
|
289
|
+
(length_validation.nil? || length_validation.validate!(value))
|
290
|
+
end
|
291
|
+
|
292
|
+
# returns true if every provided boolean validation also returns true
|
293
|
+
def validate_boolean! value
|
294
|
+
(equal_to_validation.nil? || equal_to_validation.validate!(value))
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class Arguments
|
6
|
+
class ArgumentDoesNotExistError < StandardError
|
7
|
+
def message
|
8
|
+
"This argument does not exist for this DSLMethod"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class ArgumentOrderingError < StandardError
|
13
|
+
def message
|
14
|
+
"Required arguments can not be added after optional ones"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ArgumentAlreadyExistsError < StandardError
|
19
|
+
def message
|
20
|
+
"An argument with this name already exists for this DSL method"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class RequestedOptionalArgumentIsRequiredError < StandardError
|
25
|
+
def message
|
26
|
+
"A specific argument which was expected to be optional was requested, but the argument found was flagged as required"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class RequestedRequiredArgumentIsOptionalError < StandardError
|
31
|
+
def message
|
32
|
+
"A specific argument which was expected to be required was requested, but the argument found was flagged as optional"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
@arguments = {}
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns an array of all this DSLMethods Argument objects.
|
41
|
+
def arguments
|
42
|
+
@arguments.values
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns an array of only the optional Argument objects on this DSLMethod.
|
46
|
+
def optional_arguments
|
47
|
+
arguments.filter(&:optional?)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns an array of only the required Argument objects on this DSLMethod.
|
51
|
+
def required_arguments
|
52
|
+
arguments.filter(&:required?)
|
53
|
+
end
|
54
|
+
|
55
|
+
# returns a specific Argument by it's name, if the Argument does not
|
56
|
+
# exist, then an error is raised
|
57
|
+
def argument name
|
58
|
+
if has_argument? name
|
59
|
+
@arguments[name]
|
60
|
+
else
|
61
|
+
raise ArgumentDoesNotExistError
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# returns a specific optional Argument by it's name, if the Argument does not
|
66
|
+
# exist, or if it is required, then an error is raised
|
67
|
+
def optional_argument name
|
68
|
+
arg = argument name
|
69
|
+
if arg.optional?
|
70
|
+
@arguments[name]
|
71
|
+
else
|
72
|
+
raise RequestedOptionalArgumentIsRequiredError
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# returns a specific required Argument by it's name, if the Argument does not
|
77
|
+
# exist, or if it is optional, then an error is raised
|
78
|
+
def required_argument name
|
79
|
+
arg = argument name
|
80
|
+
if arg.required?
|
81
|
+
@arguments[name]
|
82
|
+
else
|
83
|
+
raise RequestedRequiredArgumentIsOptionalError
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns `true` if an Argument with the provided name exists in this
|
88
|
+
# DSLMethod, otherwise it returns `false`.
|
89
|
+
def has_argument? name
|
90
|
+
@arguments.key? name
|
91
|
+
end
|
92
|
+
|
93
|
+
# Takes a method name, unique flag, required flag, and a block and creates
|
94
|
+
# a new Argument object.
|
95
|
+
#
|
96
|
+
# Argument `name` must be unique within the DSLMethod.
|
97
|
+
# `required` must be a boolean, and determines if this argument will be required
|
98
|
+
# or optional on the method which is exposed in our DSL.
|
99
|
+
def add_argument name, required, type, &block
|
100
|
+
if @arguments.key? name
|
101
|
+
raise ArgumentAlreadyExistsError
|
102
|
+
end
|
103
|
+
|
104
|
+
# required arguments may not come after optional ones
|
105
|
+
if required && optional_arguments.any?
|
106
|
+
raise ArgumentOrderingError
|
107
|
+
end
|
108
|
+
|
109
|
+
@arguments[name] = Argument.new(name, required, type, &block)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DSLCompose
|
4
|
+
class DSL
|
5
|
+
class DSLMethod
|
6
|
+
# This class is reponsible for parsing and executing method definitions
|
7
|
+
# within our internal DSL. These method definitions determine what methods
|
8
|
+
# will be available within our new dynamic DSL.
|
9
|
+
#
|
10
|
+
# This class is instantaited by the DSLCompose::DSL::DSLMethod class and the method definition
|
11
|
+
# part of our internal DSL is evaluated by passing a block to `instance_eval` on this class.
|
12
|
+
#
|
13
|
+
# An example of our internal DSL which includes a complex method definition:
|
14
|
+
# define_dsl :my_dsl do
|
15
|
+
# add_method :my_method, required: true do
|
16
|
+
# description "Description of my method"
|
17
|
+
# optional :my_optional_argument, :string do
|
18
|
+
# # ...
|
19
|
+
# end
|
20
|
+
# optional :my_optional_arg, String
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
class Interpreter
|
24
|
+
def initialize dsl_method
|
25
|
+
@dsl_method = dsl_method
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# sets the description of the DSLMethod
|
31
|
+
def description description
|
32
|
+
@dsl_method.set_description description
|
33
|
+
end
|
34
|
+
|
35
|
+
# adds a new optional argument to the DSLMethod
|
36
|
+
#
|
37
|
+
# name must be a symbol
|
38
|
+
# `type` can be either :integer, :boolean, :float, :string or :symbol
|
39
|
+
# `block` contains the argument definition and will be evaluated seperately
|
40
|
+
# by the Argument::Interpreter
|
41
|
+
def optional name, type, &block
|
42
|
+
@dsl_method.arguments.add_argument name, false, type, &block
|
43
|
+
end
|
44
|
+
|
45
|
+
# adds a new required argument to the DSLMethod
|
46
|
+
#
|
47
|
+
# name must be a symbol
|
48
|
+
# `type` can be either :integer, :boolean, :float, :string or :symbol
|
49
|
+
# `block` contains the argument definition and will be evaluated seperately
|
50
|
+
# by the Argument::Interpreter
|
51
|
+
def requires name, type, &block
|
52
|
+
@dsl_method.arguments.add_argument name, true, type, &block
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|