fabrication 2.20.2 → 2.23.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.markdown +1 -4
  3. data/Rakefile +8 -10
  4. data/lib/fabricate.rb +10 -13
  5. data/lib/fabrication/config.rb +28 -15
  6. data/lib/fabrication/cucumber/step_fabricator.rb +20 -13
  7. data/lib/fabrication/errors/duplicate_fabricator_error.rb +5 -3
  8. data/lib/fabrication/errors/infinite_recursion_error.rb +5 -3
  9. data/lib/fabrication/errors/misplaced_fabricate_error.rb +7 -3
  10. data/lib/fabrication/errors/unfabricatable_error.rb +5 -4
  11. data/lib/fabrication/errors/unknown_fabricator_error.rb +5 -5
  12. data/lib/fabrication/generator/active_record.rb +18 -15
  13. data/lib/fabrication/generator/base.rb +93 -81
  14. data/lib/fabrication/generator/data_mapper.rb +14 -12
  15. data/lib/fabrication/generator/sequel.rb +29 -27
  16. data/lib/fabrication/railtie.rb +1 -3
  17. data/lib/fabrication/schematic/attribute.rb +69 -62
  18. data/lib/fabrication/schematic/definition.rb +140 -134
  19. data/lib/fabrication/schematic/evaluator.rb +61 -54
  20. data/lib/fabrication/schematic/manager.rb +67 -59
  21. data/lib/fabrication/schematic/runner.rb +12 -9
  22. data/lib/fabrication/sequencer.rb +23 -22
  23. data/lib/fabrication/support.rb +63 -54
  24. data/lib/fabrication/syntax/make.rb +0 -1
  25. data/lib/fabrication/transform.rb +34 -36
  26. data/lib/fabrication/version.rb +1 -1
  27. data/lib/fabrication.rb +6 -4
  28. data/lib/rails/generators/fabrication/cucumber_steps/cucumber_steps_generator.rb +2 -3
  29. data/lib/rails/generators/fabrication/cucumber_steps/templates/fabrication_steps.rb +10 -10
  30. data/lib/rails/generators/fabrication/model/model_generator.rb +14 -9
  31. data/lib/rails/generators/fabrication/model/templates/fabricator.erb +5 -1
  32. data/lib/tasks/defined_fabricators.rake +11 -11
  33. metadata +7 -8
  34. data/lib/fabrication/generator/mongoid.rb +0 -15
@@ -1,36 +1,38 @@
1
- class Fabrication::Generator::Sequel < Fabrication::Generator::Base
2
-
3
- def initialize(klass)
4
- super
5
- load_instance_hooks
6
- end
1
+ module Fabrication
2
+ module Generator
3
+ class Sequel < Fabrication::Generator::Base
4
+ def initialize(klass)
5
+ super
6
+ load_instance_hooks
7
+ end
7
8
 
8
- def self.supports?(klass)
9
- defined?(Sequel) && klass.ancestors.include?(Sequel::Model)
10
- end
9
+ def self.supports?(klass)
10
+ defined?(::Sequel) && defined?(::Sequel::Model) && klass.ancestors.include?(::Sequel::Model)
11
+ end
11
12
 
12
- def set_attributes
13
- _attributes.each do |key, value|
14
- if (reflection = _klass.association_reflections[key]) && value.is_a?(Array)
15
- _instance.associations[key] = value
16
- _instance.after_save_hook do
17
- value.each { |o| _instance.send(reflection.add_method, o) }
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
20
+ else
21
+ _instance.send("#{key}=", value)
22
+ end
18
23
  end
19
- else
20
- _instance.send("#{key}=", value)
21
24
  end
22
- end
23
- end
24
25
 
25
- def persist
26
- _instance.save(raise_on_failure: true)
27
- end
26
+ def persist
27
+ _instance.save(raise_on_failure: true)
28
+ end
28
29
 
29
- private
30
+ private
30
31
 
31
- def load_instance_hooks
32
- klass = _klass.respond_to?(:cti_base_model) ? _klass.cti_models.first : _klass
33
- klass.plugin :instance_hooks unless klass.new.respond_to? :after_save_hook
32
+ def load_instance_hooks
33
+ klass = _klass.respond_to?(:cti_base_model) ? _klass.cti_models.first : _klass
34
+ klass.plugin :instance_hooks unless klass.new.respond_to? :after_save_hook
35
+ end
36
+ end
34
37
  end
35
-
36
38
  end
@@ -9,9 +9,7 @@ module Fabrication
9
9
  config.generators
10
10
  end
11
11
 
12
- unless generators.rails.has_key?(:fixture_replacement)
13
- generators.fixture_replacement :fabrication
14
- end
12
+ generators.fixture_replacement :fabrication unless generators.rails.key?(:fixture_replacement)
15
13
  end
16
14
  end
17
15
  end
@@ -1,65 +1,72 @@
1
- class Fabrication::Schematic::Attribute
2
-
3
- attr_accessor :klass, :name, :value
4
- attr_writer :params
5
-
6
- def initialize(klass, name, value, params={}, &block)
7
- self.klass = klass
8
- self.name = name
9
- self.params = params
10
- self.value = value.nil? ? block : value
11
- end
12
-
13
- def params
14
- @params ||= {}
15
- end
16
-
17
- def transient!
18
- params[:transient] = true
19
- end
20
-
21
- def transient?
22
- params[:transient]
23
- end
24
-
25
- def processed_value(processed_attributes)
26
- if process_count
27
- (1..process_count).map { |i| execute(processed_attributes, i, &value) }
28
- elsif value_proc?
29
- execute(processed_attributes, &value)
30
- else
31
- value
1
+ module Fabrication
2
+ module Schematic
3
+ class Attribute
4
+ attr_accessor :klass, :name, :value
5
+ attr_writer :params
6
+
7
+ def initialize(klass, name, value, params = {}, &block)
8
+ self.klass = klass
9
+ self.name = name
10
+ self.params = params
11
+ self.value = value.nil? ? block : value
12
+ end
13
+
14
+ def params
15
+ @params ||= {}
16
+ end
17
+
18
+ def transient!
19
+ params[:transient] = true
20
+ end
21
+
22
+ def transient?
23
+ params[:transient]
24
+ end
25
+
26
+ def processed_value(processed_attributes)
27
+ if process_count
28
+ (1..process_count).map { |i| execute(processed_attributes, i, &value) }
29
+ elsif value_proc?
30
+ execute(processed_attributes, &value)
31
+ else
32
+ value
33
+ end
34
+ end
35
+
36
+ def value_static?
37
+ !value_proc?
38
+ end
39
+
40
+ def value_proc?
41
+ value.is_a?(Proc)
42
+ end
43
+
44
+ private
45
+
46
+ def execute(*args, &block)
47
+ Fabrication::Schematic::Runner.new(klass).instance_exec(*args, &block)
48
+ end
49
+
50
+ def process_count
51
+ count || rand || rand_range
52
+ end
53
+
54
+ def count
55
+ params[:count]
56
+ end
57
+
58
+ def rand
59
+ return unless params[:rand]
60
+
61
+ range = params[:rand]
62
+ range = 1..range unless range.is_a? Range
63
+
64
+ Kernel.rand(range)
65
+ end
66
+
67
+ def rand_range
68
+ Kernel.rand((params[:start_range]..params[:end_range])) if params[:start_range] && params[:end_range]
69
+ end
32
70
  end
33
71
  end
34
-
35
- def value_static?; !value_proc? end
36
- def value_proc?; Proc === value end
37
-
38
- private
39
-
40
- def execute(*args, &block)
41
- Fabrication::Schematic::Runner.new(klass).instance_exec(*args, &block)
42
- end
43
-
44
- def process_count
45
- count || rand || rand_range
46
- end
47
-
48
- def count
49
- params[:count]
50
- end
51
-
52
- def rand
53
- return unless params[:rand]
54
-
55
- range = params[:rand]
56
- range = 1..range unless range.is_a? Range
57
-
58
- Kernel.rand(range)
59
- end
60
-
61
- def rand_range
62
- Kernel.rand((params[:start_range]..params[:end_range])) if params[:start_range] && params[:end_range]
63
- end
64
-
65
72
  end
@@ -1,164 +1,170 @@
1
- class Fabrication::Schematic::Definition
2
-
3
- GENERATORS = [
4
- Fabrication::Generator::ActiveRecord,
5
- Fabrication::Generator::DataMapper,
6
- Fabrication::Generator::Sequel,
7
- Fabrication::Generator::Mongoid,
8
- Fabrication::Generator::Base
9
- ]
10
-
11
- attr_accessor :name, :options, :block
12
- def initialize(name, options={}, &block)
13
- self.name = name
14
- self.options = options
15
- self.block = block
16
- end
1
+ module Fabrication
2
+ module Schematic
3
+ class Definition
4
+ GENERATORS = [
5
+ Fabrication::Generator::ActiveRecord,
6
+ Fabrication::Generator::DataMapper,
7
+ Fabrication::Generator::Sequel,
8
+ Fabrication::Generator::Base
9
+ ].freeze
10
+
11
+ attr_accessor :name, :options, :block
12
+
13
+ def initialize(name, options = {}, &block)
14
+ self.name = name
15
+ self.options = options
16
+ self.block = block
17
+ end
17
18
 
18
- def process_block(&block)
19
- Fabrication::Schematic::Evaluator.new.process(self, &block) if block_given?
20
- end
19
+ def process_block(&block)
20
+ Fabrication::Schematic::Evaluator.new.process(self, &block) if block_given?
21
+ end
21
22
 
22
- def attribute(name)
23
- attributes.detect { |a| a.name == name }
24
- end
23
+ def attribute(name)
24
+ attributes.detect { |a| a.name == name }
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)
28
- if index = attributes.index { |a| a.name == attribute.name }
29
- attribute.transient! if attributes[index].transient?
30
- attributes[index] = attribute
31
- else
32
- attributes << attribute
33
- end
34
- end
27
+ def append_or_update_attribute(attribute_name, value, params = {}, &block)
28
+ attribute = Fabrication::Schematic::Attribute.new(klass, attribute_name, value, params, &block)
29
+ index = attributes.index { |a| a.name == attribute.name }
35
30
 
36
- attr_writer :attributes
37
- def attributes
38
- load_body
39
- @attributes ||= []
40
- end
31
+ if index
32
+ attribute.transient! if attributes[index].transient?
33
+ attributes[index] = attribute
34
+ else
35
+ attributes << attribute
36
+ end
37
+ end
41
38
 
42
- attr_writer :callbacks
43
- def callbacks
44
- load_body
45
- @callbacks ||= {}
46
- end
39
+ attr_writer :attributes, :callbacks
47
40
 
48
- def generator
49
- @generator ||= Fabrication::Config.generator_for(GENERATORS, klass)
50
- end
41
+ def attributes
42
+ load_body
43
+ @attributes ||= []
44
+ end
51
45
 
52
- def sorted_attributes
53
- attributes.select(&:value_static?) + attributes.select(&:value_proc?)
54
- end
46
+ def callbacks
47
+ load_body
48
+ @callbacks ||= {}
49
+ end
55
50
 
56
- def build(overrides={}, &block)
57
- Fabrication.manager.prevent_recursion!
58
- if Fabrication.manager.to_params_stack.any?
59
- to_params(overrides, &block)
60
- else
61
- begin
62
- Fabrication.manager.build_stack << name
63
- merge(overrides, &block).instance_eval do
64
- generator.new(klass).build(sorted_attributes, callbacks)
51
+ def generator
52
+ @generator ||= Fabrication::Config.generator_for(GENERATORS, klass)
53
+ end
54
+
55
+ def sorted_attributes
56
+ attributes.select(&:value_static?) + attributes.select(&:value_proc?)
57
+ end
58
+
59
+ def build(overrides = {}, &block)
60
+ Fabrication.manager.prevent_recursion!
61
+ if Fabrication.manager.to_params_stack.any?
62
+ to_params(overrides, &block)
63
+ else
64
+ begin
65
+ Fabrication.manager.build_stack << name
66
+ merge(overrides, &block).instance_eval do
67
+ generator.new(klass).build(sorted_attributes, callbacks)
68
+ end
69
+ ensure
70
+ Fabrication.manager.build_stack.pop
71
+ end
65
72
  end
66
- ensure
67
- Fabrication.manager.build_stack.pop
68
73
  end
69
- end
70
- end
71
74
 
72
- def fabricate(overrides={}, &block)
73
- Fabrication.manager.prevent_recursion!
74
- if Fabrication.manager.build_stack.any?
75
- build(overrides, &block)
76
- elsif Fabrication.manager.to_params_stack.any?
77
- to_params(overrides, &block)
78
- else
79
- begin
80
- Fabrication.manager.create_stack << name
75
+ def fabricate(overrides = {}, &block)
76
+ Fabrication.manager.prevent_recursion!
77
+ if Fabrication.manager.build_stack.any?
78
+ build(overrides, &block)
79
+ elsif Fabrication.manager.to_params_stack.any?
80
+ to_params(overrides, &block)
81
+ else
82
+ begin
83
+ Fabrication.manager.create_stack << name
84
+ merge(overrides, &block).instance_eval do
85
+ generator.new(klass).create(sorted_attributes, callbacks)
86
+ end
87
+ ensure
88
+ Fabrication.manager.create_stack.pop
89
+ end
90
+ end
91
+ end
92
+
93
+ def to_params(overrides = {}, &block)
94
+ Fabrication.manager.prevent_recursion!
95
+ Fabrication.manager.to_params_stack << name
81
96
  merge(overrides, &block).instance_eval do
82
- generator.new(klass).create(sorted_attributes, callbacks)
97
+ generator.new(klass).to_params(sorted_attributes)
83
98
  end
84
99
  ensure
85
- Fabrication.manager.create_stack.pop
100
+ Fabrication.manager.to_params_stack.pop
86
101
  end
87
- end
88
- end
89
102
 
90
- def to_params(overrides={}, &block)
91
- Fabrication.manager.prevent_recursion!
92
- Fabrication.manager.to_params_stack << name
93
- merge(overrides, &block).instance_eval do
94
- generator.new(klass).to_params(sorted_attributes)
95
- end
96
- ensure
97
- Fabrication.manager.to_params_stack.pop
98
- end
103
+ def to_attributes(overrides = {}, &block)
104
+ merge(overrides, &block).instance_eval do
105
+ generator.new(klass).to_hash(sorted_attributes, callbacks)
106
+ end
107
+ end
99
108
 
100
- def to_attributes(overrides={}, &block)
101
- merge(overrides, &block).instance_eval do
102
- generator.new(klass).to_hash(sorted_attributes, callbacks)
103
- end
104
- end
109
+ def initialize_copy(original)
110
+ self.callbacks = {}
111
+ original.callbacks.each do |type, callbacks|
112
+ self.callbacks[type] = callbacks.clone
113
+ end
105
114
 
106
- def initialize_copy(original)
107
- self.callbacks = {}
108
- original.callbacks.each do |type, callbacks|
109
- self.callbacks[type] = callbacks.clone
110
- end
115
+ self.attributes = original.attributes.clone
116
+ end
111
117
 
112
- self.attributes = original.attributes.clone
113
- end
118
+ def generate_value(name, params)
119
+ if params[:count] || params[:rand]
120
+ name = Fabrication::Support.singularize(name.to_s)
121
+ proc { Fabricate.build(params[:fabricator] || name) }
122
+ else
123
+ proc { Fabricate(params[:fabricator] || name) }
124
+ end
125
+ end
114
126
 
115
- def generate_value(name, params)
116
- if params[:count] || params[:rand]
117
- name = Fabrication::Support.singularize(name.to_s)
118
- proc { Fabricate.build(params[:fabricator] || name) }
119
- else
120
- proc { Fabricate(params[:fabricator] || name) }
121
- end
122
- end
127
+ def merge(overrides = {}, &block)
128
+ clone.tap do |definition|
129
+ definition.process_block(&block)
130
+ overrides.each do |name, value|
131
+ definition.append_or_update_attribute(name.to_sym, value)
132
+ end
133
+ end
134
+ end
123
135
 
124
- def merge(overrides={}, &block)
125
- clone.tap do |definition|
126
- definition.process_block(&block)
127
- overrides.each do |name, value|
128
- definition.append_or_update_attribute(name.to_sym, value)
136
+ def klass
137
+ @klass ||= Fabrication::Support.class_for(
138
+ options[:class_name] ||
139
+ parent&.klass ||
140
+ options[:from] ||
141
+ name
142
+ )
129
143
  end
130
- end
131
- end
132
144
 
133
- def klass
134
- @klass ||= Fabrication::Support.class_for(
135
- options[:class_name] ||
136
- (parent && parent.klass) ||
137
- options[:from] ||
138
- name
139
- )
140
- end
145
+ protected
146
+
147
+ def loaded?
148
+ !!(@loaded ||= nil)
149
+ end
141
150
 
142
- protected
151
+ def load_body
152
+ return if loaded?
143
153
 
144
- def loaded?
145
- !!(@loaded ||= nil)
146
- end
154
+ @loaded = true
147
155
 
148
- def load_body
149
- return if loaded?
150
- @loaded = true
156
+ if parent
157
+ merge_result = parent.merge(&block)
158
+ @attributes = merge_result.attributes
159
+ @callbacks = merge_result.callbacks
160
+ else
161
+ process_block(&block)
162
+ end
163
+ end
151
164
 
152
- if parent
153
- merge_result = parent.merge(&block)
154
- @attributes = merge_result.attributes
155
- @callbacks = merge_result.callbacks
156
- else
157
- process_block(&block)
165
+ def parent
166
+ @parent ||= Fabrication.manager[options[:from].to_s] if options[:from]
167
+ end
158
168
  end
159
169
  end
160
-
161
- def parent
162
- @parent ||= Fabrication.manager[options[:from].to_s] if options[:from]
163
- end
164
170
  end
@@ -1,70 +1,77 @@
1
- class Fabrication::Schematic::Evaluator < BasicObject
1
+ module Fabrication
2
+ module Schematic
3
+ class Evaluator < BasicObject
4
+ def process(definition, &block)
5
+ @_definition = definition
6
+ instance_eval(&block)
7
+ end
2
8
 
3
- def process(definition, &block)
4
- @_definition = definition
5
- instance_eval(&block)
6
- end
9
+ def respond_to_missing?(_method_name, _include_private = false)
10
+ true
11
+ end
7
12
 
8
- def method_missing(method_name, *args, &block)
9
- params = ::Fabrication::Support.extract_options!(args)
10
- value = args.first
11
- block = @_definition.generate_value(method_name, params) if args.empty? && !block
12
- @_definition.append_or_update_attribute(method_name, value, params, &block)
13
- end
13
+ def method_missing(method_name, *args, &block)
14
+ params = ::Fabrication::Support.extract_options!(args)
15
+ value = args.first
16
+ block = @_definition.generate_value(method_name, params) if args.empty? && !block
17
+ @_definition.append_or_update_attribute(method_name, value, params, &block)
18
+ end
14
19
 
15
- def after_build(&block)
16
- @_definition.callbacks[:after_build] ||= []
17
- @_definition.callbacks[:after_build] << block
18
- end
20
+ def after_build(&block)
21
+ @_definition.callbacks[:after_build] ||= []
22
+ @_definition.callbacks[:after_build] << block
23
+ end
19
24
 
20
- def before_validation(&block)
21
- @_definition.callbacks[:before_validation] ||= []
22
- @_definition.callbacks[:before_validation] << block
23
- end
25
+ def before_validation(&block)
26
+ @_definition.callbacks[:before_validation] ||= []
27
+ @_definition.callbacks[:before_validation] << block
28
+ end
24
29
 
25
- def after_validation(&block)
26
- @_definition.callbacks[:after_validation] ||= []
27
- @_definition.callbacks[:after_validation] << block
28
- end
30
+ def after_validation(&block)
31
+ @_definition.callbacks[:after_validation] ||= []
32
+ @_definition.callbacks[:after_validation] << block
33
+ end
29
34
 
30
- def before_save(&block)
31
- @_definition.callbacks[:before_save] ||= []
32
- @_definition.callbacks[:before_save] << block
33
- end
35
+ def before_save(&block)
36
+ @_definition.callbacks[:before_save] ||= []
37
+ @_definition.callbacks[:before_save] << block
38
+ end
34
39
 
35
- def before_create(&block)
36
- @_definition.callbacks[:before_create] ||= []
37
- @_definition.callbacks[:before_create] << block
38
- end
40
+ def before_create(&block)
41
+ @_definition.callbacks[:before_create] ||= []
42
+ @_definition.callbacks[:before_create] << block
43
+ end
39
44
 
40
- def after_create(&block)
41
- @_definition.callbacks[:after_create] ||= []
42
- @_definition.callbacks[:after_create] << block
43
- end
45
+ def after_create(&block)
46
+ @_definition.callbacks[:after_create] ||= []
47
+ @_definition.callbacks[:after_create] << block
48
+ end
44
49
 
45
- def after_save(&block)
46
- @_definition.callbacks[:after_save] ||= []
47
- @_definition.callbacks[:after_save] << block
48
- end
50
+ def after_save(&block)
51
+ @_definition.callbacks[:after_save] ||= []
52
+ @_definition.callbacks[:after_save] << block
53
+ end
49
54
 
50
- def on_init(&block)
51
- @_definition.callbacks[:on_init] = block
52
- end
55
+ def on_init(&block)
56
+ @_definition.callbacks[:on_init] = block
57
+ end
53
58
 
54
- def initialize_with(&block)
55
- @_definition.callbacks[:initialize_with] = block
56
- end
59
+ def initialize_with(&block)
60
+ @_definition.callbacks[:initialize_with] = block
61
+ end
57
62
 
58
- def init_with(*args)
59
- args
60
- end
63
+ def init_with(*args)
64
+ args
65
+ end
61
66
 
62
- def transient(*field_names)
63
- field_names.each do |field_name|
64
- if field_name.kind_of?(::Hash)
65
- field_name.each_pair { |name, value| @_definition.append_or_update_attribute(name, value, transient: true) }
66
- else
67
- @_definition.append_or_update_attribute(field_name, nil, transient: true)
67
+ def transient(*field_names)
68
+ field_names.each do |field_name|
69
+ if field_name.is_a?(::Hash)
70
+ field_name.each_pair { |name, value| @_definition.append_or_update_attribute(name, value, transient: true) }
71
+ else
72
+ @_definition.append_or_update_attribute(field_name, nil, transient: true)
73
+ end
74
+ end
68
75
  end
69
76
  end
70
77
  end