factory_girl 2.0.0.beta1 → 2.0.0.beta2

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