fabrication 3.0.0.beta.1.1 → 3.0.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: 3153c373659350c2969d98f3d21cbc60c92f9aff1f00c51f32c7238357c49195
4
- data.tar.gz: d69204cacb17bfab516ecbe93d2e05edb60c596052130a1b41340e699dc25412
3
+ metadata.gz: e2d9e7e01f4fcab4cb03ccb401f16b62a5aa854e132627292a0dfaa6e57ede61
4
+ data.tar.gz: a5ef27ece35d6d35a06bcf341b001c06aa9bc1c5270d6305c7ad01344fc5cc21
5
5
  SHA512:
6
- metadata.gz: 99e08637411f94b9df1ff63572c85b9b5fc8016677d043f53b1fb2acf27495b8f1cd1162b63cc6ed6be7579facf5e6dcc9c0929d2374fb6e7b30570308e33184
7
- data.tar.gz: abffe3aeb00cb0b29589ad12daa9710801bdaecf5898d46b40e7cefa5150a0d00464df300c9edc54e22092097cdd0c712af0af5ae6b9f11f0ccd9965ce9b7582
6
+ metadata.gz: 916b51d8df3521c9423be89cb39e975a9d5e0f7a94d10b42b9c88599aa9b8a8e14163d149da0c231b87f950e247350f7177f157dcdce748bab3226d1db1a4a91
7
+ data.tar.gz: 167c0c2ab653376eb59e7217bf1e32c766284e9a776090738345e5f89695bc87c558129ad20ed9fc66b053b446c2d3dcdf3a3f296461f81860be43db23f7ada8
data/README.markdown CHANGED
@@ -12,6 +12,6 @@ Fabrication is tested against all officially supported versions of Ruby.
12
12
 
13
13
  Please see the Fabrication website for up-to-date documentation: http://fabricationgem.org
14
14
 
15
- You can also view the raw documentation without all the awesome: https://github.com/paulelliott/fabrication-site/blob/master/source/index.markdown
15
+ You can also view the raw documentation without all the awesome: https://gitlab.com/fabrication-gem/docsite/-/blob/master/source/index.html.markdown
16
16
 
17
- Get help from the mailing list: https://groups.google.com/group/fabricationgem
17
+ Get help by opening an issue: https://gitlab.com/fabrication-gem/fabrication/-/issues
data/lib/fabricate.rb CHANGED
@@ -1,40 +1,46 @@
1
1
  class Fabricate
2
- def self.times(count, name, overrides = {}, &block)
3
- count.times.map { Fabricate(name, overrides, &block) }
2
+ def self.times(count, name, overrides = {}, &)
3
+ Array.new(count).map { Fabricate(name, overrides, &) }
4
4
  end
5
5
 
6
- def self.build_times(count, name, overrides = {}, &block)
7
- count.times.map { Fabricate.build(name, overrides, &block) }
6
+ def self.build_times(count, name, overrides = {}, &)
7
+ Array.new(count).map { Fabricate.build(name, overrides, &) }
8
8
  end
9
9
 
10
- def self.attributes_for_times(count, name, overrides = {}, &block)
11
- count.times.map { Fabricate.attributes_for(name, overrides, &block) }
10
+ def self.attributes_for_times(count, name, overrides = {}, &)
11
+ Array.new(count).map { Fabricate.attributes_for(name, overrides, &) }
12
12
  end
13
13
 
14
- def self.attributes_for(name, overrides = {}, &block)
14
+ def self.attributes_for(name, overrides = {}, &)
15
15
  fail_if_initializing(name)
16
- schematic(name).to_attributes(overrides, &block)
16
+ schematic(name).to_attributes(overrides, &)
17
17
  end
18
18
 
19
- def self.to_params(name, overrides = {}, &block)
19
+ def self.to_params(name, overrides = {}, &)
20
20
  fail_if_initializing(name)
21
- schematic(name).to_params(overrides, &block)
21
+ schematic(name).to_params(overrides, &)
22
22
  end
23
23
 
24
- def self.build(name, overrides = {}, &block)
24
+ def self.build(name, overrides = {}, &)
25
25
  fail_if_initializing(name)
26
- schematic(name).build(overrides, &block).tap do |object|
27
- Fabrication::Cucumber::Fabrications[name] = object if Fabrication::Config.register_with_steps?
26
+ schematic(name).build(overrides, &).tap do |object|
27
+ Fabrication::Config.notifiers.each do |notifier|
28
+ notifier.call(name, object)
29
+ end
28
30
  end
29
31
  end
30
32
 
31
- def self.create(name, overrides = {}, &block)
33
+ def self.create(name, overrides = {}, &)
32
34
  fail_if_initializing(name)
33
- schematic(name).fabricate(overrides, &block)
35
+ schematic(name).fabricate(overrides, &).tap do |object|
36
+ Fabrication::Config.notifiers.each do |notifier|
37
+ notifier.call(name, object)
38
+ end
39
+ end
34
40
  end
35
41
 
36
- def self.sequence(name = Fabrication::Sequencer::DEFAULT, start = nil, &block)
37
- Fabrication::Sequencer.sequence(name, start, &block)
42
+ def self.sequence(name = Fabrication::Sequencer::DEFAULT, start = nil, &)
43
+ Fabrication::Sequencer.sequence(name, start, &)
38
44
  end
39
45
 
40
46
  def self.schematic(name)
@@ -1,3 +1,5 @@
1
+ require 'logger'
2
+
1
3
  module Fabrication
2
4
  module Config
3
5
  extend self
@@ -14,16 +16,34 @@ 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
 
32
+ def fabricator_dir
33
+ Support.log_deprecation('Fabrication::Config.fabricator_dir has been ' \
34
+ 'replaced by Fabrication::Config.fabricator_path')
35
+ fabricator_path
36
+ end
37
+
22
38
  def fabricator_path=(folders)
23
39
  @fabricator_path = ([] << folders).flatten
24
40
  end
25
41
 
26
- attr_writer :sequence_start, :register_with_steps
42
+ def fabricator_dir=(folders)
43
+ Support.log_deprecation('Fabrication::Config.fabricator_dir has been ' \
44
+ 'replaced by Fabrication::Config.fabricator_path')
45
+ self.fabricator_path = folders
46
+ end
27
47
 
28
48
  def sequence_start
29
49
  @sequence_start ||= 0
@@ -38,10 +58,6 @@ module Fabrication
38
58
  end
39
59
  alias path_prefixes path_prefix
40
60
 
41
- def register_with_steps?
42
- @register_with_steps ||= nil
43
- end
44
-
45
61
  def generators
46
62
  @generators ||= []
47
63
  end
@@ -57,5 +73,26 @@ module Fabrication
57
73
  def recursion_limit=(limit)
58
74
  @recursion_limit = limit
59
75
  end
76
+
77
+ def register_with_steps=(value)
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
+ )
82
+
83
+ return unless value
84
+
85
+ register_notifier do |name, object|
86
+ Fabrication::Cucumber::Fabrications[name] = object
87
+ end
88
+ end
89
+
90
+ def notifiers
91
+ @notifiers ||= []
92
+ end
93
+
94
+ def register_notifier(&block)
95
+ notifiers.push(block)
96
+ end
60
97
  end
61
98
  end
@@ -1,3 +1,5 @@
1
+ require 'singleton'
2
+
1
3
  module Fabrication
2
4
  module Cucumber
3
5
  class StepFabricator
@@ -20,7 +22,7 @@ module Fabrication
20
22
  end
21
23
 
22
24
  def n(count, attrs = {})
23
- count.times.map { make(attrs) }.tap { |o| remember(o) }
25
+ Array.new(count).map { make(attrs) }.tap { |o| remember(o) }
24
26
  end
25
27
 
26
28
  # rubocop:disable Naming/PredicateName
@@ -28,7 +30,7 @@ module Fabrication
28
30
  instance = Fabrications[@fabricator]
29
31
  children = dehumanize(children)
30
32
  [Fabrications[children]].flatten.each do |child|
31
- child.send("#{klass.to_s.underscore.downcase}=", instance)
33
+ child.send(:"#{klass.to_s.underscore.downcase}=", instance)
32
34
  child.respond_to?(:save!) && child.save!
33
35
  end
34
36
  end
@@ -76,7 +78,7 @@ module Fabrication
76
78
  parent_class_name = parent.class.to_s.underscore
77
79
 
78
80
  parent_instance = parent
79
- unless klass.new.respond_to?("#{parent_class_name}=")
81
+ unless klass.new.respond_to?(:"#{parent_class_name}=")
80
82
  parent_class_name = parent_class_name.pluralize
81
83
  parent_instance = [parent]
82
84
  end
@@ -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
@@ -6,15 +6,15 @@ module Fabrication
6
6
  # so we can't assume because we have the ActiveRecord module that we also
7
7
  # have ActiveRecord::Base. Because defined? can return nil we ensure that nil
8
8
  # becomes false.
9
- defined?(::ActiveRecord) && defined?(::ActiveRecord::Base) &&
10
- klass.ancestors.include?(::ActiveRecord::Base) || false
9
+ (defined?(::ActiveRecord::Base) &&
10
+ klass.ancestors.include?(::ActiveRecord::Base)) || false
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
@@ -54,61 +68,68 @@ module Fabrication
54
68
  end
55
69
 
56
70
  def build_instance_with_constructor_override(callback)
57
- self._instance = instance_eval(&callback)
71
+ self._instance = instance_exec(_transient_attributes, &callback)
58
72
  set_attributes
59
73
  end
60
74
 
61
75
  def build_instance_with_init_callback(callback)
62
- self._instance = _klass.new(*callback.call)
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
 
71
85
  def set_attributes
72
- if _instance.respond_to?(:attributes=)
73
- _instance.attributes = _attributes
74
- else
75
- _attributes.each do |k, v|
76
- _instance.send("#{k}=", v)
77
- end
86
+ _attributes.each do |k, v|
87
+ _instance.send(:"#{k}=", v)
78
88
  end
79
89
  end
80
90
 
81
- def initialize(klass)
82
- self._klass = klass
91
+ def initialize(resolved_class)
92
+ self.resolved_class = resolved_class
83
93
  end
84
94
 
85
95
  def respond_to_missing?(method_name, _include_private = false)
86
96
  _attributes.key?(method_name)
87
97
  end
88
98
 
89
- def method_missing(method_name, *args, &block)
99
+ def method_missing(method_name, *args, &)
90
100
  _attributes.fetch(method_name) { super }
91
101
  end
92
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
+
93
111
  protected
94
112
 
95
- attr_accessor :_klass, :_instance, :_transient_attributes
113
+ attr_accessor :resolved_class, :_instance
96
114
 
97
115
  def _attributes
98
116
  @_attributes ||= {}
99
117
  end
100
118
 
119
+ def _transient_attributes
120
+ @_transient_attributes ||= {}
121
+ end
122
+
101
123
  def persist
102
124
  _instance.save! if _instance.respond_to?(:save!)
103
125
  end
104
126
 
105
127
  def process_attributes(attributes)
106
- self._transient_attributes = ({})
107
128
  attributes.each do |attribute|
108
129
  _attributes[attribute.name] = attribute.processed_value(_attributes)
109
130
  _transient_attributes[attribute.name] = _attributes[attribute.name] if attribute.transient?
110
131
  end
111
- _attributes.reject! { |k| _transient_attributes.keys.include?(k) }
132
+ _attributes.reject! { |k| _transient_attributes.key?(k) }
112
133
  end
113
134
  end
114
135
  end
@@ -0,0 +1,17 @@
1
+ module Fabrication
2
+ module Generator
3
+ class Mongoid < Fabrication::Generator::Base
4
+ def self.supports?(klass)
5
+ defined?(::Mongoid) && klass.ancestors.include?(::Mongoid::Document)
6
+ end
7
+
8
+ def build_instance
9
+ self._instance = if resolved_class.respond_to?(:protected_attributes)
10
+ resolved_class.new(_attributes, without_protection: true)
11
+ else
12
+ resolved_class.new(_attributes)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -7,18 +7,15 @@ module Fabrication
7
7
  end
8
8
 
9
9
  def self.supports?(klass)
10
- defined?(::Sequel) && defined?(::Sequel::Model) && klass.ancestors.include?(::Sequel::Model)
10
+ defined?(::Sequel::Model) && klass.ancestors.include?(::Sequel::Model)
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
@@ -65,7 +65,7 @@ module Fabrication
65
65
  end
66
66
 
67
67
  def rand_range
68
- Kernel.rand((params[:start_range]..params[:end_range])) if params[:start_range] && params[:end_range]
68
+ Kernel.rand(params[:start_range]..params[:end_range]) if params[:start_range] && params[:end_range]
69
69
  end
70
70
  end
71
71
  end
@@ -4,6 +4,7 @@ module Fabrication
4
4
  GENERATORS = [
5
5
  Fabrication::Generator::ActiveRecord,
6
6
  Fabrication::Generator::Sequel,
7
+ Fabrication::Generator::Mongoid,
7
8
  Fabrication::Generator::Base
8
9
  ].freeze
9
10
 
@@ -16,15 +17,15 @@ module Fabrication
16
17
  end
17
18
 
18
19
  def process_block(&block)
19
- Fabrication::Schematic::Evaluator.new.process(self, &block) if block_given?
20
+ Fabrication::Schematic::Evaluator.new.process(self, &block) if block
20
21
  end
21
22
 
22
23
  def attribute(name)
23
24
  attributes.detect { |a| a.name == name }
24
25
  end
25
26
 
26
- def append_or_update_attribute(attribute_name, value, params = {}, &block)
27
- attribute = Fabrication::Schematic::Attribute.new(klass, attribute_name, value, params, &block)
27
+ def append_or_update_attribute(attribute_name, value, params = {}, &)
28
+ attribute = Fabrication::Schematic::Attribute.new(klass, attribute_name, value, params, &)
28
29
  index = attributes.index { |a| a.name == attribute.name }
29
30
 
30
31
  if index
@@ -55,14 +56,14 @@ module Fabrication
55
56
  attributes.select(&:value_static?) + attributes.select(&:value_proc?)
56
57
  end
57
58
 
58
- def build(overrides = {}, &block)
59
+ def build(overrides = {}, &)
59
60
  Fabrication.manager.prevent_recursion!
60
61
  if Fabrication.manager.to_params_stack.any?
61
- to_params(overrides, &block)
62
+ to_params(overrides, &)
62
63
  else
63
64
  begin
64
65
  Fabrication.manager.build_stack << name
65
- merge(overrides, &block).instance_eval do
66
+ merge(overrides, &).instance_eval do
66
67
  generator.new(klass).build(sorted_attributes, callbacks)
67
68
  end
68
69
  ensure
@@ -71,16 +72,16 @@ module Fabrication
71
72
  end
72
73
  end
73
74
 
74
- def fabricate(overrides = {}, &block)
75
+ def fabricate(overrides = {}, &)
75
76
  Fabrication.manager.prevent_recursion!
76
77
  if Fabrication.manager.build_stack.any?
77
- build(overrides, &block)
78
+ build(overrides, &)
78
79
  elsif Fabrication.manager.to_params_stack.any?
79
- to_params(overrides, &block)
80
+ to_params(overrides, &)
80
81
  else
81
82
  begin
82
83
  Fabrication.manager.create_stack << name
83
- merge(overrides, &block).instance_eval do
84
+ merge(overrides, &).instance_eval do
84
85
  generator.new(klass).create(sorted_attributes, callbacks)
85
86
  end
86
87
  ensure
@@ -89,18 +90,18 @@ module Fabrication
89
90
  end
90
91
  end
91
92
 
92
- def to_params(overrides = {}, &block)
93
+ def to_params(overrides = {}, &)
93
94
  Fabrication.manager.prevent_recursion!
94
95
  Fabrication.manager.to_params_stack << name
95
- merge(overrides, &block).instance_eval do
96
+ merge(overrides, &).instance_eval do
96
97
  generator.new(klass).to_params(sorted_attributes)
97
98
  end
98
99
  ensure
99
100
  Fabrication.manager.to_params_stack.pop
100
101
  end
101
102
 
102
- def to_attributes(overrides = {}, &block)
103
- merge(overrides, &block).instance_eval do
103
+ def to_attributes(overrides = {}, &)
104
+ merge(overrides, &).instance_eval do
104
105
  generator.new(klass).to_hash(sorted_attributes, callbacks)
105
106
  end
106
107
  end
@@ -123,9 +124,9 @@ module Fabrication
123
124
  end
124
125
  end
125
126
 
126
- def merge(overrides = {}, &block)
127
+ def merge(overrides = {}, &)
127
128
  clone.tap do |definition|
128
- definition.process_block(&block)
129
+ definition.process_block(&)
129
130
  overrides.each do |name, value|
130
131
  definition.append_or_update_attribute(name.to_sym, value)
131
132
  end
@@ -1,9 +1,9 @@
1
1
  module Fabrication
2
2
  module Schematic
3
3
  class Evaluator < BasicObject
4
- def process(definition, &block)
4
+ def process(definition, &)
5
5
  @_definition = definition
6
- instance_eval(&block)
6
+ instance_eval(&)
7
7
  end
8
8
 
9
9
  def respond_to_missing?(_method_name, _include_private = false)
@@ -30,10 +30,10 @@ module Fabrication
30
30
  @initializing = false
31
31
  end
32
32
 
33
- def register(name, options, &block)
33
+ def register(name, options, &)
34
34
  name = name.to_sym
35
35
  raise_if_registered(name)
36
- store(name, Array(options.delete(:aliases)), options, &block)
36
+ store(name, Array(options.delete(:aliases)), options, &)
37
37
  end
38
38
 
39
39
  def [](name)
@@ -55,14 +55,16 @@ module Fabrication
55
55
  def load_definitions
56
56
  preinitialize
57
57
  Fabrication::Config.path_prefixes.each do |prefix|
58
- Fabrication::Config.fabricator_paths.each do |folder|
59
- Dir.glob(File.join(prefix.to_s, folder, '**', '*.rb')).sort.each do |file|
60
- load file
58
+ Fabrication::Config.fabricator_paths.each do |path|
59
+ if File.file?(path)
60
+ load path
61
+ else
62
+ Dir.glob(File.join(prefix.to_s, path, '**', '*.rb')).each do |file|
63
+ load file
64
+ end
61
65
  end
62
66
  end
63
67
  end
64
- rescue StandardError => e
65
- raise e
66
68
  ensure
67
69
  freeze
68
70
  end
@@ -79,8 +81,8 @@ module Fabrication
79
81
  (raise Fabrication::DuplicateFabricatorError, name) if self[name]
80
82
  end
81
83
 
82
- def store(name, aliases, options, &block)
83
- schematic = schematics[name] = Fabrication::Schematic::Definition.new(name, options, &block)
84
+ def store(name, aliases, options, &)
85
+ schematic = schematics[name] = Fabrication::Schematic::Definition.new(name, options, &)
84
86
  aliases.each { |as| schematics[as.to_sym] = schematic }
85
87
  end
86
88
  end
@@ -7,9 +7,9 @@ module Fabrication
7
7
  self.klass = klass
8
8
  end
9
9
 
10
- def sequence(name = Fabrication::Sequencer::DEFAULT, start = nil, &block)
11
- name = "#{klass.to_s.downcase.gsub(/::/, '_')}_#{name}"
12
- Fabrication::Sequencer.sequence(name, start, &block)
10
+ def sequence(name = Fabrication::Sequencer::DEFAULT, start = nil, &)
11
+ name = "#{klass.to_s.downcase.gsub('::', '_')}_#{name}"
12
+ Fabrication::Sequencer.sequence(name, start, &)
13
13
  end
14
14
  end
15
15
  end
@@ -1,27 +1,40 @@
1
+ require 'singleton'
2
+
1
3
  module Fabrication
2
4
  class Sequencer
5
+ include Singleton
6
+
3
7
  DEFAULT = :_default
4
8
 
5
- def self.sequence(name = DEFAULT, start = nil, &block)
9
+ def self.sequence(name = DEFAULT, start = nil, &)
10
+ instance.sequence(name, start, &)
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
- if block_given?
20
+ if block
8
21
  sequence_blocks[name] = block.to_proc
9
22
  else
10
23
  sequence_blocks[name] ||= ->(i) { i }
11
24
  end.call(idx).tap do
12
- sequences[name] += 1
25
+ sequences[name] = idx.succ
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,73 +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 hash_class
55
- @hash_class ||= defined?(HashWithIndifferentAccess) ? HashWithIndifferentAccess : Hash
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 }
56
40
  end
41
+ end
57
42
 
58
- def singularize(string)
59
- string.singularize
60
- rescue StandardError
61
- string.end_with?('s') ? string[0..-2] : string
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 underscore(string)
65
- string.gsub(/::/, '/')
66
- .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
67
- .gsub(/([a-z\d])([A-Z])/, '\1_\2')
68
- .tr('-', '_')
69
- .downcase
70
- end
47
+ Fabrication.manager.load_definitions
48
+ end
49
+
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
71
66
  end
72
67
  end
73
68
  end
@@ -11,18 +11,18 @@ module Fabrication
11
11
  #
12
12
  #
13
13
  module Make
14
- def make(*args, &block)
14
+ def make(*args, &)
15
15
  overrides = Fabrication::Support.extract_options!(args)
16
16
  klass = Fabrication::Support.underscore(name).to_sym
17
17
  fabricator_name = args.first.is_a?(Symbol) ? "#{klass}_#{args.first}" : klass
18
- Fabricate.build(fabricator_name, overrides, &block)
18
+ Fabricate.build(fabricator_name, overrides, &)
19
19
  end
20
20
 
21
- def make!(*args, &block)
21
+ def make!(*args, &)
22
22
  overrides = Fabrication::Support.extract_options!(args)
23
23
  klass = Fabrication::Support.underscore(name).to_sym
24
24
  fabricator_name = args.first.is_a?(Symbol) ? "#{klass}_#{args.first}" : klass
25
- Fabricate(fabricator_name, overrides, &block)
25
+ Fabricate(fabricator_name, overrides, &)
26
26
  end
27
27
  end
28
28
  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 = '3.0.0.beta.1.1'.freeze
2
+ VERSION = '3.0.0'.freeze
3
3
  end
data/lib/fabrication.rb CHANGED
@@ -31,34 +31,38 @@ module Fabrication
31
31
 
32
32
  module Generator
33
33
  autoload :ActiveRecord, 'fabrication/generator/active_record'
34
- autoload :ActiveRecord4, 'fabrication/generator/active_record_4'
34
+ autoload :Mongoid, 'fabrication/generator/mongoid'
35
35
  autoload :Sequel, 'fabrication/generator/sequel'
36
36
  autoload :Base, 'fabrication/generator/base'
37
37
  end
38
38
 
39
39
  def self.clear_definitions
40
40
  manager.clear
41
- Sequencer.sequences.clear
41
+ Sequencer.clear
42
42
  end
43
43
 
44
- def self.configure(&block)
45
- Fabrication::Config.configure(&block)
44
+ def self.configure(&)
45
+ Fabrication::Config.configure(&)
46
46
  end
47
47
 
48
48
  def self.manager
49
- @manager ||= Fabrication::Schematic::Manager.instance
49
+ Fabrication::Schematic::Manager.instance
50
+ end
51
+
52
+ def self.schematics
53
+ Support.log_deprecation('Fabrication.schematics has been replaced by ' \
54
+ 'Fabrication.manager and will be removed in 3.0.0.')
55
+ manager
50
56
  end
51
57
  end
52
58
 
53
59
  # rubocop:disable Naming/MethodName
54
- def Fabricator(name, options = {}, &block)
55
- Fabrication.manager.register(name, options, &block)
60
+ def Fabricator(name, options = {}, &)
61
+ Fabrication.manager.register(name, options, &)
56
62
  end
57
63
 
58
- def Fabricate(name, overrides = {}, &block)
59
- Fabricate.create(name, overrides, &block).tap do |object|
60
- Fabrication::Cucumber::Fabrications[name] = object if Fabrication::Config.register_with_steps?
61
- end
64
+ def Fabricate(name, overrides = {}, &)
65
+ Fabricate.create(name, overrides, &)
62
66
  end
63
67
  # rubocop:enable Naming/MethodName
64
68
 
@@ -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
@@ -1,12 +1,14 @@
1
1
  World(FabricationMethods)
2
2
 
3
- Fabrication::Config.register_with_steps = true
3
+ Fabrication::Config.register_notifier do |name, object|
4
+ Fabrication::Cucumber::Fabrications[name] = object
5
+ end
4
6
 
5
7
  def with_ivars(fabricator)
6
8
  @they = yield fabricator
7
9
  model = @they.last.class.to_s.underscore
8
- instance_variable_set("@#{model.pluralize}", @they)
9
- instance_variable_set("@#{model.singularize}", @they.last)
10
+ instance_variable_set(:"@#{model.pluralize}", @they)
11
+ instance_variable_set(:"@#{model.singularize}", @they.last)
10
12
  Fabrication::Cucumber::Fabrications[model.singularize.gsub(/\W+/, '_').downcase] = @they.last
11
13
  end
12
14
 
@@ -23,13 +25,13 @@ Given(/^the following ([^"]*):$/) do |model_name, table|
23
25
  end
24
26
 
25
27
  Given(/^that ([^"]*) has the following ([^"]*):$/) do |parent, child, table|
26
- with_ivars Fabrication::Cucumber::StepFabricator.new(child, parent: parent) do |fab|
28
+ with_ivars Fabrication::Cucumber::StepFabricator.new(child, parent:) do |fab|
27
29
  fab.from_table(table)
28
30
  end
29
31
  end
30
32
 
31
33
  Given(/^that ([^"]*) has (\d+) ([^"]*)$/) do |parent, count, child|
32
- with_ivars Fabrication::Cucumber::StepFabricator.new(child, parent: parent) do |fab|
34
+ with_ivars Fabrication::Cucumber::StepFabricator.new(child, parent:) do |fab|
33
35
  fab.n(count.to_i)
34
36
  end
35
37
  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: 3.0.0.beta.1.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Elliott
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-16 00:00:00.000000000 Z
11
+ date: 2025-05-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Fabrication is an object generation framework for ActiveRecord, Mongoid,
14
14
  Sequel, or any other Ruby object.
@@ -32,6 +32,7 @@ files:
32
32
  - lib/fabrication/errors/unknown_fabricator_error.rb
33
33
  - lib/fabrication/generator/active_record.rb
34
34
  - lib/fabrication/generator/base.rb
35
+ - lib/fabrication/generator/mongoid.rb
35
36
  - lib/fabrication/generator/sequel.rb
36
37
  - lib/fabrication/railtie.rb
37
38
  - lib/fabrication/schematic/attribute.rb
@@ -52,8 +53,15 @@ files:
52
53
  homepage: http://fabricationgem.org
53
54
  licenses:
54
55
  - MIT
55
- metadata: {}
56
- post_install_message:
56
+ metadata:
57
+ bug_tracker_uri: https://gitlab.com/fabrication-gem/fabrication/-/issues
58
+ changelog_uri: https://gitlab.com/fabrication-gem/fabrication/-/blob/master/Changelog.markdown
59
+ documentation_uri: https://fabricationgem.org
60
+ homepage_uri: https://fabricationgem.org
61
+ mailing_list_uri: https://groups.google.com/g/fabricationgem
62
+ rubygems_mfa_required: 'true'
63
+ source_code_uri: https://gitlab.com/fabrication-gem/fabrication
64
+ post_install_message:
57
65
  rdoc_options: []
58
66
  require_paths:
59
67
  - lib
@@ -61,15 +69,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
61
69
  requirements:
62
70
  - - ">="
63
71
  - !ruby/object:Gem::Version
64
- version: 2.5.0
72
+ version: 3.2.0
65
73
  required_rubygems_version: !ruby/object:Gem::Requirement
66
74
  requirements:
67
- - - ">"
75
+ - - ">="
68
76
  - !ruby/object:Gem::Version
69
- version: 1.3.1
77
+ version: '0'
70
78
  requirements: []
71
- rubygems_version: 3.1.6
72
- signing_key:
79
+ rubygems_version: 3.4.19
80
+ signing_key:
73
81
  specification_version: 4
74
- summary: Implementing the factory pattern in Ruby so you don't have to.
82
+ summary: Generates object instances for test suites, seed files, etc.
75
83
  test_files: []