glue_gun_dsl 0.1.14 → 0.1.15

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 204effd0afcc5b7a8b1ac6f80ec1ddde4f99039817b0fe84e1a6747c76c13e27
4
- data.tar.gz: 227f7029e97ef1639ffbbebf5b0d8273ff0c7a084b5950aa8040c9f91e3be26c
3
+ metadata.gz: a573097a1db8e4af5573a1b0374e43dc12dcadc22f4e4a950bd6d5fe4a9084a1
4
+ data.tar.gz: 1db836fbee10ab0594495e5f137f0337ec62a8b90eeabc29bc55be0dab6ade9b
5
5
  SHA512:
6
- metadata.gz: 3ee786e7b526c47e62de741a0fd0eb686e890d8e176e4424157d7bd4488f81e0750b7efb2d1d27ee0092e415d92b342ae7d4f6575e1c82ce932aaebcaf56cc26
7
- data.tar.gz: 67434b47dc06d5b258d5a1f1286859879c414b4131d17e66a8651378586312ff0b157825e45e2a939625b3a355a0dcbcff7691f0220d5f61cf6fbe8ba2933746
6
+ metadata.gz: ad634073ed8206277b1eb502b2da7eff90e92cc820adcabc1dc647dee8e2f0c7cdf4ea7c2cc9fdd4b8a3b5f46caff7a6d4c55f82d3780a180b719af5729d4a51
7
+ data.tar.gz: 3048844dcbae257696ab142798ead0957b97bda029c151da4d9e5181b90d3da43099ecd6ec79784efb2499b0fd699a0dca2e24513e1fc20c461dae3648a4390d
data/lib/glue_gun/dsl.rb CHANGED
@@ -61,7 +61,10 @@ module GlueGun
61
61
  end
62
62
  end
63
63
 
64
- normal_attributes.reverse_merge!(root_dir: detect_root_dir) if attribute_definitions.keys.include?(:root_dir)
64
+ if attribute_definitions.keys.include?(:root_dir) && attribute_definitions.dig(:root_dir, :options,
65
+ :default).nil?
66
+ normal_attributes.reverse_merge!(root_dir: detect_root_dir)
67
+ end
65
68
 
66
69
  # Call super to allow ActiveModel to assign attributes
67
70
  super(normal_attributes)
@@ -98,13 +101,19 @@ module GlueGun
98
101
  end
99
102
  end
100
103
 
101
- def dependency(component_type, factory_class = nil, &block)
102
- if factory_class
103
- dependency_definitions[component_type] = factory_class
104
+ def dependency(component_type, options = {}, factory_class = nil, &block)
105
+ if options.is_a?(Class)
106
+ factory_class = options
107
+ options = {}
108
+ end
109
+ is_array = options[:array] || false
110
+
111
+ if factory_class.present?
112
+ dependency_definitions[component_type] = { factory_class: factory_class, array: is_array }
104
113
  else
105
114
  dependency_builder = DependencyBuilder.new(component_type)
106
115
  dependency_builder.instance_eval(&block)
107
- dependency_definitions[component_type] = dependency_builder
116
+ dependency_definitions[component_type] = { builder: dependency_builder, array: is_array }
108
117
  end
109
118
 
110
119
  # Define singleton method to allow hardcoding dependencies in subclasses
@@ -170,16 +179,49 @@ module GlueGun
170
179
 
171
180
  def initialize_dependency(component_type, init_args = {}, definition = nil)
172
181
  definition ||= self.class.dependency_definitions[component_type]
173
-
174
- if definition.is_a?(Class) && definition.include?(GlueGun::DSL)
175
- # If the definition is a factory class, use it to create the dependency
176
- factory_instance = definition.new
177
- return factory_instance.send(:initialize_dependency, component_type, init_args)
182
+ is_array = definition[:array]
183
+
184
+ if is_array
185
+ dep = []
186
+ config = []
187
+ Array(init_args).each do |args|
188
+ d, c = initialize_single_dependency(component_type, args, definition)
189
+ dep.push(d)
190
+ config.push(c)
191
+ end
192
+ else
193
+ dep, config = initialize_single_dependency(component_type, init_args, definition)
178
194
  end
179
195
 
180
- return init_args if dependency_injected?(component_type, init_args)
196
+ dependencies[component_type] = {
197
+ instance: dep,
198
+ option: config
199
+ }
200
+
201
+ dep
202
+ end
203
+
204
+ def initialize_factory_dependency(component_type, init_args, definition)
205
+ factory_instance = definition[:factory_class].new
181
206
 
182
- dependency_builder = definition
207
+ # Pass the parent instance to the factory
208
+ factory_instance.instance_variable_set(:@parent, self)
209
+
210
+ dep_defs = factory_instance.dependency_definitions
211
+ definition = dep_defs[dep_defs.keys.first]
212
+
213
+ if dep_defs.key?(component_type)
214
+ factory_instance.send(:initialize_single_dependency, component_type, init_args, definition)
215
+ elsif dep_defs.keys.one?
216
+ factory_instance.send(:initialize_single_dependency, dep_defs.keys.first, init_args, definition)
217
+ else
218
+ raise ArgumentError,
219
+ "Don't know how to use Factory #{factory_instance.class} to build dependency '#{component_type}'"
220
+ end
221
+ end
222
+
223
+ def initialize_builder_dependency(component_type, init_args, definition)
224
+ dependency_builder = definition[:builder]
183
225
 
184
226
  if init_args && init_args.is_a?(Hash) && init_args.key?(:option_name)
185
227
  option_name = init_args[:option_name]
@@ -192,30 +234,24 @@ module GlueGun
192
234
 
193
235
  raise ArgumentError, "Unknown #{component_type} option '#{option_name}'" unless option_config
194
236
 
195
- dep_attributes = init_args.is_a?(Hash) ? init_args : {}
196
-
197
- # Build dependency attributes, including sourcing from parent
198
- dep_attributes = build_dependency_attributes(option_config, dep_attributes)
237
+ [instantiate_dependency(option_config, init_args), option_config]
238
+ end
199
239
 
200
- if dep_attributes.key?(:id)
201
- raise ArgumentError,
202
- "cannot bind attribute 'id' between #{self.class.name} and #{option_config.class_name}. ID is reserved for primary keys in Ruby on Rails"
240
+ def initialize_single_dependency(component_type, init_args, definition)
241
+ if dependency_injected?(component_type, init_args)
242
+ dep = init_args
243
+ option_config = injected_dependency(component_type, init_args)
244
+ elsif definition[:factory_class]
245
+ dep, option_config = initialize_factory_dependency(component_type, init_args, definition)
246
+ else
247
+ dep, option_config = initialize_builder_dependency(component_type, init_args, definition)
203
248
  end
204
249
 
205
- dependency_instance = instantiate_dependency(option_config, dep_attributes)
206
-
207
- # Keep track of dependencies for attribute binding
208
- dependencies[component_type] = {
209
- instance: dependency_instance,
210
- option: option_config
211
- }
212
-
213
- dependency_instance
250
+ [dep, option_config]
214
251
  end
215
252
 
216
253
  def build_dependency_attributes(option_config, dep_attributes)
217
254
  option_config.attributes.each do |attr_name, attr_config|
218
- # If the attribute is already provided, use it
219
255
  if dep_attributes.key?(attr_name)
220
256
  value = dep_attributes[attr_name]
221
257
  else
@@ -223,6 +259,8 @@ module GlueGun
223
259
  send(attr_config.source)
224
260
  elsif respond_to?(attr_name)
225
261
  send(attr_name)
262
+ elsif instance_variable_defined?(:@parent) && @parent.respond_to?(attr_name)
263
+ @parent.send(attr_name)
226
264
  else
227
265
  attr_config.default
228
266
  end
@@ -235,7 +273,7 @@ module GlueGun
235
273
  end
236
274
 
237
275
  def determine_option_name(component_type, init_args)
238
- dependency_builder = self.class.dependency_definitions[component_type]
276
+ dependency_builder = self.class.dependency_definitions[component_type][:builder]
239
277
 
240
278
  option_name = nil
241
279
 
@@ -269,11 +307,18 @@ module GlueGun
269
307
  [option_name, init_args]
270
308
  end
271
309
 
272
- def instantiate_dependency(option_config, dep_attributes)
310
+ def instantiate_dependency(option_config, init_args)
311
+ dep_attributes = init_args.is_a?(Hash) ? init_args : {}
312
+
313
+ # Build dependency attributes, including sourcing from parent
314
+ dep_attributes = build_dependency_attributes(option_config, dep_attributes)
315
+
316
+ if dep_attributes.key?(:id)
317
+ raise ArgumentError,
318
+ "cannot bind attribute 'id' between #{self.class.name} and #{option_config.class_name}. ID is reserved for primary keys in Ruby on Rails"
319
+ end
273
320
  dependency_class = option_config.class_name
274
- dependency_instance = dependency_class.new(dep_attributes)
275
- dependency_instance.validate! if false # dependency_instance.respond_to?(:validate!)
276
- dependency_instance
321
+ dependency_class.new(dep_attributes)
277
322
  end
278
323
 
279
324
  def propagate_changes
@@ -287,33 +332,58 @@ module GlueGun
287
332
  end
288
333
 
289
334
  def propagate_attribute_change(attr_name, value)
290
- self.class.dependency_definitions.each do |component_type, _dependency_builder|
335
+ self.class.dependency_definitions.each do |component_type, _builder|
291
336
  dependency_instance = send(component_type)
292
- option_config = dependencies.dig(component_type, :option)
293
- next unless option_config
294
337
 
295
- bound_attrs = option_config.attributes.select do |_, attr_config|
296
- (attr_config.source == attr_name.to_sym) || (attr_config.name == attr_name.to_sym)
297
- end
338
+ if dependency_instance.is_a?(Array)
339
+ option_config = dependencies.dig(component_type, :option)
298
340
 
299
- bound_attrs.each do |dep_attr_name, config_attr|
300
- block = config_attr.block.present? ? config_attr.block : proc { |att| att }
301
- if dependency_instance.respond_to?("#{dep_attr_name}=")
302
- dependency_instance.send("#{dep_attr_name}=",
303
- block.call(value))
341
+ dependency_instance.zip(option_config).each do |dep, opt|
342
+ propagate_attribute_to_instance(attr_name, value, dep, opt)
304
343
  end
344
+ else
345
+ option_config = dependencies.dig(component_type, :option)
346
+ next unless option_config
347
+
348
+ propagate_attribute_to_instance(attr_name, value, dependency_instance, option_config)
305
349
  end
306
350
  end
307
351
  end
308
352
 
309
- def dependency_injected?(component_type, value)
310
- dependency_builder = self.class.dependency_definitions[component_type]
311
- dependency_builder.option_configs.values.any? do |option|
353
+ def propagate_attribute_to_instance(attr_name, value, dependency_instance, option_config)
354
+ bound_attrs = option_config.attributes.select do |_, attr_config|
355
+ (attr_config.source == attr_name.to_sym) || (attr_config.name == attr_name.to_sym)
356
+ end
357
+
358
+ bound_attrs.each do |dep_attr_name, config_attr|
359
+ block = config_attr.block.present? ? config_attr.block : proc { |att| att }
360
+ if dependency_instance.respond_to?("#{dep_attr_name}=")
361
+ dependency_instance.send("#{dep_attr_name}=",
362
+ block.call(value))
363
+ end
364
+ end
365
+ end
366
+
367
+ def injected_dependency(component_type, value)
368
+ definition = self.class.dependency_definitions[component_type]
369
+ builder = definition[:builder]
370
+ factory = definition[:factory_class]
371
+
372
+ option_configs = if builder
373
+ builder.option_configs
374
+ else
375
+ factory.dependency_definitions.values.first.values.first.option_configs
376
+ end
377
+ option_configs.values.select do |option|
312
378
  option_class = option.class_name
313
379
  value.is_a?(option_class)
314
380
  end
315
381
  end
316
382
 
383
+ def dependency_injected?(component_type, value)
384
+ injected_dependency(component_type, value).any?
385
+ end
386
+
317
387
  def dependencies
318
388
  @dependencies ||= {}
319
389
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GlueGun
4
- VERSION = "0.1.14"
4
+ VERSION = "0.1.15"
5
5
  end
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.14
4
+ version: 0.1.15
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 00:00:00.000000000 Z
11
+ date: 2024-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel