fabrication 2.27.0 → 2.30.0

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: 96b935d9bd47864641229df13dda6eda91c99ffdf692495edf1c71703d8edc0b
4
- data.tar.gz: 6b7c6d1c90ecb94b06b8464ea0bcf2127ba5cf28d1a1adac8cad483cb2a8c4f4
3
+ metadata.gz: 38d9550f8e85412ca21c540ad7f850a61f9f511dce7048487c8cfc49f965922d
4
+ data.tar.gz: a2e732f74342b3342584483af9b2a446f4bf42fea8af50edbf1d792203e4d16b
5
5
  SHA512:
6
- metadata.gz: cb0b172c07aeb2922312926e2fe62cd55f406c098d4b4d4e1c5e19bf38ea965022c1c4aa06a1c16898aa4abf443bef327bf9e48aa177a9e73a446bb568b5b3d9
7
- data.tar.gz: 45328d26eb07c9be1f95eb0648535233680379a6c014878202cdfd3707eb6fa522cea77d9d2317bd4418458ce58c846e74105300f5f244e8cab95d4001abe85a
6
+ metadata.gz: bc4ed3c24fcd1d18ffff850a98d35fafe5408e2b166d234944a82d34e272a9a1fa1da1dff5df6677f7d083ac7cade969f10dcdc95e2fe8cb2b45d3f1719096e8
7
+ data.tar.gz: 28ad7426b1426f3b1f284bf1cf172397b83734b3865f91d64e755995da846f5bf4efc4629e90ee7a800c309e9f39898fac5ff3c87ab2607e7c0a6290d57490f8
@@ -1,3 +1,5 @@
1
+ require 'logger'
2
+
1
3
  module Fabrication
2
4
  module Config
3
5
  extend self
@@ -14,14 +16,22 @@ module Fabrication
14
16
  nil
15
17
  end
16
18
 
19
+ attr_writer :logger, :sequence_start
20
+
21
+ def logger
22
+ @logger ||= Logger.new($stdout).tap do |logger|
23
+ logger.level = Logger::WARN
24
+ end
25
+ end
26
+
17
27
  def fabricator_path
18
28
  @fabricator_path ||= ['test/fabricators', 'spec/fabricators']
19
29
  end
20
30
  alias fabricator_paths fabricator_path
21
31
 
22
32
  def fabricator_dir
23
- puts 'DEPRECATION WARNING: Fabrication::Config.fabricator_dir has been ' \
24
- 'replaced by Fabrication::Config.fabricator_path'
33
+ Support.log_deprecation('Fabrication::Config.fabricator_dir has been ' \
34
+ 'replaced by Fabrication::Config.fabricator_path')
25
35
  fabricator_path
26
36
  end
27
37
 
@@ -30,13 +40,11 @@ module Fabrication
30
40
  end
31
41
 
32
42
  def fabricator_dir=(folders)
33
- puts 'DEPRECATION WARNING: Fabrication::Config.fabricator_dir has been ' \
34
- 'replaced by Fabrication::Config.fabricator_path'
43
+ Support.log_deprecation('Fabrication::Config.fabricator_dir has been ' \
44
+ 'replaced by Fabrication::Config.fabricator_path')
35
45
  self.fabricator_path = folders
36
46
  end
37
47
 
38
- attr_writer :sequence_start
39
-
40
48
  def sequence_start
41
49
  @sequence_start ||= 0
42
50
  end
@@ -67,8 +75,10 @@ module Fabrication
67
75
  end
68
76
 
69
77
  def register_with_steps=(value)
70
- puts 'DEPRECATION WARNING: Fabrication::Config.register_with_steps has been ' \
71
- 'deprecated. Please regenerate your cucumber steps with `rails g fabrication:cucumber_steps'
78
+ Support.log_deprecation(
79
+ 'Fabrication::Config.register_with_steps has been deprecated. ' \
80
+ 'Please regenerate your cucumber steps with `rails g fabrication:cucumber_steps'
81
+ )
72
82
 
73
83
  return unless value
74
84
 
@@ -1,3 +1,5 @@
1
+ require 'singleton'
2
+
1
3
  module Fabrication
2
4
  module Cucumber
3
5
  class StepFabricator
@@ -85,17 +87,23 @@ module Fabrication
85
87
  end
86
88
  end
87
89
 
88
- module Fabrications
90
+ class Fabrications
91
+ include Singleton
92
+
89
93
  def self.fabrications
90
- @fabrications ||= {}
94
+ instance.fabrications
91
95
  end
92
96
 
93
97
  def self.[](fabricator)
94
- fabrications[fabricator.to_sym]
98
+ instance.fabrications[fabricator.to_sym]
95
99
  end
96
100
 
97
101
  def self.[]=(fabricator, fabrication)
98
- fabrications[fabricator.to_sym] = fabrication
102
+ instance.fabrications[fabricator.to_sym] = fabrication
103
+ end
104
+
105
+ def fabrications
106
+ @fabrications ||= {}
99
107
  end
100
108
  end
101
109
  end
@@ -11,10 +11,10 @@ module Fabrication
11
11
  end
12
12
 
13
13
  def build_instance
14
- self._instance = if _klass.respond_to?(:protected_attributes)
15
- _klass.new(_attributes, without_protection: true)
14
+ self._instance = if resolved_class.respond_to?(:protected_attributes)
15
+ resolved_class.new(_attributes, without_protection: true)
16
16
  else
17
- _klass.new(_attributes)
17
+ resolved_class.new(_attributes)
18
18
  end
19
19
  end
20
20
  end
@@ -1,7 +1,7 @@
1
1
  module Fabrication
2
2
  module Generator
3
3
  class Base
4
- def self.supports?(_klass)
4
+ def self.supports?(_resolved_class)
5
5
  true
6
6
  end
7
7
 
@@ -11,6 +11,9 @@ module Fabrication
11
11
  if callbacks[:initialize_with]
12
12
  build_instance_with_constructor_override(callbacks[:initialize_with])
13
13
  elsif callbacks[:on_init]
14
+ Fabrication::Support.log_deprecation(
15
+ 'The on_init callback has been replaced by initialize_with. Please see the documentation for usage'
16
+ )
14
17
  build_instance_with_init_callback(callbacks[:on_init])
15
18
  else
16
19
  build_instance
@@ -19,18 +22,29 @@ module Fabrication
19
22
  _instance
20
23
  end
21
24
 
22
- def create(attributes = [], callbacks = [])
25
+ def create(attributes = [], callbacks = {})
23
26
  build(attributes, callbacks)
24
- execute_callbacks(callbacks[:before_validation])
25
- execute_callbacks(callbacks[:after_validation])
26
- execute_callbacks(callbacks[:before_save])
27
+ execute_deprecated_callbacks(callbacks, :before_validation, :before_create)
28
+ execute_deprecated_callbacks(callbacks, :after_validation, :before_create)
29
+ execute_deprecated_callbacks(callbacks, :before_save, :before_create)
27
30
  execute_callbacks(callbacks[:before_create])
28
31
  persist
29
32
  execute_callbacks(callbacks[:after_create])
30
- execute_callbacks(callbacks[:after_save])
33
+ execute_deprecated_callbacks(callbacks, :after_save, :after_create)
31
34
  _instance
32
35
  end
33
36
 
37
+ def execute_deprecated_callbacks(callbacks, callback_type, replacement_callback)
38
+ if callbacks[callback_type]
39
+ Fabrication::Support.log_deprecation(
40
+ "Using #{callback_type} is deprecated but you can replace it " \
41
+ "with #{replacement_callback} with the same result."
42
+ )
43
+ end
44
+
45
+ execute_callbacks(callbacks[callback_type])
46
+ end
47
+
34
48
  def execute_callbacks(callbacks)
35
49
  callbacks&.each { |callback| _instance.instance_exec(_instance, _transient_attributes, &callback) }
36
50
  end
@@ -59,12 +73,12 @@ module Fabrication
59
73
  end
60
74
 
61
75
  def build_instance_with_init_callback(callback)
62
- self._instance = _klass.new(*callback.call(_transient_attributes))
76
+ self._instance = resolved_class.new(*callback.call(_transient_attributes))
63
77
  set_attributes
64
78
  end
65
79
 
66
80
  def build_instance
67
- self._instance = _klass.new
81
+ self._instance = resolved_class.new
68
82
  set_attributes
69
83
  end
70
84
 
@@ -74,8 +88,8 @@ module Fabrication
74
88
  end
75
89
  end
76
90
 
77
- def initialize(klass)
78
- self._klass = klass
91
+ def initialize(resolved_class)
92
+ self.resolved_class = resolved_class
79
93
  end
80
94
 
81
95
  def respond_to_missing?(method_name, _include_private = false)
@@ -86,20 +100,31 @@ module Fabrication
86
100
  _attributes.fetch(method_name) { super }
87
101
  end
88
102
 
103
+ def _klass
104
+ Fabrication::Support.log_deprecation(
105
+ 'The `_klass` method in fabricator definitions has been replaced by `resolved_class`'
106
+ )
107
+
108
+ resolved_class
109
+ end
110
+
89
111
  protected
90
112
 
91
- attr_accessor :_klass, :_instance, :_transient_attributes
113
+ attr_accessor :resolved_class, :_instance
92
114
 
93
115
  def _attributes
94
116
  @_attributes ||= {}
95
117
  end
96
118
 
119
+ def _transient_attributes
120
+ @_transient_attributes ||= {}
121
+ end
122
+
97
123
  def persist
98
124
  _instance.save! if _instance.respond_to?(:save!)
99
125
  end
100
126
 
101
127
  def process_attributes(attributes)
102
- self._transient_attributes = ({})
103
128
  attributes.each do |attribute|
104
129
  _attributes[attribute.name] = attribute.processed_value(_attributes)
105
130
  _transient_attributes[attribute.name] = _attributes[attribute.name] if attribute.transient?
@@ -6,7 +6,7 @@ module Fabrication
6
6
  end
7
7
 
8
8
  def build_instance
9
- self._instance = _klass.new(_attributes)
9
+ self._instance = resolved_class.new(_attributes)
10
10
  end
11
11
 
12
12
  protected
@@ -6,10 +6,10 @@ module Fabrication
6
6
  end
7
7
 
8
8
  def build_instance
9
- self._instance = if _klass.respond_to?(:protected_attributes)
10
- _klass.new(_attributes, without_protection: true)
9
+ self._instance = if resolved_class.respond_to?(:protected_attributes)
10
+ resolved_class.new(_attributes, without_protection: true)
11
11
  else
12
- _klass.new(_attributes)
12
+ resolved_class.new(_attributes)
13
13
  end
14
14
  end
15
15
  end
@@ -11,14 +11,11 @@ module Fabrication
11
11
  end
12
12
 
13
13
  def set_attributes
14
- _attributes.each do |key, value|
15
- if (reflection = _klass.association_reflections[key]) && value.is_a?(Array)
16
- _instance.associations[key] = value
17
- _instance.after_save_hook do
18
- value.each { |o| _instance.send(reflection.add_method, o) }
19
- end
14
+ _attributes.each do |field_name, value|
15
+ if value.is_a?(Array) && (association = association_for(field_name))
16
+ set_association(association, field_name, value)
20
17
  else
21
- _instance.send("#{key}=", value)
18
+ set_attribute(field_name, value)
22
19
  end
23
20
  end
24
21
  end
@@ -29,8 +26,23 @@ module Fabrication
29
26
 
30
27
  private
31
28
 
29
+ def association_for(field_name)
30
+ resolved_class.association_reflections[field_name]
31
+ end
32
+
33
+ def set_attribute(field_name, value)
34
+ _instance.send("#{field_name}=", value)
35
+ end
36
+
37
+ def set_association(association, field_name, value)
38
+ _instance.associations[field_name] = value
39
+ _instance.after_save_hook do
40
+ value.each { |o| _instance.send(association.add_method, o) }
41
+ end
42
+ end
43
+
32
44
  def load_instance_hooks
33
- klass = _klass.respond_to?(:cti_base_model) ? _klass.cti_models.first : _klass
45
+ klass = resolved_class.respond_to?(:cti_base_model) ? resolved_class.cti_models.first : resolved_class
34
46
  klass.plugin :instance_hooks unless klass.new.respond_to? :after_save_hook
35
47
  end
36
48
  end
@@ -43,8 +43,8 @@ module Fabrication
43
43
 
44
44
  private
45
45
 
46
- def execute(*args, &block)
47
- Fabrication::Schematic::Runner.new(klass).instance_exec(*args, &block)
46
+ def execute(...)
47
+ Fabrication::Schematic::Runner.new(klass).instance_exec(...)
48
48
  end
49
49
 
50
50
  def process_count
@@ -1,8 +1,21 @@
1
+ require 'singleton'
2
+
1
3
  module Fabrication
2
4
  class Sequencer
5
+ include Singleton
6
+
3
7
  DEFAULT = :_default
4
8
 
5
9
  def self.sequence(name = DEFAULT, start = nil, &block)
10
+ instance.sequence(name, start, &block)
11
+ end
12
+
13
+ def self.clear
14
+ instance.sequences.clear
15
+ instance.sequence_blocks.clear
16
+ end
17
+
18
+ def sequence(name = DEFAULT, start = nil, &block)
6
19
  idx = sequences[name] ||= start || Fabrication::Config.sequence_start
7
20
  if block
8
21
  sequence_blocks[name] = block.to_proc
@@ -13,15 +26,15 @@ module Fabrication
13
26
  end
14
27
  end
15
28
 
16
- def self.sequences
29
+ def sequences
17
30
  @sequences ||= {}
18
31
  end
19
32
 
20
- def self.sequence_blocks
33
+ def sequence_blocks
21
34
  @sequence_blocks ||= {}
22
35
  end
23
36
 
24
- def self.reset
37
+ def reset
25
38
  Fabrication::Config.sequence_start = nil
26
39
  @sequences = nil
27
40
  @sequence_blocks = nil
@@ -1,79 +1,68 @@
1
1
  module Fabrication
2
- class Support
3
- class << self
4
- def fabricatable?(name)
5
- Fabrication.manager[name] || class_for(name)
6
- end
2
+ module Support
3
+ extend self
7
4
 
8
- def class_for(class_or_to_s)
9
- class_name = variable_name_to_class_name(class_or_to_s)
10
- constantize(class_name)
11
- rescue NameError => e
12
- raise Fabrication::UnfabricatableError.new(class_or_to_s, e)
13
- end
5
+ def fabricatable?(name)
6
+ Fabrication.manager[name] || class_for(name)
7
+ end
14
8
 
15
- def constantize(camel_cased_word)
16
- names = camel_cased_word.split('::')
17
- Object.const_get(camel_cased_word) if names.empty?
18
- names.shift if names.size > 1 && names.first.empty?
19
- names.inject(Object) do |constant, name|
20
- if constant == Object
21
- constant.const_get(name)
22
- else
23
- candidate = constant.const_get(name)
24
- next candidate if constant.const_defined?(name, false)
25
- next candidate unless Object.const_defined?(name)
9
+ def log_deprecation(message)
10
+ Config.logger.warn("[DEPRECATION][fabrication] #{message}")
11
+ end
26
12
 
27
- constant = constant.ancestors.inject do |const, ancestor|
28
- break const if ancestor == Object
29
- break ancestor if ancestor.const_defined?(name, false)
13
+ def class_for(class_or_to_s)
14
+ constantize(variable_name_to_class_name(class_or_to_s))
15
+ rescue NameError => e
16
+ raise Fabrication::UnfabricatableError.new(class_or_to_s, e)
17
+ end
30
18
 
31
- const
32
- end
33
- constant.const_get(name, false)
34
- end
35
- end
36
- end
19
+ def constantize(camel_cased_word)
20
+ return camel_cased_word if camel_cased_word.is_a?(Class)
37
21
 
38
- def extract_options!(args)
39
- args.last.is_a?(::Hash) ? args.pop : {}
22
+ camel_cased_word.to_s.split('::').reduce(Object) do |resolved_class, class_part|
23
+ resolved_class.const_get(class_part)
40
24
  end
25
+ end
41
26
 
42
- def variable_name_to_class_name(name)
43
- name_string = name.to_s
27
+ def extract_options!(args)
28
+ args.last.is_a?(::Hash) ? args.pop : {}
29
+ end
44
30
 
45
- if name_string.respond_to?(:camelize)
46
- name_string.camelize
47
- else
48
- name_string.gsub(%r{/(.?)}) do
49
- "::#{Regexp.last_match(1).upcase}"
50
- end.gsub(/(?:^|_)(.)/) { Regexp.last_match(1).upcase }
51
- end
52
- end
31
+ def variable_name_to_class_name(name)
32
+ name_string = name.to_s
53
33
 
54
- def find_definitions
55
- puts 'DEPRECATION WARNING: Fabrication::Support.find_definitions has been replaced ' \
56
- 'by Fabrication.manager.load_definitions and will be removed in 3.0.0.'
57
- Fabrication.manager.load_definitions
34
+ if name_string.respond_to?(:camelize)
35
+ name_string.camelize
36
+ else
37
+ name_string
38
+ .gsub(%r{/(.?)}) { "::#{Regexp.last_match(1).upcase}" }
39
+ .gsub(/(?:^|_)(.)/) { Regexp.last_match(1).upcase }
58
40
  end
41
+ end
59
42
 
60
- def hash_class
61
- @hash_class ||= defined?(HashWithIndifferentAccess) ? HashWithIndifferentAccess : Hash
62
- end
43
+ def find_definitions
44
+ log_deprecation('Fabrication::Support.find_definitions has been replaced by ' \
45
+ 'Fabrication.manager.load_definitions and will be removed in 3.0.0.')
63
46
 
64
- def singularize(string)
65
- string.singularize
66
- rescue StandardError
67
- string.end_with?('s') ? string[0..-2] : string
68
- end
47
+ Fabrication.manager.load_definitions
48
+ end
69
49
 
70
- def underscore(string)
71
- string.gsub(/::/, '/')
72
- .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
73
- .gsub(/([a-z\d])([A-Z])/, '\1_\2')
74
- .tr('-', '_')
75
- .downcase
76
- end
50
+ def hash_class
51
+ @hash_class ||= defined?(HashWithIndifferentAccess) ? HashWithIndifferentAccess : Hash
52
+ end
53
+
54
+ def singularize(string)
55
+ string.singularize
56
+ rescue StandardError
57
+ string.end_with?('s') ? string[0..-2] : string
58
+ end
59
+
60
+ def underscore(string)
61
+ string.gsub(/::/, '/')
62
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
63
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
64
+ .tr('-', '_')
65
+ .downcase
77
66
  end
78
67
  end
79
68
  end
@@ -1,37 +1,39 @@
1
+ require 'singleton'
2
+
1
3
  module Fabrication
2
4
  class Transform
5
+ include Singleton
6
+
3
7
  class << self
4
8
  def apply_to(schematic, attributes_hash)
5
9
  Fabrication.manager.load_definitions if Fabrication.manager.empty?
6
- attributes_hash.inject({}) { |h, (k, v)| h.update(k => apply_transform(schematic, k, v)) }
10
+ attributes_hash.inject({}) { |h, (k, v)| h.update(k => instance.apply_transform(schematic, k, v)) }
7
11
  end
8
12
 
9
13
  def clear_all
10
- @transforms = nil
11
- @overrides = nil
14
+ instance.transforms.clear
15
+ instance.overrides.clear
12
16
  end
13
17
 
14
18
  def define(attribute, transform)
15
- transforms[attribute] = transform
19
+ instance.transforms[attribute] = transform
16
20
  end
17
21
 
18
22
  def only_for(schematic, attribute, transform)
19
- overrides[schematic] = (overrides[schematic] || {}).merge!(attribute => transform)
23
+ instance.overrides[schematic] = (instance.overrides[schematic] || {}).merge!(attribute => transform)
20
24
  end
25
+ end
21
26
 
22
- private
23
-
24
- def overrides
25
- @overrides ||= {}
26
- end
27
+ def overrides
28
+ @overrides ||= {}
29
+ end
27
30
 
28
- def apply_transform(schematic, attribute, value)
29
- overrides.fetch(schematic, transforms)[attribute].call(value)
30
- end
31
+ def apply_transform(schematic, attribute, value)
32
+ overrides.fetch(schematic, transforms)[attribute].call(value)
33
+ end
31
34
 
32
- def transforms
33
- @transforms ||= Hash.new(->(value) { value })
34
- end
35
+ def transforms
36
+ @transforms ||= Hash.new(->(value) { value })
35
37
  end
36
38
  end
37
39
  end
@@ -1,3 +1,3 @@
1
1
  module Fabrication
2
- VERSION = '2.27.0'.freeze
2
+ VERSION = '2.30.0'.freeze
3
3
  end
data/lib/fabrication.rb CHANGED
@@ -31,7 +31,6 @@ module Fabrication
31
31
 
32
32
  module Generator
33
33
  autoload :ActiveRecord, 'fabrication/generator/active_record'
34
- autoload :ActiveRecord4, 'fabrication/generator/active_record_4'
35
34
  autoload :DataMapper, 'fabrication/generator/data_mapper'
36
35
  autoload :Mongoid, 'fabrication/generator/mongoid'
37
36
  autoload :Sequel, 'fabrication/generator/sequel'
@@ -40,7 +39,7 @@ module Fabrication
40
39
 
41
40
  def self.clear_definitions
42
41
  manager.clear
43
- Sequencer.sequences.clear
42
+ Sequencer.clear
44
43
  end
45
44
 
46
45
  def self.configure(&block)
@@ -48,12 +47,12 @@ module Fabrication
48
47
  end
49
48
 
50
49
  def self.manager
51
- @manager ||= Fabrication::Schematic::Manager.instance
50
+ Fabrication::Schematic::Manager.instance
52
51
  end
53
52
 
54
53
  def self.schematics
55
- puts 'DEPRECATION WARNING: Fabrication.schematics has been replaced by '\
56
- 'Fabrication.manager and will be removed in 3.0.0.'
54
+ Support.log_deprecation('Fabrication.schematics has been replaced by ' \
55
+ 'Fabrication.manager and will be removed in 3.0.0.')
57
56
  manager
58
57
  end
59
58
  end
@@ -8,7 +8,7 @@ module Fabrication
8
8
  end
9
9
 
10
10
  def self.source_root
11
- @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
11
+ File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
12
12
  end
13
13
  end
14
14
  end
@@ -19,7 +19,7 @@ module Fabrication
19
19
  end
20
20
 
21
21
  def self.source_root
22
- @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
22
+ File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
23
23
  end
24
24
 
25
25
  private
@@ -33,6 +33,8 @@ module Fabrication
33
33
  end
34
34
  rescue StandardError
35
35
  # no table? no problem!
36
+ rescue LoadError
37
+ # cannot find model file. This means it was already destroyed, so just continue.
36
38
  end
37
39
  end
38
40
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fabrication
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.27.0
4
+ version: 2.30.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Elliott
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-03 00:00:00.000000000 Z
11
+ date: 2022-07-25 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Fabrication is an object generation framework for ActiveRecord, Mongoid,
14
14
  DataMapper, Sequel, or any other Ruby object.
@@ -70,14 +70,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
70
70
  requirements:
71
71
  - - ">="
72
72
  - !ruby/object:Gem::Version
73
- version: 2.6.0
73
+ version: 2.7.0
74
74
  required_rubygems_version: !ruby/object:Gem::Requirement
75
75
  requirements:
76
76
  - - ">="
77
77
  - !ruby/object:Gem::Version
78
78
  version: '0'
79
79
  requirements: []
80
- rubygems_version: 3.2.32
80
+ rubygems_version: 3.3.7
81
81
  signing_key:
82
82
  specification_version: 4
83
83
  summary: Generates object instances for test suites, seed files, etc.