factory_girl 1.3.3 → 2.0.0.beta1

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