fabrication 2.20.0 → 2.22.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 +5 -5
  2. data/README.markdown +1 -4
  3. data/Rakefile +8 -10
  4. data/lib/fabricate.rb +10 -13
  5. data/lib/fabrication.rb +6 -3
  6. data/lib/fabrication/config.rb +28 -15
  7. data/lib/fabrication/cucumber/step_fabricator.rb +20 -13
  8. data/lib/fabrication/errors/duplicate_fabricator_error.rb +5 -3
  9. data/lib/fabrication/errors/infinite_recursion_error.rb +5 -3
  10. data/lib/fabrication/errors/misplaced_fabricate_error.rb +7 -3
  11. data/lib/fabrication/errors/unfabricatable_error.rb +5 -4
  12. data/lib/fabrication/errors/unknown_fabricator_error.rb +5 -5
  13. data/lib/fabrication/generator/active_record.rb +18 -11
  14. data/lib/fabrication/generator/base.rb +89 -81
  15. data/lib/fabrication/generator/data_mapper.rb +14 -12
  16. data/lib/fabrication/generator/mongoid.rb +13 -11
  17. data/lib/fabrication/generator/sequel.rb +29 -27
  18. data/lib/fabrication/railtie.rb +1 -3
  19. data/lib/fabrication/schematic/attribute.rb +69 -62
  20. data/lib/fabrication/schematic/definition.rb +141 -134
  21. data/lib/fabrication/schematic/evaluator.rb +61 -54
  22. data/lib/fabrication/schematic/manager.rb +67 -59
  23. data/lib/fabrication/schematic/runner.rb +12 -9
  24. data/lib/fabrication/sequencer.rb +23 -22
  25. data/lib/fabrication/support.rb +57 -54
  26. data/lib/fabrication/syntax/make.rb +0 -1
  27. data/lib/fabrication/transform.rb +34 -36
  28. data/lib/fabrication/version.rb +1 -1
  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 +14 -9
  32. data/lib/rails/generators/fabrication/model/templates/fabricator.erb +5 -1
  33. data/lib/tasks/defined_fabricators.rake +11 -11
  34. metadata +7 -8
@@ -1,17 +1,19 @@
1
- class Fabrication::Generator::DataMapper < Fabrication::Generator::Base
1
+ module Fabrication
2
+ module Generator
3
+ class DataMapper < Fabrication::Generator::Base
4
+ def self.supports?(klass)
5
+ defined?(::DataMapper) && klass.ancestors.include?(::DataMapper::Hook)
6
+ end
2
7
 
3
- def self.supports?(klass)
4
- defined?(DataMapper) && klass.ancestors.include?(DataMapper::Hook)
5
- end
6
-
7
- def build_instance
8
- self._instance = _klass.new(_attributes)
9
- end
8
+ def build_instance
9
+ self._instance = _klass.new(_attributes)
10
+ end
10
11
 
11
- protected
12
+ protected
12
13
 
13
- def persist
14
- _instance.save
14
+ def persist
15
+ _instance.save
16
+ end
17
+ end
15
18
  end
16
-
17
19
  end
@@ -1,15 +1,17 @@
1
- class Fabrication::Generator::Mongoid < Fabrication::Generator::Base
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
2
7
 
3
- def self.supports?(klass)
4
- defined?(Mongoid) && klass.ancestors.include?(Mongoid::Document)
5
- end
6
-
7
- def build_instance
8
- if _klass.respond_to?(:protected_attributes)
9
- self._instance = _klass.new(_attributes, without_protection: true)
10
- else
11
- self._instance = _klass.new(_attributes)
8
+ def build_instance
9
+ self._instance = if _klass.respond_to?(:protected_attributes)
10
+ _klass.new(_attributes, without_protection: true)
11
+ else
12
+ _klass.new(_attributes)
13
+ end
14
+ end
12
15
  end
13
16
  end
14
-
15
17
  end
@@ -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) && 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_given?
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]
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
- protected
146
+ protected
134
147
 
135
- def loaded?
136
- !!(@loaded ||= nil)
137
- end
148
+ def loaded?
149
+ !!(@loaded ||= nil)
150
+ end
138
151
 
139
- def load_body
140
- return if loaded?
141
- @loaded = true
152
+ def load_body
153
+ return if loaded?
142
154
 
143
- if parent
144
- merge_result = parent.merge(&block)
145
- @attributes = merge_result.attributes
146
- @callbacks = merge_result.callbacks
147
- else
148
- process_block(&block)
149
- end
150
- end
155
+ @loaded = true
151
156
 
152
- def parent
153
- @parent ||= Fabrication.manager[options[:from].to_s] if options[:from]
154
- end
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
155
165
 
156
- def klass
157
- @klass ||= Fabrication::Support.class_for(
158
- options[:class_name] ||
159
- (parent && parent.klass) ||
160
- options[:from] ||
161
- name
162
- )
166
+ def parent
167
+ @parent ||= Fabrication.manager[options[:from].to_s] if options[:from]
168
+ end
169
+ end
163
170
  end
164
171
  end