glue_gun_dsl 0.1.14 → 0.1.15

Sign up to get free protection for your applications and to get access to all the features.
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