factory_girl 2.0.0.beta2 → 2.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
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 = {})