factory_girl 2.5.2 → 2.6.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/.travis.yml +0 -1
- data/Changelog +6 -0
- data/GETTING_STARTED.md +52 -7
- data/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/gemfiles/3.2.gemfile.lock +1 -1
- data/lib/factory_girl.rb +2 -1
- data/lib/factory_girl/association_runner.rb +50 -0
- data/lib/factory_girl/definition_proxy.rb +1 -1
- data/lib/factory_girl/evaluator.rb +12 -1
- data/lib/factory_girl/factory.rb +5 -5
- data/lib/factory_girl/strategy.rb +32 -0
- data/lib/factory_girl/{proxy → strategy}/attributes_for.rb +5 -2
- data/lib/factory_girl/strategy/build.rb +15 -0
- data/lib/factory_girl/{proxy → strategy}/create.rb +6 -2
- data/lib/factory_girl/{proxy → strategy}/stub.rb +4 -5
- data/lib/factory_girl/syntax/generate.rb +3 -3
- data/lib/factory_girl/syntax/make.rb +2 -2
- data/lib/factory_girl/syntax/methods.rb +6 -6
- data/lib/factory_girl/version.rb +1 -1
- data/spec/acceptance/build_spec.rb +2 -2
- data/spec/acceptance/create_list_spec.rb +41 -0
- data/spec/acceptance/create_spec.rb +39 -10
- data/spec/acceptance/stub_spec.rb +40 -13
- data/spec/acceptance/syntax/vintage_spec.rb +10 -10
- data/spec/acceptance/traits_spec.rb +1 -1
- data/spec/acceptance/transient_attributes_spec.rb +2 -2
- data/spec/factory_girl/association_runner_spec.rb +31 -0
- data/spec/factory_girl/attribute/association_spec.rb +0 -1
- data/spec/factory_girl/attribute_spec.rb +0 -1
- data/spec/factory_girl/declaration/implicit_spec.rb +0 -1
- data/spec/factory_girl/factory_spec.rb +16 -16
- data/spec/factory_girl/{proxy → strategy}/attributes_for_spec.rb +2 -2
- data/spec/factory_girl/strategy/build_spec.rb +7 -0
- data/spec/factory_girl/{proxy → strategy}/create_spec.rb +3 -3
- data/spec/factory_girl/{proxy → strategy}/stub_spec.rb +4 -4
- data/spec/factory_girl/strategy_spec.rb +21 -0
- data/spec/support/shared_examples/strategy.rb +112 -0
- metadata +47 -48
- data/gemfiles/2.1.gemfile +0 -8
- data/gemfiles/2.1.gemfile.lock +0 -74
- data/lib/factory_girl/proxy.rb +0 -64
- data/lib/factory_girl/proxy/build.rb +0 -27
- data/spec/factory_girl/proxy/build_spec.rb +0 -7
- data/spec/factory_girl/proxy_spec.rb +0 -19
- data/spec/support/shared_examples/proxy.rb +0 -90
data/.travis.yml
CHANGED
data/Changelog
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
2.6.0 (February 17, 2012)
|
2
|
+
Improve documentation of has_many associations in the GETTING_STARTED
|
3
|
+
document
|
4
|
+
Deprecate :method in favor of :strategy when overriding an association's
|
5
|
+
build strategy
|
6
|
+
|
1
7
|
2.5.2 (February 10, 2012)
|
2
8
|
Fix step definitions to use associations defined in parent factories
|
3
9
|
Add inline trait support to (build|create)_list
|
data/GETTING_STARTED.md
CHANGED
@@ -165,7 +165,7 @@ end
|
|
165
165
|
Dependent Attributes
|
166
166
|
--------------------
|
167
167
|
|
168
|
-
Attributes can be based on the values of other attributes using the
|
168
|
+
Attributes can be based on the values of other attributes using the evaluator that is yielded to lazy attribute blocks:
|
169
169
|
|
170
170
|
```ruby
|
171
171
|
factory :user do
|
@@ -193,8 +193,8 @@ factory :user do
|
|
193
193
|
name { "John Doe#{" - Rockstar" if rockstar}" }
|
194
194
|
email { "#{name.downcase}@example.com" }
|
195
195
|
|
196
|
-
after_create do |user,
|
197
|
-
user.name.upcase! if
|
196
|
+
after_create do |user, evaluator|
|
197
|
+
user.name.upcase! if evaluator.upcased
|
198
198
|
end
|
199
199
|
end
|
200
200
|
|
@@ -207,8 +207,8 @@ within attributes\_for and won't be set on the model, even if the attribute
|
|
207
207
|
exists or you attempt to override it.
|
208
208
|
|
209
209
|
Within Factory Girl's dynamic attributes, you can access ignored attributes as
|
210
|
-
you would expect. If you need to access the
|
211
|
-
you'll need to declare a second block argument (for the
|
210
|
+
you would expect. If you need to access the evaluator in a Factory Girl callback,
|
211
|
+
you'll need to declare a second block argument (for the evaluator) and access
|
212
212
|
ignored attributes from there.
|
213
213
|
|
214
214
|
Associations
|
@@ -246,12 +246,12 @@ post.new_record? # => true
|
|
246
246
|
post.author.new_record? # => false
|
247
247
|
```
|
248
248
|
|
249
|
-
To not save the associated object, specify :
|
249
|
+
To not save the associated object, specify :strategy => :build in the factory:
|
250
250
|
|
251
251
|
```ruby
|
252
252
|
factory :post do
|
253
253
|
# ...
|
254
|
-
association :author, :factory => :user, :
|
254
|
+
association :author, :factory => :user, :strategy => :build
|
255
255
|
end
|
256
256
|
|
257
257
|
# Builds a User, and then builds a Post, but does not save either
|
@@ -260,6 +260,51 @@ post.new_record? # => true
|
|
260
260
|
post.author.new_record? # => true
|
261
261
|
```
|
262
262
|
|
263
|
+
Generating data for a `has_many` relationship is a bit more involved,
|
264
|
+
depending on the amount of flexibility desired, but here's a surefire example
|
265
|
+
of generating associated data.
|
266
|
+
|
267
|
+
```ruby
|
268
|
+
FactoryGirl.define do
|
269
|
+
|
270
|
+
# post factory with a `belongs_to` association for the user
|
271
|
+
factory :post do
|
272
|
+
title "Through the Looking Glass"
|
273
|
+
user
|
274
|
+
end
|
275
|
+
|
276
|
+
# user factory without associated posts
|
277
|
+
factory :user do
|
278
|
+
name "John Doe"
|
279
|
+
|
280
|
+
# user_with_posts will create post data after the user has been created
|
281
|
+
factory :user_with_posts do
|
282
|
+
# posts_count is declared as an ignored attribute and available in
|
283
|
+
# attributes on the factory, as well as the callback via the evaluator
|
284
|
+
ignore do
|
285
|
+
posts_count 5
|
286
|
+
end
|
287
|
+
|
288
|
+
# the after_create yields two values; the user instance itself and the
|
289
|
+
# evaluator, which stores all values from the factory, including ignored
|
290
|
+
# attributes; `create_list`'s second argument is the number of records
|
291
|
+
# to create and we make sure the user is associated properly to the post
|
292
|
+
after_create do |user, evaluator|
|
293
|
+
FactoryGirl.create_list(:post, evaluator.posts_count, :user => user)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
```
|
299
|
+
|
300
|
+
This allows us to do:
|
301
|
+
|
302
|
+
```ruby
|
303
|
+
FactoryGirl.create(:user).posts.length # 0
|
304
|
+
FactoryGirl.create(:user_with_posts).posts.length # 5
|
305
|
+
FactoryGirl.create(:user_with_posts, :posts_count => 15).posts.length # 15
|
306
|
+
```
|
307
|
+
|
263
308
|
Inheritance
|
264
309
|
-----------
|
265
310
|
|
data/Gemfile.lock
CHANGED
data/gemfiles/2.3.gemfile.lock
CHANGED
data/gemfiles/3.0.gemfile.lock
CHANGED
data/gemfiles/3.1.gemfile.lock
CHANGED
data/gemfiles/3.2.gemfile.lock
CHANGED
data/lib/factory_girl.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require "active_support/core_ext/module/delegation"
|
2
2
|
|
3
3
|
require 'factory_girl/errors'
|
4
|
-
require 'factory_girl/
|
4
|
+
require 'factory_girl/association_runner'
|
5
|
+
require 'factory_girl/strategy'
|
5
6
|
require 'factory_girl/registry'
|
6
7
|
require 'factory_girl/null_factory'
|
7
8
|
require 'factory_girl/null_object'
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module FactoryGirl
|
2
|
+
class AssociationRunner
|
3
|
+
def initialize(factory_name, strategy_name_or_object, overrides)
|
4
|
+
@factory_name = factory_name
|
5
|
+
@strategy_name_or_object = strategy_name_or_object
|
6
|
+
@overrides = overrides
|
7
|
+
end
|
8
|
+
|
9
|
+
def run(strategy_override = nil)
|
10
|
+
strategy_name_or_object = strategy_override || @strategy_name_or_object
|
11
|
+
strategy = StrategyCalculator.new(strategy_name_or_object).strategy
|
12
|
+
factory.run(strategy, @overrides)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def factory
|
18
|
+
FactoryGirl.factory_by_name(@factory_name)
|
19
|
+
end
|
20
|
+
|
21
|
+
class StrategyCalculator
|
22
|
+
def initialize(name_or_object)
|
23
|
+
@name_or_object = name_or_object
|
24
|
+
end
|
25
|
+
|
26
|
+
def strategy
|
27
|
+
if strategy_is_object?
|
28
|
+
@name_or_object
|
29
|
+
else
|
30
|
+
strategy_name_to_object
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def strategy_is_object?
|
37
|
+
@name_or_object.is_a?(Class) && @name_or_object.ancestors.include?(::FactoryGirl::Strategy)
|
38
|
+
end
|
39
|
+
|
40
|
+
def strategy_name_to_object
|
41
|
+
case @name_or_object
|
42
|
+
when :build then Strategy::Build
|
43
|
+
when :create then Strategy::Create
|
44
|
+
when nil then Strategy::Create
|
45
|
+
else raise "unrecognized method #{@name_or_object}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -22,7 +22,7 @@ module FactoryGirl
|
|
22
22
|
# instance is generated. Lazy attribute blocks will not be called if that
|
23
23
|
# attribute is overridden for a specific instance.
|
24
24
|
#
|
25
|
-
# When defining lazy attributes, an instance of FactoryGirl::
|
25
|
+
# When defining lazy attributes, an instance of FactoryGirl::Strategy will
|
26
26
|
# be yielded, allowing associations to be built using the correct build
|
27
27
|
# strategy.
|
28
28
|
#
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require "active_support/core_ext/hash/except"
|
1
2
|
require "active_support/core_ext/class/attribute"
|
2
3
|
|
3
4
|
module FactoryGirl
|
@@ -29,7 +30,17 @@ module FactoryGirl
|
|
29
30
|
@build_strategy.add_observer(CallbackRunner.new(self.class.callbacks, self))
|
30
31
|
end
|
31
32
|
|
32
|
-
|
33
|
+
def association(factory_name, overrides = {})
|
34
|
+
build_strategy = if overrides.has_key?(:method)
|
35
|
+
$stderr.puts "DEPRECATION WARNING: using :method to specify a build strategy is deprecated; use :strategy instead"
|
36
|
+
overrides[:method]
|
37
|
+
elsif overrides.has_key?(:strategy)
|
38
|
+
overrides[:strategy]
|
39
|
+
end
|
40
|
+
|
41
|
+
runner = AssociationRunner.new(factory_name, build_strategy, overrides.except(:method, :strategy))
|
42
|
+
@build_strategy.association(runner)
|
43
|
+
end
|
33
44
|
|
34
45
|
def instance=(object_instance)
|
35
46
|
@instance = object_instance
|
data/lib/factory_girl/factory.rb
CHANGED
@@ -36,16 +36,16 @@ module FactoryGirl
|
|
36
36
|
@default_strategy || parent.default_strategy
|
37
37
|
end
|
38
38
|
|
39
|
-
def run(
|
39
|
+
def run(strategy_class, overrides, &block) #:nodoc:
|
40
40
|
block ||= lambda {|result| result }
|
41
41
|
compile
|
42
42
|
|
43
|
-
|
43
|
+
strategy = strategy_class.new
|
44
44
|
|
45
|
-
evaluator = evaluator_class.new(
|
45
|
+
evaluator = evaluator_class.new(strategy, overrides.symbolize_keys)
|
46
46
|
attribute_assigner = AttributeAssigner.new(evaluator, &instance_builder)
|
47
47
|
|
48
|
-
|
48
|
+
strategy.result(attribute_assigner, to_create).tap(&block)
|
49
49
|
end
|
50
50
|
|
51
51
|
def human_names
|
@@ -133,7 +133,7 @@ module FactoryGirl
|
|
133
133
|
options.assert_valid_keys(:class, :parent, :default_strategy, :aliases, :traits)
|
134
134
|
|
135
135
|
if options[:default_strategy]
|
136
|
-
|
136
|
+
Strategy.ensure_strategy_exists!(options[:default_strategy])
|
137
137
|
$stderr.puts "DEPRECATION WARNING: default_strategy is deprecated."
|
138
138
|
$stderr.puts "Override to_create if you need to prevent a call to #save!."
|
139
139
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "factory_girl/strategy/build"
|
2
|
+
require "factory_girl/strategy/create"
|
3
|
+
require "factory_girl/strategy/attributes_for"
|
4
|
+
require "factory_girl/strategy/stub"
|
5
|
+
require "observer"
|
6
|
+
|
7
|
+
module FactoryGirl
|
8
|
+
class Strategy #:nodoc:
|
9
|
+
include Observable
|
10
|
+
|
11
|
+
def association(runner)
|
12
|
+
raise NotImplementedError, "Strategies must return an association"
|
13
|
+
end
|
14
|
+
|
15
|
+
def result(attribute_assigner, to_create)
|
16
|
+
raise NotImplementedError, "Strategies must return a result"
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.ensure_strategy_exists!(strategy)
|
20
|
+
unless Strategy.const_defined? strategy.to_s.camelize
|
21
|
+
raise ArgumentError, "Unknown strategy: #{strategy}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def run_callbacks(name, result_instance)
|
28
|
+
changed
|
29
|
+
notify_observers(name, result_instance)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module FactoryGirl
|
2
|
+
class Strategy #:nodoc:
|
3
|
+
class Build < Strategy #:nodoc:
|
4
|
+
def association(runner)
|
5
|
+
runner.run
|
6
|
+
end
|
7
|
+
|
8
|
+
def result(attribute_assigner, to_create)
|
9
|
+
attribute_assigner.object.tap do |result_instance|
|
10
|
+
run_callbacks(:after_build, result_instance)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
module FactoryGirl
|
2
|
-
class
|
3
|
-
class Create <
|
2
|
+
class Strategy #:nodoc:
|
3
|
+
class Create < Strategy #:nodoc:
|
4
|
+
def association(runner)
|
5
|
+
runner.run
|
6
|
+
end
|
7
|
+
|
4
8
|
def result(attribute_assigner, to_create)
|
5
9
|
attribute_assigner.object.tap do |result_instance|
|
6
10
|
run_callbacks(:after_build, result_instance)
|
@@ -1,11 +1,10 @@
|
|
1
1
|
module FactoryGirl
|
2
|
-
class
|
3
|
-
class Stub <
|
2
|
+
class Strategy
|
3
|
+
class Stub < Strategy #:nodoc:
|
4
4
|
@@next_id = 1000
|
5
5
|
|
6
|
-
def association(
|
7
|
-
|
8
|
-
factory.run(Proxy::Stub, overrides.except(:method))
|
6
|
+
def association(runner)
|
7
|
+
runner.run(Strategy::Stub)
|
9
8
|
end
|
10
9
|
|
11
10
|
def result(attribute_assigner, to_create)
|
@@ -43,7 +43,7 @@ module FactoryGirl
|
|
43
43
|
|
44
44
|
def generate(overrides = {}, &block)
|
45
45
|
factory = FactoryGirl.factory_by_name(name.underscore)
|
46
|
-
instance = factory.run(
|
46
|
+
instance = factory.run(Strategy::Build, overrides)
|
47
47
|
instance.save
|
48
48
|
yield(instance) if block_given?
|
49
49
|
instance
|
@@ -51,14 +51,14 @@ module FactoryGirl
|
|
51
51
|
|
52
52
|
def generate!(overrides = {}, &block)
|
53
53
|
factory = FactoryGirl.factory_by_name(name.underscore)
|
54
|
-
instance = factory.run(
|
54
|
+
instance = factory.run(Strategy::Create, overrides)
|
55
55
|
yield(instance) if block_given?
|
56
56
|
instance
|
57
57
|
end
|
58
58
|
|
59
59
|
def spawn(overrides = {}, &block)
|
60
60
|
factory = FactoryGirl.factory_by_name(name.underscore)
|
61
|
-
instance = factory.run(
|
61
|
+
instance = factory.run(Strategy::Build, overrides)
|
62
62
|
yield(instance) if block_given?
|
63
63
|
instance
|
64
64
|
end
|
@@ -28,11 +28,11 @@ module FactoryGirl
|
|
28
28
|
module ClassMethods #:nodoc:
|
29
29
|
|
30
30
|
def make(overrides = {})
|
31
|
-
FactoryGirl.factory_by_name(name.underscore).run(
|
31
|
+
FactoryGirl.factory_by_name(name.underscore).run(Strategy::Build, overrides)
|
32
32
|
end
|
33
33
|
|
34
34
|
def make!(overrides = {})
|
35
|
-
FactoryGirl.factory_by_name(name.underscore).run(
|
35
|
+
FactoryGirl.factory_by_name(name.underscore).run(Strategy::Create, overrides)
|
36
36
|
end
|
37
37
|
|
38
38
|
end
|
@@ -18,7 +18,7 @@ module FactoryGirl
|
|
18
18
|
# A set of attributes that can be used to build an instance of the class
|
19
19
|
# this factory generates.
|
20
20
|
def attributes_for(name, *traits_and_overrides, &block)
|
21
|
-
|
21
|
+
run_factory_girl_strategy(name, traits_and_overrides, Strategy::AttributesFor, &block)
|
22
22
|
end
|
23
23
|
|
24
24
|
# Generates and returns an instance from this factory. Attributes can be
|
@@ -37,7 +37,7 @@ module FactoryGirl
|
|
37
37
|
# An instance of the class this factory generates, with generated attributes
|
38
38
|
# assigned.
|
39
39
|
def build(name, *traits_and_overrides, &block)
|
40
|
-
|
40
|
+
run_factory_girl_strategy(name, traits_and_overrides, Strategy::Build, &block)
|
41
41
|
end
|
42
42
|
|
43
43
|
# Generates, saves, and returns an instance from this factory. Attributes can
|
@@ -60,7 +60,7 @@ module FactoryGirl
|
|
60
60
|
# A saved instance of the class this factory generates, with generated
|
61
61
|
# attributes assigned.
|
62
62
|
def create(name, *traits_and_overrides, &block)
|
63
|
-
|
63
|
+
run_factory_girl_strategy(name, traits_and_overrides, Strategy::Create, &block)
|
64
64
|
end
|
65
65
|
|
66
66
|
# Generates and returns an object with all attributes from this factory
|
@@ -79,7 +79,7 @@ module FactoryGirl
|
|
79
79
|
# Returns: +Object+
|
80
80
|
# An object with generated attributes stubbed out.
|
81
81
|
def build_stubbed(name, *traits_and_overrides, &block)
|
82
|
-
|
82
|
+
run_factory_girl_strategy(name, traits_and_overrides, Strategy::Stub, &block)
|
83
83
|
end
|
84
84
|
|
85
85
|
# Builds and returns multiple instances from this factory as an array. Attributes can be
|
@@ -134,7 +134,7 @@ module FactoryGirl
|
|
134
134
|
|
135
135
|
private
|
136
136
|
|
137
|
-
def
|
137
|
+
def run_factory_girl_strategy(name, traits_and_overrides, strategy, &block)
|
138
138
|
overrides = if traits_and_overrides.last.respond_to?(:has_key?)
|
139
139
|
traits_and_overrides.pop
|
140
140
|
else
|
@@ -147,7 +147,7 @@ module FactoryGirl
|
|
147
147
|
factory = factory.with_traits(traits_and_overrides)
|
148
148
|
end
|
149
149
|
|
150
|
-
factory.run(
|
150
|
+
factory.run(strategy, overrides, &block)
|
151
151
|
end
|
152
152
|
end
|
153
153
|
end
|