factory_girl 3.2.0 → 3.3.0

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