faker_maker 5.0.2 → 5.0.3

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: fdb0b495c6d3cbcfcb4f833e8446bd8cb3a3119643e2281e09000e751027000e
4
- data.tar.gz: bc8465e73262915db5807e48c523de100d33169e82d5529051725b10ea10bc9a
3
+ metadata.gz: 513de304bb5e07889bc3ebcfa0f79264aedca13b7d01ab29fc1fb5559d3d5266
4
+ data.tar.gz: 9e5475d85f6a5eb58934450f4d7d4075e8c3778d678dffa9e9ace40b074e23d8
5
5
  SHA512:
6
- metadata.gz: 8c95a76906f98b03896be2e1b1b99196d3b745eccfcb84fde9c00000e6a4d32ce566491e88af6ddbcd5b0ab48dbeb3ad0291527db702913db6364ce5afdf511f
7
- data.tar.gz: 3ea216e352581c7a33b7741862bf0b2f232b4b5cafda4521dc11756b92460d628e3ee943dd538877925854b9ef75c0f903798a102e274db73d85f389abcf4f26
6
+ metadata.gz: a190cd322a17ccf3ad4376e80ba27584bfd8f821432539dc738e39c9ec9bfae7dada1de12db82fa866d799daaa4c13746218142e20f534da5c5f3abfa5b4e44a
7
+ data.tar.gz: fada3749b0b6a767a7134375e7732ab8a14b545d7b118f6ef07365c397274ae3d3ef927791fb6be7a146cb1e358965f275d420edba60df6ba1406c05ddd6cc5b
@@ -66,7 +66,6 @@ module FakerMaker
66
66
  @instance = nil
67
67
  before_build if respond_to? :before_build
68
68
 
69
- # TODO: make this cleverer to handle nested attributes
70
69
  assert_only_known_attributes_for_override( attributes )
71
70
 
72
71
  assert_chaos_options chaos if chaos
@@ -238,7 +237,7 @@ module FakerMaker
238
237
  def assert_only_known_and_optional_attributes_for_chaos( chaos_attr_values )
239
238
  chaos_attr_values = chaos_attr_values.map(&:to_sym)
240
239
  unknown_attrs = chaos_attr_values - attribute_names.flat_map do |item|
241
- item.is_a?(Hash) ? item.keys : item
240
+ non_empty_hash?(item) ? item.keys : item
242
241
  end
243
242
  issue = "Can't build an instance of '#{class_name}' " \
244
243
  "setting '#{unknown_attrs.join( ', ' )}', no such attribute(s)"
@@ -255,7 +254,12 @@ module FakerMaker
255
254
  end
256
255
 
257
256
  def value_for_attribute( instance, attr, attr_override_values, chaos: false )
258
- if overridden_value?( attr, attr_override_values ) && !attr_override_values[attr.name].is_a?( Hash )
257
+ # Note: This is a behaviour change on the 5.x branch
258
+ # If the attribute is overriden, that value will be supplied UNLESS
259
+ # - the value is a Hash, in which case FM will attempt to set nested parameters
260
+ # EXCEPT if the hash is empty, in which case the assumptions is that the user intends to always
261
+ # return an empty hash value
262
+ if overridden_value?( attr, attr_override_values ) && !non_empty_hash?(attr_override_values[attr.name])
259
263
  attr_override_values[attr.name]
260
264
  elsif attr.array?
261
265
  [].tap do |a|
@@ -275,15 +279,11 @@ module FakerMaker
275
279
  def manufacture_from_embedded_factory( attr, attributes = {}, chaos: false )
276
280
  attributes ||= {}
277
281
  # The name of the embedded factory randomly selected from the list of embedded factories.
278
- embedded_factory = attr.embedded_factories.sample
282
+ embedded_factory = select_embedded_factory_or_sample(attr, attributes)
279
283
 
280
- # filter out attributes for non-chosen embedded factories to avoid triggering
281
- # the NoSuchAttribute exception
282
- attributes = attr
283
- .embedded_factories
284
- .reject { |e| e == embedded_factory }
285
- .flat_map { |f| f.attributes(include_embeddings: false).map(&:name) }
286
- .then { |excl| attributes.delete_if { |k, _v| excl.include?(k) } }
284
+ if !embedded_factory && !attr.embedded_factories.empty?
285
+ raise NoSuchFactoryError, "Unable to match given attributes to an embedded factory. Atributes: #{attributes.keys}"
286
+ end
287
287
 
288
288
  # The object that is being manufactured by the factory.
289
289
  # If an embedded factory name is provided, it builds the object using FakerMaker.
@@ -293,6 +293,23 @@ module FakerMaker
293
293
  embedded_factory&.build(attributes:, chaos: embedded_chaos)
294
294
  end
295
295
 
296
+ # Given an attribute, see if there are one or more factory embeddings to choose from.
297
+ # If there are more than one, examine the fields and select the most appropriate facotry
298
+ # otherwise return a random factory
299
+ def select_embedded_factory_or_sample(attr, attribute_overrides)
300
+ factory_options = attr.embedded_factories
301
+ return nil unless !factory_options&.empty?
302
+
303
+ factory_options.filter { |factory_option|
304
+ attribute_overrides
305
+ .keys
306
+ .all? { |attribute_name|
307
+ factory_option
308
+ .attributes(include_embeddings: false)
309
+ .map(&:name).include?(attribute_name) }
310
+ }.sample
311
+ end
312
+
296
313
  def instantiate
297
314
  assemble.new
298
315
  end
@@ -341,6 +358,12 @@ module FakerMaker
341
358
  @optional_attributes ||= @attributes.select(&:optional)
342
359
  end
343
360
 
361
+ # Return true is the item is a Hash object and it is non-empty.
362
+ # Convenience method to improve readability elsewhere
363
+ def non_empty_hash?(item)
364
+ item.is_a?(Hash) && !item.empty?
365
+ end
366
+
344
367
  # Randomly selects optional attributes
345
368
  # Attributes selected from parent will also be selected for the child
346
369
  # @param [Array || TrueClass] chaos_attrs
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FakerMaker
4
- VERSION = '5.0.2'
4
+ VERSION = '5.0.3'
5
5
  end
@@ -65,7 +65,7 @@ end
65
65
  This will build a object of the form (in its `as_json` guise):
66
66
 
67
67
  ```ruby
68
- {item: {name: "toothpaste", price: 0.99}, quantity: 10}
68
+ {item: {name: "toothpaste", price: 0.99}, quantity: 10}
69
69
  ```
70
70
 
71
71
  When it comes to overriding values at build time, a hash can be passed to set the nested values:
@@ -74,6 +74,8 @@ When it comes to overriding values at build time, a hash can be passed to set th
74
74
  FM[:inventory].build( attributes: { item: { name: 'floor cleaner' } } )
75
75
  ```
76
76
 
77
+ There is **one exception** to this. Passing in an empty Hash will always set the attribute to an empty Hash. This is by-design to support the testing of invalid message formats with JSON APIs.
78
+
77
79
  When you allow Faker Maker to make a choice of factory by giving it an array:
78
80
 
79
81
  ```ruby
@@ -83,7 +85,9 @@ FakerMaker.factory :inventory do
83
85
  end
84
86
  ```
85
87
 
86
- ...either the `item` or `coupon` fields could be added to each build of the `inventory` factory. Faker Maker will ignore any fields for the non-chosen factory if they are paseed in the overrides hash. This means that a `NoSuchAttribute` error will not be raised.
88
+ ...either the `item` or `coupon` fields could be added to each build of the `inventory` factory.
89
+
90
+ **Since v5.0.3** when passing override values to `#build` and where the factory has a choice of embedded factory, as in the example above where an inventory may contain either an item or a coupon, Faker Maker will attempt to locate the embedded factory which most matches the values give in the override. For example, if the attributes given to build the `item` field most match `coupon` fields, that embedded factory will be chosen. If there are still several choices which match the given attributes, a random selection will be made.
87
91
 
88
92
  ## Alternative method
89
93
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faker_maker
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.2
4
+ version: 5.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nigel Brookes-Thomas
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-07-22 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activesupport