glue_gun_dsl 0.1.13 → 0.1.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/glue_gun/dsl.rb +130 -47
- 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: a573097a1db8e4af5573a1b0374e43dc12dcadc22f4e4a950bd6d5fe4a9084a1
|
4
|
+
data.tar.gz: 1db836fbee10ab0594495e5f137f0337ec62a8b90eeabc29bc55be0dab6ade9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad634073ed8206277b1eb502b2da7eff90e92cc820adcabc1dc647dee8e2f0c7cdf4ea7c2cc9fdd4b8a3b5f46caff7a6d4c55f82d3780a180b719af5729d4a51
|
7
|
+
data.tar.gz: 3048844dcbae257696ab142798ead0957b97bda029c151da4d9e5181b90d3da43099ecd6ec79784efb2499b0fd699a0dca2e24513e1fc20c461dae3648a4390d
|
data/lib/glue_gun/dsl.rb
CHANGED
@@ -28,7 +28,7 @@ module GlueGun
|
|
28
28
|
prepend ClassMethods
|
29
29
|
end
|
30
30
|
|
31
|
-
# Overriding ActiveModel.assign_attributes to ensure change propagation to
|
31
|
+
# Overriding ActiveModel.assign_attributes to ensure change propagation to dependencies
|
32
32
|
def assign_attributes(new_attributes)
|
33
33
|
super(new_attributes)
|
34
34
|
propagate_changes if initialized?
|
@@ -61,7 +61,10 @@ module GlueGun
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
|
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)
|
@@ -79,6 +82,7 @@ module GlueGun
|
|
79
82
|
elsif ActiveModel.version >= Gem::Version.new("5")
|
80
83
|
ActiveModel::Type::Value.new
|
81
84
|
end
|
85
|
+
|
82
86
|
# Override the attribute method to define custom setters
|
83
87
|
def attribute(name, type = DEFAULT_TYPE, **options)
|
84
88
|
super(name, type, **options)
|
@@ -97,10 +101,20 @@ module GlueGun
|
|
97
101
|
end
|
98
102
|
end
|
99
103
|
|
100
|
-
def dependency(component_type, &block)
|
101
|
-
|
102
|
-
|
103
|
-
|
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 }
|
113
|
+
else
|
114
|
+
dependency_builder = DependencyBuilder.new(component_type)
|
115
|
+
dependency_builder.instance_eval(&block)
|
116
|
+
dependency_definitions[component_type] = { builder: dependency_builder, array: is_array }
|
117
|
+
end
|
104
118
|
|
105
119
|
# Define singleton method to allow hardcoding dependencies in subclasses
|
106
120
|
define_singleton_method component_type do |option = nil, options = {}|
|
@@ -157,16 +171,57 @@ module GlueGun
|
|
157
171
|
end
|
158
172
|
|
159
173
|
def initialize_dependencies(attributes)
|
160
|
-
self.class.dependency_definitions.each do |component_type,
|
174
|
+
self.class.dependency_definitions.each do |component_type, definition|
|
161
175
|
value = attributes[component_type] || self.class.hardcoded_dependencies[component_type]
|
162
|
-
instance_variable_set("@#{component_type}", initialize_dependency(component_type, value))
|
176
|
+
instance_variable_set("@#{component_type}", initialize_dependency(component_type, value, definition))
|
163
177
|
end
|
164
178
|
end
|
165
179
|
|
166
|
-
def initialize_dependency(component_type, init_args = {})
|
167
|
-
|
180
|
+
def initialize_dependency(component_type, init_args = {}, definition = nil)
|
181
|
+
definition ||= self.class.dependency_definitions[component_type]
|
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)
|
194
|
+
end
|
195
|
+
|
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
|
168
206
|
|
169
|
-
|
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]
|
170
225
|
|
171
226
|
if init_args && init_args.is_a?(Hash) && init_args.key?(:option_name)
|
172
227
|
option_name = init_args[:option_name]
|
@@ -179,30 +234,24 @@ module GlueGun
|
|
179
234
|
|
180
235
|
raise ArgumentError, "Unknown #{component_type} option '#{option_name}'" unless option_config
|
181
236
|
|
182
|
-
|
183
|
-
|
184
|
-
# Build dependency attributes, including sourcing from parent
|
185
|
-
dep_attributes = build_dependency_attributes(option_config, dep_attributes)
|
237
|
+
[instantiate_dependency(option_config, init_args), option_config]
|
238
|
+
end
|
186
239
|
|
187
|
-
|
188
|
-
|
189
|
-
|
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)
|
190
248
|
end
|
191
249
|
|
192
|
-
|
193
|
-
|
194
|
-
# Keep track of dependencies for attribute binding
|
195
|
-
dependencies[component_type] = {
|
196
|
-
instance: dependency_instance,
|
197
|
-
option: option_config
|
198
|
-
}
|
199
|
-
|
200
|
-
dependency_instance
|
250
|
+
[dep, option_config]
|
201
251
|
end
|
202
252
|
|
203
253
|
def build_dependency_attributes(option_config, dep_attributes)
|
204
254
|
option_config.attributes.each do |attr_name, attr_config|
|
205
|
-
# If the attribute is already provided, use it
|
206
255
|
if dep_attributes.key?(attr_name)
|
207
256
|
value = dep_attributes[attr_name]
|
208
257
|
else
|
@@ -210,6 +259,8 @@ module GlueGun
|
|
210
259
|
send(attr_config.source)
|
211
260
|
elsif respond_to?(attr_name)
|
212
261
|
send(attr_name)
|
262
|
+
elsif instance_variable_defined?(:@parent) && @parent.respond_to?(attr_name)
|
263
|
+
@parent.send(attr_name)
|
213
264
|
else
|
214
265
|
attr_config.default
|
215
266
|
end
|
@@ -222,7 +273,7 @@ module GlueGun
|
|
222
273
|
end
|
223
274
|
|
224
275
|
def determine_option_name(component_type, init_args)
|
225
|
-
dependency_builder = self.class.dependency_definitions[component_type]
|
276
|
+
dependency_builder = self.class.dependency_definitions[component_type][:builder]
|
226
277
|
|
227
278
|
option_name = nil
|
228
279
|
|
@@ -256,11 +307,18 @@ module GlueGun
|
|
256
307
|
[option_name, init_args]
|
257
308
|
end
|
258
309
|
|
259
|
-
def instantiate_dependency(option_config,
|
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
|
260
320
|
dependency_class = option_config.class_name
|
261
|
-
|
262
|
-
dependency_instance.validate! if false # dependency_instance.respond_to?(:validate!)
|
263
|
-
dependency_instance
|
321
|
+
dependency_class.new(dep_attributes)
|
264
322
|
end
|
265
323
|
|
266
324
|
def propagate_changes
|
@@ -274,33 +332,58 @@ module GlueGun
|
|
274
332
|
end
|
275
333
|
|
276
334
|
def propagate_attribute_change(attr_name, value)
|
277
|
-
self.class.dependency_definitions.each do |component_type,
|
335
|
+
self.class.dependency_definitions.each do |component_type, _builder|
|
278
336
|
dependency_instance = send(component_type)
|
279
|
-
option_config = dependencies.dig(component_type, :option)
|
280
|
-
next unless option_config
|
281
337
|
|
282
|
-
|
283
|
-
|
284
|
-
end
|
338
|
+
if dependency_instance.is_a?(Array)
|
339
|
+
option_config = dependencies.dig(component_type, :option)
|
285
340
|
|
286
|
-
|
287
|
-
|
288
|
-
if dependency_instance.respond_to?("#{dep_attr_name}=")
|
289
|
-
dependency_instance.send("#{dep_attr_name}=",
|
290
|
-
block.call(value))
|
341
|
+
dependency_instance.zip(option_config).each do |dep, opt|
|
342
|
+
propagate_attribute_to_instance(attr_name, value, dep, opt)
|
291
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)
|
292
349
|
end
|
293
350
|
end
|
294
351
|
end
|
295
352
|
|
296
|
-
def
|
297
|
-
|
298
|
-
|
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|
|
299
378
|
option_class = option.class_name
|
300
379
|
value.is_a?(option_class)
|
301
380
|
end
|
302
381
|
end
|
303
382
|
|
383
|
+
def dependency_injected?(component_type, value)
|
384
|
+
injected_dependency(component_type, value).any?
|
385
|
+
end
|
386
|
+
|
304
387
|
def dependencies
|
305
388
|
@dependencies ||= {}
|
306
389
|
end
|
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.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
|
+
date: 2024-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|