cloud-templates 0.1.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 +7 -0
- data/.rubocop.yml +29 -0
- data/.simplecov +6 -0
- data/Gemfile +2 -0
- data/LICENSE +201 -0
- data/NOTICE +13 -0
- data/README.md +124 -0
- data/Rakefile +27 -0
- data/cloud-templates.gemspec +27 -0
- data/examples/lib/user_directory/artifacts/catalogized.rb +11 -0
- data/examples/lib/user_directory/artifacts/group.rb +37 -0
- data/examples/lib/user_directory/artifacts/ided.rb +11 -0
- data/examples/lib/user_directory/artifacts/organization.rb +17 -0
- data/examples/lib/user_directory/artifacts/pathed.rb +22 -0
- data/examples/lib/user_directory/artifacts/person.rb +20 -0
- data/examples/lib/user_directory/artifacts/team.rb +31 -0
- data/examples/lib/user_directory/artifacts/unit.rb +24 -0
- data/examples/lib/user_directory/artifacts/user.rb +29 -0
- data/examples/lib/user_directory/render/etc/artifact_view.rb +15 -0
- data/examples/lib/user_directory/render/etc/composite_view.rb +26 -0
- data/examples/lib/user_directory/render/etc/group_view.rb +23 -0
- data/examples/lib/user_directory/render/etc/person_view.rb +19 -0
- data/examples/lib/user_directory/render/etc/registry.rb +33 -0
- data/examples/lib/user_directory/render/etc/user_view.rb +35 -0
- data/examples/lib/user_directory/render/etc.rb +3 -0
- data/examples/lib/user_directory/render/ldap/artifact_view.rb +27 -0
- data/examples/lib/user_directory/render/ldap/composite_view.rb +32 -0
- data/examples/lib/user_directory/render/ldap/group_view.rb +28 -0
- data/examples/lib/user_directory/render/ldap/organization_view.rb +26 -0
- data/examples/lib/user_directory/render/ldap/person_view.rb +39 -0
- data/examples/lib/user_directory/render/ldap/registry.rb +16 -0
- data/examples/lib/user_directory/render/ldap/unit_view.rb +26 -0
- data/examples/lib/user_directory/render/ldap/user_view.rb +39 -0
- data/examples/lib/user_directory/render/ldap.rb +3 -0
- data/examples/lib/user_directory/utils.rb +18 -0
- data/examples/lib/user_directory.rb +23 -0
- data/examples/lib_path.rb +2 -0
- data/examples/spec/spec_helper.rb +1 -0
- data/examples/spec/user_directory_spec.rb +568 -0
- data/lib/aws/templates/artifact.rb +140 -0
- data/lib/aws/templates/composite.rb +178 -0
- data/lib/aws/templates/exceptions.rb +221 -0
- data/lib/aws/templates/render/registry.rb +60 -0
- data/lib/aws/templates/render/utils/base_type_views.rb +131 -0
- data/lib/aws/templates/render/view.rb +127 -0
- data/lib/aws/templates/render.rb +72 -0
- data/lib/aws/templates/utils/artifact_storage.rb +141 -0
- data/lib/aws/templates/utils/contextualized/filters.rb +437 -0
- data/lib/aws/templates/utils/contextualized/hash.rb +13 -0
- data/lib/aws/templates/utils/contextualized/nil.rb +13 -0
- data/lib/aws/templates/utils/contextualized/proc.rb +13 -0
- data/lib/aws/templates/utils/contextualized.rb +113 -0
- data/lib/aws/templates/utils/default.rb +185 -0
- data/lib/aws/templates/utils/dependency/enumerable.rb +13 -0
- data/lib/aws/templates/utils/dependency/object.rb +46 -0
- data/lib/aws/templates/utils/dependency.rb +121 -0
- data/lib/aws/templates/utils/dependent.rb +28 -0
- data/lib/aws/templates/utils/inheritable.rb +52 -0
- data/lib/aws/templates/utils/late_bound.rb +89 -0
- data/lib/aws/templates/utils/memoized.rb +27 -0
- data/lib/aws/templates/utils/named.rb +19 -0
- data/lib/aws/templates/utils/options.rb +279 -0
- data/lib/aws/templates/utils/parametrized/constraints.rb +423 -0
- data/lib/aws/templates/utils/parametrized/getters.rb +293 -0
- data/lib/aws/templates/utils/parametrized/guarded.rb +32 -0
- data/lib/aws/templates/utils/parametrized/mapper.rb +73 -0
- data/lib/aws/templates/utils/parametrized/nested.rb +72 -0
- data/lib/aws/templates/utils/parametrized/transformations.rb +660 -0
- data/lib/aws/templates/utils/parametrized.rb +240 -0
- data/lib/aws/templates/utils.rb +219 -0
- data/lib/aws/templates.rb +16 -0
- data/spec/aws/templates/artifact_spec.rb +161 -0
- data/spec/aws/templates/composite_spec.rb +361 -0
- data/spec/aws/templates/render/utils/base_type_views_spec.rb +104 -0
- data/spec/aws/templates/render_spec.rb +62 -0
- data/spec/aws/templates/utils/as_named_spec.rb +31 -0
- data/spec/aws/templates/utils/contextualized/filters_spec.rb +108 -0
- data/spec/aws/templates/utils/contextualized_spec.rb +115 -0
- data/spec/aws/templates/utils/late_bound_spec.rb +52 -0
- data/spec/aws/templates/utils/options_spec.rb +67 -0
- data/spec/aws/templates/utils/parametrized/constraint_spec.rb +175 -0
- data/spec/aws/templates/utils/parametrized/getters_spec.rb +139 -0
- data/spec/aws/templates/utils/parametrized/transformation_spec.rb +314 -0
- data/spec/aws/templates/utils/parametrized_spec.rb +241 -0
- data/spec/spec_helper.rb +6 -0
- metadata +244 -0
@@ -0,0 +1,660 @@
|
|
1
|
+
require 'aws/templates/exceptions'
|
2
|
+
require 'aws/templates/utils/parametrized'
|
3
|
+
require 'aws/templates/utils/parametrized/nested'
|
4
|
+
require 'aws/templates/utils/parametrized/mapper'
|
5
|
+
require 'singleton'
|
6
|
+
|
7
|
+
module Aws
|
8
|
+
module Templates
|
9
|
+
module Utils
|
10
|
+
module Parametrized #:nodoc:
|
11
|
+
##
|
12
|
+
# Transformation functor class
|
13
|
+
#
|
14
|
+
# A transformation is a Proc accepting input value and providing output
|
15
|
+
# value which is expected to be a transformation of the input.
|
16
|
+
# The proc is executed in instance context so instance methods can
|
17
|
+
# be used for calculation.
|
18
|
+
#
|
19
|
+
# The class implements functor pattern through to_proc method and
|
20
|
+
# closure. Essentially, all transformations can be used everywhere where
|
21
|
+
# a block is expected.
|
22
|
+
#
|
23
|
+
# It provides protected method transform which should be overriden in
|
24
|
+
# all concrete transformation classes.
|
25
|
+
class Transformation
|
26
|
+
##
|
27
|
+
# Apply several transformation sequentially
|
28
|
+
#
|
29
|
+
# Useful when a few transformations need to be applied to a single value to get
|
30
|
+
# the final result
|
31
|
+
#
|
32
|
+
# === Example
|
33
|
+
#
|
34
|
+
# class Piece
|
35
|
+
# include Aws::Templates::Utils::Parametrized
|
36
|
+
#
|
37
|
+
# parameter :param,
|
38
|
+
# transform: as_chain(
|
39
|
+
# as_hash,
|
40
|
+
# as_object(Aws::Templates::Utils::AsNamed)
|
41
|
+
# )
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# i = Piece.new(param: [:name, 'Rex'])
|
45
|
+
# i.param.name # => 'Rex'
|
46
|
+
class AsChain < Transformation
|
47
|
+
attr_reader :components
|
48
|
+
|
49
|
+
def initialize(components)
|
50
|
+
@components = _check_components(components)
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
def transform(parameter, value, instance)
|
56
|
+
return if value.nil?
|
57
|
+
components.inject(value) { |acc, elem| instance.instance_exec(parameter, acc, &elem) }
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def _check_components(components)
|
63
|
+
result = components.to_a
|
64
|
+
|
65
|
+
invalid_components = result.reject { |component| component.respond_to?(:to_proc) }
|
66
|
+
raise "Invalid components: #{invalid_components}" unless invalid_components.empty?
|
67
|
+
|
68
|
+
result
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Transform input value into the object
|
74
|
+
#
|
75
|
+
# Input value can be either hash or object. The transformation performs
|
76
|
+
# nested object evaluation recusrsively as the input were Parametrized
|
77
|
+
# instance. As a parameter for the transformation you can
|
78
|
+
# specify either Module which mixes in Parametrized or to use
|
79
|
+
# a block which is to be evaluated as a part of Parametrized definition
|
80
|
+
# or both.
|
81
|
+
#
|
82
|
+
# With as_object transformation you can have as many nested levels
|
83
|
+
# as it's needed.
|
84
|
+
#
|
85
|
+
# === Example
|
86
|
+
#
|
87
|
+
# class Piece
|
88
|
+
# include Aws::Templates::Utils::Parametrized
|
89
|
+
#
|
90
|
+
# parameter :param1,
|
91
|
+
# :transform => as_object(Aws::Templates::Utils::AsNamed)
|
92
|
+
# parameter :param2, :transform => as_object {
|
93
|
+
# parameter :id, :description => 'Just ID',
|
94
|
+
# :constraint => not_nil
|
95
|
+
# }
|
96
|
+
# parameter :param3,
|
97
|
+
# :transform => as_object(Aws::Templates::Utils::AsNamed) {
|
98
|
+
# parameter :path, :description => 'Just path',
|
99
|
+
# :constraint => not_nil
|
100
|
+
# }
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# i = Piece.new
|
104
|
+
# i.param1 # => nil
|
105
|
+
# i = Piece.new(:param1 => {:name => 'Zed'})
|
106
|
+
# i.param1.name # => 'Zed'
|
107
|
+
# i = Piece.new(:param2 => {:id => 123})
|
108
|
+
# i.param2.id # => 123
|
109
|
+
# i = Piece.new(:param3 => {:path => 'a/b', :name => 'Rex'})
|
110
|
+
# i.param3.path # => 'a/b'
|
111
|
+
# i.param3.name # => 123
|
112
|
+
class AsObject < Transformation
|
113
|
+
attr_reader :klass
|
114
|
+
|
115
|
+
def initialize(scope, klass = nil, &definition)
|
116
|
+
@klass = if klass.nil?
|
117
|
+
Nested.create_class(scope)
|
118
|
+
elsif klass.is_a?(Class)
|
119
|
+
klass
|
120
|
+
elsif klass.is_a?(Module)
|
121
|
+
Nested.create_class(scope).with(klass)
|
122
|
+
else
|
123
|
+
raise "#{klass} is neither a class nor a module"
|
124
|
+
end
|
125
|
+
|
126
|
+
@klass.class_eval(&definition) unless definition.nil?
|
127
|
+
end
|
128
|
+
|
129
|
+
protected
|
130
|
+
|
131
|
+
def transform(_, value, instance)
|
132
|
+
return if value.nil?
|
133
|
+
klass.new instance.root,
|
134
|
+
if Utils.hashable?(value)
|
135
|
+
value
|
136
|
+
elsif Utils.parametrized?(value)
|
137
|
+
Mapper.new(value)
|
138
|
+
else
|
139
|
+
raise "Value #{value} doesn't have parameters"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
##
|
145
|
+
# Transform input value into a list
|
146
|
+
#
|
147
|
+
# Input value can be either an array or something which implements
|
148
|
+
# to_a method standard semantics. Each list entry is evaluated
|
149
|
+
# with specified constraints and transformations.
|
150
|
+
#
|
151
|
+
# With as_list transformation you can have as many nested levels
|
152
|
+
# as it's needed in terms of nested lists or nested objects.
|
153
|
+
#
|
154
|
+
# === Example
|
155
|
+
#
|
156
|
+
# class Piece
|
157
|
+
# include Aws::Templates::Utils::Parametrized
|
158
|
+
#
|
159
|
+
# parameter :param1, :transform => as_list(
|
160
|
+
# # alias for all elements. Plays a role during introspection
|
161
|
+
# :name => :element,
|
162
|
+
# # description of what the element represents
|
163
|
+
# :description => 'List element',
|
164
|
+
# # constraint for list element
|
165
|
+
# :constraint => not_nil
|
166
|
+
# )
|
167
|
+
# parameter :param2, :transform => as_list(
|
168
|
+
# :name => :element,
|
169
|
+
# :description => 'List element',
|
170
|
+
# :transform => as_list( # nested list
|
171
|
+
# :name => :sub_element,
|
172
|
+
# :description => 'Sub-list element',
|
173
|
+
# :constraint => not_nil
|
174
|
+
# )
|
175
|
+
# )
|
176
|
+
# parameter :param3, :transform => as_list(
|
177
|
+
# :name => :particle,
|
178
|
+
# :description => 'Small particle',
|
179
|
+
# :transform => as_object( # nested object
|
180
|
+
# Aws::Templates::Utils::AsNamed
|
181
|
+
# )
|
182
|
+
# )
|
183
|
+
# end
|
184
|
+
#
|
185
|
+
# i = Piece.new(:param1 => [1,2,3])
|
186
|
+
# i.param1 # => [1,2,3]
|
187
|
+
# i = Piece.new(:param1 => [1,nil,3])
|
188
|
+
# i.param1 # throws exception
|
189
|
+
# i = Piece.new(:param2 => [[1],[2],[3]])
|
190
|
+
# i.param2 # => [[1],[2],[3]]
|
191
|
+
# i = Piece.new(:param2 => [1,[2],[3]])
|
192
|
+
# i.param2 # throws exception
|
193
|
+
# i = Piece.new(:param2 => [[1],[nil],[3]])
|
194
|
+
# i.param2 # throws exception
|
195
|
+
# i = Piece.new(:param3 => [{:name => 'Zed'}])
|
196
|
+
# i.param3.first.name # => 'Zed'
|
197
|
+
class AsList < Transformation
|
198
|
+
attr_reader :sub_parameter
|
199
|
+
|
200
|
+
def initialize(klass = nil, options = nil)
|
201
|
+
return if options.nil?
|
202
|
+
|
203
|
+
@sub_parameter = Parameter.new(
|
204
|
+
options[:name],
|
205
|
+
klass,
|
206
|
+
description: options[:description],
|
207
|
+
transform: options[:transform],
|
208
|
+
constraint: options[:constraint]
|
209
|
+
)
|
210
|
+
end
|
211
|
+
|
212
|
+
protected
|
213
|
+
|
214
|
+
def transform(parameter, value, instance)
|
215
|
+
return if value.nil?
|
216
|
+
|
217
|
+
unless value.respond_to?(:to_a)
|
218
|
+
raise "#{parameter.name} is assigned to " \
|
219
|
+
"#{value.inspect} which is not a list"
|
220
|
+
end
|
221
|
+
|
222
|
+
if sub_parameter
|
223
|
+
value.to_a.map { |el| sub_parameter.process_value(instance, el) }
|
224
|
+
else
|
225
|
+
value.to_a
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
##
|
231
|
+
# Transform value with the specified render
|
232
|
+
#
|
233
|
+
# Input value can be anything which could be rendered by the
|
234
|
+
# specified render type. Returned value is rendered input.
|
235
|
+
#
|
236
|
+
# The transformation is useful when you have a document of some
|
237
|
+
# format embedded into a document of another format. An example
|
238
|
+
# could be Bash scripts embedded into AWS CFN template.
|
239
|
+
#
|
240
|
+
# === Example
|
241
|
+
#
|
242
|
+
# class Brush
|
243
|
+
# attr_reader :color
|
244
|
+
# attr_reader :thickness
|
245
|
+
# attr_reader :type
|
246
|
+
#
|
247
|
+
# def initialize(c, thick, t)
|
248
|
+
# @c = c
|
249
|
+
# @thick = thick
|
250
|
+
# @t = t
|
251
|
+
# end
|
252
|
+
# end
|
253
|
+
#
|
254
|
+
# class Circle
|
255
|
+
# attr_reader :radius
|
256
|
+
# attr_reader :brush
|
257
|
+
#
|
258
|
+
# def initialize(r, b)
|
259
|
+
# @radius = r
|
260
|
+
# @brush = b
|
261
|
+
# end
|
262
|
+
# end
|
263
|
+
#
|
264
|
+
# class Piece
|
265
|
+
# include Aws::Templates::Utils::Parametrized
|
266
|
+
#
|
267
|
+
# parameter :picture, :transform => as_rendered(
|
268
|
+
# # Render Type
|
269
|
+
# Graphics::Renders::JPEG,
|
270
|
+
# # parameter section for the render
|
271
|
+
# format: :base64
|
272
|
+
# )
|
273
|
+
# end
|
274
|
+
#
|
275
|
+
# i = Piece.new(picture: Circle.new(10, Brush.new(:red, 2, :dots)))
|
276
|
+
# i.picture # => <rendered representation>
|
277
|
+
class AsRendered < Transformation
|
278
|
+
attr_reader :type
|
279
|
+
attr_reader :parameters
|
280
|
+
|
281
|
+
def initialize(render_type, params)
|
282
|
+
@type = _check_render_type(render_type)
|
283
|
+
@parameters = params
|
284
|
+
end
|
285
|
+
|
286
|
+
protected
|
287
|
+
|
288
|
+
def transform(_, value, instance)
|
289
|
+
return if value.nil?
|
290
|
+
type.view_for(value, _compute_render_parameters(instance)).to_rendered
|
291
|
+
end
|
292
|
+
|
293
|
+
private
|
294
|
+
|
295
|
+
def _check_render_type(render_type)
|
296
|
+
unless render_type.respond_to?(:view_for)
|
297
|
+
raise(
|
298
|
+
"Wrong render type object #{params}. " \
|
299
|
+
'The instance should have #view_for method.'
|
300
|
+
)
|
301
|
+
end
|
302
|
+
|
303
|
+
render_type
|
304
|
+
end
|
305
|
+
|
306
|
+
def _compute_render_parameters(instance)
|
307
|
+
return if parameters.nil?
|
308
|
+
|
309
|
+
if parameters.respond_to?(:to_hash)
|
310
|
+
parameters
|
311
|
+
elsif parameters.respond_to?(:to_proc)
|
312
|
+
instance.instance_exec(¶meters)
|
313
|
+
else
|
314
|
+
parameters
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
##
|
320
|
+
# Convert input into integer
|
321
|
+
#
|
322
|
+
# Input value can be anything implementing :to_i method.
|
323
|
+
#
|
324
|
+
# === Example
|
325
|
+
#
|
326
|
+
# class Piece
|
327
|
+
# include Aws::Templates::Utils::Parametrized
|
328
|
+
#
|
329
|
+
# parameter :param, :transform => as_integer
|
330
|
+
# end
|
331
|
+
#
|
332
|
+
# i = Piece.new
|
333
|
+
# i.param # => nil
|
334
|
+
# i = Piece.new(:param => '23')
|
335
|
+
# i.param # => 23
|
336
|
+
class AsInteger < Transformation
|
337
|
+
include Singleton
|
338
|
+
|
339
|
+
protected
|
340
|
+
|
341
|
+
def transform(_, value, _)
|
342
|
+
return if value.nil?
|
343
|
+
Integer(value)
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
##
|
348
|
+
# Convert input into string
|
349
|
+
#
|
350
|
+
# Input value can be anything implementing :to_s method.
|
351
|
+
#
|
352
|
+
# === Example
|
353
|
+
#
|
354
|
+
# class Piece
|
355
|
+
# include Aws::Templates::Utils::Parametrized
|
356
|
+
#
|
357
|
+
# parameter :param, :transform => as_string
|
358
|
+
# end
|
359
|
+
#
|
360
|
+
# i = Piece.new
|
361
|
+
# i.param # => nil
|
362
|
+
# i = Piece.new(:param => 23)
|
363
|
+
# i.param # => '23'
|
364
|
+
class AsString < Transformation
|
365
|
+
include Singleton
|
366
|
+
|
367
|
+
protected
|
368
|
+
|
369
|
+
def transform(_, value, _)
|
370
|
+
return if value.nil?
|
371
|
+
String(value)
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
##
|
376
|
+
# Convert input into boolean
|
377
|
+
#
|
378
|
+
# Input value can be anything implementing :to_s method. Value considered false if it is:
|
379
|
+
# * +'false' as a string+
|
380
|
+
# * +FalseClass+
|
381
|
+
# Otherwise, value is true. If value is nil, it won't be replaced by "false"
|
382
|
+
#
|
383
|
+
# === Example
|
384
|
+
#
|
385
|
+
# class Piece
|
386
|
+
# include Aws::Templates::Utils::Parametrized
|
387
|
+
#
|
388
|
+
# parameter :param, :transform => as_boolean
|
389
|
+
# end
|
390
|
+
#
|
391
|
+
# i = Piece.new
|
392
|
+
# i.param # => false
|
393
|
+
# i = Piece.new(:param => 0)
|
394
|
+
# i.param # => true
|
395
|
+
class AsBoolean < Transformation
|
396
|
+
include Singleton
|
397
|
+
|
398
|
+
protected
|
399
|
+
|
400
|
+
def transform(_, value, _)
|
401
|
+
return if value.nil?
|
402
|
+
!value.to_s.casecmp('false').zero?
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
##
|
407
|
+
# Convert input into hash
|
408
|
+
#
|
409
|
+
# Input value can be anything implementing :to_hash method.
|
410
|
+
#
|
411
|
+
# === Example
|
412
|
+
#
|
413
|
+
# class Piece
|
414
|
+
# include Aws::Templates::Utils::Parametrized
|
415
|
+
#
|
416
|
+
# parameter :param, :transform => as_hash
|
417
|
+
# parameter :param2,
|
418
|
+
# transform: as_hash {
|
419
|
+
# value name: :number,
|
420
|
+
# description: 'Number',
|
421
|
+
# constraint: not_nil,
|
422
|
+
# transform: as_integer
|
423
|
+
# }
|
424
|
+
# end
|
425
|
+
#
|
426
|
+
# i = Piece.new
|
427
|
+
# i.param # => nil
|
428
|
+
# i = Piece.new(:param => [[1,2]])
|
429
|
+
# i.param # => {1=>2}
|
430
|
+
# i = Piece.new(:param2 => [[1,'3']])
|
431
|
+
# i.param # => {1=>3}
|
432
|
+
class AsHash < Transformation
|
433
|
+
include Parametrized.class_scope
|
434
|
+
|
435
|
+
def key(opts)
|
436
|
+
@key_parameter = _create_parameter(opts)
|
437
|
+
end
|
438
|
+
|
439
|
+
def value(opts)
|
440
|
+
@value_parameter = _create_parameter(opts)
|
441
|
+
end
|
442
|
+
|
443
|
+
def initialize(klass = nil, &blk)
|
444
|
+
@klass = klass
|
445
|
+
instance_eval(&blk) if blk
|
446
|
+
end
|
447
|
+
|
448
|
+
protected
|
449
|
+
|
450
|
+
def transform(_, value, instance)
|
451
|
+
return if value.nil?
|
452
|
+
|
453
|
+
Hash[
|
454
|
+
Hash[value].map do |k, v|
|
455
|
+
[
|
456
|
+
_process_value(@key_parameter, instance, k),
|
457
|
+
_process_value(@value_parameter, instance, v)
|
458
|
+
]
|
459
|
+
end
|
460
|
+
]
|
461
|
+
end
|
462
|
+
|
463
|
+
def _process_value(parameter, instance, value)
|
464
|
+
return value if parameter.nil?
|
465
|
+
parameter.process_value(instance, value)
|
466
|
+
end
|
467
|
+
|
468
|
+
private
|
469
|
+
|
470
|
+
def _create_parameter(opts)
|
471
|
+
Parameter.new(
|
472
|
+
opts[:name],
|
473
|
+
@klass,
|
474
|
+
description: opts[:description],
|
475
|
+
transform: opts[:transform],
|
476
|
+
constraint: opts[:constraint]
|
477
|
+
)
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
##
|
482
|
+
# Convert to a Ruby class
|
483
|
+
#
|
484
|
+
# The transformation allows to use elements of metaprogramming in the framework. It
|
485
|
+
# tries to transform passed value to a Ruby class.
|
486
|
+
#
|
487
|
+
# === Example
|
488
|
+
#
|
489
|
+
# class Piece
|
490
|
+
# include Aws::Templates::Utils::Parametrized
|
491
|
+
#
|
492
|
+
# parameter :param, :transform => as_module
|
493
|
+
# end
|
494
|
+
#
|
495
|
+
# i = Piece.new
|
496
|
+
# i.param # => nil
|
497
|
+
# i = Piece.new(:param => 'Object')
|
498
|
+
# i.param # => Object
|
499
|
+
class AsModule < Transformation
|
500
|
+
include Singleton
|
501
|
+
|
502
|
+
protected
|
503
|
+
|
504
|
+
def transform(_, value, _)
|
505
|
+
return if value.nil?
|
506
|
+
return value if value.is_a?(Module)
|
507
|
+
return _lookup(value.to_s) if value.respond_to?(:to_s)
|
508
|
+
raise "#{value} can't be transformed to a class"
|
509
|
+
end
|
510
|
+
|
511
|
+
private
|
512
|
+
|
513
|
+
PATH_REGEXP = Regexp.compile('::|[.]|/')
|
514
|
+
|
515
|
+
def _lookup(class_name)
|
516
|
+
target = class_name.split(PATH_REGEXP)
|
517
|
+
.inject(::Kernel) { |acc, elem| acc.const_get(elem) }
|
518
|
+
|
519
|
+
raise "#{class_name} == #{target} which is not a class" unless target.is_a?(Module)
|
520
|
+
|
521
|
+
target
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
##
|
526
|
+
# Creates closure with transformation invocation
|
527
|
+
#
|
528
|
+
# It's an interface method required for Transformation to expose
|
529
|
+
# functor properties. It encloses invocation of Transformation
|
530
|
+
# transform_wrapper method into a closure. The closure itself is
|
531
|
+
# executed in the context of Parametrized instance which provides
|
532
|
+
# proper set "self" variable.
|
533
|
+
#
|
534
|
+
# The closure itself accepts 2 parameters:
|
535
|
+
# * +parameter+ - the Parameter object which the transformation
|
536
|
+
# will be performed for
|
537
|
+
# * +value+ - parameter value to be transformed
|
538
|
+
# ...where instance is assumed from self
|
539
|
+
def to_proc
|
540
|
+
transform = self
|
541
|
+
|
542
|
+
lambda do |parameter, value|
|
543
|
+
transform.transform_wrapper(parameter, value, self)
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
##
|
548
|
+
# Wraps transformation-dependent method
|
549
|
+
#
|
550
|
+
# It wraps constraint-dependent "transform" method into a rescue block
|
551
|
+
# to standardize exception type and information provided by failed
|
552
|
+
# transformation calculation
|
553
|
+
# * +parameter+ - the Parameter object which the transformation will
|
554
|
+
# be performed for
|
555
|
+
# * +value+ - parameter value to be transformed
|
556
|
+
# * +instance+ - the instance value is transform
|
557
|
+
def transform_wrapper(parameter, value, instance)
|
558
|
+
transform(parameter, value, instance)
|
559
|
+
rescue StandardError
|
560
|
+
raise NestedParameterException.new(parameter)
|
561
|
+
end
|
562
|
+
|
563
|
+
protected
|
564
|
+
|
565
|
+
##
|
566
|
+
# Transform method
|
567
|
+
#
|
568
|
+
# * +parameter+ - the Parameter object which the transformation is
|
569
|
+
# performed for
|
570
|
+
# * +value+ - parameter value to be transformed
|
571
|
+
# * +instance+ - the instance value is transform
|
572
|
+
def transform(parameter, value, instance); end
|
573
|
+
end
|
574
|
+
|
575
|
+
##
|
576
|
+
# Syntax sugar for transformations definition
|
577
|
+
#
|
578
|
+
# It injects the methods as class-scope methods into mixing classes.
|
579
|
+
# The methods are factories to create particular type of transformation
|
580
|
+
class_scope do
|
581
|
+
##
|
582
|
+
# Chain a few transformations into a single one
|
583
|
+
#
|
584
|
+
# alias for AsChain class
|
585
|
+
def as_chain(*components)
|
586
|
+
Transformation::AsChain.new(components)
|
587
|
+
end
|
588
|
+
|
589
|
+
##
|
590
|
+
# Transform the value into an object
|
591
|
+
#
|
592
|
+
# alias for AsObject class
|
593
|
+
def as_object(klass = nil, &definition)
|
594
|
+
Transformation::AsObject.new(self, klass, &definition)
|
595
|
+
end
|
596
|
+
|
597
|
+
##
|
598
|
+
# Transform the value into a list
|
599
|
+
#
|
600
|
+
# alias for AsList class
|
601
|
+
def as_list(parameters = nil)
|
602
|
+
Transformation::AsList.new(self, parameters)
|
603
|
+
end
|
604
|
+
|
605
|
+
##
|
606
|
+
# Transform value with the specified render
|
607
|
+
#
|
608
|
+
# alias for AsRendered class
|
609
|
+
def as_rendered(render_type, params = nil, ¶ms_block)
|
610
|
+
Transformation::AsRendered.new(render_type, params || params_block)
|
611
|
+
end
|
612
|
+
|
613
|
+
##
|
614
|
+
# Convert input into integer
|
615
|
+
#
|
616
|
+
# alias for AsInteger class
|
617
|
+
def as_integer
|
618
|
+
Transformation::AsInteger.instance
|
619
|
+
end
|
620
|
+
|
621
|
+
##
|
622
|
+
# Convert input into string
|
623
|
+
#
|
624
|
+
# alias for AsString class
|
625
|
+
def as_string
|
626
|
+
Transformation::AsString.instance
|
627
|
+
end
|
628
|
+
|
629
|
+
##
|
630
|
+
# Convert input into boolean
|
631
|
+
#
|
632
|
+
# alias for AsBoolean class
|
633
|
+
def as_boolean
|
634
|
+
Transformation::AsBoolean.instance
|
635
|
+
end
|
636
|
+
|
637
|
+
##
|
638
|
+
# Convert input into hash
|
639
|
+
#
|
640
|
+
# alias for AsHash class
|
641
|
+
def as_hash(&blk)
|
642
|
+
Transformation::AsHash.new(self, &blk)
|
643
|
+
end
|
644
|
+
|
645
|
+
##
|
646
|
+
# Convert input into a class
|
647
|
+
#
|
648
|
+
# alias for AsModule class
|
649
|
+
def as_module
|
650
|
+
Transformation::AsModule.instance
|
651
|
+
end
|
652
|
+
end
|
653
|
+
|
654
|
+
class Nested #:nodoc:
|
655
|
+
include Parametrized
|
656
|
+
end
|
657
|
+
end
|
658
|
+
end
|
659
|
+
end
|
660
|
+
end
|