factory_girl 2.2.0 → 2.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/.autotest +1 -1
- data/CONTRIBUTION_GUIDELINES.md +1 -1
- data/Changelog +16 -3
- data/GETTING_STARTED.md +22 -2
- data/Gemfile.lock +1 -1
- data/Rakefile +11 -15
- data/gemfiles/2.1.gemfile.lock +1 -1
- data/gemfiles/2.3.gemfile.lock +1 -1
- data/gemfiles/3.0.gemfile.lock +1 -1
- data/gemfiles/3.1.gemfile.lock +1 -1
- data/lib/factory_girl.rb +8 -3
- data/lib/factory_girl/attribute.rb +8 -0
- data/lib/factory_girl/attribute/dynamic.rb +1 -5
- data/lib/factory_girl/attribute/sequence.rb +1 -5
- data/lib/factory_girl/attribute/static.rb +1 -5
- data/lib/factory_girl/attribute_list.rb +18 -44
- data/lib/factory_girl/callback.rb +5 -0
- data/lib/factory_girl/declaration.rb +3 -0
- data/lib/factory_girl/declaration/association.rb +8 -0
- data/lib/factory_girl/declaration/dynamic.rb +9 -0
- data/lib/factory_girl/declaration/implicit.rb +11 -2
- data/lib/factory_girl/declaration/static.rb +9 -0
- data/lib/factory_girl/declaration_list.rb +48 -0
- data/lib/factory_girl/definition.rb +62 -0
- data/lib/factory_girl/definition_proxy.rb +11 -11
- data/lib/factory_girl/factory.rb +100 -111
- data/lib/factory_girl/null_factory.rb +15 -0
- data/lib/factory_girl/proxy.rb +14 -9
- data/lib/factory_girl/proxy/attributes_for.rb +2 -3
- data/lib/factory_girl/proxy/build.rb +12 -20
- data/lib/factory_girl/proxy/create.rb +0 -6
- data/lib/factory_girl/proxy/stub.rb +4 -10
- data/lib/factory_girl/registry.rb +4 -3
- data/lib/factory_girl/step_definitions.rb +1 -1
- data/lib/factory_girl/syntax/default.rb +3 -4
- data/lib/factory_girl/syntax/methods.rb +38 -16
- data/lib/factory_girl/trait.rb +13 -21
- data/lib/factory_girl/version.rb +1 -1
- data/spec/acceptance/modify_factories_spec.rb +1 -1
- data/spec/acceptance/traits_spec.rb +87 -1
- data/spec/factory_girl/attribute/dynamic_spec.rb +1 -1
- data/spec/factory_girl/attribute_list_spec.rb +9 -58
- data/spec/factory_girl/declaration_list_spec.rb +71 -0
- data/spec/factory_girl/definition_proxy_spec.rb +135 -139
- data/spec/factory_girl/definition_spec.rb +81 -0
- data/spec/factory_girl/factory_spec.rb +42 -17
- data/spec/factory_girl/null_factory_spec.rb +12 -0
- data/spec/factory_girl/proxy/build_spec.rb +1 -24
- data/spec/factory_girl/proxy/create_spec.rb +14 -11
- data/spec/factory_girl/proxy_spec.rb +23 -40
- data/spec/factory_girl/registry_spec.rb +4 -3
- data/spec/spec_helper.rb +2 -0
- data/spec/support/matchers/callback.rb +9 -0
- data/spec/support/matchers/declaration.rb +71 -0
- data/spec/support/matchers/delegate.rb +44 -0
- data/spec/support/matchers/trait.rb +9 -0
- data/spec/support/shared_examples/proxy.rb +4 -5
- metadata +191 -115
@@ -6,6 +6,15 @@ module FactoryGirl
|
|
6
6
|
@factory = factory
|
7
7
|
end
|
8
8
|
|
9
|
+
def ==(other)
|
10
|
+
name == other.name &&
|
11
|
+
factory == other.factory &&
|
12
|
+
ignored == other.ignored
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
attr_reader :factory
|
17
|
+
|
9
18
|
private
|
10
19
|
|
11
20
|
def build
|
@@ -14,8 +23,8 @@ module FactoryGirl
|
|
14
23
|
elsif FactoryGirl.sequences.registered?(name)
|
15
24
|
[Attribute::Sequence.new(name, name, @ignored)]
|
16
25
|
else
|
17
|
-
|
18
|
-
|
26
|
+
@factory.inherit_traits([name])
|
27
|
+
[]
|
19
28
|
end
|
20
29
|
end
|
21
30
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module FactoryGirl
|
2
|
+
class DeclarationList
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(name = nil)
|
6
|
+
@declarations = []
|
7
|
+
@name = name
|
8
|
+
@overridable = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def declare_attribute(declaration)
|
12
|
+
delete_declaration(declaration) if overridable?
|
13
|
+
|
14
|
+
@declarations << declaration
|
15
|
+
declaration
|
16
|
+
end
|
17
|
+
|
18
|
+
def overridable
|
19
|
+
@overridable = true
|
20
|
+
end
|
21
|
+
|
22
|
+
def attribute_list
|
23
|
+
AttributeList.new(@name).tap do |list|
|
24
|
+
to_attributes.each do |attribute|
|
25
|
+
list.define_attribute(attribute)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def each(&block)
|
31
|
+
@declarations.each(&block)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def delete_declaration(declaration)
|
37
|
+
@declarations.delete_if {|decl| decl.name == declaration.name }
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_attributes
|
41
|
+
@declarations.inject([]) {|result, declaration| result += declaration.to_attributes }
|
42
|
+
end
|
43
|
+
|
44
|
+
def overridable?
|
45
|
+
@overridable
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module FactoryGirl
|
2
|
+
class Definition
|
3
|
+
attr_reader :callbacks, :defined_traits, :declarations
|
4
|
+
|
5
|
+
def initialize(name = nil)
|
6
|
+
@declarations = DeclarationList.new(name)
|
7
|
+
@callbacks = []
|
8
|
+
@defined_traits = []
|
9
|
+
@to_create = nil
|
10
|
+
@traits = []
|
11
|
+
end
|
12
|
+
|
13
|
+
delegate :declare_attribute, :to => :declarations
|
14
|
+
|
15
|
+
def attributes
|
16
|
+
@attributes ||= declarations.attribute_list
|
17
|
+
end
|
18
|
+
|
19
|
+
def compile
|
20
|
+
attributes
|
21
|
+
end
|
22
|
+
|
23
|
+
def overridable
|
24
|
+
declarations.overridable
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def traits
|
29
|
+
@traits.reverse.map { |name| trait_by_name(name) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def inherit_traits(new_traits)
|
33
|
+
@traits += new_traits
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_callback(callback)
|
37
|
+
@callbacks << callback
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_create(&block)
|
41
|
+
if block_given?
|
42
|
+
@to_create = block
|
43
|
+
else
|
44
|
+
@to_create
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def define_trait(trait)
|
49
|
+
@defined_traits << trait
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def trait_by_name(name)
|
55
|
+
trait_for(name) || FactoryGirl.trait_by_name(name)
|
56
|
+
end
|
57
|
+
|
58
|
+
def trait_for(name)
|
59
|
+
defined_traits.detect {|trait| trait.name == name }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -8,8 +8,8 @@ module FactoryGirl
|
|
8
8
|
|
9
9
|
attr_reader :child_factories
|
10
10
|
|
11
|
-
def initialize(
|
12
|
-
@
|
11
|
+
def initialize(definition, ignore = false)
|
12
|
+
@definition = definition
|
13
13
|
@ignore = ignore
|
14
14
|
@child_factories = []
|
15
15
|
end
|
@@ -41,11 +41,11 @@ module FactoryGirl
|
|
41
41
|
Declaration::Static.new(name, value, @ignore)
|
42
42
|
end
|
43
43
|
|
44
|
-
@
|
44
|
+
@definition.declare_attribute(declaration)
|
45
45
|
end
|
46
46
|
|
47
47
|
def ignore(&block)
|
48
|
-
proxy = DefinitionProxy.new(@
|
48
|
+
proxy = DefinitionProxy.new(@definition, true)
|
49
49
|
proxy.instance_eval(&block)
|
50
50
|
end
|
51
51
|
|
@@ -82,7 +82,7 @@ module FactoryGirl
|
|
82
82
|
# are equivalent.
|
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
86
|
elsif args.first.is_a?(Hash) && args.first.has_key?(:factory)
|
87
87
|
association(name, *args)
|
88
88
|
else
|
@@ -135,23 +135,23 @@ module FactoryGirl
|
|
135
135
|
# name of the factory. For example, a "user" association will by
|
136
136
|
# default use the "user" factory.
|
137
137
|
def association(name, options = {})
|
138
|
-
@
|
138
|
+
@definition.declare_attribute(Declaration::Association.new(name, options))
|
139
139
|
end
|
140
140
|
|
141
141
|
def after_build(&block)
|
142
|
-
@
|
142
|
+
@definition.add_callback(Callback.new(:after_build, block))
|
143
143
|
end
|
144
144
|
|
145
145
|
def after_create(&block)
|
146
|
-
@
|
146
|
+
@definition.add_callback(Callback.new(:after_create, block))
|
147
147
|
end
|
148
148
|
|
149
149
|
def after_stub(&block)
|
150
|
-
@
|
150
|
+
@definition.add_callback(Callback.new(:after_stub, block))
|
151
151
|
end
|
152
152
|
|
153
153
|
def to_create(&block)
|
154
|
-
@
|
154
|
+
@definition.to_create(&block)
|
155
155
|
end
|
156
156
|
|
157
157
|
def factory(name, options = {}, &block)
|
@@ -159,7 +159,7 @@ module FactoryGirl
|
|
159
159
|
end
|
160
160
|
|
161
161
|
def trait(name, &block)
|
162
|
-
@
|
162
|
+
@definition.define_trait(Trait.new(name, &block))
|
163
163
|
end
|
164
164
|
end
|
165
165
|
end
|
data/lib/factory_girl/factory.rb
CHANGED
@@ -3,76 +3,46 @@ require "active_support/inflector"
|
|
3
3
|
|
4
4
|
module FactoryGirl
|
5
5
|
class Factory
|
6
|
-
attr_reader :name #:nodoc:
|
6
|
+
attr_reader :name, :definition #:nodoc:
|
7
7
|
|
8
8
|
def initialize(name, options = {}) #:nodoc:
|
9
9
|
assert_valid_options(options)
|
10
|
-
@name = name.to_s.underscore.to_sym
|
10
|
+
@name = name.is_a?(Symbol) ? name : name.to_s.underscore.to_sym
|
11
11
|
@parent = options[:parent]
|
12
12
|
@aliases = options[:aliases] || []
|
13
|
-
@traits = options[:traits] || []
|
14
13
|
@class_name = options[:class]
|
15
14
|
@default_strategy = options[:default_strategy]
|
16
|
-
@
|
17
|
-
|
18
|
-
|
15
|
+
@definition = Definition.new(@name)
|
16
|
+
|
17
|
+
inherit_traits(options[:traits] || [])
|
19
18
|
end
|
20
19
|
|
20
|
+
delegate :add_callback, :declare_attribute, :to_create, :define_trait,
|
21
|
+
:defined_traits, :traits, :inherit_traits, :to => :@definition
|
22
|
+
|
21
23
|
def factory_name
|
22
24
|
$stderr.puts "DEPRECATION WARNING: factory.factory_name is deprecated; use factory.name instead."
|
23
25
|
name
|
24
26
|
end
|
25
27
|
|
26
28
|
def build_class #:nodoc:
|
27
|
-
|
29
|
+
class_name.to_s.camelize.constantize
|
28
30
|
end
|
29
31
|
|
30
32
|
def default_strategy #:nodoc:
|
31
|
-
@default_strategy ||
|
32
|
-
end
|
33
|
-
|
34
|
-
def allow_overrides
|
35
|
-
@compiled = false
|
36
|
-
@attribute_list.overridable
|
37
|
-
self
|
38
|
-
end
|
39
|
-
|
40
|
-
def allow_overrides?
|
41
|
-
@attribute_list.overridable?
|
42
|
-
end
|
43
|
-
|
44
|
-
def define_trait(trait)
|
45
|
-
@defined_traits << trait
|
46
|
-
end
|
47
|
-
|
48
|
-
def add_callback(name, &block)
|
49
|
-
@attribute_list.add_callback(Callback.new(name, block))
|
33
|
+
@default_strategy || parent.default_strategy || :create
|
50
34
|
end
|
51
35
|
|
52
36
|
def run(proxy_class, overrides, &block) #:nodoc:
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
else
|
63
|
-
factory_overrides.each do |attr, val|
|
64
|
-
if attribute.ignored
|
65
|
-
proxy.set_ignored(attr, val)
|
66
|
-
else
|
67
|
-
proxy.set(attr, val)
|
68
|
-
end
|
69
|
-
|
70
|
-
overrides.delete(attr)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
overrides.each { |attr, val| proxy.set(attr, val) }
|
75
|
-
result = proxy.result(@to_create_block)
|
37
|
+
runner_options = {
|
38
|
+
:attributes => attributes,
|
39
|
+
:callbacks => callbacks,
|
40
|
+
:to_create => to_create,
|
41
|
+
:build_class => build_class,
|
42
|
+
:proxy_class => proxy_class
|
43
|
+
}
|
44
|
+
|
45
|
+
result = Runner.new(runner_options).run(overrides)
|
76
46
|
|
77
47
|
block ? block.call(result) : result
|
78
48
|
end
|
@@ -85,16 +55,6 @@ module FactoryGirl
|
|
85
55
|
attributes.select {|attribute| attribute.association? }
|
86
56
|
end
|
87
57
|
|
88
|
-
def trait_by_name(name)
|
89
|
-
if existing_attribute = trait_for(name)
|
90
|
-
existing_attribute
|
91
|
-
elsif parent
|
92
|
-
parent.trait_by_name(name)
|
93
|
-
else
|
94
|
-
FactoryGirl.trait_by_name(name)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
58
|
# Names for this factory, including aliases.
|
99
59
|
#
|
100
60
|
# Example:
|
@@ -124,94 +84,123 @@ module FactoryGirl
|
|
124
84
|
[name] + @aliases
|
125
85
|
end
|
126
86
|
|
127
|
-
def
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
def ensure_compiled
|
132
|
-
compile unless @compiled
|
87
|
+
def compile
|
88
|
+
parent.defined_traits.each {|trait| define_trait(trait) }
|
89
|
+
parent.compile
|
90
|
+
@definition.compile
|
133
91
|
end
|
134
92
|
|
135
|
-
def
|
136
|
-
|
93
|
+
def with_traits(traits)
|
94
|
+
self.clone.tap do |factory_with_traits|
|
95
|
+
factory_with_traits.inherit_traits traits
|
96
|
+
end
|
137
97
|
end
|
138
98
|
|
139
99
|
protected
|
140
100
|
|
141
101
|
def class_name #:nodoc:
|
142
|
-
@class_name ||
|
102
|
+
@class_name || parent.class_name || name
|
143
103
|
end
|
144
104
|
|
145
105
|
def attributes
|
146
|
-
|
147
|
-
AttributeList.new.tap do |list|
|
148
|
-
|
106
|
+
compile
|
107
|
+
AttributeList.new(@name).tap do |list|
|
108
|
+
traits.each do |trait|
|
149
109
|
list.apply_attributes(trait.attributes)
|
150
110
|
end
|
151
111
|
|
152
|
-
list.apply_attributes(@
|
153
|
-
list.apply_attributes(parent.attributes)
|
112
|
+
list.apply_attributes(@definition.attributes)
|
113
|
+
list.apply_attributes(parent.attributes)
|
154
114
|
end
|
155
115
|
end
|
156
116
|
|
157
|
-
private
|
158
|
-
|
159
117
|
def callbacks
|
160
|
-
|
118
|
+
[parent.callbacks, traits.map(&:callbacks), @definition.callbacks].flatten
|
161
119
|
end
|
162
120
|
|
163
|
-
|
164
|
-
inherit_factory(parent) if parent
|
121
|
+
private
|
165
122
|
|
166
|
-
|
167
|
-
|
168
|
-
define_attribute(attribute)
|
169
|
-
end
|
170
|
-
end
|
123
|
+
def assert_valid_options(options)
|
124
|
+
options.assert_valid_keys(:class, :parent, :default_strategy, :aliases, :traits)
|
171
125
|
|
172
|
-
|
126
|
+
if options[:default_strategy]
|
127
|
+
Proxy.ensure_strategy_exists!(options[:default_strategy])
|
128
|
+
$stderr.puts "DEPRECATION WARNING: default_strategy is deprecated."
|
129
|
+
$stderr.puts "Override to_create if you need to prevent a call to #save!."
|
130
|
+
end
|
173
131
|
end
|
174
132
|
|
175
|
-
def
|
176
|
-
parent
|
177
|
-
|
133
|
+
def parent
|
134
|
+
if @parent
|
135
|
+
FactoryGirl.factory_by_name(@parent)
|
136
|
+
else
|
137
|
+
NullFactory.new
|
138
|
+
end
|
178
139
|
end
|
179
140
|
|
180
|
-
def
|
181
|
-
|
141
|
+
def initialize_copy(source)
|
142
|
+
super
|
143
|
+
@definition = @definition.clone
|
182
144
|
end
|
183
145
|
|
184
|
-
|
185
|
-
|
186
|
-
|
146
|
+
class Runner
|
147
|
+
def initialize(options = {})
|
148
|
+
@attributes = options[:attributes]
|
149
|
+
@callbacks = options[:callbacks]
|
150
|
+
@to_create = options[:to_create]
|
151
|
+
@build_class = options[:build_class]
|
152
|
+
@proxy_class = options[:proxy_class]
|
153
|
+
|
154
|
+
@overrides = {}
|
187
155
|
end
|
188
156
|
|
189
|
-
|
190
|
-
|
157
|
+
def run(overrides = {})
|
158
|
+
@overrides = overrides.symbolize_keys
|
191
159
|
|
192
|
-
|
193
|
-
|
160
|
+
apply_attributes
|
161
|
+
apply_remaining_overrides
|
194
162
|
|
195
|
-
|
196
|
-
assert_valid_strategy(options[:default_strategy])
|
197
|
-
$stderr.puts "DEPRECATION WARNING: default_strategy is deprecated."
|
198
|
-
$stderr.puts "Override to_create if you need to prevent a call to #save!."
|
163
|
+
proxy.result(@to_create)
|
199
164
|
end
|
200
|
-
end
|
201
165
|
|
202
|
-
|
203
|
-
|
204
|
-
|
166
|
+
private
|
167
|
+
|
168
|
+
def apply_attributes
|
169
|
+
@attributes.each do |attribute|
|
170
|
+
if overrides_for_attribute(attribute).any?
|
171
|
+
handle_attribute_with_overrides(attribute)
|
172
|
+
else
|
173
|
+
handle_attribute_without_overrides(attribute)
|
174
|
+
end
|
175
|
+
end
|
205
176
|
end
|
206
|
-
end
|
207
177
|
|
208
|
-
|
209
|
-
|
210
|
-
|
178
|
+
def apply_remaining_overrides
|
179
|
+
@overrides.each { |attr, val| add_static_attribute(attr, val) }
|
180
|
+
end
|
211
181
|
|
212
|
-
|
213
|
-
|
214
|
-
|
182
|
+
def overrides_for_attribute(attribute)
|
183
|
+
@overrides.select { |attr, val| attribute.aliases_for?(attr) }
|
184
|
+
end
|
185
|
+
|
186
|
+
def handle_attribute_with_overrides(attribute)
|
187
|
+
overrides_for_attribute(attribute).each do |attr, val|
|
188
|
+
add_static_attribute(attr, val, attribute.ignored)
|
189
|
+
@overrides.delete(attr)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def add_static_attribute(attr, val, ignored = false)
|
194
|
+
Attribute::Static.new(attr, val, ignored).add_to(proxy)
|
195
|
+
end
|
196
|
+
|
197
|
+
def handle_attribute_without_overrides(attribute)
|
198
|
+
attribute.add_to(proxy)
|
199
|
+
end
|
200
|
+
|
201
|
+
def proxy
|
202
|
+
@proxy ||= @proxy_class.new(@build_class, @callbacks)
|
203
|
+
end
|
215
204
|
end
|
216
205
|
end
|
217
206
|
end
|