factory_girl 2.1.0 → 2.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +3 -0
- data/Changelog +9 -0
- data/GETTING_STARTED.md +47 -16
- data/Gemfile.lock +10 -9
- data/gemfiles/2.1.gemfile.lock +2 -1
- data/gemfiles/2.3.gemfile.lock +2 -1
- data/gemfiles/3.0.gemfile.lock +2 -1
- data/gemfiles/3.1.gemfile.lock +2 -1
- data/lib/factory_girl.rb +6 -3
- data/lib/factory_girl/attribute/static.rb +8 -0
- data/lib/factory_girl/attribute_list.rb +20 -12
- data/lib/factory_girl/callback.rb +30 -0
- data/lib/factory_girl/declaration.rb +19 -0
- data/lib/factory_girl/declaration/association.rb +17 -0
- data/lib/factory_girl/declaration/dynamic.rb +16 -0
- data/lib/factory_girl/declaration/implicit.rb +23 -0
- data/lib/factory_girl/declaration/static.rb +16 -0
- data/lib/factory_girl/definition_proxy.rb +6 -6
- data/lib/factory_girl/factory.rb +63 -79
- data/lib/factory_girl/proxy.rb +7 -11
- data/lib/factory_girl/proxy/attributes_for.rb +1 -0
- data/lib/factory_girl/proxy/build.rb +1 -0
- data/lib/factory_girl/proxy/stub.rb +1 -0
- data/lib/factory_girl/syntax/default.rb +4 -2
- data/lib/factory_girl/syntax/vintage.rb +1 -1
- data/lib/factory_girl/trait.rb +12 -4
- data/lib/factory_girl/version.rb +1 -1
- data/spec/acceptance/callbacks_spec.rb +7 -1
- data/spec/acceptance/modify_inherited_spec.rb +52 -0
- data/spec/acceptance/syntax/vintage_spec.rb +19 -7
- data/spec/factory_girl/attribute_list_spec.rb +18 -45
- data/spec/factory_girl/callback_spec.rb +41 -0
- data/spec/factory_girl/{attribute → declaration}/implicit_spec.rb +16 -11
- data/spec/factory_girl/definition_proxy_spec.rb +16 -12
- data/spec/factory_girl/factory_spec.rb +43 -34
- data/spec/factory_girl/proxy/create_spec.rb +7 -9
- data/spec/factory_girl/proxy_spec.rb +26 -39
- data/spec/support/shared_examples/proxy.rb +1 -1
- metadata +137 -114
- data/lib/factory_girl/attribute/callback.rb +0 -14
- data/lib/factory_girl/attribute/implicit.rb +0 -39
- data/lib/factory_girl/attribute/trait.rb +0 -22
- data/spec/factory_girl/attribute/callback_spec.rb +0 -22
data/.travis.yml
CHANGED
data/Changelog
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
2.1.0 (September 02, 2011)
|
2
|
+
Bugfix: created_at now defined for stubbed models
|
3
|
+
Gemspec updated for use with Rails 3.1
|
4
|
+
Factories can now be modified post-definition (useful for overriding defaults from gems/plugins)
|
5
|
+
All factories can now be reloaded with Factory.reload
|
6
|
+
Add :method => build to factory associations to prevent saving of associated objects
|
7
|
+
Factories defined in {Rails.root}/factories are now loaded by default
|
8
|
+
Various documentation updates
|
9
|
+
|
1
10
|
1.1.4 (November 28, 2008)
|
2
11
|
Factory.build now uses Factory.create for associations of the built object
|
3
12
|
Factory definitions are now detected in subdirectories, such as
|
data/GETTING_STARTED.md
CHANGED
@@ -4,13 +4,13 @@ Getting Started
|
|
4
4
|
Update Your Gemfile
|
5
5
|
-------------------
|
6
6
|
|
7
|
-
If you're using Rails, you'll need to
|
7
|
+
If you're using Rails, you'll need to change the required version of `factory_girl_rails`:
|
8
8
|
|
9
|
-
gem "factory_girl_rails", "~> 1.
|
9
|
+
gem "factory_girl_rails", "~> 1.2"
|
10
10
|
|
11
11
|
If you're *not* using Rails, you'll just have to change the required version of `factory_girl`:
|
12
12
|
|
13
|
-
gem "factory_girl", "~> 2.
|
13
|
+
gem "factory_girl", "~> 2.1.0"
|
14
14
|
|
15
15
|
Once your Gemfile is updated, you'll want to update your bundle.
|
16
16
|
|
@@ -57,7 +57,7 @@ are defined in files at the following locations:
|
|
57
57
|
Using factories
|
58
58
|
---------------
|
59
59
|
|
60
|
-
|
60
|
+
factory\_girl supports several different build strategies: build, create, attributes\_for and stub:
|
61
61
|
|
62
62
|
# Returns a User instance that's not saved
|
63
63
|
user = FactoryGirl.build(:user)
|
@@ -101,7 +101,11 @@ This would allow you to write:
|
|
101
101
|
Lazy Attributes
|
102
102
|
---------------
|
103
103
|
|
104
|
-
Most factory attributes can be added using static values that are evaluated when
|
104
|
+
Most factory attributes can be added using static values that are evaluated when
|
105
|
+
the factory is defined, but some attributes (such as associations and other
|
106
|
+
attributes that must be dynamically generated) will need values assigned each
|
107
|
+
time an instance is generated. These "lazy" attributes can be added by passing a
|
108
|
+
block instead of a parameter:
|
105
109
|
|
106
110
|
factory :user do
|
107
111
|
# ...
|
@@ -169,9 +173,14 @@ There may be times where your code can be DRYed up by passing in transient attri
|
|
169
173
|
FactoryGirl.create(:user, :upcased => true).name
|
170
174
|
#=> "JOHN DOE - ROCKSTAR"
|
171
175
|
|
172
|
-
Static and dynamic attributes can be ignored. Ignored attributes will be ignored
|
176
|
+
Static and dynamic attributes can be ignored. Ignored attributes will be ignored
|
177
|
+
within attributes\_for and won't be set on the model, even if the attribute
|
178
|
+
exists or you attempt to override it.
|
173
179
|
|
174
|
-
Within Factory Girl's dynamic attributes, you can access ignored attributes as
|
180
|
+
Within Factory Girl's dynamic attributes, you can access ignored attributes as
|
181
|
+
you would expect. If you need to access the proxy in a Factory Girl callback,
|
182
|
+
you'll need to declare a second block argument (for the proxy) and access
|
183
|
+
ignored attributes from there.
|
175
184
|
|
176
185
|
Associations
|
177
186
|
------------
|
@@ -241,7 +250,10 @@ You can also assign the parent explicitly:
|
|
241
250
|
approved true
|
242
251
|
end
|
243
252
|
|
244
|
-
As mentioned above, it's good practice to define a basic factory for each class
|
253
|
+
As mentioned above, it's good practice to define a basic factory for each class
|
254
|
+
with only the attributes required to create it. Then, create more specific
|
255
|
+
factories that inherit from this basic parent. Factory definitions are still
|
256
|
+
code, so keep them DRY.
|
245
257
|
|
246
258
|
Sequences
|
247
259
|
---------
|
@@ -367,10 +379,28 @@ the trait that defines the attribute latest gets precedence.
|
|
367
379
|
factory :female_admin, :traits => [:admin, :female] # login will be "Jane Doe (F)"
|
368
380
|
end
|
369
381
|
|
382
|
+
You can also override individual attributes granted by a trait in subclasses.
|
383
|
+
|
384
|
+
factory :user do
|
385
|
+
name "Friendly User"
|
386
|
+
login { name }
|
387
|
+
|
388
|
+
trait :male do
|
389
|
+
name "John Doe"
|
390
|
+
gender "Male"
|
391
|
+
login { "#{name} (M)" }
|
392
|
+
end
|
393
|
+
|
394
|
+
factory :brandon do
|
395
|
+
male
|
396
|
+
name "Brandon"
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
370
400
|
Callbacks
|
371
401
|
---------
|
372
402
|
|
373
|
-
|
403
|
+
factory\_girl makes available three callbacks for injecting some code:
|
374
404
|
|
375
405
|
* after_build - called after a factory is built (via FactoryGirl.build)
|
376
406
|
* after_create - called after a factory is saved (via FactoryGirl.create)
|
@@ -399,7 +429,7 @@ Factories can also define any number of the same kind of callback. These callba
|
|
399
429
|
after_create { then_this }
|
400
430
|
end
|
401
431
|
|
402
|
-
Calling FactoryGirl.create will invoke both
|
432
|
+
Calling FactoryGirl.create will invoke both after\_build and after\_create callbacks.
|
403
433
|
|
404
434
|
Also, like standard attributes, child factories will inherit (and can also define) callbacks from their parent factory.
|
405
435
|
|
@@ -445,10 +475,8 @@ When modifying a factory, you can change any of the attributes you want (aside f
|
|
445
475
|
|
446
476
|
`FactoryGirl.modify` must be called outside of a `FactoryGirl.define` block as it operates on factories differently.
|
447
477
|
|
448
|
-
A
|
478
|
+
A caveat: you can only modify factories (not sequences or traits) and callbacks *still compound as they normally would*. So, if
|
449
479
|
the factory you're modifying defines an `after_create` callback, you defining an `after_create` won't override it, it'll just get run after the first callback.
|
450
|
-
You also can't modify attributes assigned by traits. So, if you have a trait that grants a name attribute, and you modify the factory to set the name,
|
451
|
-
it currently will reflect the name in the trait instead of the modified name.
|
452
480
|
|
453
481
|
Building or Creating Multiple Records
|
454
482
|
-------------------------------------
|
@@ -466,14 +494,17 @@ To set the attributes for each of the factories, you can pass in a hash as you n
|
|
466
494
|
Cucumber Integration
|
467
495
|
--------------------
|
468
496
|
|
469
|
-
|
497
|
+
factory\_girl ships with step definitions that make calling factories from Cucumber easier. To use them, add the following to features/support/env.rb:
|
470
498
|
|
471
|
-
require 'factory_girl/step_definitions'
|
499
|
+
require 'factory_girl/step_definitions'
|
472
500
|
|
473
501
|
Alternate Syntaxes
|
474
502
|
------------------
|
475
503
|
|
476
|
-
Users' tastes for syntax vary dramatically, but most users are looking for a
|
504
|
+
Users' tastes for syntax vary dramatically, but most users are looking for a
|
505
|
+
common feature set. Because of this factory\_girl supports "syntax layers" which
|
506
|
+
provide alternate interfaces. See Factory::Syntax for information about the
|
507
|
+
various layers available. For example, the Machinist-style syntax is popular:
|
477
508
|
|
478
509
|
require 'factory_girl/syntax/blueprint'
|
479
510
|
require 'factory_girl/syntax/make'
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
factory_girl (2.1.
|
4
|
+
factory_girl (2.1.2)
|
5
|
+
activesupport
|
5
6
|
|
6
7
|
GEM
|
7
8
|
remote: http://rubygems.org/
|
@@ -28,31 +29,31 @@ GEM
|
|
28
29
|
cucumber (>= 1.0.2)
|
29
30
|
rdiscount (>= 1.6.8)
|
30
31
|
rspec (>= 2.6.0)
|
31
|
-
bcat (0.6.
|
32
|
+
bcat (0.6.2)
|
32
33
|
rack (~> 1.0)
|
33
|
-
bcrypt-ruby (3.0.
|
34
|
+
bcrypt-ruby (3.0.1)
|
34
35
|
bluecloth (2.1.0)
|
35
36
|
bourne (1.0)
|
36
37
|
mocha (= 0.9.8)
|
37
38
|
builder (3.0.0)
|
38
39
|
childprocess (0.2.2)
|
39
40
|
ffi (~> 1.0.6)
|
40
|
-
cucumber (1.0.
|
41
|
+
cucumber (1.0.6)
|
41
42
|
builder (>= 2.1.2)
|
42
43
|
diff-lcs (>= 1.1.2)
|
43
|
-
gherkin (~> 2.4.
|
44
|
+
gherkin (~> 2.4.18)
|
44
45
|
json (>= 1.4.6)
|
45
|
-
term-ansicolor (>= 1.0.
|
46
|
+
term-ansicolor (>= 1.0.6)
|
46
47
|
diff-lcs (1.1.3)
|
47
48
|
ffi (1.0.9)
|
48
|
-
gherkin (2.4.
|
49
|
+
gherkin (2.4.21)
|
49
50
|
json (>= 1.4.6)
|
50
51
|
i18n (0.6.0)
|
51
|
-
json (1.
|
52
|
+
json (1.6.1)
|
52
53
|
mocha (0.9.8)
|
53
54
|
rake
|
54
55
|
multi_json (1.0.3)
|
55
|
-
rack (1.3.
|
56
|
+
rack (1.3.3)
|
56
57
|
rake (0.9.2)
|
57
58
|
rcov (0.9.10)
|
58
59
|
rdiscount (1.6.8)
|
data/gemfiles/2.1.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/lib/factory_girl.rb
CHANGED
@@ -9,10 +9,13 @@ require 'factory_girl/attribute'
|
|
9
9
|
require 'factory_girl/attribute/static'
|
10
10
|
require 'factory_girl/attribute/dynamic'
|
11
11
|
require 'factory_girl/attribute/association'
|
12
|
-
require 'factory_girl/attribute/callback'
|
13
12
|
require 'factory_girl/attribute/sequence'
|
14
|
-
require 'factory_girl/
|
15
|
-
require 'factory_girl/
|
13
|
+
require 'factory_girl/callback'
|
14
|
+
require 'factory_girl/declaration'
|
15
|
+
require 'factory_girl/declaration/static'
|
16
|
+
require 'factory_girl/declaration/dynamic'
|
17
|
+
require 'factory_girl/declaration/association'
|
18
|
+
require 'factory_girl/declaration/implicit'
|
16
19
|
require 'factory_girl/sequence'
|
17
20
|
require 'factory_girl/attribute_list'
|
18
21
|
require 'factory_girl/trait'
|
@@ -3,6 +3,8 @@ module FactoryGirl
|
|
3
3
|
|
4
4
|
class Static < Attribute #:nodoc:
|
5
5
|
|
6
|
+
attr_reader :value
|
7
|
+
|
6
8
|
def initialize(name, value)
|
7
9
|
super(name)
|
8
10
|
@value = value
|
@@ -15,6 +17,12 @@ module FactoryGirl
|
|
15
17
|
def priority
|
16
18
|
0
|
17
19
|
end
|
20
|
+
|
21
|
+
def ==(another)
|
22
|
+
self.name == another.name &&
|
23
|
+
self.value == another.value &&
|
24
|
+
self.ignored == another.ignored
|
25
|
+
end
|
18
26
|
end
|
19
27
|
end
|
20
28
|
end
|
@@ -2,9 +2,17 @@ module FactoryGirl
|
|
2
2
|
class AttributeList
|
3
3
|
include Enumerable
|
4
4
|
|
5
|
+
attr_reader :callbacks, :declarations
|
6
|
+
|
5
7
|
def initialize
|
6
8
|
@attributes = {}
|
9
|
+
@declarations = []
|
7
10
|
@overridable = false
|
11
|
+
@callbacks = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def declare_attribute(declaration)
|
15
|
+
@declarations << declaration
|
8
16
|
end
|
9
17
|
|
10
18
|
def define_attribute(attribute)
|
@@ -15,12 +23,8 @@ module FactoryGirl
|
|
15
23
|
add_attribute attribute
|
16
24
|
end
|
17
25
|
|
18
|
-
def add_callback(
|
19
|
-
|
20
|
-
raise InvalidCallbackNameError, "#{name} is not a valid callback name. Valid callback names are #{valid_callback_names.inspect}"
|
21
|
-
end
|
22
|
-
|
23
|
-
add_attribute Attribute::Callback.new(name.to_sym, block)
|
26
|
+
def add_callback(callback)
|
27
|
+
@callbacks << callback
|
24
28
|
end
|
25
29
|
|
26
30
|
def each(&block)
|
@@ -32,6 +36,7 @@ module FactoryGirl
|
|
32
36
|
end
|
33
37
|
|
34
38
|
def apply_attributes(attributes_to_apply)
|
39
|
+
attributes_to_apply.callbacks.reverse.each { |callback| prepend_callback(callback) }
|
35
40
|
new_attributes = []
|
36
41
|
|
37
42
|
attributes_to_apply.each do |attribute|
|
@@ -56,12 +61,12 @@ module FactoryGirl
|
|
56
61
|
@overridable
|
57
62
|
end
|
58
63
|
|
59
|
-
|
60
|
-
|
61
|
-
def valid_callback_names
|
62
|
-
[:after_build, :after_create, :after_stub]
|
64
|
+
def size
|
65
|
+
to_a.size
|
63
66
|
end
|
64
67
|
|
68
|
+
private
|
69
|
+
|
65
70
|
def add_attribute(attribute)
|
66
71
|
delete_attribute(attribute.name) if overridable?
|
67
72
|
|
@@ -70,6 +75,10 @@ module FactoryGirl
|
|
70
75
|
attribute
|
71
76
|
end
|
72
77
|
|
78
|
+
def prepend_callback(callback)
|
79
|
+
@callbacks.unshift(callback)
|
80
|
+
end
|
81
|
+
|
73
82
|
def prepend_attributes(new_attributes)
|
74
83
|
new_attributes.group_by {|attr| attr.priority }.each do |priority, attributes|
|
75
84
|
@attributes[priority] ||= []
|
@@ -86,8 +95,7 @@ module FactoryGirl
|
|
86
95
|
|
87
96
|
def find_attribute(attribute_name)
|
88
97
|
@attributes.values.flatten.detect do |attribute|
|
89
|
-
attribute.name == attribute_name
|
90
|
-
!attribute.is_a?(FactoryGirl::Attribute::Callback)
|
98
|
+
attribute.name == attribute_name
|
91
99
|
end
|
92
100
|
end
|
93
101
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module FactoryGirl
|
2
|
+
class Callback
|
3
|
+
VALID_NAMES = [:after_build, :after_create, :after_stub].freeze
|
4
|
+
|
5
|
+
attr_reader :name, :block
|
6
|
+
|
7
|
+
def initialize(name, block)
|
8
|
+
@name = name.to_sym
|
9
|
+
@block = block
|
10
|
+
check_name
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(instance, proxy)
|
14
|
+
case block.arity
|
15
|
+
when 1 then block.call(instance)
|
16
|
+
when 2 then block.call(instance, proxy)
|
17
|
+
else block.call
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def check_name
|
24
|
+
unless VALID_NAMES.include?(name)
|
25
|
+
raise InvalidCallbackNameError, "#{name} is not a valid callback name. " +
|
26
|
+
"Valid callback names are #{VALID_NAMES.inspect}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module FactoryGirl
|
2
|
+
class Declaration
|
3
|
+
attr_reader :name
|
4
|
+
|
5
|
+
def initialize(name)
|
6
|
+
@name = name
|
7
|
+
end
|
8
|
+
|
9
|
+
def ignore
|
10
|
+
@ignored = true
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_attributes
|
14
|
+
build.tap do |attributes|
|
15
|
+
attributes.each(&:ignore) if @ignored
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module FactoryGirl
|
2
|
+
class Declaration
|
3
|
+
class Association < Declaration
|
4
|
+
def initialize(name, options)
|
5
|
+
super(name)
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def build
|
12
|
+
factory_name = @options.delete(:factory) || name
|
13
|
+
[Attribute::Association.new(name, factory_name, @options)]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|