glue_gun_dsl 0.1.16 → 0.1.18
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/lib/glue_gun/dsl.rb +194 -153
- data/lib/glue_gun/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1cf96906f1af3fd62ba4c0e7aa061d9d109aee45ced7284e7776cb74d7dca313
|
4
|
+
data.tar.gz: 47f2454a802ce7a9bd335e7413fd2851551eae2437d4de9bebb0f1f31ad82b53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f4be572fe72494ab001d7ea71ec0f35064d1914a7982ab026ffd12f40126dd01051c1594e9baf78ae3a6415b3bfb44d7524f512986af53dcaa0db3ab5924ba3
|
7
|
+
data.tar.gz: fcf9a586af6236a3595b6a215daca49239a5e7407ab4086626dbcc105f755a76a82ae45de536047a7a8464be0035a89b81e8c4ca5bb11dd1c7aca31eae049b97
|
data/lib/glue_gun/dsl.rb
CHANGED
@@ -106,16 +106,15 @@ module GlueGun
|
|
106
106
|
factory_class = options
|
107
107
|
options = {}
|
108
108
|
end
|
109
|
-
|
110
|
-
|
109
|
+
|
110
|
+
dependency_builder = DependencyBuilder.new(component_type)
|
111
111
|
|
112
112
|
if factory_class.present?
|
113
|
-
|
113
|
+
dependency_builder.set_factory_class(factory_class)
|
114
114
|
else
|
115
|
-
dependency_builder = DependencyBuilder.new(component_type)
|
116
115
|
dependency_builder.instance_eval(&block)
|
117
|
-
dependency_definitions[component_type] = { builder: dependency_builder, array: is_array, hash: is_hash }
|
118
116
|
end
|
117
|
+
dependency_definitions[component_type] = dependency_builder
|
119
118
|
|
120
119
|
# Define singleton method to allow hardcoding dependencies in subclasses
|
121
120
|
define_singleton_method component_type do |option = nil, options = {}|
|
@@ -178,29 +177,33 @@ module GlueGun
|
|
178
177
|
end
|
179
178
|
end
|
180
179
|
|
181
|
-
def initialize_dependency(component_type, init_args =
|
180
|
+
def initialize_dependency(component_type, init_args = nil, definition = nil)
|
182
181
|
definition ||= self.class.dependency_definitions[component_type]
|
183
|
-
is_array =
|
184
|
-
is_hash = definition
|
182
|
+
is_array = init_args.is_a?(Array)
|
183
|
+
is_hash = definition.is_hash?(init_args)
|
184
|
+
|
185
|
+
return nil if init_args.nil? && definition.default_option_name.nil?
|
185
186
|
|
186
187
|
if is_array
|
187
188
|
dep = []
|
188
189
|
config = []
|
189
190
|
Array(init_args).each do |args|
|
190
|
-
d, c = initialize_single_dependency(
|
191
|
+
d, c = definition.initialize_single_dependency(args, self)
|
191
192
|
dep.push(d)
|
192
193
|
config.push(c)
|
193
194
|
end
|
194
195
|
elsif is_hash
|
195
196
|
dep = {}
|
196
197
|
config = {}
|
198
|
+
definition.validate_hash_dependencies(init_args)
|
199
|
+
|
197
200
|
init_args.each do |key, args|
|
198
|
-
d, c = initialize_single_dependency(
|
201
|
+
d, c = definition.initialize_single_dependency(args, self)
|
199
202
|
dep[key] = d
|
200
203
|
config[key] = c
|
201
204
|
end
|
202
205
|
else
|
203
|
-
dep, config = initialize_single_dependency(
|
206
|
+
dep, config = definition.initialize_single_dependency(init_args, self)
|
204
207
|
end
|
205
208
|
|
206
209
|
dependencies[component_type] = {
|
@@ -211,126 +214,6 @@ module GlueGun
|
|
211
214
|
dep
|
212
215
|
end
|
213
216
|
|
214
|
-
def initialize_factory_dependency(component_type, init_args, definition)
|
215
|
-
factory_instance = definition[:factory_class].new
|
216
|
-
|
217
|
-
# Pass the parent instance to the factory
|
218
|
-
factory_instance.instance_variable_set(:@parent, self)
|
219
|
-
|
220
|
-
dep_defs = factory_instance.dependency_definitions
|
221
|
-
definition = dep_defs[dep_defs.keys.first]
|
222
|
-
|
223
|
-
if dep_defs.key?(component_type)
|
224
|
-
factory_instance.send(:initialize_single_dependency, component_type, init_args, definition)
|
225
|
-
elsif dep_defs.keys.one?
|
226
|
-
factory_instance.send(:initialize_single_dependency, dep_defs.keys.first, init_args, definition)
|
227
|
-
else
|
228
|
-
raise ArgumentError,
|
229
|
-
"Don't know how to use Factory #{factory_instance.class} to build dependency '#{component_type}'"
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
def initialize_builder_dependency(component_type, init_args, definition)
|
234
|
-
dependency_builder = definition[:builder]
|
235
|
-
|
236
|
-
if init_args && init_args.is_a?(Hash) && init_args.key?(:option_name)
|
237
|
-
option_name = init_args[:option_name]
|
238
|
-
init_args = init_args[:value]
|
239
|
-
else
|
240
|
-
option_name, init_args = determine_option_name(component_type, init_args)
|
241
|
-
end
|
242
|
-
|
243
|
-
option_config = dependency_builder.option_configs[option_name]
|
244
|
-
|
245
|
-
raise ArgumentError, "Unknown #{component_type} option '#{option_name}'" unless option_config
|
246
|
-
|
247
|
-
[instantiate_dependency(option_config, init_args), option_config]
|
248
|
-
end
|
249
|
-
|
250
|
-
def initialize_single_dependency(component_type, init_args, definition)
|
251
|
-
if dependency_injected?(component_type, init_args)
|
252
|
-
dep = init_args
|
253
|
-
option_config = injected_dependency(component_type, init_args)
|
254
|
-
elsif definition[:factory_class]
|
255
|
-
dep, option_config = initialize_factory_dependency(component_type, init_args, definition)
|
256
|
-
else
|
257
|
-
dep, option_config = initialize_builder_dependency(component_type, init_args, definition)
|
258
|
-
end
|
259
|
-
|
260
|
-
[dep, option_config]
|
261
|
-
end
|
262
|
-
|
263
|
-
def build_dependency_attributes(option_config, dep_attributes)
|
264
|
-
option_config.attributes.each do |attr_name, attr_config|
|
265
|
-
if dep_attributes.key?(attr_name)
|
266
|
-
value = dep_attributes[attr_name]
|
267
|
-
else
|
268
|
-
value = if attr_config.source && respond_to?(attr_config.source)
|
269
|
-
send(attr_config.source)
|
270
|
-
elsif respond_to?(attr_name)
|
271
|
-
send(attr_name)
|
272
|
-
elsif instance_variable_defined?(:@parent) && @parent.respond_to?(attr_name)
|
273
|
-
@parent.send(attr_name)
|
274
|
-
else
|
275
|
-
attr_config.default
|
276
|
-
end
|
277
|
-
value = attr_config.process_value(value, self) if attr_config.respond_to?(:process_value)
|
278
|
-
dep_attributes[attr_name] = value
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
dep_attributes
|
283
|
-
end
|
284
|
-
|
285
|
-
def determine_option_name(component_type, init_args)
|
286
|
-
dependency_builder = self.class.dependency_definitions[component_type][:builder]
|
287
|
-
|
288
|
-
option_name = nil
|
289
|
-
|
290
|
-
# Use when block if defined
|
291
|
-
if dependency_builder.when_block
|
292
|
-
result = instance_exec(init_args, &dependency_builder.when_block)
|
293
|
-
if result.is_a?(Hash) && result[:option]
|
294
|
-
option_name = result[:option]
|
295
|
-
as_attr = result[:as]
|
296
|
-
init_args = { as_attr => init_args } if as_attr && init_args
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
# Detect option from user input
|
301
|
-
if option_name.nil? && (init_args.is_a?(Hash) && init_args.keys.size == 1)
|
302
|
-
if dependency_builder.option_configs.key?(init_args.keys.first)
|
303
|
-
option_name = init_args.keys.first
|
304
|
-
init_args = init_args[option_name] # Extract the inner value
|
305
|
-
else
|
306
|
-
default_option = dependency_builder.get_option(dependency_builder.default_option_name)
|
307
|
-
raise ArgumentError, "Unknown #{component_type} option: #{init_args.keys.first}." unless default_option.only?
|
308
|
-
unless default_option.attributes.keys.include?(init_args.keys.first)
|
309
|
-
raise ArgumentError, "#{default_option.class_name} does not respond to #{init_args.keys.first}"
|
310
|
-
end
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
# Use default option if none determined
|
315
|
-
option_name ||= dependency_builder.default_option_name
|
316
|
-
|
317
|
-
[option_name, init_args]
|
318
|
-
end
|
319
|
-
|
320
|
-
def instantiate_dependency(option_config, init_args)
|
321
|
-
dep_attributes = init_args.is_a?(Hash) ? init_args : {}
|
322
|
-
|
323
|
-
# Build dependency attributes, including sourcing from parent
|
324
|
-
dep_attributes = build_dependency_attributes(option_config, dep_attributes)
|
325
|
-
|
326
|
-
if dep_attributes.key?(:id)
|
327
|
-
raise ArgumentError,
|
328
|
-
"cannot bind attribute 'id' between #{self.class.name} and #{option_config.class_name}. ID is reserved for primary keys in Ruby on Rails"
|
329
|
-
end
|
330
|
-
dependency_class = option_config.class_name
|
331
|
-
dependency_class.new(dep_attributes)
|
332
|
-
end
|
333
|
-
|
334
217
|
def propagate_changes
|
335
218
|
changed_attributes.each do |attr_name, _old_value|
|
336
219
|
new_value = read_attribute(attr_name)
|
@@ -380,26 +263,6 @@ module GlueGun
|
|
380
263
|
end
|
381
264
|
end
|
382
265
|
|
383
|
-
def injected_dependency(component_type, value)
|
384
|
-
definition = self.class.dependency_definitions[component_type]
|
385
|
-
builder = definition[:builder]
|
386
|
-
factory = definition[:factory_class]
|
387
|
-
|
388
|
-
option_configs = if builder
|
389
|
-
builder.option_configs
|
390
|
-
else
|
391
|
-
factory.dependency_definitions.values.first.values.first.option_configs
|
392
|
-
end
|
393
|
-
option_configs.values.select do |option|
|
394
|
-
option_class = option.class_name
|
395
|
-
value.is_a?(option_class)
|
396
|
-
end
|
397
|
-
end
|
398
|
-
|
399
|
-
def dependency_injected?(component_type, value)
|
400
|
-
injected_dependency(component_type, value).any?
|
401
|
-
end
|
402
|
-
|
403
266
|
def dependencies
|
404
267
|
@dependencies ||= {}
|
405
268
|
end
|
@@ -449,7 +312,7 @@ module GlueGun
|
|
449
312
|
end
|
450
313
|
|
451
314
|
class DependencyBuilder
|
452
|
-
attr_reader :component_type, :option_configs, :when_block, :is_only
|
315
|
+
attr_reader :component_type, :option_configs, :when_block, :is_only, :factory_class
|
453
316
|
|
454
317
|
def initialize(component_type)
|
455
318
|
@component_type = component_type
|
@@ -459,6 +322,180 @@ module GlueGun
|
|
459
322
|
@is_only = false
|
460
323
|
end
|
461
324
|
|
325
|
+
def set_factory_class(factory_class)
|
326
|
+
@factory_class = factory_class
|
327
|
+
end
|
328
|
+
|
329
|
+
def builder
|
330
|
+
if factory?
|
331
|
+
factory_instance = factory_class.new
|
332
|
+
dep_defs = factory_instance.dependency_definitions
|
333
|
+
dep_defs[dep_defs.keys.first]
|
334
|
+
else
|
335
|
+
self
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def get_option_configs
|
340
|
+
builder.option_configs
|
341
|
+
end
|
342
|
+
|
343
|
+
def allowed_configurations
|
344
|
+
get_option_configs.keys
|
345
|
+
end
|
346
|
+
|
347
|
+
def allowed_classes
|
348
|
+
get_option_configs.values
|
349
|
+
end
|
350
|
+
|
351
|
+
def factory?
|
352
|
+
@factory_class.present?
|
353
|
+
end
|
354
|
+
|
355
|
+
def builder?
|
356
|
+
!factory?
|
357
|
+
end
|
358
|
+
|
359
|
+
def is_hash?(init_args)
|
360
|
+
return false unless init_args.is_a?(Hash)
|
361
|
+
|
362
|
+
allowed_configs = allowed_configurations
|
363
|
+
return false if allowed_configs.count == 1 && allowed_configs == [:default]
|
364
|
+
|
365
|
+
if init_args.key?(:option_name)
|
366
|
+
allowed_configs.exclude?(init_args[:option_name])
|
367
|
+
else
|
368
|
+
init_args.keys.none? { |k| allowed_configs.include?(k) }
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
def initialize_factory_dependency(init_args, parent)
|
373
|
+
builder.initialize_single_dependency(init_args, parent)
|
374
|
+
end
|
375
|
+
|
376
|
+
def initialize_builder_dependency(init_args, parent)
|
377
|
+
if init_args && init_args.is_a?(Hash) && init_args.key?(:option_name)
|
378
|
+
option_name = init_args[:option_name]
|
379
|
+
init_args = init_args[:value]
|
380
|
+
else
|
381
|
+
option_name, init_args = determine_option_name(init_args)
|
382
|
+
end
|
383
|
+
|
384
|
+
option_config = option_configs[option_name]
|
385
|
+
|
386
|
+
raise ArgumentError, "Unknown #{component_type} option '#{option_name}'" unless option_config
|
387
|
+
|
388
|
+
[instantiate_dependency(option_config, init_args, parent), option_config]
|
389
|
+
end
|
390
|
+
|
391
|
+
def initialize_single_dependency(init_args, parent)
|
392
|
+
if dependency_injected?(init_args)
|
393
|
+
dep = init_args
|
394
|
+
option_config = injected_dependency(init_args)
|
395
|
+
elsif factory?
|
396
|
+
dep, option_config = initialize_factory_dependency(init_args, parent)
|
397
|
+
else
|
398
|
+
dep, option_config = initialize_builder_dependency(init_args, parent)
|
399
|
+
end
|
400
|
+
|
401
|
+
[dep, option_config]
|
402
|
+
end
|
403
|
+
|
404
|
+
def build_dependency_attributes(option_config, dep_attributes, parent)
|
405
|
+
option_config.attributes.each do |attr_name, attr_config|
|
406
|
+
if dep_attributes.key?(attr_name)
|
407
|
+
value = dep_attributes[attr_name]
|
408
|
+
else
|
409
|
+
value = if attr_config.source && parent.respond_to?(attr_config.source)
|
410
|
+
parent.send(attr_config.source)
|
411
|
+
elsif parent.respond_to?(attr_name)
|
412
|
+
parent.send(attr_name)
|
413
|
+
else
|
414
|
+
attr_config.default
|
415
|
+
end
|
416
|
+
value = attr_config.process_value(value, self) if attr_config.respond_to?(:process_value)
|
417
|
+
dep_attributes[attr_name] = value
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
dep_attributes
|
422
|
+
end
|
423
|
+
|
424
|
+
def determine_option_name(init_args)
|
425
|
+
option_name = nil
|
426
|
+
|
427
|
+
# Use when block if defined
|
428
|
+
if when_block
|
429
|
+
result = instance_exec(init_args, &when_block)
|
430
|
+
if result.is_a?(Hash) && result[:option]
|
431
|
+
option_name = result[:option]
|
432
|
+
as_attr = result[:as]
|
433
|
+
init_args = { as_attr => init_args } if as_attr && init_args
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
# Detect option from user input
|
438
|
+
if option_name.nil? && (init_args.is_a?(Hash) && init_args.keys.size == 1)
|
439
|
+
if option_configs.key?(init_args.keys.first)
|
440
|
+
option_name = init_args.keys.first
|
441
|
+
init_args = init_args[option_name] # Extract the inner value
|
442
|
+
else
|
443
|
+
default_option = get_option(default_option_name)
|
444
|
+
unless default_option.only?
|
445
|
+
raise ArgumentError,
|
446
|
+
"Unknown #{component_type} option: #{init_args.keys.first}."
|
447
|
+
end
|
448
|
+
unless default_option.attributes.keys.include?(init_args.keys.first)
|
449
|
+
raise ArgumentError, "#{default_option.class_name} does not respond to #{init_args.keys.first}"
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
# Use default option if none determined
|
455
|
+
option_name ||= default_option_name
|
456
|
+
|
457
|
+
[option_name, init_args]
|
458
|
+
end
|
459
|
+
|
460
|
+
def instantiate_dependency(option_config, init_args, parent)
|
461
|
+
dep_attributes = init_args.is_a?(Hash) ? init_args : {}
|
462
|
+
|
463
|
+
# Build dependency attributes, including sourcing from parent
|
464
|
+
dep_attributes = build_dependency_attributes(option_config, dep_attributes, parent)
|
465
|
+
|
466
|
+
if dep_attributes.key?(:id)
|
467
|
+
raise ArgumentError,
|
468
|
+
"cannot bind attribute 'id' between #{parent.class.name} and #{option_config.class_name}. ID is reserved for primary keys in Ruby on Rails"
|
469
|
+
end
|
470
|
+
dependency_class = option_config.class_name
|
471
|
+
dependency_class.new(dep_attributes)
|
472
|
+
end
|
473
|
+
|
474
|
+
def injected_dependency(value)
|
475
|
+
allowed_classes.detect do |option|
|
476
|
+
option_class = option.class_name
|
477
|
+
value.is_a?(option_class)
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
def dependency_injected?(value)
|
482
|
+
injected_dependency(value).present?
|
483
|
+
end
|
484
|
+
|
485
|
+
def validate_hash_dependencies(init_args)
|
486
|
+
allowed_configs = allowed_configurations
|
487
|
+
|
488
|
+
init_args.each do |_named_key, configuration|
|
489
|
+
next unless configuration.is_a?(Hash)
|
490
|
+
|
491
|
+
key = configuration.keys.first
|
492
|
+
if key.nil? || allowed_configs.exclude?(key)
|
493
|
+
raise ArgumentError,
|
494
|
+
"Unknown #{component_type} option: #{init_args.keys.first}."
|
495
|
+
end
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
462
499
|
# Support set_class and attribute for single-option dependencies
|
463
500
|
def set_class(class_name)
|
464
501
|
single_option.set_class(class_name)
|
@@ -482,7 +519,11 @@ module GlueGun
|
|
482
519
|
end
|
483
520
|
|
484
521
|
def default_option_name
|
485
|
-
|
522
|
+
if factory?
|
523
|
+
builder.default_option_name
|
524
|
+
else
|
525
|
+
@default_option_name || (@single_option ? :default : nil)
|
526
|
+
end
|
486
527
|
end
|
487
528
|
|
488
529
|
def when(&block)
|
data/lib/glue_gun/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glue_gun_dsl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Shollenberger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-10-
|
11
|
+
date: 2024-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|