factory_girl 3.2.0 → 3.3.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.
- data/Appraisals +3 -3
- data/GETTING_STARTED.md +74 -15
- data/Gemfile.lock +38 -44
- data/NEWS +12 -0
- data/gemfiles/3.0.gemfile +1 -1
- data/gemfiles/3.0.gemfile.lock +23 -24
- data/gemfiles/3.1.gemfile +1 -1
- data/gemfiles/3.1.gemfile.lock +19 -19
- data/gemfiles/3.2.gemfile +1 -1
- data/gemfiles/3.2.gemfile.lock +10 -10
- data/lib/factory_girl.rb +39 -37
- data/lib/factory_girl/aliases.rb +3 -4
- data/lib/factory_girl/attribute.rb +33 -11
- data/lib/factory_girl/attribute/association.rb +3 -2
- data/lib/factory_girl/attribute/dynamic.rb +3 -2
- data/lib/factory_girl/attribute/sequence.rb +1 -2
- data/lib/factory_girl/attribute/static.rb +3 -2
- data/lib/factory_girl/attribute_assigner.rb +6 -5
- data/lib/factory_girl/attribute_list.rb +16 -3
- data/lib/factory_girl/callback.rb +7 -3
- data/lib/factory_girl/callbacks_observer.rb +1 -0
- data/lib/factory_girl/configuration.rb +24 -0
- data/lib/factory_girl/declaration.rb +5 -4
- data/lib/factory_girl/declaration/association.rb +1 -0
- data/lib/factory_girl/declaration/dynamic.rb +1 -0
- data/lib/factory_girl/declaration/implicit.rb +1 -0
- data/lib/factory_girl/declaration/static.rb +1 -0
- data/lib/factory_girl/declaration_list.rb +1 -0
- data/lib/factory_girl/definition.rb +22 -3
- data/lib/factory_girl/definition_list.rb +31 -0
- data/lib/factory_girl/definition_proxy.rb +19 -4
- data/lib/factory_girl/evaluation.rb +3 -3
- data/lib/factory_girl/evaluator.rb +24 -14
- data/lib/factory_girl/evaluator_class_definer.rb +2 -13
- data/lib/factory_girl/factory.rb +22 -24
- data/lib/factory_girl/factory_runner.rb +6 -3
- data/lib/factory_girl/find_definitions.rb +2 -2
- data/lib/factory_girl/null_factory.rb +3 -1
- data/lib/factory_girl/null_object.rb +1 -0
- data/lib/factory_girl/reload.rb +4 -6
- data/lib/factory_girl/sequence.rb +3 -2
- data/lib/factory_girl/step_definitions.rb +1 -0
- data/lib/factory_girl/strategy/attributes_for.rb +1 -1
- data/lib/factory_girl/strategy/stub.rb +6 -6
- data/lib/factory_girl/strategy_calculator.rb +1 -0
- data/lib/factory_girl/strategy_syntax_method_registrar.rb +37 -0
- data/lib/factory_girl/syntax.rb +5 -4
- data/lib/factory_girl/syntax/blueprint.rb +5 -8
- data/lib/factory_girl/syntax/default.rb +18 -6
- data/lib/factory_girl/syntax/generate.rb +10 -13
- data/lib/factory_girl/syntax/make.rb +8 -11
- data/lib/factory_girl/syntax/methods.rb +76 -36
- data/lib/factory_girl/syntax/sham.rb +3 -2
- data/lib/factory_girl/syntax/vintage.rb +9 -9
- data/lib/factory_girl/syntax_runner.rb +1 -0
- data/lib/factory_girl/trait.rb +5 -4
- data/lib/factory_girl/version.rb +1 -2
- data/spec/acceptance/activesupport_instrumentation_spec.rb +15 -2
- data/spec/acceptance/callbacks_spec.rb +113 -9
- data/spec/acceptance/create_list_spec.rb +1 -1
- data/spec/acceptance/global_initialize_with_spec.rb +82 -0
- data/spec/acceptance/global_to_create_spec.rb +122 -0
- data/spec/acceptance/modify_factories_spec.rb +2 -2
- data/spec/acceptance/parent_spec.rb +1 -1
- data/spec/acceptance/register_strategies_spec.rb +8 -0
- data/spec/acceptance/syntax/vintage_spec.rb +8 -8
- data/spec/acceptance/traits_spec.rb +145 -3
- data/spec/acceptance/transient_attributes_spec.rb +1 -1
- data/spec/factory_girl/attribute_list_spec.rb +66 -1
- data/spec/factory_girl/attribute_spec.rb +1 -1
- data/spec/factory_girl/definition_proxy_spec.rb +6 -6
- data/spec/factory_girl/definition_spec.rb +22 -16
- data/spec/factory_girl/factory_spec.rb +6 -4
- data/spec/factory_girl/strategy/build_spec.rb +2 -2
- data/spec/factory_girl/strategy/create_spec.rb +1 -1
- data/spec/factory_girl/strategy/stub_spec.rb +2 -2
- data/spec/factory_girl/strategy_calculator_spec.rb +20 -14
- data/spec/support/shared_examples/strategy.rb +8 -9
- metadata +94 -29
- data/gemfiles/2.3.gemfile +0 -7
@@ -1,9 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require 'factory_girl/declaration/static'
|
2
|
+
require 'factory_girl/declaration/dynamic'
|
3
|
+
require 'factory_girl/declaration/association'
|
4
|
+
require 'factory_girl/declaration/implicit'
|
5
5
|
|
6
6
|
module FactoryGirl
|
7
|
+
# @api private
|
7
8
|
class Declaration
|
8
9
|
attr_reader :name
|
9
10
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module FactoryGirl
|
2
|
+
# @api private
|
2
3
|
class Definition
|
3
4
|
attr_reader :callbacks, :defined_traits, :declarations, :constructor
|
4
5
|
|
@@ -6,7 +7,7 @@ module FactoryGirl
|
|
6
7
|
@declarations = DeclarationList.new(name)
|
7
8
|
@callbacks = []
|
8
9
|
@defined_traits = []
|
9
|
-
@to_create =
|
10
|
+
@to_create = nil
|
10
11
|
@base_traits = base_traits
|
11
12
|
@additional_traits = []
|
12
13
|
@constructor = nil
|
@@ -22,8 +23,10 @@ module FactoryGirl
|
|
22
23
|
attributes
|
23
24
|
end
|
24
25
|
|
25
|
-
def
|
26
|
-
|
26
|
+
def definition_list
|
27
|
+
DefinitionList.new(
|
28
|
+
base_traits.map(&:definition) + [self] + additional_traits.map(&:definition)
|
29
|
+
)
|
27
30
|
end
|
28
31
|
|
29
32
|
def overridable
|
@@ -32,6 +35,10 @@ module FactoryGirl
|
|
32
35
|
end
|
33
36
|
|
34
37
|
def inherit_traits(new_traits)
|
38
|
+
@base_traits += new_traits
|
39
|
+
end
|
40
|
+
|
41
|
+
def append_traits(new_traits)
|
35
42
|
@additional_traits += new_traits
|
36
43
|
end
|
37
44
|
|
@@ -39,6 +46,14 @@ module FactoryGirl
|
|
39
46
|
@callbacks << callback
|
40
47
|
end
|
41
48
|
|
49
|
+
def compiled_to_create
|
50
|
+
definition_list.to_create
|
51
|
+
end
|
52
|
+
|
53
|
+
def compiled_constructor
|
54
|
+
definition_list.constructor
|
55
|
+
end
|
56
|
+
|
42
57
|
def to_create(&block)
|
43
58
|
if block_given?
|
44
59
|
@to_create = block
|
@@ -47,6 +62,10 @@ module FactoryGirl
|
|
47
62
|
end
|
48
63
|
end
|
49
64
|
|
65
|
+
def skip_create
|
66
|
+
@to_create = ->(instance) { }
|
67
|
+
end
|
68
|
+
|
50
69
|
def define_trait(trait)
|
51
70
|
@defined_traits << trait
|
52
71
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module FactoryGirl
|
2
|
+
class DefinitionList
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(definitions = [])
|
6
|
+
@definitions = definitions
|
7
|
+
end
|
8
|
+
|
9
|
+
def each(&block)
|
10
|
+
@definitions.each &block
|
11
|
+
end
|
12
|
+
|
13
|
+
def callbacks
|
14
|
+
map(&:callbacks).flatten
|
15
|
+
end
|
16
|
+
|
17
|
+
def attributes
|
18
|
+
map {|definition| definition.attributes.to_a }.flatten
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_create
|
22
|
+
map(&:to_create).compact.last
|
23
|
+
end
|
24
|
+
|
25
|
+
def constructor
|
26
|
+
map(&:constructor).compact.last
|
27
|
+
end
|
28
|
+
|
29
|
+
delegate :[], :==, to: :@definitions
|
30
|
+
end
|
31
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module FactoryGirl
|
2
2
|
class DefinitionProxy
|
3
|
-
UNPROXIED_METHODS = %w(__send__ __id__ nil? send object_id extend instance_eval initialize block_given? raise)
|
3
|
+
UNPROXIED_METHODS = %w(__send__ __id__ nil? send object_id extend instance_eval initialize block_given? raise caller)
|
4
4
|
|
5
5
|
(instance_methods + private_instance_methods).each do |method|
|
6
6
|
undef_method(method) unless UNPROXIED_METHODS.include?(method.to_s)
|
@@ -33,7 +33,7 @@ module FactoryGirl
|
|
33
33
|
# * value: +Object+
|
34
34
|
# If no block is given, this value will be used for this attribute.
|
35
35
|
def add_attribute(name, value = nil, &block)
|
36
|
-
raise AttributeDefinitionError,
|
36
|
+
raise AttributeDefinitionError, 'Both value and block given' if value && block_given?
|
37
37
|
|
38
38
|
declaration = if block_given?
|
39
39
|
Declaration::Dynamic.new(name, @ignore, block)
|
@@ -83,9 +83,11 @@ module FactoryGirl
|
|
83
83
|
def method_missing(name, *args, &block)
|
84
84
|
if args.empty? && block.nil?
|
85
85
|
@definition.declare_attribute(Declaration::Implicit.new(name, @definition, @ignore))
|
86
|
-
elsif args.first.
|
86
|
+
elsif args.first.respond_to?(:has_key?) && args.first.has_key?(:factory)
|
87
87
|
association(name, *args)
|
88
88
|
elsif FactoryGirl.callback_names.include?(name)
|
89
|
+
callback_when, callback_name = name.to_s.split('_', 2)
|
90
|
+
ActiveSupport::Deprecation.warn "Calling #{name} is deprecated; use the syntax #{callback_when}(:#{callback_name}) {}", caller
|
89
91
|
@definition.add_callback(Callback.new(name, block))
|
90
92
|
else
|
91
93
|
add_attribute(name, *args, &block)
|
@@ -145,7 +147,7 @@ module FactoryGirl
|
|
145
147
|
end
|
146
148
|
|
147
149
|
def skip_create
|
148
|
-
@definition.
|
150
|
+
@definition.skip_create
|
149
151
|
end
|
150
152
|
|
151
153
|
def factory(name, options = {}, &block)
|
@@ -159,5 +161,18 @@ module FactoryGirl
|
|
159
161
|
def initialize_with(&block)
|
160
162
|
@definition.define_constructor(&block)
|
161
163
|
end
|
164
|
+
|
165
|
+
def before(name, &block)
|
166
|
+
callback("before_#{name}", &block)
|
167
|
+
end
|
168
|
+
|
169
|
+
def after(name, &block)
|
170
|
+
callback("after_#{name}", &block)
|
171
|
+
end
|
172
|
+
|
173
|
+
def callback(name, &block)
|
174
|
+
FactoryGirl.register_callback(name)
|
175
|
+
@definition.add_callback(Callback.new(name, block))
|
176
|
+
end
|
162
177
|
end
|
163
178
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'observer'
|
2
2
|
|
3
3
|
module FactoryGirl
|
4
4
|
class Evaluation
|
@@ -9,12 +9,12 @@ module FactoryGirl
|
|
9
9
|
@to_create = to_create
|
10
10
|
end
|
11
11
|
|
12
|
+
delegate :object, :hash, to: :@attribute_assigner
|
13
|
+
|
12
14
|
def create(result_instance)
|
13
15
|
@to_create[result_instance]
|
14
16
|
end
|
15
17
|
|
16
|
-
delegate :object, :hash, to: :@attribute_assigner
|
17
|
-
|
18
18
|
def notify(name, result_instance)
|
19
19
|
changed
|
20
20
|
notify_observers(name, result_instance)
|
@@ -1,18 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'active_support/core_ext/hash/except'
|
2
|
+
require 'active_support/core_ext/class/attribute'
|
3
3
|
|
4
4
|
module FactoryGirl
|
5
|
+
# @api private
|
5
6
|
class Evaluator
|
6
7
|
class_attribute :attribute_lists
|
7
8
|
|
8
|
-
def self.attribute_list
|
9
|
-
AttributeList.new.tap do |list|
|
10
|
-
attribute_lists.each do |attribute_list|
|
11
|
-
list.apply_attributes attribute_list.to_a
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
9
|
private_instance_methods.each do |method|
|
17
10
|
undef_method(method) unless method =~ /^__|initialize/
|
18
11
|
end
|
@@ -24,17 +17,16 @@ module FactoryGirl
|
|
24
17
|
@cached_attributes = overrides
|
25
18
|
|
26
19
|
@overrides.each do |name, value|
|
27
|
-
singleton_class.
|
20
|
+
singleton_class.define_attribute(name) { value }
|
28
21
|
end
|
29
22
|
end
|
30
23
|
|
31
24
|
delegate :new, to: :@build_class
|
32
25
|
|
33
26
|
def association(factory_name, overrides = {})
|
34
|
-
strategy_override = overrides.fetch(:strategy) {
|
27
|
+
strategy_override = overrides.fetch(:strategy) { :create }
|
35
28
|
|
36
|
-
|
37
|
-
runner = FactoryRunner.new(factory_name, build_strategy, [overrides.except(:strategy)])
|
29
|
+
runner = FactoryRunner.new(factory_name, strategy_override, [overrides.except(:strategy)])
|
38
30
|
@build_strategy.association(runner)
|
39
31
|
end
|
40
32
|
|
@@ -57,5 +49,23 @@ module FactoryGirl
|
|
57
49
|
def __override_names__
|
58
50
|
@overrides.keys
|
59
51
|
end
|
52
|
+
|
53
|
+
def self.attribute_list
|
54
|
+
AttributeList.new.tap do |list|
|
55
|
+
attribute_lists.each do |attribute_list|
|
56
|
+
list.apply_attributes attribute_list.to_a
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.define_attribute(name, &block)
|
62
|
+
define_method(name) do
|
63
|
+
if @cached_attributes.key?(name)
|
64
|
+
@cached_attributes[name]
|
65
|
+
else
|
66
|
+
@cached_attributes[name] = instance_exec(&block)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
60
70
|
end
|
61
71
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module FactoryGirl
|
2
|
+
# @api private
|
2
3
|
class EvaluatorClassDefiner
|
3
4
|
def initialize(attributes, parent_class)
|
4
5
|
@parent_class = parent_class
|
5
6
|
@attributes = attributes
|
6
7
|
|
7
8
|
attributes.each do |attribute|
|
8
|
-
define_attribute(attribute.name, attribute.to_proc)
|
9
|
+
evaluator_class.define_attribute(attribute.name, &attribute.to_proc)
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
@@ -15,17 +16,5 @@ module FactoryGirl
|
|
15
16
|
klass.attribute_lists += [@attributes]
|
16
17
|
end
|
17
18
|
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def define_attribute(attribute_name, attribute_proc)
|
22
|
-
evaluator_class.send(:define_method, attribute_name) do
|
23
|
-
if @cached_attributes.key?(attribute_name)
|
24
|
-
@cached_attributes[attribute_name]
|
25
|
-
else
|
26
|
-
@cached_attributes[attribute_name] = instance_exec(&attribute_proc)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
19
|
end
|
31
20
|
end
|
data/lib/factory_girl/factory.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'active_support/core_ext/hash/keys'
|
2
|
+
require 'active_support/inflector'
|
3
3
|
|
4
4
|
module FactoryGirl
|
5
|
+
# @api private
|
5
6
|
class Factory
|
6
|
-
attr_reader :name, :definition
|
7
|
+
attr_reader :name, :definition
|
7
8
|
|
8
|
-
def initialize(name, options = {})
|
9
|
+
def initialize(name, options = {})
|
9
10
|
assert_valid_options(options)
|
10
11
|
@name = name.is_a?(Symbol) ? name : name.to_s.underscore.to_sym
|
11
12
|
@parent = options[:parent]
|
@@ -15,10 +16,10 @@ module FactoryGirl
|
|
15
16
|
@compiled = false
|
16
17
|
end
|
17
18
|
|
18
|
-
delegate :add_callback, :declare_attribute, :to_create, :define_trait,
|
19
|
-
:defined_traits, :inherit_traits, :
|
19
|
+
delegate :add_callback, :declare_attribute, :to_create, :define_trait, :constructor,
|
20
|
+
:defined_traits, :inherit_traits, :append_traits, :definition_list, to: :@definition
|
20
21
|
|
21
|
-
def build_class
|
22
|
+
def build_class
|
22
23
|
@build_class ||= if class_name.is_a? Class
|
23
24
|
class_name
|
24
25
|
else
|
@@ -26,16 +27,16 @@ module FactoryGirl
|
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
29
|
-
def run(
|
30
|
+
def run(build_strategy, overrides, &block)
|
30
31
|
block ||= ->(result) { result }
|
31
32
|
compile
|
32
33
|
|
33
|
-
strategy =
|
34
|
+
strategy = StrategyCalculator.new(build_strategy).strategy.new
|
34
35
|
|
35
36
|
evaluator = evaluator_class.new(build_class, strategy, overrides.symbolize_keys)
|
36
|
-
attribute_assigner = AttributeAssigner.new(evaluator, build_class, &
|
37
|
+
attribute_assigner = AttributeAssigner.new(evaluator, build_class, &compiled_constructor)
|
37
38
|
|
38
|
-
evaluation = Evaluation.new(attribute_assigner,
|
39
|
+
evaluation = Evaluation.new(attribute_assigner, compiled_to_create)
|
39
40
|
evaluation.add_observer(CallbacksObserver.new(callbacks, evaluator))
|
40
41
|
|
41
42
|
strategy.result(evaluation).tap(&block)
|
@@ -89,13 +90,13 @@ module FactoryGirl
|
|
89
90
|
|
90
91
|
def with_traits(traits)
|
91
92
|
self.clone.tap do |factory_with_traits|
|
92
|
-
factory_with_traits.
|
93
|
+
factory_with_traits.append_traits traits
|
93
94
|
end
|
94
95
|
end
|
95
96
|
|
96
97
|
protected
|
97
98
|
|
98
|
-
def class_name
|
99
|
+
def class_name
|
99
100
|
@class_name || parent.class_name || name
|
100
101
|
end
|
101
102
|
|
@@ -106,18 +107,20 @@ module FactoryGirl
|
|
106
107
|
def attributes
|
107
108
|
compile
|
108
109
|
AttributeList.new(@name).tap do |list|
|
109
|
-
|
110
|
-
list.apply_attributes factory.attributes
|
111
|
-
end
|
110
|
+
list.apply_attributes definition_list.attributes
|
112
111
|
end
|
113
112
|
end
|
114
113
|
|
115
114
|
def callbacks
|
116
|
-
parent.callbacks +
|
115
|
+
parent.callbacks + definition_list.callbacks
|
117
116
|
end
|
118
117
|
|
119
|
-
def
|
120
|
-
@
|
118
|
+
def compiled_to_create
|
119
|
+
@definition.compiled_to_create || parent.compiled_to_create || FactoryGirl.to_create
|
120
|
+
end
|
121
|
+
|
122
|
+
def compiled_constructor
|
123
|
+
@definition.compiled_constructor || parent.compiled_constructor || FactoryGirl.constructor
|
121
124
|
end
|
122
125
|
|
123
126
|
private
|
@@ -134,11 +137,6 @@ module FactoryGirl
|
|
134
137
|
end
|
135
138
|
end
|
136
139
|
|
137
|
-
def instance_builder
|
138
|
-
build_class = self.build_class
|
139
|
-
constructor || -> { build_class.new }
|
140
|
-
end
|
141
|
-
|
142
140
|
def initialize_copy(source)
|
143
141
|
super
|
144
142
|
@definition = @definition.clone
|
@@ -8,8 +8,7 @@ module FactoryGirl
|
|
8
8
|
@traits = traits_and_overrides
|
9
9
|
end
|
10
10
|
|
11
|
-
def run(
|
12
|
-
strategy_override ||= @strategy
|
11
|
+
def run(runner_strategy = @strategy, &block)
|
13
12
|
factory = FactoryGirl.factory_by_name(@name)
|
14
13
|
|
15
14
|
factory.compile
|
@@ -18,7 +17,11 @@ module FactoryGirl
|
|
18
17
|
factory = factory.with_traits(@traits)
|
19
18
|
end
|
20
19
|
|
21
|
-
|
20
|
+
instrumentation_payload = { name: @name, strategy: runner_strategy }
|
21
|
+
|
22
|
+
ActiveSupport::Notifications.instrument('factory_girl.run_factory', instrumentation_payload) do
|
23
|
+
factory.run(runner_strategy, @overrides, &block)
|
24
|
+
end
|
22
25
|
end
|
23
26
|
end
|
24
27
|
end
|