factory_girl 1.3.3 → 2.0.0.beta1

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 (53) hide show
  1. data/README.rdoc +68 -60
  2. data/features/support/test.db +0 -0
  3. data/lib/factory_girl.rb +6 -12
  4. data/lib/factory_girl/aliases.rb +2 -31
  5. data/lib/factory_girl/attribute.rb +1 -1
  6. data/lib/factory_girl/attribute/association.rb +1 -1
  7. data/lib/factory_girl/attribute/callback.rb +1 -1
  8. data/lib/factory_girl/attribute/dynamic.rb +3 -3
  9. data/lib/factory_girl/attribute/static.rb +1 -1
  10. data/lib/factory_girl/definition_proxy.rb +180 -0
  11. data/lib/factory_girl/deprecated.rb +18 -0
  12. data/lib/factory_girl/factory.rb +120 -355
  13. data/lib/factory_girl/find_definitions.rb +25 -0
  14. data/lib/factory_girl/proxy.rb +4 -6
  15. data/lib/factory_girl/proxy/attributes_for.rb +1 -1
  16. data/lib/factory_girl/proxy/build.rb +7 -5
  17. data/lib/factory_girl/proxy/create.rb +1 -1
  18. data/lib/factory_girl/proxy/stub.rb +11 -5
  19. data/lib/factory_girl/rails2.rb +1 -1
  20. data/lib/factory_girl/sequence.rb +5 -40
  21. data/lib/factory_girl/step_definitions.rb +7 -7
  22. data/lib/factory_girl/syntax.rb +7 -7
  23. data/lib/factory_girl/syntax/blueprint.rb +5 -4
  24. data/lib/factory_girl/syntax/default.rb +31 -0
  25. data/lib/factory_girl/syntax/generate.rb +13 -8
  26. data/lib/factory_girl/syntax/make.rb +8 -6
  27. data/lib/factory_girl/syntax/sham.rb +11 -8
  28. data/lib/factory_girl/syntax/vintage.rb +196 -0
  29. data/lib/factory_girl/version.rb +4 -0
  30. data/spec/acceptance/acceptance_spec.rb +43 -60
  31. data/spec/acceptance/syntax/blueprint_spec.rb +1 -5
  32. data/spec/acceptance/syntax/generate_spec.rb +1 -4
  33. data/spec/acceptance/syntax/make_spec.rb +1 -4
  34. data/spec/acceptance/syntax/sham_spec.rb +9 -7
  35. data/spec/acceptance/syntax/vintage_spec.rb +184 -0
  36. data/spec/factory_girl/aliases_spec.rb +5 -5
  37. data/spec/factory_girl/attribute/association_spec.rb +3 -3
  38. data/spec/factory_girl/attribute/callback_spec.rb +3 -3
  39. data/spec/factory_girl/attribute/dynamic_spec.rb +20 -9
  40. data/spec/factory_girl/attribute/static_spec.rb +5 -5
  41. data/spec/factory_girl/attribute_spec.rb +5 -5
  42. data/spec/factory_girl/definition_proxy_spec.rb +138 -0
  43. data/spec/factory_girl/deprecated_spec.rb +66 -0
  44. data/spec/factory_girl/factory_spec.rb +283 -566
  45. data/spec/factory_girl/find_definitions_spec.rb +89 -0
  46. data/spec/factory_girl/proxy/attributes_for_spec.rb +2 -2
  47. data/spec/factory_girl/proxy/build_spec.rb +17 -12
  48. data/spec/factory_girl/proxy/create_spec.rb +17 -12
  49. data/spec/factory_girl/proxy/stub_spec.rb +6 -5
  50. data/spec/factory_girl/proxy_spec.rb +2 -2
  51. data/spec/factory_girl/sequence_spec.rb +15 -38
  52. data/spec/spec_helper.rb +4 -0
  53. metadata +28 -11
@@ -0,0 +1,25 @@
1
+ module FactoryGirl
2
+
3
+ class << self
4
+ attr_accessor :factories #:nodoc:
5
+
6
+ # An Array of strings specifying locations that should be searched for
7
+ # factory definitions. By default, factory_girl will attempt to require
8
+ # "factories," "test/factories," and "spec/factories." Only the first
9
+ # existing file will be loaded.
10
+ attr_accessor :definition_file_paths
11
+ end
12
+ self.definition_file_paths = %w(factories test/factories spec/factories)
13
+
14
+ def self.find_definitions #:nodoc:
15
+ definition_file_paths.each do |path|
16
+ require("#{path}.rb") if File.exists?("#{path}.rb")
17
+
18
+ if File.directory? path
19
+ Dir[File.join(path, '*.rb')].sort.each do |file|
20
+ require file
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,5 +1,4 @@
1
- class Factory
2
-
1
+ module FactoryGirl
3
2
  class Proxy #:nodoc:
4
3
 
5
4
  attr_reader :callbacks
@@ -47,13 +46,13 @@ class Factory
47
46
  #
48
47
  # Example:
49
48
  #
50
- # Factory.define :user do |f|
49
+ # factory :user do
51
50
  # # ...
52
51
  # end
53
52
  #
54
- # Factory.define :post do |f|
53
+ # factory :post do
55
54
  # # ...
56
- # f.author {|a| a.association :user, :name => 'Joe' }
55
+ # author { |post| post.association(:user, :name => 'Joe') }
57
56
  # end
58
57
  #
59
58
  # # Builds (but doesn't save) a Post and a User
@@ -75,5 +74,4 @@ class Factory
75
74
  raise NotImplementedError, "Strategies must return a result"
76
75
  end
77
76
  end
78
-
79
77
  end
@@ -1,4 +1,4 @@
1
- class Factory
1
+ module FactoryGirl
2
2
  class Proxy #:nodoc:
3
3
  class AttributesFor < Proxy #:nodoc:
4
4
  def initialize(klass)
@@ -1,4 +1,4 @@
1
- class Factory
1
+ module FactoryGirl
2
2
  class Proxy #:nodoc:
3
3
  class Build < Proxy #:nodoc:
4
4
  def initialize(klass)
@@ -13,12 +13,14 @@ class Factory
13
13
  @instance.send(:"#{attribute}=", value)
14
14
  end
15
15
 
16
- def associate(name, factory, attributes)
17
- set(name, Factory.create(factory, attributes))
16
+ def associate(name, factory_name, overrides)
17
+ factory = FactoryGirl.factory_by_name(factory_name)
18
+ set(name, factory.run(Proxy::Create, overrides))
18
19
  end
19
20
 
20
- def association(factory, overrides = {})
21
- Factory.create(factory, overrides)
21
+ def association(factory_name, overrides = {})
22
+ factory = FactoryGirl.factory_by_name(factory_name)
23
+ factory.run(Proxy::Create, overrides)
22
24
  end
23
25
 
24
26
  def result
@@ -1,4 +1,4 @@
1
- class Factory
1
+ module FactoryGirl
2
2
  class Proxy #:nodoc:
3
3
  class Create < Build #:nodoc:
4
4
  def result
@@ -1,4 +1,4 @@
1
- class Factory
1
+ module FactoryGirl
2
2
  class Proxy
3
3
  class Stub < Proxy #:nodoc:
4
4
  @@next_id = 1000
@@ -26,6 +26,10 @@ class Factory
26
26
  def reload
27
27
  raise "stubbed models are not allowed to access the database"
28
28
  end
29
+
30
+ def update_attribute(*args)
31
+ raise "stubbed models are not allowed to access the database"
32
+ end
29
33
  end
30
34
  end
31
35
 
@@ -41,12 +45,14 @@ class Factory
41
45
  @instance.send(:"#{attribute}=", value)
42
46
  end
43
47
 
44
- def associate(name, factory, attributes)
45
- set(name, Factory.stub(factory, attributes))
48
+ def associate(name, factory_name, overrides)
49
+ factory = FactoryGirl.factory_by_name(factory_name)
50
+ set(name, factory.run(Proxy::Stub, overrides))
46
51
  end
47
52
 
48
- def association(factory, overrides = {})
49
- Factory.stub(factory, overrides)
53
+ def association(factory_name, overrides = {})
54
+ factory = FactoryGirl.factory_by_name(factory_name)
55
+ factory.run(Proxy::Stub, overrides)
50
56
  end
51
57
 
52
58
  def result
@@ -1 +1 @@
1
- Rails.configuration.after_initialize { Factory.find_definitions }
1
+ Rails.configuration.after_initialize { FactoryGirl.find_definitions }
@@ -1,4 +1,4 @@
1
- class Factory
1
+ module FactoryGirl
2
2
 
3
3
  # Raised when calling Factory.sequence from a dynamic attribute block
4
4
  class SequenceAbuseError < StandardError; end
@@ -7,15 +7,16 @@ class Factory
7
7
  # using next.
8
8
  class Sequence
9
9
 
10
- def initialize (&proc) #:nodoc:
10
+ def initialize(value = 1, &proc) #:nodoc:
11
11
  @proc = proc
12
- @value = 0
12
+ @value = value || 1
13
13
  end
14
14
 
15
15
  # Returns the next value for this sequence
16
16
  def next
17
- @value += 1
18
17
  @proc.call(@value)
18
+ ensure
19
+ @value = @value.next
19
20
  end
20
21
 
21
22
  end
@@ -24,40 +25,4 @@ class Factory
24
25
  attr_accessor :sequences #:nodoc:
25
26
  end
26
27
  self.sequences = {}
27
-
28
- # Defines a new sequence that can be used to generate unique values in a specific format.
29
- #
30
- # Arguments:
31
- # name: (Symbol)
32
- # A unique name for this sequence. This name will be referenced when
33
- # calling next to generate new values from this sequence.
34
- # block: (Proc)
35
- # The code to generate each value in the sequence. This block will be
36
- # called with a unique number each time a value in the sequence is to be
37
- # generated. The block should return the generated value for the
38
- # sequence.
39
- #
40
- # Example:
41
- #
42
- # Factory.sequence(:email) {|n| "somebody_#{n}@example.com" }
43
- def self.sequence (name, &block)
44
- self.sequences[name] = Sequence.new(&block)
45
- end
46
-
47
- # Generates and returns the next value in a sequence.
48
- #
49
- # Arguments:
50
- # name: (Symbol)
51
- # The name of the sequence that a value should be generated for.
52
- #
53
- # Returns:
54
- # The next value in the sequence. (Object)
55
- def self.next (sequence)
56
- unless self.sequences.key?(sequence)
57
- raise "No such sequence: #{sequence}"
58
- end
59
-
60
- self.sequences[sequence].next
61
- end
62
-
63
28
  end
@@ -3,7 +3,7 @@ module FactoryGirlStepHelpers
3
3
  attribute, value = assignment.split(':', 2)
4
4
  return if value.blank?
5
5
  attributes = convert_human_hash_to_attribute_hash(attribute => value.strip)
6
- factory = Factory.factory_by_name(factory_name)
6
+ factory = FactoryGirl.factory_by_name(factory_name)
7
7
  model_class = factory.build_class
8
8
  model_class.find(:first, :conditions => attributes) or
9
9
  Factory(factory_name, attributes)
@@ -22,31 +22,31 @@ end
22
22
 
23
23
  World(FactoryGirlStepHelpers)
24
24
 
25
- Factory.factories.values.each do |factory|
25
+ FactoryGirl.factories.values.each do |factory|
26
26
  Given /^the following (?:#{factory.human_name}|#{factory.human_name.pluralize}) exists?:$/ do |table|
27
27
  table.hashes.each do |human_hash|
28
28
  attributes = convert_human_hash_to_attribute_hash(human_hash, factory.associations)
29
- Factory.create(factory.factory_name, attributes)
29
+ factory.run(FactoryGirl::Proxy::Create, attributes)
30
30
  end
31
31
  end
32
32
 
33
33
  Given /^an? #{factory.human_name} exists$/ do
34
- Factory(factory.factory_name)
34
+ Factory(factory.name)
35
35
  end
36
36
 
37
37
  Given /^(\d+) #{factory.human_name.pluralize} exist$/ do |count|
38
- count.to_i.times { Factory(factory.factory_name) }
38
+ count.to_i.times { Factory(factory.name) }
39
39
  end
40
40
 
41
41
  if factory.build_class.respond_to?(:columns)
42
42
  factory.build_class.columns.each do |column|
43
43
  human_column_name = column.name.downcase.gsub('_', ' ')
44
44
  Given /^an? #{factory.human_name} exists with an? #{human_column_name} of "([^"]*)"$/i do |value|
45
- Factory(factory.factory_name, column.name => value)
45
+ Factory(factory.name, column.name => value)
46
46
  end
47
47
 
48
48
  Given /^(\d+) #{factory.human_name.pluralize} exist with an? #{human_column_name} of "([^"]*)"$/i do |count, value|
49
- count.to_i.times { Factory(factory.factory_name, column.name => value) }
49
+ count.to_i.times { Factory(factory.name, column.name => value) }
50
50
  end
51
51
  end
52
52
  end
@@ -1,12 +1,12 @@
1
- class Factory
1
+ module FactoryGirl
2
2
  # Provides alternate syntaxes for factory_girl. If you don't like the default
3
- # syntax for defining or using factories, look at one of the Factory::Syntax
4
- # modules:
3
+ # syntax for defining or using factories, look at one of the
4
+ # FactoryGirl::Syntax modules:
5
5
  #
6
- # * Factory::Syntax::Blueprint: definition syntax similar to Machinist
7
- # * Factory::Syntax::Generate: usage syntax similar to Object Daddy
8
- # * Factory::Syntax::Make: usage syntax similar to Machinist
9
- # * Factory::Syntax::Sham: sequence syntax similar to Machinist
6
+ # * FactoryGirl::Syntax::Blueprint: definition syntax similar to Machinist
7
+ # * FactoryGirl::Syntax::Generate: usage syntax similar to Object Daddy
8
+ # * FactoryGirl::Syntax::Make: usage syntax similar to Machinist
9
+ # * FactoryGirl::Syntax::Sham: sequence syntax similar to Machinist
10
10
  module Syntax
11
11
  end
12
12
  end
@@ -1,4 +1,4 @@
1
- class Factory
1
+ module FactoryGirl
2
2
  module Syntax
3
3
 
4
4
  # Extends ActiveRecord::Base to provide a make class method, which is an
@@ -27,8 +27,9 @@ class Factory
27
27
 
28
28
  def blueprint(&block)
29
29
  instance = Factory.new(name.underscore, :class => self)
30
- instance.instance_eval(&block)
31
- Factory.factories[instance.factory_name] = instance
30
+ proxy = FactoryGirl::DefinitionProxy.new(instance)
31
+ proxy.instance_eval(&block)
32
+ FactoryGirl.register_factory(instance)
32
33
  end
33
34
 
34
35
  end
@@ -38,4 +39,4 @@ class Factory
38
39
  end
39
40
  end
40
41
 
41
- ActiveRecord::Base.send(:include, Factory::Syntax::Blueprint::ActiveRecord)
42
+ ActiveRecord::Base.send(:include, FactoryGirl::Syntax::Blueprint::ActiveRecord)
@@ -0,0 +1,31 @@
1
+ module FactoryGirl
2
+ module Syntax
3
+ module Default
4
+ def define(&block)
5
+ DSL.run(block)
6
+ end
7
+
8
+ class DSL
9
+ def self.run(block)
10
+ new.instance_eval(&block)
11
+ end
12
+
13
+ def factory(name, options = {}, &block)
14
+ factory = Factory.new(name, options)
15
+ proxy = FactoryGirl::DefinitionProxy.new(factory)
16
+ proxy.instance_eval(&block)
17
+ if parent = options.delete(:parent)
18
+ factory.inherit_from(FactoryGirl.factory_by_name(parent))
19
+ end
20
+ FactoryGirl.register_factory(factory)
21
+ end
22
+
23
+ def sequence(name, start_value = 1, &block)
24
+ FactoryGirl.sequences[name] = Sequence.new(start_value, &block)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ extend Syntax::Default
31
+ end
@@ -1,4 +1,4 @@
1
- class Factory
1
+ module FactoryGirl
2
2
  module Syntax
3
3
 
4
4
  # Extends ActiveRecord::Base to provide generation methods for factories.
@@ -7,9 +7,11 @@ class Factory
7
7
  #
8
8
  # require 'factory_girl/syntax/generate'
9
9
  #
10
- # Factory.define :user do |factory|
11
- # factory.name 'Billy Bob'
12
- # factory.email 'billy@bob.example.com'
10
+ # FactoryGirl.define do
11
+ # factory :user do
12
+ # name 'Billy Bob'
13
+ # email 'billy@bob.example.com'
14
+ # end
13
15
  # end
14
16
  #
15
17
  # # Creates a saved instance without raising (same as saving the result
@@ -40,20 +42,23 @@ class Factory
40
42
  module ClassMethods #:nodoc:
41
43
 
42
44
  def generate(overrides = {}, &block)
43
- instance = Factory.build(name.underscore, overrides)
45
+ factory = FactoryGirl.factory_by_name(name.underscore)
46
+ instance = factory.run(Proxy::Build, overrides)
44
47
  instance.save
45
48
  yield(instance) if block_given?
46
49
  instance
47
50
  end
48
51
 
49
52
  def generate!(overrides = {}, &block)
50
- instance = Factory.create(name.underscore, overrides)
53
+ factory = FactoryGirl.factory_by_name(name.underscore)
54
+ instance = factory.run(Proxy::Create, overrides)
51
55
  yield(instance) if block_given?
52
56
  instance
53
57
  end
54
58
 
55
59
  def spawn(overrides = {}, &block)
56
- instance = Factory.build(name.underscore, overrides)
60
+ factory = FactoryGirl.factory_by_name(name.underscore)
61
+ instance = factory.run(Proxy::Build, overrides)
57
62
  yield(instance) if block_given?
58
63
  instance
59
64
  end
@@ -65,4 +70,4 @@ class Factory
65
70
  end
66
71
  end
67
72
 
68
- ActiveRecord::Base.send(:include, Factory::Syntax::Generate::ActiveRecord)
73
+ ActiveRecord::Base.send(:include, FactoryGirl::Syntax::Generate::ActiveRecord)
@@ -1,4 +1,4 @@
1
- class Factory
1
+ module FactoryGirl
2
2
  module Syntax
3
3
 
4
4
  # Extends ActiveRecord::Base to provide a make class method, which is a
@@ -8,9 +8,11 @@ class Factory
8
8
  #
9
9
  # require 'factory_girl/syntax/make'
10
10
  #
11
- # Factory.define :user do |factory|
12
- # factory.name 'Billy Bob'
13
- # factory.email 'billy@bob.example.com'
11
+ # FactoryGirl.define do
12
+ # factory :user do
13
+ # name 'Billy Bob'
14
+ # email 'billy@bob.example.com'
15
+ # end
14
16
  # end
15
17
  #
16
18
  # User.make(:name => 'Johnny')
@@ -26,7 +28,7 @@ class Factory
26
28
  module ClassMethods #:nodoc:
27
29
 
28
30
  def make(overrides = {})
29
- Factory.create(name.underscore, overrides)
31
+ FactoryGirl.factory_by_name(name.underscore).run(Proxy::Create, overrides)
30
32
  end
31
33
 
32
34
  end
@@ -36,4 +38,4 @@ class Factory
36
38
  end
37
39
  end
38
40
 
39
- ActiveRecord::Base.send(:include, Factory::Syntax::Make::ActiveRecord)
41
+ ActiveRecord::Base.send(:include, FactoryGirl::Syntax::Make::ActiveRecord)
@@ -1,8 +1,8 @@
1
- class Factory
1
+ module FactoryGirl
2
2
  module Syntax
3
3
 
4
4
  # Adds a Sham module, which provides an alternate interface to
5
- # Factory::Sequence.
5
+ # FactoryGirl::Sequence.
6
6
  #
7
7
  # Usage:
8
8
  #
@@ -10,8 +10,10 @@ class Factory
10
10
  #
11
11
  # Sham.email {|n| "somebody#{n}@example.com" }
12
12
  #
13
- # Factory.define :user do |factory|
14
- # factory.email { Sham.email }
13
+ # FactoryGirl.define do
14
+ # factory :user do
15
+ # email
16
+ # end
15
17
  # end
16
18
  #
17
19
  # Note that you can also use Faker, but it is recommended that you simply
@@ -22,11 +24,12 @@ class Factory
22
24
  # This syntax was derived from Pete Yandell's machinist.
23
25
  module Sham
24
26
  module Sham #:nodoc:
25
- def self.method_missing(name, &block)
27
+ def self.method_missing(name, *args, &block)
26
28
  if block_given?
27
- Factory.sequence(name, &block)
29
+ start_value = args.first
30
+ FactoryGirl.sequences[name] = Sequence.new(start_value || 1, &block)
28
31
  else
29
- Factory.next(name)
32
+ FactoryGirl.sequences[name].next
30
33
  end
31
34
  end
32
35
 
@@ -39,4 +42,4 @@ class Factory
39
42
  end
40
43
  end
41
44
 
42
- include Factory::Syntax::Sham
45
+ include FactoryGirl::Syntax::Sham