factory_girl 2.0.0.beta1 → 2.0.0.beta2

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 (63) hide show
  1. data/Appraisals +12 -0
  2. data/{CONTRIBUTION_GUIDELINES.rdoc → CONTRIBUTION_GUIDELINES.md} +3 -3
  3. data/GETTING_STARTED.md +246 -0
  4. data/Gemfile +12 -0
  5. data/Gemfile.lock +62 -0
  6. data/README.md +64 -0
  7. data/Rakefile +15 -30
  8. data/features/factory_girl_steps.feature +26 -0
  9. data/features/step_definitions/database_steps.rb +2 -0
  10. data/features/support/env.rb +0 -9
  11. data/features/support/factories.rb +15 -0
  12. data/features/support/test.db +0 -0
  13. data/lib/factory_girl.rb +2 -0
  14. data/lib/factory_girl/definition_proxy.rb +10 -43
  15. data/lib/factory_girl/factory.rb +48 -17
  16. data/lib/factory_girl/proxy.rb +3 -3
  17. data/lib/factory_girl/proxy/attributes_for.rb +1 -1
  18. data/lib/factory_girl/proxy/build.rb +3 -3
  19. data/lib/factory_girl/proxy/create.rb +6 -2
  20. data/lib/factory_girl/proxy/stub.rb +3 -3
  21. data/lib/factory_girl/registry.rb +59 -0
  22. data/lib/factory_girl/sequence.rb +23 -9
  23. data/lib/factory_girl/step_definitions.rb +16 -9
  24. data/lib/factory_girl/syntax/blueprint.rb +2 -2
  25. data/lib/factory_girl/syntax/default.rb +5 -3
  26. data/lib/factory_girl/syntax/generate.rb +6 -6
  27. data/lib/factory_girl/syntax/make.rb +2 -2
  28. data/lib/factory_girl/syntax/methods.rb +75 -0
  29. data/lib/factory_girl/syntax/sham.rb +2 -2
  30. data/lib/factory_girl/syntax/vintage.rb +16 -79
  31. data/lib/factory_girl/version.rb +1 -1
  32. data/spec/acceptance/acceptance_helper.rb +7 -12
  33. data/spec/acceptance/attribute_aliases_spec.rb +26 -0
  34. data/spec/acceptance/attributes_for_spec.rb +48 -0
  35. data/spec/acceptance/build_spec.rb +35 -0
  36. data/spec/acceptance/build_stubbed_spec.rb +79 -0
  37. data/spec/acceptance/callbacks_spec.rb +42 -0
  38. data/spec/acceptance/create_spec.rb +67 -0
  39. data/spec/acceptance/default_strategy_spec.rb +27 -0
  40. data/spec/acceptance/definition_spec.rb +28 -0
  41. data/spec/acceptance/parent_spec.rb +39 -0
  42. data/spec/acceptance/sequence_spec.rb +32 -0
  43. data/spec/acceptance/syntax/blueprint_spec.rb +7 -5
  44. data/spec/acceptance/syntax/generate_spec.rb +10 -4
  45. data/spec/acceptance/syntax/make_spec.rb +7 -4
  46. data/spec/acceptance/syntax/sham_spec.rb +15 -8
  47. data/spec/acceptance/syntax/vintage_spec.rb +57 -17
  48. data/spec/factory_girl/attribute/dynamic_spec.rb +1 -1
  49. data/spec/factory_girl/definition_proxy_spec.rb +13 -11
  50. data/spec/factory_girl/factory_spec.rb +29 -52
  51. data/spec/factory_girl/find_definitions_spec.rb +34 -23
  52. data/spec/factory_girl/proxy/attributes_for_spec.rb +6 -6
  53. data/spec/factory_girl/proxy/build_spec.rb +4 -4
  54. data/spec/factory_girl/proxy/create_spec.rb +11 -3
  55. data/spec/factory_girl/proxy/stub_spec.rb +6 -6
  56. data/spec/factory_girl/proxy_spec.rb +1 -1
  57. data/spec/factory_girl/registry_spec.rb +92 -0
  58. data/spec/factory_girl/sequence_spec.rb +65 -8
  59. data/spec/spec_helper.rb +75 -29
  60. metadata +66 -43
  61. data/README.rdoc +0 -282
  62. data/spec/acceptance/acceptance_spec.rb +0 -288
  63. data/spec/acceptance/models.rb +0 -48
@@ -3,26 +3,40 @@ module FactoryGirl
3
3
  # Raised when calling Factory.sequence from a dynamic attribute block
4
4
  class SequenceAbuseError < StandardError; end
5
5
 
6
- # Sequences are defined using Factory.sequence. Sequence values are generated
7
- # using next.
6
+ # Sequences are defined using sequence within a FactoryGirl.define block.
7
+ # Sequence values are generated using next.
8
8
  class Sequence
9
-
10
- def initialize(value = 1, &proc) #:nodoc:
9
+ def initialize(name, value = 1, &proc) #:nodoc:
10
+ @name = name
11
11
  @proc = proc
12
12
  @value = value || 1
13
13
  end
14
14
 
15
15
  # Returns the next value for this sequence
16
- def next
17
- @proc.call(@value)
16
+ def run(proxy_class = nil, overrides = {})
17
+ @proc ? @proc.call(@value) : @value
18
18
  ensure
19
19
  @value = @value.next
20
20
  end
21
21
 
22
+ def next
23
+ puts "WARNING: FactoryGirl::Sequence#next is deprecated."
24
+ puts "Use #run instead."
25
+ run
26
+ end
27
+
28
+ def default_strategy
29
+ :create
30
+ end
31
+
32
+ def names
33
+ [@name]
34
+ end
22
35
  end
23
36
 
24
- class << self
25
- attr_accessor :sequences #:nodoc:
37
+ def self.sequences
38
+ puts "WARNING: FactoryGirl.sequences is deprecated."
39
+ puts "Use FactoryGirl.registry instead."
40
+ registry
26
41
  end
27
- self.sequences = {}
28
42
  end
@@ -1,12 +1,18 @@
1
1
  module FactoryGirlStepHelpers
2
+
2
3
  def convert_association_string_to_instance(factory_name, assignment)
3
4
  attribute, value = assignment.split(':', 2)
4
5
  return if value.blank?
5
- attributes = convert_human_hash_to_attribute_hash(attribute => value.strip)
6
- factory = FactoryGirl.factory_by_name(factory_name)
6
+ factory = FactoryGirl.find(factory_name)
7
+ attributes = convert_human_hash_to_attribute_hash({attribute => value.strip}, factory.associations)
8
+ attributes_find = {}
9
+ attributes.each do |k, v|
10
+ k = "#{k}_id" if v.is_a? ActiveRecord::Base
11
+ attributes_find[k] = v
12
+ end
7
13
  model_class = factory.build_class
8
- model_class.find(:first, :conditions => attributes) or
9
- Factory(factory_name, attributes)
14
+ model_class.find(:first, :conditions => attributes_find) or
15
+ FactoryGirl.create(factory_name, attributes)
10
16
  end
11
17
 
12
18
  def convert_human_hash_to_attribute_hash(human_hash, associations = [])
@@ -22,7 +28,7 @@ end
22
28
 
23
29
  World(FactoryGirlStepHelpers)
24
30
 
25
- FactoryGirl.factories.values.each do |factory|
31
+ FactoryGirl.registry.each do |name, factory|
26
32
  Given /^the following (?:#{factory.human_name}|#{factory.human_name.pluralize}) exists?:$/ do |table|
27
33
  table.hashes.each do |human_hash|
28
34
  attributes = convert_human_hash_to_attribute_hash(human_hash, factory.associations)
@@ -31,23 +37,24 @@ FactoryGirl.factories.values.each do |factory|
31
37
  end
32
38
 
33
39
  Given /^an? #{factory.human_name} exists$/ do
34
- Factory(factory.name)
40
+ FactoryGirl.create(factory.name)
35
41
  end
36
42
 
37
43
  Given /^(\d+) #{factory.human_name.pluralize} exist$/ do |count|
38
- count.to_i.times { Factory(factory.name) }
44
+ count.to_i.times { FactoryGirl.create(factory.name) }
39
45
  end
40
46
 
41
47
  if factory.build_class.respond_to?(:columns)
42
48
  factory.build_class.columns.each do |column|
43
49
  human_column_name = column.name.downcase.gsub('_', ' ')
44
50
  Given /^an? #{factory.human_name} exists with an? #{human_column_name} of "([^"]*)"$/i do |value|
45
- Factory(factory.name, column.name => value)
51
+ FactoryGirl.create(factory.name, column.name => value)
46
52
  end
47
53
 
48
54
  Given /^(\d+) #{factory.human_name.pluralize} exist with an? #{human_column_name} of "([^"]*)"$/i do |count, value|
49
- count.to_i.times { Factory(factory.name, column.name => value) }
55
+ count.to_i.times { FactoryGirl.create(factory.name, column.name => value) }
50
56
  end
51
57
  end
52
58
  end
53
59
  end
60
+
@@ -13,7 +13,7 @@ module FactoryGirl
13
13
  # email { 'billy@bob.example.com' }
14
14
  # end
15
15
  #
16
- # Factory(:user, :name => 'Johnny')
16
+ # FactoryGirl.create(:user, :name => 'Johnny')
17
17
  #
18
18
  # This syntax was derived from Pete Yandell's machinist.
19
19
  module Blueprint
@@ -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_factory(instance)
32
+ FactoryGirl.register(instance)
33
33
  end
34
34
 
35
35
  end
@@ -1,6 +1,8 @@
1
1
  module FactoryGirl
2
2
  module Syntax
3
3
  module Default
4
+ include Methods
5
+
4
6
  def define(&block)
5
7
  DSL.run(block)
6
8
  end
@@ -15,13 +17,13 @@ module FactoryGirl
15
17
  proxy = FactoryGirl::DefinitionProxy.new(factory)
16
18
  proxy.instance_eval(&block)
17
19
  if parent = options.delete(:parent)
18
- factory.inherit_from(FactoryGirl.factory_by_name(parent))
20
+ factory.inherit_from(FactoryGirl.find(parent))
19
21
  end
20
- FactoryGirl.register_factory(factory)
22
+ FactoryGirl.register(factory)
21
23
  end
22
24
 
23
25
  def sequence(name, start_value = 1, &block)
24
- FactoryGirl.sequences[name] = Sequence.new(start_value, &block)
26
+ FactoryGirl.register(Sequence.new(name, start_value, &block))
25
27
  end
26
28
  end
27
29
  end
@@ -15,14 +15,14 @@ module FactoryGirl
15
15
  # end
16
16
  #
17
17
  # # Creates a saved instance without raising (same as saving the result
18
- # # of Factory.build)
18
+ # # of FactoryGirl.build)
19
19
  # User.generate(:name => 'Johnny')
20
20
  #
21
21
  # # Creates a saved instance and raises when invalid (same as
22
- # # Factory.create)
22
+ # # FactoryGirl.create)
23
23
  # User.generate!
24
24
  #
25
- # # Creates an unsaved instance (same as Factory.build)
25
+ # # Creates an unsaved instance (same as FactoryGirl.build)
26
26
  # User.spawn
27
27
  #
28
28
  # # Creates an instance and yields it to the passed block
@@ -42,7 +42,7 @@ module FactoryGirl
42
42
  module ClassMethods #:nodoc:
43
43
 
44
44
  def generate(overrides = {}, &block)
45
- factory = FactoryGirl.factory_by_name(name.underscore)
45
+ factory = FactoryGirl.find(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.factory_by_name(name.underscore)
53
+ factory = FactoryGirl.find(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.factory_by_name(name.underscore)
60
+ factory = FactoryGirl.find(name.underscore)
61
61
  instance = factory.run(Proxy::Build, overrides)
62
62
  yield(instance) if block_given?
63
63
  instance
@@ -2,7 +2,7 @@ module FactoryGirl
2
2
  module Syntax
3
3
 
4
4
  # Extends ActiveRecord::Base to provide a make class method, which is a
5
- # shortcut for Factory.create.
5
+ # shortcut for FactoryGirl.create.
6
6
  #
7
7
  # Usage:
8
8
  #
@@ -28,7 +28,7 @@ module FactoryGirl
28
28
  module ClassMethods #:nodoc:
29
29
 
30
30
  def make(overrides = {})
31
- FactoryGirl.factory_by_name(name.underscore).run(Proxy::Create, overrides)
31
+ FactoryGirl.find(name.underscore).run(Proxy::Create, overrides)
32
32
  end
33
33
 
34
34
  end
@@ -0,0 +1,75 @@
1
+ module FactoryGirl
2
+ module Syntax
3
+ module Methods
4
+ # Generates and returns a Hash of attributes from this factory. Attributes
5
+ # can be individually overridden by passing in a Hash of attribute => value
6
+ # pairs.
7
+ #
8
+ # Arguments:
9
+ # * name: +Symbol+ or +String+
10
+ # The name of the factory that should be used.
11
+ # * overrides: +Hash+
12
+ # Attributes to overwrite for this set.
13
+ #
14
+ # Returns: +Hash+
15
+ # A set of attributes that can be used to build an instance of the class
16
+ # this factory generates.
17
+ def attributes_for(name, overrides = {})
18
+ FactoryGirl.find(name).run(Proxy::AttributesFor, overrides)
19
+ end
20
+
21
+ # Generates and returns an instance from this factory. Attributes can be
22
+ # individually overridden by passing in a Hash of attribute => value pairs.
23
+ #
24
+ # Arguments:
25
+ # * name: +Symbol+ or +String+
26
+ # The name of the factory that should be used.
27
+ # * overrides: +Hash+
28
+ # Attributes to overwrite for this instance.
29
+ #
30
+ # Returns: +Object+
31
+ # An instance of the class this factory generates, with generated attributes
32
+ # assigned.
33
+ def build(name, overrides = {})
34
+ FactoryGirl.find(name).run(Proxy::Build, overrides)
35
+ end
36
+
37
+ # Generates, saves, and returns an instance from this factory. Attributes can
38
+ # be individually overridden by passing in a Hash of attribute => value
39
+ # pairs.
40
+ #
41
+ # Instances are saved using the +save!+ method, so ActiveRecord models will
42
+ # raise ActiveRecord::RecordInvalid exceptions for invalid attribute sets.
43
+ #
44
+ # Arguments:
45
+ # * name: +Symbol+ or +String+
46
+ # The name of the factory that should be used.
47
+ # * overrides: +Hash+
48
+ # Attributes to overwrite for this instance.
49
+ #
50
+ # Returns: +Object+
51
+ # A saved instance of the class this factory generates, with generated
52
+ # attributes assigned.
53
+ def create(name, overrides = {})
54
+ FactoryGirl.find(name).run(Proxy::Create, overrides)
55
+ end
56
+
57
+ # Generates and returns an object with all attributes from this factory
58
+ # stubbed out. Attributes can be individually overridden by passing in a Hash
59
+ # of attribute => value pairs.
60
+ #
61
+ # Arguments:
62
+ # * name: +Symbol+ or +String+
63
+ # The name of the factory that should be used.
64
+ # * overrides: +Hash+
65
+ # Attributes to overwrite for this instance.
66
+ #
67
+ # Returns: +Object+
68
+ # An object with generated attributes stubbed out.
69
+ def build_stubbed(name, overrides = {})
70
+ FactoryGirl.find(name).run(Proxy::Stub, overrides)
71
+ end
72
+
73
+ end
74
+ end
75
+ 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.sequences[name] = Sequence.new(start_value || 1, &block)
30
+ FactoryGirl.register(Sequence.new(name, start_value || 1, &block))
31
31
  else
32
- FactoryGirl.sequences[name].next
32
+ FactoryGirl.find(name).run
33
33
  end
34
34
  end
35
35
 
@@ -2,6 +2,8 @@ module FactoryGirl
2
2
  module Syntax
3
3
  module Vintage
4
4
  module Factory
5
+ extend Syntax::Methods
6
+
5
7
  # Defines a new factory that can be used by the build strategies (create and
6
8
  # build) to build new objects.
7
9
  #
@@ -18,6 +20,7 @@ module FactoryGirl
18
20
  # factory will be copied to the current one with an ability to override
19
21
  # them.
20
22
  # * default_strategy: +Symbol+
23
+ # DEPRECATED.
21
24
  # The strategy that will be used by the Factory shortcut method.
22
25
  # Defaults to :create.
23
26
  #
@@ -28,78 +31,9 @@ module FactoryGirl
28
31
  proxy = FactoryGirl::DefinitionProxy.new(factory)
29
32
  yield(proxy)
30
33
  if parent = options.delete(:parent)
31
- factory.inherit_from(FactoryGirl.factory_by_name(parent))
34
+ factory.inherit_from(FactoryGirl.find(parent))
32
35
  end
33
- FactoryGirl.register_factory(factory)
34
- end
35
-
36
- # Generates and returns a Hash of attributes from this factory. Attributes
37
- # can be individually overridden by passing in a Hash of attribute => value
38
- # pairs.
39
- #
40
- # Arguments:
41
- # * name: +Symbol+ or +String+
42
- # The name of the factory that should be used.
43
- # * overrides: +Hash+
44
- # Attributes to overwrite for this set.
45
- #
46
- # Returns: +Hash+
47
- # A set of attributes that can be used to build an instance of the class
48
- # this factory generates.
49
- def self.attributes_for(name, overrides = {})
50
- FactoryGirl.factory_by_name(name).run(Proxy::AttributesFor, overrides)
51
- end
52
-
53
- # Generates and returns an instance from this factory. Attributes can be
54
- # individually overridden by passing in a Hash of attribute => value pairs.
55
- #
56
- # Arguments:
57
- # * name: +Symbol+ or +String+
58
- # The name of the factory that should be used.
59
- # * overrides: +Hash+
60
- # Attributes to overwrite for this instance.
61
- #
62
- # Returns: +Object+
63
- # An instance of the class this factory generates, with generated attributes
64
- # assigned.
65
- def self.build(name, overrides = {})
66
- FactoryGirl.factory_by_name(name).run(Proxy::Build, overrides)
67
- end
68
-
69
- # Generates, saves, and returns an instance from this factory. Attributes can
70
- # be individually overridden by passing in a Hash of attribute => value
71
- # pairs.
72
- #
73
- # Instances are saved using the +save!+ method, so ActiveRecord models will
74
- # raise ActiveRecord::RecordInvalid exceptions for invalid attribute sets.
75
- #
76
- # Arguments:
77
- # * name: +Symbol+ or +String+
78
- # The name of the factory that should be used.
79
- # * overrides: +Hash+
80
- # Attributes to overwrite for this instance.
81
- #
82
- # Returns: +Object+
83
- # A saved instance of the class this factory generates, with generated
84
- # attributes assigned.
85
- def self.create(name, overrides = {})
86
- FactoryGirl.factory_by_name(name).run(Proxy::Create, overrides)
87
- end
88
-
89
- # Generates and returns an object with all attributes from this factory
90
- # stubbed out. Attributes can be individually overridden by passing in a Hash
91
- # of attribute => value pairs.
92
- #
93
- # Arguments:
94
- # * name: +Symbol+ or +String+
95
- # The name of the factory that should be used.
96
- # * overrides: +Hash+
97
- # Attributes to overwrite for this instance.
98
- #
99
- # Returns: +Object+
100
- # An object with generated attributes stubbed out.
101
- def self.stub(name, overrides = {})
102
- FactoryGirl.factory_by_name(name).run(Proxy::Stub, overrides)
36
+ FactoryGirl.register(factory)
103
37
  end
104
38
 
105
39
  # Executes the default strategy for the given factory. This is usually create,
@@ -114,7 +48,7 @@ module FactoryGirl
114
48
  # Returns: +Object+
115
49
  # The result of the default strategy.
116
50
  def self.default_strategy(name, overrides = {})
117
- self.send(FactoryGirl.factory_by_name(name).default_strategy, name, overrides)
51
+ self.send(FactoryGirl.find(name).default_strategy, name, overrides)
118
52
  end
119
53
 
120
54
  # Defines a new sequence that can be used to generate unique values in a specific format.
@@ -133,7 +67,7 @@ module FactoryGirl
133
67
  #
134
68
  # Factory.sequence(:email) {|n| "somebody_#{n}@example.com" }
135
69
  def self.sequence(name, start_value = 1, &block)
136
- FactoryGirl.sequences[name] = Sequence.new(start_value, &block)
70
+ FactoryGirl.register(Sequence.new(name, start_value, &block))
137
71
  end
138
72
 
139
73
  # Generates and returns the next value in a sequence.
@@ -142,14 +76,12 @@ module FactoryGirl
142
76
  # name: (Symbol)
143
77
  # The name of the sequence that a value should be generated for.
144
78
  #
79
+ # DEPRECATED. Use create instead.
80
+ #
145
81
  # Returns:
146
82
  # The next value in the sequence. (Object)
147
- def self.next(sequence)
148
- unless FactoryGirl.sequences.key?(sequence)
149
- raise "No such sequence: #{sequence}"
150
- end
151
-
152
- FactoryGirl.sequences[sequence].next
83
+ def self.next(name)
84
+ FactoryGirl.find(name).next
153
85
  end
154
86
 
155
87
  # Defines a new alias for attributes.
@@ -180,6 +112,11 @@ module FactoryGirl
180
112
  FactoryGirl.aliases << [pattern, replace]
181
113
  end
182
114
 
115
+ # Alias for build_stubbed. Deprecated.
116
+ def self.stub(name, overrides = {})
117
+ build_stubbed(name, overrides)
118
+ end
119
+
183
120
  end
184
121
 
185
122
  # Shortcut for Factory.default_strategy.