factory_girl 2.0.0.beta2 → 2.0.0.beta3

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.
Files changed (54) hide show
  1. data/Appraisals +1 -0
  2. data/CONTRIBUTION_GUIDELINES.md +7 -7
  3. data/GETTING_STARTED.md +36 -11
  4. data/Gemfile +2 -2
  5. data/Gemfile.lock +28 -21
  6. data/README.md +2 -2
  7. data/Rakefile +2 -2
  8. data/features/factory_girl_steps.feature +33 -0
  9. data/features/support/factories.rb +25 -18
  10. data/features/support/test.db +0 -0
  11. data/lib/factory_girl.rb +27 -0
  12. data/lib/factory_girl/attribute.rb +4 -0
  13. data/lib/factory_girl/attribute/association.rb +4 -0
  14. data/lib/factory_girl/attribute/dynamic.rb +1 -1
  15. data/lib/factory_girl/attribute/implicit.rb +36 -0
  16. data/lib/factory_girl/attribute/sequence.rb +16 -0
  17. data/lib/factory_girl/definition_proxy.rb +2 -2
  18. data/lib/factory_girl/factory.rb +1 -13
  19. data/lib/factory_girl/find_definitions.rb +1 -3
  20. data/lib/factory_girl/proxy/build.rb +2 -2
  21. data/lib/factory_girl/proxy/stub.rb +6 -2
  22. data/lib/factory_girl/rails2.rb +7 -1
  23. data/lib/factory_girl/registry.rb +7 -21
  24. data/lib/factory_girl/sequence.rb +3 -14
  25. data/lib/factory_girl/step_definitions.rb +5 -5
  26. data/lib/factory_girl/syntax/blueprint.rb +1 -1
  27. data/lib/factory_girl/syntax/default.rb +3 -3
  28. data/lib/factory_girl/syntax/generate.rb +3 -3
  29. data/lib/factory_girl/syntax/make.rb +5 -1
  30. data/lib/factory_girl/syntax/methods.rb +51 -4
  31. data/lib/factory_girl/syntax/sham.rb +2 -2
  32. data/lib/factory_girl/syntax/vintage.rb +31 -12
  33. data/lib/factory_girl/version.rb +1 -1
  34. data/spec/acceptance/build_list_spec.rb +42 -0
  35. data/spec/acceptance/create_list_spec.rb +42 -0
  36. data/spec/acceptance/sequence_spec.rb +6 -4
  37. data/spec/acceptance/syntax/blueprint_spec.rb +3 -3
  38. data/spec/acceptance/syntax/make_spec.rb +19 -1
  39. data/spec/acceptance/syntax/vintage_spec.rb +4 -4
  40. data/spec/factory_girl/attribute/association_spec.rb +4 -0
  41. data/spec/factory_girl/attribute/implicit_spec.rb +50 -0
  42. data/spec/factory_girl/attribute/sequence_spec.rb +21 -0
  43. data/spec/factory_girl/attribute_spec.rb +4 -0
  44. data/spec/factory_girl/definition_proxy_spec.rb +2 -13
  45. data/spec/factory_girl/factory_spec.rb +4 -2
  46. data/spec/factory_girl/find_definitions_spec.rb +9 -0
  47. data/spec/factory_girl/proxy/build_spec.rb +2 -2
  48. data/spec/factory_girl/proxy/create_spec.rb +2 -2
  49. data/spec/factory_girl/proxy/stub_spec.rb +5 -1
  50. data/spec/factory_girl/registry_spec.rb +11 -20
  51. data/spec/factory_girl/sequence_spec.rb +15 -19
  52. data/spec/factory_girl_spec.rb +17 -0
  53. data/spec/spec_helper.rb +2 -1
  54. metadata +45 -73
@@ -0,0 +1,16 @@
1
+ module FactoryGirl
2
+ class Attribute
3
+
4
+ class Sequence < Attribute
5
+ def initialize(name, sequence)
6
+ super(name)
7
+ @sequence = sequence
8
+ end
9
+
10
+ def add_to(proxy)
11
+ proxy.set(name, FactoryGirl.generate(@sequence))
12
+ end
13
+ end
14
+
15
+ end
16
+ end
@@ -73,7 +73,7 @@ module FactoryGirl
73
73
  # are equivilent.
74
74
  def method_missing(name, *args, &block)
75
75
  if args.empty? && block.nil?
76
- association(name)
76
+ @factory.define_attribute(Attribute::Implicit.new(name))
77
77
  else
78
78
  add_attribute(name, *args, &block)
79
79
  end
@@ -97,7 +97,7 @@ module FactoryGirl
97
97
  # Except that no globally available sequence will be defined.
98
98
  def sequence(name, start_value = 1, &block)
99
99
  sequence = Sequence.new(name, start_value, &block)
100
- add_attribute(name) { sequence.run }
100
+ add_attribute(name) { sequence.next }
101
101
  end
102
102
 
103
103
  # Adds an attribute that builds an association. The associated instance will
@@ -1,16 +1,4 @@
1
1
  module FactoryGirl
2
- def self.factories
3
- puts "WARNING: FactoryGirl.factories is deprecated."
4
- puts "Use FactoryGirl.registry instead."
5
- registry
6
- end
7
-
8
- def self.factory_by_name(name)
9
- puts "WARNING: FactoryGirl.factory_by_name is deprecated."
10
- puts "Use FactoryGirl.find instead."
11
- registry.find(name)
12
- end
13
-
14
2
  # Raised when a factory is defined that attempts to instantiate itself.
15
3
  class AssociationDefinitionError < RuntimeError
16
4
  end
@@ -101,7 +89,7 @@ module FactoryGirl
101
89
  end
102
90
 
103
91
  def associations
104
- attributes.select {|attribute| attribute.is_a?(Attribute::Association) }
92
+ attributes.select {|attribute| attribute.association? }
105
93
  end
106
94
 
107
95
  # Names for this factory, including aliases.
@@ -1,8 +1,6 @@
1
1
  module FactoryGirl
2
2
 
3
3
  class << self
4
- attr_accessor :factories #:nodoc:
5
-
6
4
  # An Array of strings specifying locations that should be searched for
7
5
  # factory definitions. By default, factory_girl will attempt to require
8
6
  # "factories," "test/factories," and "spec/factories." Only the first
@@ -16,7 +14,7 @@ module FactoryGirl
16
14
  require("#{path}.rb") if File.exists?("#{path}.rb")
17
15
 
18
16
  if File.directory? path
19
- Dir[File.join(path, '*.rb')].sort.each do |file|
17
+ Dir[File.join(path, '**', '*.rb')].sort.each do |file|
20
18
  require file
21
19
  end
22
20
  end
@@ -14,12 +14,12 @@ module FactoryGirl
14
14
  end
15
15
 
16
16
  def associate(name, factory_name, overrides)
17
- factory = FactoryGirl.find(factory_name)
17
+ factory = FactoryGirl.factory_by_name(factory_name)
18
18
  set(name, factory.run(Proxy::Create, overrides))
19
19
  end
20
20
 
21
21
  def association(factory_name, overrides = {})
22
- factory = FactoryGirl.find(factory_name)
22
+ factory = FactoryGirl.factory_by_name(factory_name)
23
23
  factory.run(Proxy::Create, overrides)
24
24
  end
25
25
 
@@ -7,6 +7,10 @@ module FactoryGirl
7
7
  @instance = klass.new
8
8
  @instance.id = next_id
9
9
  @instance.instance_eval do
10
+ def persisted?
11
+ !new_record?
12
+ end
13
+
10
14
  def new_record?
11
15
  id.nil?
12
16
  end
@@ -46,12 +50,12 @@ module FactoryGirl
46
50
  end
47
51
 
48
52
  def associate(name, factory_name, overrides)
49
- factory = FactoryGirl.find(factory_name)
53
+ factory = FactoryGirl.factory_by_name(factory_name)
50
54
  set(name, factory.run(Proxy::Stub, overrides))
51
55
  end
52
56
 
53
57
  def association(factory_name, overrides = {})
54
- factory = FactoryGirl.find(factory_name)
58
+ factory = FactoryGirl.factory_by_name(factory_name)
55
59
  factory.run(Proxy::Stub, overrides)
56
60
  end
57
61
 
@@ -1 +1,7 @@
1
- Rails.configuration.after_initialize { FactoryGirl.find_definitions }
1
+ Rails.configuration.after_initialize do
2
+ FactoryGirl.definition_file_paths = [
3
+ File.join(Rails.root, 'test', 'factories'),
4
+ File.join(Rails.root, 'spec', 'factories')
5
+ ]
6
+ FactoryGirl.find_definitions
7
+ end
@@ -1,5 +1,7 @@
1
1
  module FactoryGirl
2
2
  class Registry
3
+ include Enumerable
4
+
3
5
  def initialize
4
6
  @items = {}
5
7
  end
@@ -14,7 +16,7 @@ module FactoryGirl
14
16
  end
15
17
 
16
18
  def each(&block)
17
- @items.each(&block)
19
+ @items.values.each(&block)
18
20
  end
19
21
 
20
22
  def [](name)
@@ -25,6 +27,10 @@ module FactoryGirl
25
27
  @items.key?(name.to_sym)
26
28
  end
27
29
 
30
+ def clear
31
+ @items.clear
32
+ end
33
+
28
34
  private
29
35
 
30
36
  def add_as(name, item)
@@ -35,25 +41,5 @@ module FactoryGirl
35
41
  end
36
42
  end
37
43
  end
38
-
39
- def self.register(item)
40
- registry.add(item)
41
- end
42
-
43
- def self.registered?(name)
44
- registry.registered?(name)
45
- end
46
-
47
- def self.find(name)
48
- registry.find(name)
49
- end
50
-
51
- def self.registry
52
- @registry ||= Registry.new
53
- end
54
-
55
- def self.registry=(registry)
56
- @registry = registry
57
- end
58
44
  end
59
45
 
@@ -6,25 +6,20 @@ module FactoryGirl
6
6
  # Sequences are defined using sequence within a FactoryGirl.define block.
7
7
  # Sequence values are generated using next.
8
8
  class Sequence
9
+ attr_reader :name
10
+
9
11
  def initialize(name, value = 1, &proc) #:nodoc:
10
12
  @name = name
11
13
  @proc = proc
12
14
  @value = value || 1
13
15
  end
14
16
 
15
- # Returns the next value for this sequence
16
- def run(proxy_class = nil, overrides = {})
17
+ def next
17
18
  @proc ? @proc.call(@value) : @value
18
19
  ensure
19
20
  @value = @value.next
20
21
  end
21
22
 
22
- def next
23
- puts "WARNING: FactoryGirl::Sequence#next is deprecated."
24
- puts "Use #run instead."
25
- run
26
- end
27
-
28
23
  def default_strategy
29
24
  :create
30
25
  end
@@ -33,10 +28,4 @@ module FactoryGirl
33
28
  [@name]
34
29
  end
35
30
  end
36
-
37
- def self.sequences
38
- puts "WARNING: FactoryGirl.sequences is deprecated."
39
- puts "Use FactoryGirl.registry instead."
40
- registry
41
- end
42
31
  end
@@ -3,7 +3,7 @@ module FactoryGirlStepHelpers
3
3
  def convert_association_string_to_instance(factory_name, assignment)
4
4
  attribute, value = assignment.split(':', 2)
5
5
  return if value.blank?
6
- factory = FactoryGirl.find(factory_name)
6
+ factory = FactoryGirl.factory_by_name(factory_name)
7
7
  attributes = convert_human_hash_to_attribute_hash({attribute => value.strip}, factory.associations)
8
8
  attributes_find = {}
9
9
  attributes.each do |k, v|
@@ -28,19 +28,19 @@ end
28
28
 
29
29
  World(FactoryGirlStepHelpers)
30
30
 
31
- FactoryGirl.registry.each do |name, factory|
32
- Given /^the following (?:#{factory.human_name}|#{factory.human_name.pluralize}) exists?:$/ do |table|
31
+ FactoryGirl.factories.each do |factory|
32
+ Given /^the following (?:#{factory.human_name}|#{factory.human_name.pluralize}) exists?:$/i do |table|
33
33
  table.hashes.each do |human_hash|
34
34
  attributes = convert_human_hash_to_attribute_hash(human_hash, factory.associations)
35
35
  factory.run(FactoryGirl::Proxy::Create, attributes)
36
36
  end
37
37
  end
38
38
 
39
- Given /^an? #{factory.human_name} exists$/ do
39
+ Given /^an? #{factory.human_name} exists$/i do
40
40
  FactoryGirl.create(factory.name)
41
41
  end
42
42
 
43
- Given /^(\d+) #{factory.human_name.pluralize} exist$/ do |count|
43
+ Given /^(\d+) #{factory.human_name.pluralize} exist$/i do |count|
44
44
  count.to_i.times { FactoryGirl.create(factory.name) }
45
45
  end
46
46
 
@@ -29,7 +29,7 @@ module FactoryGirl
29
29
  instance = Factory.new(name.underscore, :class => self)
30
30
  proxy = FactoryGirl::DefinitionProxy.new(instance)
31
31
  proxy.instance_eval(&block)
32
- FactoryGirl.register(instance)
32
+ FactoryGirl.register_factory(instance)
33
33
  end
34
34
 
35
35
  end
@@ -17,13 +17,13 @@ module FactoryGirl
17
17
  proxy = FactoryGirl::DefinitionProxy.new(factory)
18
18
  proxy.instance_eval(&block)
19
19
  if parent = options.delete(:parent)
20
- factory.inherit_from(FactoryGirl.find(parent))
20
+ factory.inherit_from(FactoryGirl.factory_by_name(parent))
21
21
  end
22
- FactoryGirl.register(factory)
22
+ FactoryGirl.register_factory(factory)
23
23
  end
24
24
 
25
25
  def sequence(name, start_value = 1, &block)
26
- FactoryGirl.register(Sequence.new(name, start_value, &block))
26
+ FactoryGirl.register_sequence(Sequence.new(name, start_value, &block))
27
27
  end
28
28
  end
29
29
  end
@@ -42,7 +42,7 @@ module FactoryGirl
42
42
  module ClassMethods #:nodoc:
43
43
 
44
44
  def generate(overrides = {}, &block)
45
- factory = FactoryGirl.find(name.underscore)
45
+ factory = FactoryGirl.factory_by_name(name.underscore)
46
46
  instance = factory.run(Proxy::Build, overrides)
47
47
  instance.save
48
48
  yield(instance) if block_given?
@@ -50,14 +50,14 @@ module FactoryGirl
50
50
  end
51
51
 
52
52
  def generate!(overrides = {}, &block)
53
- factory = FactoryGirl.find(name.underscore)
53
+ factory = FactoryGirl.factory_by_name(name.underscore)
54
54
  instance = factory.run(Proxy::Create, overrides)
55
55
  yield(instance) if block_given?
56
56
  instance
57
57
  end
58
58
 
59
59
  def spawn(overrides = {}, &block)
60
- factory = FactoryGirl.find(name.underscore)
60
+ factory = FactoryGirl.factory_by_name(name.underscore)
61
61
  instance = factory.run(Proxy::Build, overrides)
62
62
  yield(instance) if block_given?
63
63
  instance
@@ -28,7 +28,11 @@ module FactoryGirl
28
28
  module ClassMethods #:nodoc:
29
29
 
30
30
  def make(overrides = {})
31
- FactoryGirl.find(name.underscore).run(Proxy::Create, overrides)
31
+ FactoryGirl.factory_by_name(name.underscore).run(Proxy::Build, overrides)
32
+ end
33
+
34
+ def make!(overrides = {})
35
+ FactoryGirl.factory_by_name(name.underscore).run(Proxy::Create, overrides)
32
36
  end
33
37
 
34
38
  end
@@ -15,7 +15,7 @@ module FactoryGirl
15
15
  # A set of attributes that can be used to build an instance of the class
16
16
  # this factory generates.
17
17
  def attributes_for(name, overrides = {})
18
- FactoryGirl.find(name).run(Proxy::AttributesFor, overrides)
18
+ FactoryGirl.factory_by_name(name).run(Proxy::AttributesFor, overrides)
19
19
  end
20
20
 
21
21
  # Generates and returns an instance from this factory. Attributes can be
@@ -31,7 +31,7 @@ module FactoryGirl
31
31
  # An instance of the class this factory generates, with generated attributes
32
32
  # assigned.
33
33
  def build(name, overrides = {})
34
- FactoryGirl.find(name).run(Proxy::Build, overrides)
34
+ FactoryGirl.factory_by_name(name).run(Proxy::Build, overrides)
35
35
  end
36
36
 
37
37
  # Generates, saves, and returns an instance from this factory. Attributes can
@@ -51,7 +51,7 @@ module FactoryGirl
51
51
  # A saved instance of the class this factory generates, with generated
52
52
  # attributes assigned.
53
53
  def create(name, overrides = {})
54
- FactoryGirl.find(name).run(Proxy::Create, overrides)
54
+ FactoryGirl.factory_by_name(name).run(Proxy::Create, overrides)
55
55
  end
56
56
 
57
57
  # Generates and returns an object with all attributes from this factory
@@ -67,9 +67,56 @@ module FactoryGirl
67
67
  # Returns: +Object+
68
68
  # An object with generated attributes stubbed out.
69
69
  def build_stubbed(name, overrides = {})
70
- FactoryGirl.find(name).run(Proxy::Stub, overrides)
70
+ FactoryGirl.factory_by_name(name).run(Proxy::Stub, overrides)
71
71
  end
72
72
 
73
+ # Builds and returns multiple instances from this factory as an array. Attributes can be
74
+ # individually overridden by passing in a Hash of attribute => value pairs.
75
+ #
76
+ # Arguments:
77
+ # * name: +Symbol+ or +String+
78
+ # The name of the factory to be used.
79
+ # * amount: +Integer+
80
+ # number of instances to be built.
81
+ # * overrides: +Hash+
82
+ # Attributes to overwrite for each instance.
83
+ #
84
+ # Returns: +Array+
85
+ # An array of instances of the class this factory generates, with generated attributes
86
+ # assigned.
87
+ def build_list(name, amount, overrides = {})
88
+ amount.times.map { build(name, overrides) }
89
+ end
90
+
91
+ # Creates and returns multiple instances from this factory as an array. Attributes can be
92
+ # individually overridden by passing in a Hash of attribute => value pairs.
93
+ #
94
+ # Arguments:
95
+ # * name: +Symbol+ or +String+
96
+ # The name of the factory to be used.
97
+ # * amount: +Integer+
98
+ # number of instances to be created.
99
+ # * overrides: +Hash+
100
+ # Attributes to overwrite for each instance.
101
+ #
102
+ # Returns: +Array+
103
+ # An array of instances of the class this factory generates, with generated attributes
104
+ # assigned.
105
+ def create_list(name, amount, overrides = {})
106
+ amount.times.map { create(name, overrides) }
107
+ end
108
+
109
+ # Generates and returns the next value in a sequence.
110
+ #
111
+ # Arguments:
112
+ # name: (Symbol)
113
+ # The name of the sequence that a value should be generated for.
114
+ #
115
+ # Returns:
116
+ # The next value in the sequence. (Object)
117
+ def generate(name)
118
+ FactoryGirl.sequence_by_name(name).next
119
+ end
73
120
  end
74
121
  end
75
122
  end
@@ -27,9 +27,9 @@ module FactoryGirl
27
27
  def self.method_missing(name, *args, &block)
28
28
  if block_given?
29
29
  start_value = args.first
30
- FactoryGirl.register(Sequence.new(name, start_value || 1, &block))
30
+ FactoryGirl.register_sequence(Sequence.new(name, start_value || 1, &block))
31
31
  else
32
- FactoryGirl.find(name).run
32
+ FactoryGirl.sequence_by_name(name).next
33
33
  end
34
34
  end
35
35
 
@@ -2,8 +2,6 @@ module FactoryGirl
2
2
  module Syntax
3
3
  module Vintage
4
4
  module Factory
5
- extend Syntax::Methods
6
-
7
5
  # Defines a new factory that can be used by the build strategies (create and
8
6
  # build) to build new objects.
9
7
  #
@@ -31,14 +29,18 @@ module FactoryGirl
31
29
  proxy = FactoryGirl::DefinitionProxy.new(factory)
32
30
  yield(proxy)
33
31
  if parent = options.delete(:parent)
34
- factory.inherit_from(FactoryGirl.find(parent))
32
+ factory.inherit_from(FactoryGirl.factory_by_name(parent))
35
33
  end
36
- FactoryGirl.register(factory)
34
+ FactoryGirl.register_factory(factory)
37
35
  end
38
36
 
39
37
  # Executes the default strategy for the given factory. This is usually create,
40
38
  # but it can be overridden for each factory.
41
39
  #
40
+ # DEPRECATED
41
+ #
42
+ # Use create instead.
43
+ #
42
44
  # Arguments:
43
45
  # * name: +Symbol+ or +String+
44
46
  # The name of the factory that should be used.
@@ -48,7 +50,7 @@ module FactoryGirl
48
50
  # Returns: +Object+
49
51
  # The result of the default strategy.
50
52
  def self.default_strategy(name, overrides = {})
51
- self.send(FactoryGirl.find(name).default_strategy, name, overrides)
53
+ FactoryGirl.send(FactoryGirl.factory_by_name(name).default_strategy, name, overrides)
52
54
  end
53
55
 
54
56
  # Defines a new sequence that can be used to generate unique values in a specific format.
@@ -67,7 +69,7 @@ module FactoryGirl
67
69
  #
68
70
  # Factory.sequence(:email) {|n| "somebody_#{n}@example.com" }
69
71
  def self.sequence(name, start_value = 1, &block)
70
- FactoryGirl.register(Sequence.new(name, start_value, &block))
72
+ FactoryGirl.register_sequence(Sequence.new(name, start_value, &block))
71
73
  end
72
74
 
73
75
  # Generates and returns the next value in a sequence.
@@ -76,12 +78,10 @@ module FactoryGirl
76
78
  # name: (Symbol)
77
79
  # The name of the sequence that a value should be generated for.
78
80
  #
79
- # DEPRECATED. Use create instead.
80
- #
81
81
  # Returns:
82
82
  # The next value in the sequence. (Object)
83
83
  def self.next(name)
84
- FactoryGirl.find(name).next
84
+ FactoryGirl.generate(name)
85
85
  end
86
86
 
87
87
  # Defines a new alias for attributes.
@@ -112,15 +112,34 @@ module FactoryGirl
112
112
  FactoryGirl.aliases << [pattern, replace]
113
113
  end
114
114
 
115
- # Alias for build_stubbed. Deprecated.
116
- def self.stub(name, overrides = {})
117
- build_stubbed(name, overrides)
115
+ # Alias for FactoryGirl.attributes_for
116
+ def self.attributes_for(name, overrides = {})
117
+ FactoryGirl.attributes_for(name, overrides)
118
+ end
119
+
120
+ # Alias for FactoryGirl.build
121
+ def self.build(name, overrides = {})
122
+ FactoryGirl.build(name, overrides)
118
123
  end
119
124
 
125
+ # Alias for FactoryGirl.create
126
+ def self.create(name, overrides = {})
127
+ FactoryGirl.create(name, overrides)
128
+ end
129
+
130
+ # Alias for FactoryGirl.build_stubbed.
131
+ def self.stub(name, overrides = {})
132
+ FactoryGirl.build_stubbed(name, overrides)
133
+ end
120
134
  end
121
135
 
122
136
  # Shortcut for Factory.default_strategy.
123
137
  #
138
+ # DEPRECATION WARNING:
139
+ #
140
+ # In a future release, default_strategy will be removed and this will
141
+ # simply call create instead.
142
+ #
124
143
  # Example:
125
144
  # Factory(:user, :name => 'Joe')
126
145
  def Factory(name, attrs = {})