fabrication 2.21.1 → 2.24.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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.markdown +1 -4
  3. data/Rakefile +8 -10
  4. data/lib/fabricate.rb +13 -16
  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 +89 -81
  14. data/lib/fabrication/generator/data_mapper.rb +14 -12
  15. data/lib/fabrication/generator/mongoid.rb +13 -11
  16. data/lib/fabrication/generator/sequel.rb +29 -27
  17. data/lib/fabrication/railtie.rb +1 -3
  18. data/lib/fabrication/schematic/attribute.rb +69 -62
  19. data/lib/fabrication/schematic/definition.rb +141 -134
  20. data/lib/fabrication/schematic/evaluator.rb +61 -54
  21. data/lib/fabrication/schematic/manager.rb +69 -59
  22. data/lib/fabrication/schematic/runner.rb +12 -9
  23. data/lib/fabrication/sequencer.rb +23 -22
  24. data/lib/fabrication/support.rb +63 -54
  25. data/lib/fabrication/syntax/make.rb +0 -1
  26. data/lib/fabrication/transform.rb +34 -36
  27. data/lib/fabrication/version.rb +1 -1
  28. data/lib/fabrication.rb +6 -3
  29. data/lib/rails/generators/fabrication/cucumber_steps/cucumber_steps_generator.rb +2 -3
  30. data/lib/rails/generators/fabrication/cucumber_steps/templates/fabrication_steps.rb +10 -10
  31. data/lib/rails/generators/fabrication/model/model_generator.rb +9 -9
  32. data/lib/tasks/defined_fabricators.rake +11 -11
  33. metadata +7 -7
@@ -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,171 @@
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::Mongoid,
9
+ Fabrication::Generator::Base
10
+ ].freeze
11
+
12
+ attr_accessor :name, :options, :block
13
+
14
+ def initialize(name, options = {}, &block)
15
+ self.name = name
16
+ self.options = options
17
+ self.block = block
18
+ end
17
19
 
18
- def process_block(&block)
19
- Fabrication::Schematic::Evaluator.new.process(self, &block) if block_given?
20
- end
20
+ def process_block(&block)
21
+ Fabrication::Schematic::Evaluator.new.process(self, &block) if block
22
+ end
21
23
 
22
- def attribute(name)
23
- attributes.detect { |a| a.name == name }
24
- end
24
+ def attribute(name)
25
+ attributes.detect { |a| a.name == name }
26
+ end
25
27
 
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
28
+ def append_or_update_attribute(attribute_name, value, params = {}, &block)
29
+ attribute = Fabrication::Schematic::Attribute.new(klass, attribute_name, value, params, &block)
30
+ index = attributes.index { |a| a.name == attribute.name }
35
31
 
36
- attr_writer :attributes
37
- def attributes
38
- load_body
39
- @attributes ||= []
40
- end
32
+ if index
33
+ attribute.transient! if attributes[index].transient?
34
+ attributes[index] = attribute
35
+ else
36
+ attributes << attribute
37
+ end
38
+ end
41
39
 
42
- attr_writer :callbacks
43
- def callbacks
44
- load_body
45
- @callbacks ||= {}
46
- end
40
+ attr_writer :attributes, :callbacks
47
41
 
48
- def generator
49
- @generator ||= Fabrication::Config.generator_for(GENERATORS, klass)
50
- end
42
+ def attributes
43
+ load_body
44
+ @attributes ||= []
45
+ end
51
46
 
52
- def sorted_attributes
53
- attributes.select(&:value_static?) + attributes.select(&:value_proc?)
54
- end
47
+ def callbacks
48
+ load_body
49
+ @callbacks ||= {}
50
+ end
55
51
 
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)
52
+ def generator
53
+ @generator ||= Fabrication::Config.generator_for(GENERATORS, klass)
54
+ end
55
+
56
+ def sorted_attributes
57
+ attributes.select(&:value_static?) + attributes.select(&:value_proc?)
58
+ end
59
+
60
+ def build(overrides = {}, &block)
61
+ Fabrication.manager.prevent_recursion!
62
+ if Fabrication.manager.to_params_stack.any?
63
+ to_params(overrides, &block)
64
+ else
65
+ begin
66
+ Fabrication.manager.build_stack << name
67
+ merge(overrides, &block).instance_eval do
68
+ generator.new(klass).build(sorted_attributes, callbacks)
69
+ end
70
+ ensure
71
+ Fabrication.manager.build_stack.pop
72
+ end
65
73
  end
66
- ensure
67
- Fabrication.manager.build_stack.pop
68
74
  end
69
- end
70
- end
71
75
 
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
76
+ def fabricate(overrides = {}, &block)
77
+ Fabrication.manager.prevent_recursion!
78
+ if Fabrication.manager.build_stack.any?
79
+ build(overrides, &block)
80
+ elsif Fabrication.manager.to_params_stack.any?
81
+ to_params(overrides, &block)
82
+ else
83
+ begin
84
+ Fabrication.manager.create_stack << name
85
+ merge(overrides, &block).instance_eval do
86
+ generator.new(klass).create(sorted_attributes, callbacks)
87
+ end
88
+ ensure
89
+ Fabrication.manager.create_stack.pop
90
+ end
91
+ end
92
+ end
93
+
94
+ def to_params(overrides = {}, &block)
95
+ Fabrication.manager.prevent_recursion!
96
+ Fabrication.manager.to_params_stack << name
81
97
  merge(overrides, &block).instance_eval do
82
- generator.new(klass).create(sorted_attributes, callbacks)
98
+ generator.new(klass).to_params(sorted_attributes)
83
99
  end
84
100
  ensure
85
- Fabrication.manager.create_stack.pop
101
+ Fabrication.manager.to_params_stack.pop
86
102
  end
87
- end
88
- end
89
103
 
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
104
+ def to_attributes(overrides = {}, &block)
105
+ merge(overrides, &block).instance_eval do
106
+ generator.new(klass).to_hash(sorted_attributes, callbacks)
107
+ end
108
+ end
99
109
 
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
110
+ def initialize_copy(original)
111
+ self.callbacks = {}
112
+ original.callbacks.each do |type, callbacks|
113
+ self.callbacks[type] = callbacks.clone
114
+ end
105
115
 
106
- def initialize_copy(original)
107
- self.callbacks = {}
108
- original.callbacks.each do |type, callbacks|
109
- self.callbacks[type] = callbacks.clone
110
- end
116
+ self.attributes = original.attributes.clone
117
+ end
111
118
 
112
- self.attributes = original.attributes.clone
113
- end
119
+ def generate_value(name, params)
120
+ if params[:count] || params[:rand]
121
+ name = Fabrication::Support.singularize(name.to_s)
122
+ proc { Fabricate.build(params[:fabricator] || name) }
123
+ else
124
+ proc { Fabricate(params[:fabricator] || name) }
125
+ end
126
+ end
114
127
 
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
128
+ def merge(overrides = {}, &block)
129
+ clone.tap do |definition|
130
+ definition.process_block(&block)
131
+ overrides.each do |name, value|
132
+ definition.append_or_update_attribute(name.to_sym, value)
133
+ end
134
+ end
135
+ end
123
136
 
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)
137
+ def klass
138
+ @klass ||= Fabrication::Support.class_for(
139
+ options[:class_name] ||
140
+ parent&.klass ||
141
+ options[:from] ||
142
+ name
143
+ )
129
144
  end
130
- end
131
- end
132
145
 
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
146
+ protected
147
+
148
+ def loaded?
149
+ !!(@loaded ||= nil)
150
+ end
141
151
 
142
- protected
152
+ def load_body
153
+ return if loaded?
143
154
 
144
- def loaded?
145
- !!(@loaded ||= nil)
146
- end
155
+ @loaded = true
147
156
 
148
- def load_body
149
- return if loaded?
150
- @loaded = true
157
+ if parent
158
+ merge_result = parent.merge(&block)
159
+ @attributes = merge_result.attributes
160
+ @callbacks = merge_result.callbacks
161
+ else
162
+ process_block(&block)
163
+ end
164
+ end
151
165
 
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)
166
+ def parent
167
+ @parent ||= Fabrication.manager[options[:from].to_s] if options[:from]
168
+ end
158
169
  end
159
170
  end
160
-
161
- def parent
162
- @parent ||= Fabrication.manager[options[:from].to_s] if options[:from]
163
- end
164
171
  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