factory_girl 2.1.0 → 2.1.2
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 +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
|