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
@@ -0,0 +1,23 @@
|
|
1
|
+
module FactoryGirl
|
2
|
+
class Declaration
|
3
|
+
class Implicit < Declaration
|
4
|
+
def initialize(name, factory = nil)
|
5
|
+
super(name)
|
6
|
+
@factory = factory
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def build
|
12
|
+
if FactoryGirl.factories.registered?(name)
|
13
|
+
[Attribute::Association.new(name, name, {})]
|
14
|
+
elsif FactoryGirl.sequences.registered?(name)
|
15
|
+
[Attribute::Sequence.new(name, name)]
|
16
|
+
else
|
17
|
+
trait_root = @factory || FactoryGirl
|
18
|
+
trait_root.trait_by_name(name).attributes.to_a
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -36,13 +36,14 @@ module FactoryGirl
|
|
36
36
|
if value
|
37
37
|
raise AttributeDefinitionError, "Both value and block given"
|
38
38
|
else
|
39
|
-
|
39
|
+
declaration = Declaration::Dynamic.new(name, block)
|
40
40
|
end
|
41
41
|
else
|
42
|
-
|
42
|
+
declaration = FactoryGirl::Declaration::Static.new(name, value)
|
43
43
|
end
|
44
44
|
|
45
|
-
@factory.
|
45
|
+
@factory.declare_attribute(declaration)
|
46
|
+
declaration
|
46
47
|
end
|
47
48
|
|
48
49
|
# Calls add_attribute using the missing method name as the name of the
|
@@ -78,7 +79,7 @@ module FactoryGirl
|
|
78
79
|
# are equivalent.
|
79
80
|
def method_missing(name, *args, &block)
|
80
81
|
if args.empty? && block.nil?
|
81
|
-
@factory.
|
82
|
+
@factory.declare_attribute(Declaration::Implicit.new(name, @factory))
|
82
83
|
elsif args.first.is_a?(Hash) && args.first.has_key?(:factory)
|
83
84
|
association(name, *args)
|
84
85
|
else
|
@@ -131,8 +132,7 @@ module FactoryGirl
|
|
131
132
|
# name of the factory. For example, a "user" association will by
|
132
133
|
# default use the "user" factory.
|
133
134
|
def association(name, options = {})
|
134
|
-
|
135
|
-
@factory.define_attribute(Attribute::Association.new(name, factory_name, options))
|
135
|
+
@factory.declare_attribute(Declaration::Association.new(name, options))
|
136
136
|
end
|
137
137
|
|
138
138
|
def after_build(&block)
|
data/lib/factory_girl/factory.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require "active_support/core_ext/hash/keys"
|
2
|
+
require "active_support/inflector"
|
3
|
+
|
1
4
|
module FactoryGirl
|
2
5
|
# Raised when a factory is defined that attempts to instantiate itself.
|
3
6
|
class AssociationDefinitionError < RuntimeError
|
@@ -13,7 +16,6 @@ module FactoryGirl
|
|
13
16
|
|
14
17
|
class Factory
|
15
18
|
attr_reader :name #:nodoc:
|
16
|
-
attr_reader :traits #:nodoc:
|
17
19
|
|
18
20
|
def factory_name
|
19
21
|
puts "WARNING: factory.factory_name is deprecated. Use factory.name instead."
|
@@ -25,7 +27,7 @@ module FactoryGirl
|
|
25
27
|
end
|
26
28
|
|
27
29
|
def build_class #:nodoc:
|
28
|
-
@build_class ||=
|
30
|
+
@build_class ||= class_name.to_s.camelize.constantize
|
29
31
|
end
|
30
32
|
|
31
33
|
def default_strategy #:nodoc:
|
@@ -34,18 +36,19 @@ module FactoryGirl
|
|
34
36
|
|
35
37
|
def initialize(name, options = {}) #:nodoc:
|
36
38
|
assert_valid_options(options)
|
37
|
-
@name
|
38
|
-
@parent
|
39
|
-
@
|
40
|
-
@
|
41
|
-
@
|
42
|
-
@
|
43
|
-
@
|
39
|
+
@name = name.to_s.underscore.to_sym
|
40
|
+
@parent = options[:parent]
|
41
|
+
@parent_factory = nil
|
42
|
+
@options = options
|
43
|
+
@defined_traits = []
|
44
|
+
@traits = []
|
45
|
+
@children = []
|
46
|
+
@attribute_list = AttributeList.new
|
47
|
+
@compiled = false
|
44
48
|
end
|
45
49
|
|
46
50
|
def allow_overrides
|
47
51
|
@attribute_list.overridable
|
48
|
-
@inherited_attribute_list.overridable
|
49
52
|
self
|
50
53
|
end
|
51
54
|
|
@@ -53,56 +56,48 @@ module FactoryGirl
|
|
53
56
|
@attribute_list.overridable?
|
54
57
|
end
|
55
58
|
|
56
|
-
def
|
59
|
+
def inherit_factory(parent) #:nodoc:
|
57
60
|
@options[:class] ||= parent.class_name
|
58
61
|
@options[:default_strategy] ||= parent.default_strategy
|
59
62
|
|
60
63
|
allow_overrides if parent.allow_overrides?
|
61
64
|
parent.add_child(self)
|
62
65
|
|
63
|
-
@
|
66
|
+
@parent_factory = parent
|
64
67
|
end
|
65
68
|
|
66
69
|
def add_child(factory)
|
67
70
|
@children << factory unless @children.include?(factory)
|
68
71
|
end
|
69
72
|
|
70
|
-
def
|
71
|
-
traits
|
72
|
-
apply_attributes(trait.attributes)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def apply_attributes(attributes_to_apply)
|
77
|
-
@attribute_list.apply_attributes(attributes_to_apply)
|
78
|
-
end
|
79
|
-
|
80
|
-
def define_attribute(attribute)
|
81
|
-
if attribute.respond_to?(:factory) && attribute.factory == self.name
|
82
|
-
raise AssociationDefinitionError, "Self-referencing association '#{attribute.name}' in factory '#{self.name}'"
|
83
|
-
end
|
84
|
-
|
85
|
-
@attribute_list.define_attribute(attribute).tap { update_children }
|
73
|
+
def inherit_traits(traits)
|
74
|
+
@traits = traits
|
86
75
|
end
|
87
76
|
|
88
77
|
def define_trait(trait)
|
89
|
-
@
|
78
|
+
@defined_traits << trait
|
90
79
|
end
|
91
80
|
|
92
81
|
def add_callback(name, &block)
|
93
|
-
@attribute_list.add_callback(name,
|
82
|
+
@attribute_list.add_callback(Callback.new(name, block))
|
94
83
|
end
|
95
84
|
|
96
85
|
def attributes
|
86
|
+
ensure_compiled
|
97
87
|
AttributeList.new.tap do |list|
|
88
|
+
@traits.reverse.map { |name| trait_by_name(name) }.each do |trait|
|
89
|
+
list.apply_attributes(trait.attributes)
|
90
|
+
end
|
91
|
+
|
98
92
|
list.apply_attributes(@attribute_list)
|
99
|
-
list.apply_attributes(@
|
100
|
-
end
|
93
|
+
list.apply_attributes(@parent_factory.attributes) if @parent_factory
|
94
|
+
end
|
101
95
|
end
|
102
96
|
|
103
97
|
def run(proxy_class, overrides) #:nodoc:
|
104
98
|
proxy = proxy_class.new(build_class)
|
105
|
-
|
99
|
+
callbacks.each { |callback| proxy.add_callback(callback) }
|
100
|
+
overrides = overrides.symbolize_keys
|
106
101
|
|
107
102
|
attributes.each do |attribute|
|
108
103
|
factory_overrides = overrides.select { |attr, val| attribute.aliases_for?(attr) }
|
@@ -117,7 +112,7 @@ module FactoryGirl
|
|
117
112
|
end
|
118
113
|
|
119
114
|
def human_names
|
120
|
-
names.map {|name| name.to_s.
|
115
|
+
names.map {|name| name.to_s.humanize.downcase }
|
121
116
|
end
|
122
117
|
|
123
118
|
def associations
|
@@ -167,36 +162,45 @@ module FactoryGirl
|
|
167
162
|
@to_create_block = block
|
168
163
|
end
|
169
164
|
|
170
|
-
|
171
|
-
|
172
|
-
def update_children
|
173
|
-
@children.each { |child| child.inherit_from(self) }
|
165
|
+
def callbacks
|
166
|
+
attributes.callbacks
|
174
167
|
end
|
175
168
|
|
176
|
-
def
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
object.const_get(string)
|
169
|
+
def compile
|
170
|
+
declarations.each do |declaration|
|
171
|
+
declaration.to_attributes.each do |attribute|
|
172
|
+
define_attribute(attribute)
|
181
173
|
end
|
182
|
-
else
|
183
|
-
class_or_to_s
|
184
174
|
end
|
175
|
+
@compiled = true
|
185
176
|
end
|
186
177
|
|
187
|
-
def
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
178
|
+
def declare_attribute(declaration)
|
179
|
+
@attribute_list.declare_attribute(declaration)
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def declarations
|
185
|
+
@attribute_list.declarations
|
186
|
+
end
|
187
|
+
|
188
|
+
def update_children
|
189
|
+
@children.each { |child| child.inherit_factory(self) }
|
190
|
+
end
|
191
|
+
|
192
|
+
def define_attribute(attribute)
|
193
|
+
if attribute.respond_to?(:factory) && attribute.factory == self.name
|
194
|
+
raise AssociationDefinitionError, "Self-referencing association '#{attribute.name}' in factory '#{self.name}'"
|
192
195
|
end
|
196
|
+
|
197
|
+
@attribute_list.define_attribute(attribute)
|
198
|
+
update_children if allow_overrides?
|
193
199
|
end
|
194
200
|
|
195
201
|
def assert_valid_options(options)
|
196
|
-
|
197
|
-
|
198
|
-
raise ArgumentError, "Unknown arguments: #{invalid_keys.inspect}"
|
199
|
-
end
|
202
|
+
options.assert_valid_keys(:class, :parent, :default_strategy, :aliases, :traits)
|
203
|
+
|
200
204
|
if options[:default_strategy]
|
201
205
|
assert_valid_strategy(options[:default_strategy])
|
202
206
|
puts "WARNING: default_strategy is deprecated."
|
@@ -205,37 +209,17 @@ module FactoryGirl
|
|
205
209
|
end
|
206
210
|
|
207
211
|
def assert_valid_strategy(strategy)
|
208
|
-
unless Proxy.const_defined?
|
212
|
+
unless Proxy.const_defined? strategy.to_s.camelize
|
209
213
|
raise ArgumentError, "Unknown strategy: #{strategy}"
|
210
214
|
end
|
211
215
|
end
|
212
216
|
|
213
|
-
|
214
|
-
|
215
|
-
name.to_s.gsub(/::/, '/').
|
216
|
-
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
217
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
218
|
-
tr("-", "_").
|
219
|
-
downcase
|
220
|
-
end
|
221
|
-
|
222
|
-
# Based on ActiveSupport's camelize inflector
|
223
|
-
def variable_name_to_class_name(name)
|
224
|
-
name.to_s.
|
225
|
-
gsub(/\/(.?)/) { "::#{$1.upcase}" }.
|
226
|
-
gsub(/(?:^|_)(.)/) { $1.upcase }
|
227
|
-
end
|
228
|
-
|
229
|
-
# From ActiveSupport
|
230
|
-
def symbolize_keys(hash)
|
231
|
-
hash.inject({}) do |options, (key, value)|
|
232
|
-
options[(key.to_sym rescue key) || key] = value
|
233
|
-
options
|
234
|
-
end
|
217
|
+
def trait_for(name)
|
218
|
+
@defined_traits.detect {|trait| trait.name == name }
|
235
219
|
end
|
236
220
|
|
237
|
-
def
|
238
|
-
|
221
|
+
def ensure_compiled
|
222
|
+
compile unless @compiled
|
239
223
|
end
|
240
224
|
end
|
241
225
|
end
|
data/lib/factory_girl/proxy.rb
CHANGED
@@ -4,6 +4,7 @@ module FactoryGirl
|
|
4
4
|
attr_reader :callbacks
|
5
5
|
|
6
6
|
def initialize(klass)
|
7
|
+
@callbacks = {}
|
7
8
|
end
|
8
9
|
|
9
10
|
def get(attribute)
|
@@ -15,20 +16,15 @@ module FactoryGirl
|
|
15
16
|
def associate(name, factory, attributes)
|
16
17
|
end
|
17
18
|
|
18
|
-
def add_callback(
|
19
|
-
@callbacks ||=
|
20
|
-
@callbacks[name]
|
21
|
-
@callbacks[name] << block
|
19
|
+
def add_callback(callback)
|
20
|
+
@callbacks[callback.name] ||= []
|
21
|
+
@callbacks[callback.name] << callback
|
22
22
|
end
|
23
23
|
|
24
24
|
def run_callbacks(name)
|
25
|
-
if @callbacks
|
26
|
-
@callbacks[name].each do |
|
27
|
-
|
28
|
-
when 0 then block.call
|
29
|
-
when 2 then block.call(@instance, self)
|
30
|
-
else block.call(@instance)
|
31
|
-
end
|
25
|
+
if @callbacks[name]
|
26
|
+
@callbacks[name].each do |callback|
|
27
|
+
callback.run(@instance, self)
|
32
28
|
end
|
33
29
|
end
|
34
30
|
end
|
@@ -22,12 +22,13 @@ module FactoryGirl
|
|
22
22
|
proxy.instance_eval(&block) if block_given?
|
23
23
|
|
24
24
|
if traits = options.delete(:traits)
|
25
|
-
factory.
|
25
|
+
factory.inherit_traits(traits)
|
26
26
|
end
|
27
27
|
|
28
28
|
if parent = options.delete(:parent)
|
29
|
-
factory.
|
29
|
+
factory.inherit_factory(FactoryGirl.factory_by_name(parent))
|
30
30
|
end
|
31
|
+
|
31
32
|
FactoryGirl.register_factory(factory)
|
32
33
|
|
33
34
|
proxy.child_factories.each do |(child_name, child_options, child_block)|
|
@@ -53,6 +54,7 @@ module FactoryGirl
|
|
53
54
|
factory = FactoryGirl.factory_by_name(name).allow_overrides
|
54
55
|
proxy = FactoryGirl::DefinitionProxy.new(factory)
|
55
56
|
proxy.instance_eval(&block)
|
57
|
+
factory.compile
|
56
58
|
end
|
57
59
|
end
|
58
60
|
end
|
@@ -29,7 +29,7 @@ module FactoryGirl
|
|
29
29
|
proxy = FactoryGirl::DefinitionProxy.new(factory)
|
30
30
|
yield(proxy)
|
31
31
|
if parent = options.delete(:parent)
|
32
|
-
factory.
|
32
|
+
factory.inherit_factory(FactoryGirl.factory_by_name(parent))
|
33
33
|
end
|
34
34
|
FactoryGirl.register_factory(factory)
|
35
35
|
end
|
data/lib/factory_girl/trait.rb
CHANGED
@@ -10,16 +10,24 @@ module FactoryGirl
|
|
10
10
|
proxy.instance_eval(&block) if block_given?
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
@attribute_list.
|
13
|
+
def declare_attribute(declaration)
|
14
|
+
@attribute_list.declare_attribute(declaration)
|
15
|
+
declaration
|
15
16
|
end
|
16
17
|
|
17
18
|
def add_callback(name, &block)
|
18
|
-
@attribute_list.add_callback(name,
|
19
|
+
@attribute_list.add_callback(Callback.new(name, block))
|
19
20
|
end
|
20
21
|
|
21
22
|
def attributes
|
22
|
-
|
23
|
+
AttributeList.new.tap do |list|
|
24
|
+
@attribute_list.declarations.each do |declaration|
|
25
|
+
declaration.to_attributes.each do |attribute|
|
26
|
+
list.define_attribute(attribute)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
list.apply_attributes @attribute_list
|
30
|
+
end
|
23
31
|
end
|
24
32
|
|
25
33
|
def names
|
data/lib/factory_girl/version.rb
CHANGED