factory_girl 3.2.0 → 3.3.0

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 (80) hide show
  1. data/Appraisals +3 -3
  2. data/GETTING_STARTED.md +74 -15
  3. data/Gemfile.lock +38 -44
  4. data/NEWS +12 -0
  5. data/gemfiles/3.0.gemfile +1 -1
  6. data/gemfiles/3.0.gemfile.lock +23 -24
  7. data/gemfiles/3.1.gemfile +1 -1
  8. data/gemfiles/3.1.gemfile.lock +19 -19
  9. data/gemfiles/3.2.gemfile +1 -1
  10. data/gemfiles/3.2.gemfile.lock +10 -10
  11. data/lib/factory_girl.rb +39 -37
  12. data/lib/factory_girl/aliases.rb +3 -4
  13. data/lib/factory_girl/attribute.rb +33 -11
  14. data/lib/factory_girl/attribute/association.rb +3 -2
  15. data/lib/factory_girl/attribute/dynamic.rb +3 -2
  16. data/lib/factory_girl/attribute/sequence.rb +1 -2
  17. data/lib/factory_girl/attribute/static.rb +3 -2
  18. data/lib/factory_girl/attribute_assigner.rb +6 -5
  19. data/lib/factory_girl/attribute_list.rb +16 -3
  20. data/lib/factory_girl/callback.rb +7 -3
  21. data/lib/factory_girl/callbacks_observer.rb +1 -0
  22. data/lib/factory_girl/configuration.rb +24 -0
  23. data/lib/factory_girl/declaration.rb +5 -4
  24. data/lib/factory_girl/declaration/association.rb +1 -0
  25. data/lib/factory_girl/declaration/dynamic.rb +1 -0
  26. data/lib/factory_girl/declaration/implicit.rb +1 -0
  27. data/lib/factory_girl/declaration/static.rb +1 -0
  28. data/lib/factory_girl/declaration_list.rb +1 -0
  29. data/lib/factory_girl/definition.rb +22 -3
  30. data/lib/factory_girl/definition_list.rb +31 -0
  31. data/lib/factory_girl/definition_proxy.rb +19 -4
  32. data/lib/factory_girl/evaluation.rb +3 -3
  33. data/lib/factory_girl/evaluator.rb +24 -14
  34. data/lib/factory_girl/evaluator_class_definer.rb +2 -13
  35. data/lib/factory_girl/factory.rb +22 -24
  36. data/lib/factory_girl/factory_runner.rb +6 -3
  37. data/lib/factory_girl/find_definitions.rb +2 -2
  38. data/lib/factory_girl/null_factory.rb +3 -1
  39. data/lib/factory_girl/null_object.rb +1 -0
  40. data/lib/factory_girl/reload.rb +4 -6
  41. data/lib/factory_girl/sequence.rb +3 -2
  42. data/lib/factory_girl/step_definitions.rb +1 -0
  43. data/lib/factory_girl/strategy/attributes_for.rb +1 -1
  44. data/lib/factory_girl/strategy/stub.rb +6 -6
  45. data/lib/factory_girl/strategy_calculator.rb +1 -0
  46. data/lib/factory_girl/strategy_syntax_method_registrar.rb +37 -0
  47. data/lib/factory_girl/syntax.rb +5 -4
  48. data/lib/factory_girl/syntax/blueprint.rb +5 -8
  49. data/lib/factory_girl/syntax/default.rb +18 -6
  50. data/lib/factory_girl/syntax/generate.rb +10 -13
  51. data/lib/factory_girl/syntax/make.rb +8 -11
  52. data/lib/factory_girl/syntax/methods.rb +76 -36
  53. data/lib/factory_girl/syntax/sham.rb +3 -2
  54. data/lib/factory_girl/syntax/vintage.rb +9 -9
  55. data/lib/factory_girl/syntax_runner.rb +1 -0
  56. data/lib/factory_girl/trait.rb +5 -4
  57. data/lib/factory_girl/version.rb +1 -2
  58. data/spec/acceptance/activesupport_instrumentation_spec.rb +15 -2
  59. data/spec/acceptance/callbacks_spec.rb +113 -9
  60. data/spec/acceptance/create_list_spec.rb +1 -1
  61. data/spec/acceptance/global_initialize_with_spec.rb +82 -0
  62. data/spec/acceptance/global_to_create_spec.rb +122 -0
  63. data/spec/acceptance/modify_factories_spec.rb +2 -2
  64. data/spec/acceptance/parent_spec.rb +1 -1
  65. data/spec/acceptance/register_strategies_spec.rb +8 -0
  66. data/spec/acceptance/syntax/vintage_spec.rb +8 -8
  67. data/spec/acceptance/traits_spec.rb +145 -3
  68. data/spec/acceptance/transient_attributes_spec.rb +1 -1
  69. data/spec/factory_girl/attribute_list_spec.rb +66 -1
  70. data/spec/factory_girl/attribute_spec.rb +1 -1
  71. data/spec/factory_girl/definition_proxy_spec.rb +6 -6
  72. data/spec/factory_girl/definition_spec.rb +22 -16
  73. data/spec/factory_girl/factory_spec.rb +6 -4
  74. data/spec/factory_girl/strategy/build_spec.rb +2 -2
  75. data/spec/factory_girl/strategy/create_spec.rb +1 -1
  76. data/spec/factory_girl/strategy/stub_spec.rb +2 -2
  77. data/spec/factory_girl/strategy_calculator_spec.rb +20 -14
  78. data/spec/support/shared_examples/strategy.rb +8 -9
  79. metadata +94 -29
  80. data/gemfiles/2.3.gemfile +0 -7
@@ -1,5 +1,4 @@
1
1
  module FactoryGirl
2
-
3
2
  class << self
4
3
  # An Array of strings specifying locations that should be searched for
5
4
  # factory definitions. By default, factory_girl will attempt to require
@@ -7,9 +6,10 @@ module FactoryGirl
7
6
  # existing file will be loaded.
8
7
  attr_accessor :definition_file_paths
9
8
  end
9
+
10
10
  self.definition_file_paths = %w(factories test/factories spec/factories)
11
11
 
12
- def self.find_definitions #:nodoc:
12
+ def self.find_definitions
13
13
  absolute_definition_file_paths = definition_file_paths.map {|path| File.expand_path(path) }
14
14
 
15
15
  absolute_definition_file_paths.uniq.each do |path|
@@ -1,4 +1,5 @@
1
1
  module FactoryGirl
2
+ # @api private
2
3
  class NullFactory
3
4
  attr_reader :definition
4
5
 
@@ -6,7 +7,8 @@ module FactoryGirl
6
7
  @definition = Definition.new
7
8
  end
8
9
 
9
- delegate :defined_traits, :callbacks, :attributes, :constructor, to: :definition
10
+ delegate :defined_traits, :callbacks, :attributes, :constructor,
11
+ :compiled_to_create, :compiled_constructor, to: :definition
10
12
 
11
13
  def compile; end
12
14
  def class_name; end
@@ -1,4 +1,5 @@
1
1
  module FactoryGirl
2
+ # @api private
2
3
  class NullObject < ::BasicObject
3
4
  def initialize(methods_to_respond_to)
4
5
  @methods_to_respond_to = methods_to_respond_to.map(&:to_s)
@@ -1,10 +1,8 @@
1
1
  module FactoryGirl
2
2
  def self.reload
3
- self.factories.clear
4
- self.sequences.clear
5
- self.traits.clear
6
- self.strategies.clear
7
- self.register_default_strategies
8
- self.find_definitions
3
+ reset_configuration
4
+ register_default_strategies
5
+ register_default_callbacks
6
+ find_definitions
9
7
  end
10
8
  end
@@ -2,16 +2,17 @@ module FactoryGirl
2
2
 
3
3
  # Sequences are defined using sequence within a FactoryGirl.define block.
4
4
  # Sequence values are generated using next.
5
+ # @api private
5
6
  class Sequence
6
7
  attr_reader :name
7
8
 
8
- def initialize(name, *args, &proc) #:nodoc:
9
+ def initialize(name, *args, &proc)
9
10
  @name = name
10
11
  @proc = proc
11
12
 
12
13
  options = args.extract_options!
13
14
  @value = args.first || 1
14
- @aliases = options[:aliases] || []
15
+ @aliases = options.fetch(:aliases) { [] }
15
16
  end
16
17
 
17
18
  def next
@@ -1,3 +1,4 @@
1
+ # @api private
1
2
  module FactoryGirlStepHelpers
2
3
  def convert_human_hash_to_attribute_hash(human_hash, associations = [])
3
4
  HumanHashToAttributeHash.new(human_hash, associations).attributes
@@ -2,7 +2,7 @@ module FactoryGirl
2
2
  module Strategy
3
3
  class AttributesFor
4
4
  def association(runner)
5
- runner.run(Strategy::Null)
5
+ runner.run(:null)
6
6
  end
7
7
 
8
8
  def result(evaluation)
@@ -4,7 +4,7 @@ module FactoryGirl
4
4
  @@next_id = 1000
5
5
 
6
6
  def association(runner)
7
- runner.run(Strategy::Stub)
7
+ runner.run(:build_stubbed)
8
8
  end
9
9
 
10
10
  def result(evaluation)
@@ -36,23 +36,23 @@ module FactoryGirl
36
36
  end
37
37
 
38
38
  def save(*args)
39
- raise "stubbed models are not allowed to access the database"
39
+ raise 'stubbed models are not allowed to access the database'
40
40
  end
41
41
 
42
42
  def destroy(*args)
43
- raise "stubbed models are not allowed to access the database"
43
+ raise 'stubbed models are not allowed to access the database'
44
44
  end
45
45
 
46
46
  def connection
47
- raise "stubbed models are not allowed to access the database"
47
+ raise 'stubbed models are not allowed to access the database'
48
48
  end
49
49
 
50
50
  def reload
51
- raise "stubbed models are not allowed to access the database"
51
+ raise 'stubbed models are not allowed to access the database'
52
52
  end
53
53
 
54
54
  def update_attribute(*args)
55
- raise "stubbed models are not allowed to access the database"
55
+ raise 'stubbed models are not allowed to access the database'
56
56
  end
57
57
  end
58
58
  end
@@ -1,4 +1,5 @@
1
1
  module FactoryGirl
2
+ # @api private
2
3
  class StrategyCalculator
3
4
  def initialize(name_or_object)
4
5
  @name_or_object = name_or_object
@@ -0,0 +1,37 @@
1
+ module FactoryGirl
2
+ # @api private
3
+ class StrategySyntaxMethodRegistrar
4
+ def initialize(strategy_name)
5
+ @strategy_name = strategy_name
6
+ end
7
+
8
+ def define_strategy_methods
9
+ define_singular_strategy_method
10
+ define_list_strategy_method
11
+ end
12
+
13
+ private
14
+
15
+ def define_singular_strategy_method
16
+ strategy_name = @strategy_name
17
+
18
+ define_syntax_method(strategy_name) do |name, *traits_and_overrides, &block|
19
+ FactoryRunner.new(name, strategy_name, traits_and_overrides).run(&block)
20
+ end
21
+ end
22
+
23
+ def define_list_strategy_method
24
+ strategy_name = @strategy_name
25
+
26
+ define_syntax_method("#{strategy_name}_list") do |name, amount, *traits_and_overrides|
27
+ amount.times.map { send(strategy_name, name, *traits_and_overrides) }
28
+ end
29
+ end
30
+
31
+ def define_syntax_method(name, &block)
32
+ FactoryGirl::Syntax::Methods.module_exec do
33
+ define_method(name, &block)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,7 +1,8 @@
1
- require "active_support/deprecation"
2
- require "factory_girl/syntax/methods"
3
- require "factory_girl/syntax/default"
4
- require "factory_girl/syntax/vintage"
1
+ require 'active_support/deprecation'
2
+
3
+ require 'factory_girl/syntax/methods'
4
+ require 'factory_girl/syntax/default'
5
+ require 'factory_girl/syntax/vintage'
5
6
 
6
7
  module FactoryGirl
7
8
  # Provides alternate syntaxes for factory_girl. If you don't like the default
@@ -16,25 +16,22 @@ module FactoryGirl
16
16
  # FactoryGirl.create(:user, name: 'Johnny')
17
17
  #
18
18
  # This syntax was derived from Pete Yandell's machinist.
19
+ # @api private
19
20
  module Blueprint
20
- module ActiveRecord #:nodoc:
21
-
22
- def self.included(base) # :nodoc:
21
+ module ActiveRecord
22
+ def self.included(base)
23
23
  base.extend ClassMethods
24
24
  end
25
25
 
26
- module ClassMethods #:nodoc:
27
-
26
+ module ClassMethods
28
27
  def blueprint(&block)
29
- ActiveSupport::Deprecation.warn "Model.blueprint is deprecated; use the FactoryGirl.define syntax instead", caller
28
+ ActiveSupport::Deprecation.warn 'Model.blueprint is deprecated; use the FactoryGirl.define syntax instead', caller
30
29
  instance = Factory.new(name.underscore, class: self)
31
30
  proxy = FactoryGirl::DefinitionProxy.new(instance)
32
31
  proxy.instance_eval(&block)
33
32
  FactoryGirl.register_factory(instance)
34
33
  end
35
-
36
34
  end
37
-
38
35
  end
39
36
  end
40
37
  end
@@ -12,10 +12,6 @@ module FactoryGirl
12
12
  end
13
13
 
14
14
  class DSL
15
- def self.run(block)
16
- new.instance_eval(&block)
17
- end
18
-
19
15
  def factory(name, options = {}, &block)
20
16
  factory = Factory.new(name, options)
21
17
  proxy = FactoryGirl::DefinitionProxy.new(factory.definition)
@@ -36,18 +32,34 @@ module FactoryGirl
36
32
  def trait(name, &block)
37
33
  FactoryGirl.register_trait(Trait.new(name, &block))
38
34
  end
39
- end
40
35
 
41
- class ModifyDSL
36
+ def to_create(&block)
37
+ FactoryGirl.to_create(&block)
38
+ end
39
+
40
+ def skip_create
41
+ FactoryGirl.skip_create
42
+ end
43
+
44
+ def initialize_with(&block)
45
+ FactoryGirl.initialize_with(&block)
46
+ end
47
+
42
48
  def self.run(block)
43
49
  new.instance_eval(&block)
44
50
  end
51
+ end
45
52
 
53
+ class ModifyDSL
46
54
  def factory(name, options = {}, &block)
47
55
  factory = FactoryGirl.factory_by_name(name)
48
56
  proxy = FactoryGirl::DefinitionProxy.new(factory.definition.overridable)
49
57
  proxy.instance_eval(&block)
50
58
  end
59
+
60
+ def self.run(block)
61
+ new.instance_eval(&block)
62
+ end
51
63
  end
52
64
  end
53
65
  end
@@ -32,39 +32,36 @@ module FactoryGirl
32
32
  #
33
33
  # This syntax was derived from Rick Bradley and Yossef Mendelssohn's
34
34
  # object_daddy.
35
+ # @api private
35
36
  module Generate
36
- module ActiveRecord #:nodoc:
37
-
38
- def self.included(base) # :nodoc:
37
+ module ActiveRecord
38
+ def self.included(base)
39
39
  base.extend ClassMethods
40
40
  end
41
41
 
42
- module ClassMethods #:nodoc:
43
-
42
+ module ClassMethods
44
43
  def generate(overrides = {}, &block)
45
- ActiveSupport::Deprecation.warn "Model.generate is deprecated; use the FactoryGirl.define syntax instead", caller
46
- instance = FactoryRunner.new(name.underscore, FactoryGirl.strategy_by_name(:build), [overrides]).run
44
+ ActiveSupport::Deprecation.warn 'Model.generate is deprecated; use FactoryGirl.build(:name) instead.', caller
45
+ instance = FactoryRunner.new(name.underscore, :build, [overrides]).run
47
46
  instance.save
48
47
  yield(instance) if block_given?
49
48
  instance
50
49
  end
51
50
 
52
51
  def generate!(overrides = {}, &block)
53
- ActiveSupport::Deprecation.warn "Model.generate! is deprecated; use the FactoryGirl.define syntax instead", caller
54
- instance = FactoryRunner.new(name.underscore, FactoryGirl.strategy_by_name(:create), [overrides]).run
52
+ ActiveSupport::Deprecation.warn 'Model.generate! is deprecated; use FactoryGirl.create(:name) instead.', caller
53
+ instance = FactoryRunner.new(name.underscore, :create, [overrides]).run
55
54
  yield(instance) if block_given?
56
55
  instance
57
56
  end
58
57
 
59
58
  def spawn(overrides = {}, &block)
60
- ActiveSupport::Deprecation.warn "Model.spawn is deprecated; use the FactoryGirl.define syntax instead", caller
61
- instance = FactoryRunner.new(name.underscore, FactoryGirl.strategy_by_name(:build), [overrides]).run
59
+ ActiveSupport::Deprecation.warn 'Model.spawn is deprecated; use FactoryGirl.build(:name) instead.', caller
60
+ instance = FactoryRunner.new(name.underscore, :build, [overrides]).run
62
61
  yield(instance) if block_given?
63
62
  instance
64
63
  end
65
-
66
64
  end
67
-
68
65
  end
69
66
  end
70
67
  end
@@ -18,27 +18,24 @@ module FactoryGirl
18
18
  # User.make(name: 'Johnny')
19
19
  #
20
20
  # This syntax was derived from Pete Yandell's machinist.
21
+ # @api private
21
22
  module Make
22
- module ActiveRecord #:nodoc:
23
-
24
- def self.included(base) # :nodoc:
23
+ module ActiveRecord
24
+ def self.included(base)
25
25
  base.extend ClassMethods
26
26
  end
27
27
 
28
- module ClassMethods #:nodoc:
29
-
28
+ module ClassMethods
30
29
  def make(overrides = {})
31
- ActiveSupport::Deprecation.warn "Model.make is deprecated; use the FactoryGirl.define syntax instead", caller
32
- FactoryRunner.new(name.underscore, FactoryGirl.strategy_by_name(:build), [overrides]).run
30
+ ActiveSupport::Deprecation.warn 'Model.make is deprecated; use FactoryGirl.build(:model) instead.', caller
31
+ FactoryRunner.new(name.underscore, :build, [overrides]).run
33
32
  end
34
33
 
35
34
  def make!(overrides = {})
36
- ActiveSupport::Deprecation.warn "Model.make! is deprecated; use the FactoryGirl.define syntax instead", caller
37
- FactoryRunner.new(name.underscore, FactoryGirl.strategy_by_name(:create), [overrides]).run
35
+ ActiveSupport::Deprecation.warn 'Model.make! is deprecated; use FactoryGirl.create(:model) instead.', caller
36
+ FactoryRunner.new(name.underscore, :create, [overrides]).run
38
37
  end
39
-
40
38
  end
41
-
42
39
  end
43
40
  end
44
41
  end
@@ -1,43 +1,83 @@
1
1
  module FactoryGirl
2
2
  module Syntax
3
+ ## This module is a container for all strategy methods provided by
4
+ ## FactoryGirl. This includes all the default strategies provided ({Methods#build},
5
+ ## {Methods#create}, {Methods#build_stubbed}, and {Methods#attributes_for}), as well as
6
+ ## the complementary *_list methods.
7
+ ## @example singular factory execution
8
+ ## # basic use case
9
+ ## build(:completed_order)
10
+ ##
11
+ ## # factory yielding its result to a block
12
+ ## create(:post) do |post|
13
+ ## create(:comment, post: post)
14
+ ## end
15
+ ##
16
+ ## # factory with attribute override
17
+ ## attributes_for(:post, title: "I love Ruby!")
18
+ ##
19
+ ## # factory with traits and attribute override
20
+ ## build_stubbed(:user, :admin, :male, name: "John Doe")
21
+ ##
22
+ ## @example multiple factory execution
23
+ ## # basic use case
24
+ ## build_list(:completed_order, 2)
25
+ ## create_list(:completed_order, 2)
26
+ ##
27
+ ## # factory with attribute override
28
+ ## attributes_for_list(:post, 4, title: "I love Ruby!")
29
+ ##
30
+ ## # factory with traits and attribute override
31
+ ## build_stubbed_list(:user, 15, :admin, :male, name: "John Doe")
3
32
  module Methods
4
- # Builds and returns multiple instances from this factory as an array. Attributes can be
5
- # individually overridden by passing in a Hash of attribute => value pairs.
6
- #
7
- # Arguments:
8
- # * name: +Symbol+ or +String+
9
- # The name of the factory to be used.
10
- # * amount: +Integer+
11
- # number of instances to be built.
12
- # * traits_and_overrides: +Array+
13
- # [+*Array+] Traits to be applied
14
- # [+Hash+] Attributes to overwrite for this instance.
15
- #
16
- # Returns: +Array+
17
- # An array of instances of the class this factory generates, with generated attributes
18
- # assigned.
19
- def build_list(name, amount, *traits_and_overrides)
20
- amount.times.map { build(name, *traits_and_overrides) }
21
- end
33
+ # @!parse FactoryGirl.register_default_strategies
34
+ # @!method build(name, *traits_and_overrides, &block)
35
+ # (see #strategy_method)
36
+ # Builds a registered factory by name.
37
+ # @return [Object] instantiated object defined by the factory
22
38
 
23
- # Creates and returns multiple instances from this factory as an array. Attributes can be
24
- # individually overridden by passing in a Hash of attribute => value pairs.
25
- #
26
- # Arguments:
27
- # * name: +Symbol+ or +String+
28
- # The name of the factory to be used.
29
- # * amount: +Integer+
30
- # number of instances to be created.
31
- # * traits_and_overrides: +Array+
32
- # [+*Array+] Traits to be applied
33
- # [+Hash+] Attributes to overwrite for this instance.
34
- #
35
- # Returns: +Array+
36
- # An array of instances of the class this factory generates, with generated attributes
37
- # assigned.
38
- def create_list(name, amount, *traits_and_overrides)
39
- amount.times.map { create(name, *traits_and_overrides) }
40
- end
39
+ # @!method create(name, *traits_and_overrides, &block)
40
+ # (see #strategy_method)
41
+ # Creates a registered factory by name.
42
+ # @return [Object] instantiated object defined by the factory
43
+
44
+ # @!method build_stubbed(name, *traits_and_overrides, &block)
45
+ # (see #strategy_method)
46
+ # Builds a stubbed registered factory by name.
47
+ # @return [Object] instantiated object defined by the factory
48
+
49
+ # @!method attributes_for(name, *traits_and_overrides, &block)
50
+ # (see #strategy_method)
51
+ # Generates a hash of attributes for a registered factory by name.
52
+ # @return [Hash] hash of attributes for the factory
53
+
54
+ # @!method build_list(name, amount, *traits_and_overrides)
55
+ # (see #strategy_method_list)
56
+ # @return [Array] array of built objects defined by the factory
57
+
58
+ # @!method create_list(name, amount, *traits_and_overrides)
59
+ # (see #strategy_method_list)
60
+ # @return [Array] array of created objects defined by the factory
61
+
62
+ # @!method build_stubbed_list(name, amount, *traits_and_overrides)
63
+ # (see #strategy_method_list)
64
+ # @return [Array] array of stubbed objects defined by the factory
65
+
66
+ # @!method attributes_for_list(name, amount, *traits_and_overrides)
67
+ # (see #strategy_method_list)
68
+ # @return [Array<Hash>] array of attribute hashes for the factory
69
+
70
+ # @!method strategy_method
71
+ # @!visibility private
72
+ # @param [Symbol] name name of the factory to build
73
+ # @param [Array<Symbol, Symbol, Hash>] traits_and_overrides splat args traits and a hash of overrides
74
+ # @param [Proc] block block to be executed
75
+
76
+ # @!method strategy_method_list
77
+ # @!visibility private
78
+ # @param [Symbol] name name of the factory to execute
79
+ # @param [Integer] amount the number of instances to execute
80
+ # @param [Array<Symbol, Symbol, Hash>] traits_and_overrides splat args traits and a hash of overrides
41
81
 
42
82
  # Generates and returns the next value in a sequence.
43
83
  #