object_forge 0.3.0 → 0.4.1

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.
@@ -5,7 +5,12 @@ require_relative "forge_dsl"
5
5
  require_relative "molds"
6
6
 
7
7
  module ObjectForge
8
- # Object instantitation forge.
8
+ # Object building forge.
9
+ #
10
+ # Usually created through {.define} or {Forgeyard#define} using {ForgeDSL}.
11
+ # Alternatively, can be directly initalized with {Parameters} if you prefer not using the DSL.
12
+ #
13
+ # Then, {#forge} can be called to build instances of {#forge_target}.
9
14
  #
10
15
  # @since 0.1.0
11
16
  class Forge
@@ -14,62 +19,72 @@ module ObjectForge
14
19
  # through means other than {ForgeDSL}.
15
20
  #
16
21
  # @!attribute [r] attributes
17
- # Non-trait values of the attributes.
18
- # @return [Hash{Symbol => Any}]
22
+ # Default values of the attributes.
23
+ # @return [Hash{Symbol => Proc, Any}]
19
24
  #
20
25
  # @!attribute [r] traits
21
26
  # Attributes belonging to traits.
22
- # @return [Hash{Symbol => Hash{Symbol => Any}}]
23
- #
24
- # @!attribute [r] settings
25
- # A forge's settings.
26
- # Must include a +:mold+ key, containing an object that knows how to build the instance
27
- # with a +call+ method that takes a class and a hash of attributes.
27
+ # @return [Hash{Symbol => Hash{Symbol => Proc, Any}}]
28
+ #
29
+ # @!attribute [r] options
30
+ # A forge's options.
31
+ # Known options:
32
+ # - +:mold+ — a +call+able object that knows how to build the instance,
33
+ # taking a class and a hash of attributes.
34
+ # - +:crucible+ — a +call+able object that knows how to resolve attributes,
35
+ # taking a hash of initial attributes.
36
+ # - +:after_forge+/+:after_build+ — a +call+able object that is passed
37
+ # the forged instance and can do anything with it.
28
38
  # @since 0.3.0
29
39
  # @return [Hash{Symbol => Any}]
30
- Parameters = Struct.new(:attributes, :traits, :settings, keyword_init: true)
40
+ Parameters = Struct.new(:attributes, :traits, :options, keyword_init: true)
31
41
 
32
- # Define (and create) a forge using DSL.
42
+ # Define (and initialize) a forge using DSL.
33
43
  #
34
44
  # @see ForgeDSL
35
45
  # @thread_safety Thread-safe if DSL definition is thread-safe.
36
46
  #
37
- # @param forged [Class, Any] class or object to forge
47
+ # @param forge_target [Class, Any] class or object to forge
38
48
  # @param name [Symbol, nil] forge name
39
- # @yieldparam f [ForgeDSL]
49
+ # @yieldparam dsl [ForgeDSL]
40
50
  # @yieldreturn [void]
41
51
  # @return [Forge] forge
42
- def self.define(forged, name: nil, &)
43
- new(forged, ForgeDSL.new(&), name:)
52
+ def self.define(forge_target, name: nil, &)
53
+ new(forge_target, ForgeDSL.new(&), name:)
44
54
  end
45
55
 
46
- # @return [Symbol, nil] forge name
56
+ # @return [Symbol, nil] forge name, only used for identification purposes
47
57
  attr_reader :name
48
58
 
49
59
  # @return [Class, Any] class or object to forge
50
- attr_reader :forged
60
+ # @since 0.4.0
61
+ attr_reader :forge_target
62
+ alias target forge_target
51
63
 
52
64
  # @return [Parameters, ForgeDSL] forge parameters
53
65
  attr_reader :parameters
54
66
 
55
- # @param forged [Class, Any] class or object to forge
67
+ # @param forge_target [Class, Any] class or object to forge,
68
+ # will be passed to mold as +forge_target+ argument
56
69
  # @param parameters [Parameters, ForgeDSL] forge parameters
57
- # @param name [Symbol, nil] forge name;
58
- # only used for identification purposes
59
- def initialize(forged, parameters, name: nil)
70
+ # @param name [Symbol, nil] forge name
71
+ #
72
+ # @raise [ObjectInterfaceError] if forge options do not have expected interface;
73
+ # see {Parameters#options} for details
74
+ def initialize(forge_target, parameters, name: nil)
60
75
  @name = name
61
- @forged = forged
76
+ @forge_target = forge_target
62
77
  @parameters = parameters
63
- @mold = determine_mold(forged, parameters.settings[:mold])
78
+
79
+ options = @parameters.options
80
+ @crucible = determine_crucible(options)
81
+ @mold = determine_mold(forge_target, options)
82
+ @after_forge_hook = determine_after_forge_hook(options)
64
83
  end
65
84
 
66
- # Forge a new instance.
85
+ # Forge a new instance, applying attributes to forge target.
67
86
  #
68
- # @overload forge(*traits, **overrides, &)
69
- # @overload forge(traits, overrides, &)
70
- #
71
- # Positional arguments are taken as trait names, keyword arguments as attribute overrides,
72
- # unless there are exactly two positional arguments: an array and a hash.
87
+ # Positional arguments are taken as trait names, keyword arguments as attribute overrides.
73
88
  #
74
89
  # All traits and overrides are applied in argument order,
75
90
  # with overrides always applied after traits.
@@ -80,13 +95,16 @@ module ObjectForge
80
95
  # +traits+ and +overrides+ are thread-safe.
81
96
  #
82
97
  # @param traits [Array<Symbol>] traits to apply
83
- # @param overrides [Hash{Symbol => Any}] attribute overrides
98
+ # @param overrides [Hash{Symbol => Proc, Any}] attribute overrides
84
99
  # @yieldparam object [Any] forged instance
85
100
  # @yieldreturn [void]
86
- # @return [Any] built instance
101
+ # @return [Any] forged instance
102
+ #
103
+ # @raise [ArgumentError] if a trait name is unknown
87
104
  def forge(*traits, **overrides)
88
105
  resolved_attributes = resolve_attributes(traits, overrides)
89
- instance = @mold.call(forged: @forged, attributes: resolved_attributes)
106
+ instance = @mold.call(forge_target: @forge_target, attributes: resolved_attributes)
107
+ @after_forge_hook&.call(instance)
90
108
  yield instance if block_given?
91
109
  instance
92
110
  end
@@ -96,31 +114,84 @@ module ObjectForge
96
114
 
97
115
  private
98
116
 
117
+ # Get a crucible object based on parameters.
118
+ #
119
+ # It's either the object provided in options, or {Crucible}.
120
+ #
121
+ # @param options [Hash]
122
+ # @option options [#call, nil] :crucible
123
+ # @return [#call]
124
+ #
125
+ # @raise [ObjectInterfaceError]
126
+ #
127
+ # @since 0.4.0
128
+ def determine_crucible(options)
129
+ crucible = options[:crucible] || Crucible
130
+
131
+ unless crucible.respond_to?(:call)
132
+ raise ObjectInterfaceError, "crucible must respond to #call"
133
+ end
134
+
135
+ crucible
136
+ end
137
+
99
138
  # Get appropriate mold based on parameters.
100
139
  #
101
140
  # If +mold+ is already set, it will be used directly, or,
102
141
  # if it is Class, it will be wrapped in {Molds::WrappedMold} if posssible.
103
- # If +nil+, a mold will be selected based on +forged+ class.
142
+ # If +nil+, a mold will be selected based on +forge_target+ class.
104
143
  #
105
- # @param forged [Class, Any]
106
- # @param mold [#call, Class, nil]
144
+ # @param forge_target [Class, Any]
145
+ # @param options [Hash]
146
+ # @option options [#call, Class, nil] :mold
107
147
  # @return [#call]
108
148
  #
109
- # @raise [MoldError]
149
+ # @raise [ObjectInterfaceError]
110
150
  #
111
151
  # @since 0.3.0
112
- def determine_mold(forged, mold)
113
- Molds.wrap_mold(mold) || Molds.mold_for(forged)
152
+ def determine_mold(forge_target, options)
153
+ Molds.wrap_mold(options[:mold]) || Molds.mold_for(forge_target)
154
+ end
155
+
156
+ # Get after-forge hook if specified.
157
+ #
158
+ # Both +:after_forge+ and +:after_build+ are accepted, but +:after_forge+
159
+ # wins if both are present.
160
+ #
161
+ # @param options [Hash]
162
+ # @option options [#call, nil] :after_forge
163
+ # @option options [#call, nil] :after_build
164
+ # @return [#call, nil]
165
+ #
166
+ # @raise [ObjectInterfaceError]
167
+ #
168
+ # @since 0.4.0
169
+ def determine_after_forge_hook(options)
170
+ hook = options[:after_forge] || options[:after_build] || nil
171
+
172
+ unless hook.nil? || hook.respond_to?(:call)
173
+ raise ObjectInterfaceError, "after-forge hook must respond to #call"
174
+ end
175
+
176
+ hook
114
177
  end
115
178
 
116
179
  # Resolve attributes using default attributes, specified traits and overrides.
117
180
  #
118
181
  # @param traits [Array<Symbol>]
119
- # @param overrides [Hash{Symbol => Any}]
182
+ # @param overrides [Hash{Symbol => Proc, Any}]
120
183
  # @return [Hash{Symbol => Any}]
184
+ #
185
+ # @raise [ArgumentError]
121
186
  def resolve_attributes(traits, overrides)
122
- attributes = @parameters.attributes.merge(*@parameters.traits.values_at(*traits), overrides)
123
- Crucible.new(attributes).resolve!
187
+ unless (unknown_traits = traits.difference(@parameters.traits.keys)).empty?
188
+ raise ArgumentError,
189
+ "unknown traits for forge#{" #{name}" if name}: #{unknown_traits.join(", ")}"
190
+ end
191
+
192
+ trait_attributes = @parameters.traits.values_at(*traits) # : Array[Hash[Symbol, ObjectForge::attribute]]
193
+ attributes = @parameters.attributes.merge(*trait_attributes, overrides)
194
+ @crucible.call(attributes)
124
195
  end
125
196
  end
126
197
  end
@@ -27,8 +27,8 @@ module ObjectForge
27
27
  # @return [Hash{Symbol => Hash{Symbol => Proc}}] trait definitions
28
28
  attr_reader :traits
29
29
 
30
- # @return [Hash{Symbol => Any}] settings for forge, such as mold
31
- attr_reader :settings
30
+ # @return [Hash{Symbol => Any}] options for forge, such as mold
31
+ attr_reader :options
32
32
 
33
33
  # Define forge's parameters through DSL.
34
34
  #
@@ -39,7 +39,7 @@ module ObjectForge
39
39
  #
40
40
  # @example with block parameter
41
41
  # ForgeDSL.new do |f|
42
- # f.mold = ObjectForge::Molds::KeywordsMolds.new
42
+ # f.mold = ObjectForge::Molds::KeywordsMold.new
43
43
  # f.attribute(:name) { "Name" }
44
44
  # f[:description] { name.upcase }
45
45
  # f.duration { rand(1000) }
@@ -47,27 +47,27 @@ module ObjectForge
47
47
  #
48
48
  # @example without block parameter
49
49
  # ForgeDSL.new do
50
- # self.mold = ::ObjectForge::Molds::KeywordsMolds.new
50
+ # self.mold = ::ObjectForge::Molds::KeywordsMold.new
51
51
  # attribute(:name) { "Name" }
52
52
  # self[:description] { name.upcase }
53
53
  # duration { rand(1000) }
54
54
  # end
55
55
  #
56
- # @yieldparam f [ForgeDSL] self
56
+ # @yieldparam dsl [ForgeDSL] self
57
57
  # @yieldreturn [void]
58
58
  def initialize(&dsl)
59
59
  super
60
60
  @attributes = {}
61
61
  @sequences = {}
62
62
  @traits = {}
63
- @settings = {}
63
+ @options = {}
64
64
 
65
65
  dsl.arity.zero? ? instance_exec(&dsl) : yield(self)
66
66
 
67
67
  freeze
68
68
  end
69
69
 
70
- # Freezes the instance, including +settings+, +attributes+, +sequences+ and +traits+.
70
+ # Freezes the instance, including +options+, +attributes+, +sequences+ and +traits+.
71
71
  # Prevents further responses through +#method_missing+.
72
72
  #
73
73
  # @note Called automatically in {#initialize}.
@@ -78,40 +78,43 @@ module ObjectForge
78
78
  @attributes.freeze
79
79
  @sequences.freeze
80
80
  @traits.freeze
81
- @settings.freeze
81
+ @options.freeze
82
82
  self
83
83
  end
84
84
 
85
- # Set a value for a forge's setting.
85
+ # Set a value for a forge's option.
86
86
  #
87
- # Possible settings depend on used forge, but for default {Forge} a +mold+ is expected.
87
+ # Possible options depend on used forge, but for default {Forge} a +:mold+ is expected.
88
+ # Check its documentation for full list of available options.
88
89
  #
89
- # It is also possible to set settings through +method_missing+, using name with a +=+ suffix.
90
+ # It is also possible to set options through +method_missing+, using name with a +=+ suffix.
90
91
  #
91
92
  # @see Molds
93
+ # @see Forge::Parameters#options
92
94
  #
93
95
  # @example
94
- # f.setting(:mold, ->(forged:, attributes:, **) { forge.new(**attributes) })
96
+ # f.option(:mold, ->(forge_target:, attributes:, **) { forge.new(**attributes) })
95
97
  # f.mold = ObjectForge::Molds::SingleArgumentMold.new
96
98
  #
97
- # @param name [Sumbol] setting name
98
- # @param value [Any] value for the setting
99
- # @return [Symbol] setting name
99
+ # @param name [Symbol] option name
100
+ # @param value [Any] value for the option
101
+ # @return [Symbol] option name
100
102
  #
101
- # @raise [ArgumentError] if +name+ is not a Symbol
102
- def setting(name, value)
103
+ # @raise [TypeError] if +name+ is not a Symbol
104
+ def option(name, value)
103
105
  unless ::Symbol === name
104
- raise ::ArgumentError, "setting name must be a Symbol, #{name.class} given"
106
+ raise ::TypeError, "option name must be a Symbol, #{name.class} given (in #{name.inspect})"
105
107
  end
108
+ raise DSLError, "option definition does not take a block (in #{name.inspect})" if block_given?
106
109
 
107
- @settings[name] = value
110
+ @options[name] = value
108
111
 
109
112
  name
110
113
  end
111
114
 
112
115
  # Define an attribute, possibly transient.
113
116
  #
114
- # DSL does not know or care what attributes the forged class has,
117
+ # DSL does not know or care what attributes the target class has,
115
118
  # so the only difference between "real" and "transient" attributes
116
119
  # is how the class itself treats them.
117
120
  #
@@ -125,6 +128,7 @@ module ObjectForge
125
128
  # f.attribute(:name) { "Name" }
126
129
  # f[:description] { name.downcase }
127
130
  # f.duration { rand(1000) }
131
+ #
128
132
  # @example using conflicting and reserved names
129
133
  # f.attribute(:[]) { "Brackets" }
130
134
  # f.attribute(:[]=) { "#{self[:[]]} are brackets" }
@@ -134,11 +138,11 @@ module ObjectForge
134
138
  # @yieldreturn [Any] attribute value
135
139
  # @return [Symbol] attribute name
136
140
  #
137
- # @raise [ArgumentError] if +name+ is not a Symbol
141
+ # @raise [TypeError] if +name+ is not a Symbol
138
142
  # @raise [DSLError] if no block is given
139
143
  def attribute(name, &definition)
140
144
  unless ::Symbol === name
141
- raise ::ArgumentError,
145
+ raise ::TypeError,
142
146
  "attribute name must be a Symbol, #{name.class} given (in #{name.inspect})"
143
147
  end
144
148
  unless block_given?
@@ -166,9 +170,11 @@ module ObjectForge
166
170
  # f.sequence(:date, Date.today)
167
171
  # f.sequence(:id) { _1.to_s }
168
172
  # f.sequence(:dated_id, 10) { |n| "#{Date.today}/#{n}-#{id}" }
173
+ #
169
174
  # @example using external sequence
170
175
  # seq = Sequence.new(1)
171
176
  # f.sequence(:global_id, seq)
177
+ #
172
178
  # @example sequence reuse
173
179
  # f.sequence(:id, "a") # => "a", "b", ...
174
180
  # f.trait :new_id do
@@ -181,18 +187,18 @@ module ObjectForge
181
187
  # @yieldreturn [Any] attribute value
182
188
  # @return [Symbol] attribute name
183
189
  #
184
- # @raise [ArgumentError] if +name+ is not a Symbol
185
- # @raise [DSLError] if +initial+ does not respond to #succ and is not a {Sequence}
190
+ # @raise [TypeError] if +name+ is not a Symbol
191
+ # @raise [ObjectInterfaceError] if +initial+ does not respond to #succ and is not a {Sequence}
186
192
  def sequence(name, initial = 1, **nil, &)
187
193
  unless ::Symbol === name
188
- raise ::ArgumentError,
194
+ raise ::TypeError,
189
195
  "sequence name must be a Symbol, #{name.class} given (in #{name.inspect})"
190
196
  end
191
197
 
192
198
  seq = @sequences[name] ||= Sequence.new(initial)
193
199
 
194
200
  if block_given?
195
- attribute(name) { instance_exec(seq.next, &) }
201
+ attribute(name) { instance_exec(seq.next, &) } # steep:ignore BlockTypeMismatch
196
202
  else
197
203
  attribute(name) { seq.next }
198
204
  end
@@ -210,6 +216,7 @@ module ObjectForge
210
216
  # f.name { "***xXxSPECIALxXx***" }
211
217
  # f.sequence(:special_id) { "~~~ SpEcIaL #{_1} ~~~" }
212
218
  # end
219
+ #
213
220
  # @example externally defined trait
214
221
  # # Variable defined outside of DSL:
215
222
  # success_trait = ->(ft) do
@@ -227,13 +234,12 @@ module ObjectForge
227
234
  # @yieldreturn [void]
228
235
  # @return [Symbol] trait name
229
236
  #
230
- # @raise [ArgumentError] if +name+ is not a Symbol
237
+ # @raise [TypeError] if +name+ is not a Symbol
231
238
  # @raise [DSLError] if no block is given
232
239
  # @raise [DSLError] if called inside of another trait definition
233
240
  def trait(name, **nil)
234
241
  unless ::Symbol === name
235
- raise ::ArgumentError,
236
- "trait name must be a Symbol, #{name.class} given (in #{name.inspect})"
242
+ raise ::TypeError, "trait name must be a Symbol, #{name.class} given (in #{name.inspect})"
237
243
  end
238
244
  if @current_trait
239
245
  raise DSLError, "can not define trait inside of another trait (in #{name.inspect})"
@@ -261,12 +267,12 @@ module ObjectForge
261
267
 
262
268
  private
263
269
 
264
- # Define an attribute (like +name+) or set a setting (like +name=+) using a shorthand.
270
+ # Define an attribute (like +name+) or set a option (like +name=+) using a shorthand.
265
271
  #
266
272
  # Can not be used with reserved names.
267
273
  # Trying to use a conflicting name will lead to usual issues
268
274
  # with calling random methods.
269
- # When in doubt, use {#attribute} or {#setting} instead.
275
+ # When in doubt, use {#attribute} or {#option} instead.
270
276
  #
271
277
  # Reserved names are:
272
278
  # - all names ending in +?+, +!+
@@ -274,29 +280,32 @@ module ObjectForge
274
280
  # (operators, +`+, +[]+, +[]=+)
275
281
  # - +rand+
276
282
  #
277
- # @param name [Symbol] attribute or setting name
278
- # @param value [Any] value for setting
283
+ # @param name [Symbol] attribute or option name
284
+ # @param value [Any] value for option
279
285
  # @yieldreturn [Any] attribute value
280
- # @return [Symbol] attribute or setting name
286
+ # @return [Symbol] attribute or option name
281
287
  #
282
288
  # @raise [DSLError] if a reserved +name+ is used
283
289
  def method_missing(name, value = nil, **nil, &)
284
290
  return super(name) if frozen?
285
- if valid_setting_method?(name)
286
- return setting(name[...-1].to_sym, value) # steep:ignore NoMethod
291
+
292
+ if valid_option_method?(name)
293
+ # Intentionally passing block to `option` to trigger DSLError if it is present.
294
+ return option(name[...-1].to_sym, value, &) # steep:ignore NoMethod, UnexpectedBlockGiven
287
295
  end
288
- return attribute(name, &) if respond_to_missing?(name, false)
296
+ # Block can be missing, but `attribute` will raise if it is.
297
+ return attribute(name, &) if respond_to_missing?(name, false) # steep:ignore BlockTypeMismatch
289
298
 
290
299
  raise DSLError, "#{name.inspect} is a reserved name (in #{name.inspect})"
291
300
  end
292
301
 
293
302
  def respond_to_missing?(name, _include_all)
294
- return false if frozen?
303
+ return super if frozen?
295
304
 
296
305
  !name.end_with?("?", "!") && !name.match?(/\A(?=\p{ASCII})\P{Word}/) && name != :rand
297
306
  end
298
307
 
299
- def valid_setting_method?(name)
308
+ def valid_option_method?(name)
300
309
  name.match?(/\A\p{Word}.*=\z/)
301
310
  end
302
311
  end
@@ -22,12 +22,12 @@ module ObjectForge
22
22
  # @see Forge.define
23
23
  #
24
24
  # @param name [Symbol] name to register forge under
25
- # @param forged [Class, Any] class or object to forge
26
- # @yieldparam f [ForgeDSL]
25
+ # @param forge_target [Class, Any] class or object to forge
26
+ # @yieldparam dsl [ForgeDSL]
27
27
  # @yieldreturn [void]
28
28
  # @return [Forge] forge
29
- def define(name, forged, &)
30
- register(name, Forge.define(forged, name: name, &))
29
+ def define(name, forge_target, &)
30
+ register(name, Forge.define(forge_target, name: name, &))
31
31
  end
32
32
 
33
33
  # Add a forge under a specified name.
@@ -59,14 +59,15 @@ module ObjectForge
59
59
  #
60
60
  # @see Forge#forge
61
61
  #
62
- # @param name [Symbol] name of the forge
63
- # @param traits [Array<Symbol>] traits to apply
64
- # @param overrides [Hash{Symbol => Any}] attribute overrides
65
- # @yieldparam object [Any] forged instance
66
- # @yieldreturn [void]
67
- # @return [Any] built instance
68
- #
69
- # @raise [KeyError] if forge with the specified name is not registered
62
+ # @overload forge(name, *traits, **overrides)
63
+ # @param name [Symbol] name of the forge
64
+ # @param traits [Array<Symbol>] traits to apply
65
+ # @param overrides [Hash{Symbol => Any}] attribute overrides
66
+ # @yieldparam object [Any] forged instance
67
+ # @yieldreturn [void]
68
+ # @return [Any] forged instance
69
+ # @raise [ArgumentError] if a trait name is unknown
70
+ # @raise [KeyError] if forge with the specified name is not registered
70
71
  def forge(name, ...)
71
72
  @forges.fetch(name).call(...)
72
73
  end
@@ -36,15 +36,15 @@ module ObjectForge
36
36
  @default_proc = default_proc
37
37
  end
38
38
 
39
- # Build a new hash using +forged.[]+.
39
+ # Build a new hash using +forge_target.[]+.
40
40
  #
41
41
  # @see Hash.[]
42
42
  #
43
- # @param forged [Class] Hash or a subclass of Hash
43
+ # @param forge_target [Class] Hash or a subclass of Hash
44
44
  # @param attributes [Hash{Symbol => Any}]
45
45
  # @return [Hash]
46
- def call(forged:, attributes:, **_)
47
- hash = forged[attributes]
46
+ def call(forge_target:, attributes:, **_)
47
+ hash = forge_target[attributes]
48
48
  hash.default = @default if @default
49
49
  hash.default_proc = @default_proc if @default_proc
50
50
  hash
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ObjectForge
4
4
  module Molds
5
- # Basic mold which calls +forged.new(**attributes)+.
5
+ # Basic mold which calls +forge_target.new(**attributes)+.
6
6
  #
7
7
  # Can be used instead of {SingleArgumentMold}
8
8
  # due to how keyword arguments are treated in Ruby,
@@ -11,13 +11,13 @@ module ObjectForge
11
11
  # @thread_safety Thread-safe.
12
12
  # @since 0.2.0
13
13
  class KeywordsMold
14
- # Instantiate +forged+ with a hash of attributes.
14
+ # Instantiate forge target with a hash of attributes.
15
15
  #
16
- # @param forged [Class, #new]
16
+ # @param forge_target [Class, #new]
17
17
  # @param attributes [Hash{Symbol => Any}]
18
18
  # @return [Any]
19
- def call(forged:, attributes:, **_)
20
- forged.new(**attributes)
19
+ def call(forge_target:, attributes:, **_)
20
+ forge_target.new(**attributes)
21
21
  end
22
22
  end
23
23
  end
@@ -2,18 +2,18 @@
2
2
 
3
3
  module ObjectForge
4
4
  module Molds
5
- # Basic mold which calls +forged.new(attributes)+.
5
+ # Basic mold which calls +forge_target.new(attributes)+.
6
6
  #
7
7
  # @thread_safety Thread-safe.
8
8
  # @since 0.2.0
9
9
  class SingleArgumentMold
10
- # Instantiate +forged+ with a hash of attributes.
10
+ # Instantiate forge target with a hash of attributes.
11
11
  #
12
- # @param forged [Class, #new]
12
+ # @param forge_target [Class, #new]
13
13
  # @param attributes [Hash{Symbol => Any}]
14
14
  # @return [Any]
15
- def call(forged:, attributes:, **_)
16
- forged.new(attributes)
15
+ def call(forge_target:, attributes:, **_)
16
+ forge_target.new(attributes)
17
17
  end
18
18
  end
19
19
  end
@@ -32,18 +32,22 @@ module ObjectForge
32
32
  @lax = lax
33
33
  end
34
34
 
35
- # Instantiate +forged+ struct with a hash of attributes.
35
+ # Instantiate target struct with a hash of attributes.
36
36
  #
37
- # @param forged [Class] a subclass of Struct
37
+ # @param forge_target [Class] a subclass of Struct
38
38
  # @param attributes [Hash{Symbol => Any}]
39
39
  # @return [Struct]
40
- def call(forged:, attributes:, **_)
41
- if forged.keyword_init?
42
- lax ? forged.new(attributes.slice(*forged.members)) : forged.new(attributes)
43
- elsif forged.keyword_init? == false
44
- forged.new(*attributes.values_at(*forged.members))
40
+ def call(forge_target:, attributes:, **_)
41
+ if forge_target.keyword_init?
42
+ if lax
43
+ forge_target.new(attributes.slice(*forge_target.members))
44
+ else
45
+ forge_target.new(attributes)
46
+ end
47
+ elsif forge_target.keyword_init? == false
48
+ forge_target.new(*attributes.values_at(*forge_target.members))
45
49
  else
46
- build_struct_with_unspecified_keyword_init(forged, attributes)
50
+ build_struct_with_unspecified_keyword_init(forge_target, attributes)
47
51
  end
48
52
  end
49
53
 
@@ -51,18 +55,18 @@ module ObjectForge
51
55
 
52
56
  if RUBY_FEATURE_AUTO_KEYWORDS
53
57
  # Build struct by using keywords to specify member values.
54
- def build_struct_with_unspecified_keyword_init(forged, attributes)
58
+ def build_struct_with_unspecified_keyword_init(forge_target, attributes)
55
59
  if lax
56
- forged.new(**attributes.slice(*forged.members))
60
+ forge_target.new(**attributes.slice(*forge_target.members))
57
61
  else
58
- forged.new(**attributes)
62
+ forge_target.new(**attributes)
59
63
  end
60
64
  end
61
65
  else
62
66
  # :nocov:
63
67
  # Build struct by using positional arguments to specify member values.
64
- def build_struct_with_unspecified_keyword_init(forged, attributes)
65
- forged.new(*attributes.values_at(*forged.members))
68
+ def build_struct_with_unspecified_keyword_init(forge_target, attributes)
69
+ forge_target.new(*attributes.values_at(*forge_target.members))
66
70
  end
67
71
  # :nocov:
68
72
  end
@@ -20,10 +20,10 @@ module ObjectForge
20
20
  @wrapped_mold = wrapped_mold
21
21
  end
22
22
 
23
- # @overload call(...)
24
23
  # Instantiate {wrapped_mold} and call it.
25
24
  #
26
- # @return [Any] result of +wrapped_mold.new.call(...)+
25
+ # @overload call(...)
26
+ # @return [Any] result of +wrapped_mold.new.call(...)+
27
27
  def call(...)
28
28
  wrapped_mold.new.call(...)
29
29
  end