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
data/gemfiles/3.2.gemfile CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "http://rubygems.org"
4
4
 
5
- gem "activerecord", "~> 3.2"
5
+ gem "activerecord", "~> 3.2.0"
6
6
 
7
7
  gemspec :path=>"../"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/joshuaclayton/dev/gems/factory_girl
3
3
  specs:
4
- factory_girl (3.2.0)
4
+ factory_girl (3.3.0)
5
5
  activesupport (>= 3.0.0)
6
6
 
7
7
  GEM
@@ -31,7 +31,7 @@ GEM
31
31
  bourne (1.1.2)
32
32
  mocha (= 0.10.5)
33
33
  builder (3.0.0)
34
- childprocess (0.3.1)
34
+ childprocess (0.3.2)
35
35
  ffi (~> 1.0.6)
36
36
  cucumber (1.1.9)
37
37
  builder (>= 2.1.2)
@@ -44,11 +44,11 @@ GEM
44
44
  gherkin (2.9.3)
45
45
  json (>= 1.4.6)
46
46
  i18n (0.6.0)
47
- json (1.6.6)
47
+ json (1.7.0)
48
48
  metaclass (0.0.1)
49
49
  mocha (0.10.5)
50
50
  metaclass (~> 0.0.1)
51
- multi_json (1.2.0)
51
+ multi_json (1.3.4)
52
52
  rake (0.9.2.2)
53
53
  rspec (2.9.0)
54
54
  rspec-core (~> 2.9.0)
@@ -58,23 +58,23 @@ GEM
58
58
  rspec-expectations (2.9.1)
59
59
  diff-lcs (~> 1.1.3)
60
60
  rspec-mocks (2.9.0)
61
- simplecov (0.6.1)
62
- multi_json (~> 1.0)
61
+ simplecov (0.6.2)
62
+ multi_json (~> 1.3)
63
63
  simplecov-html (~> 0.5.3)
64
64
  simplecov-html (0.5.3)
65
- sqlite3 (1.3.5)
65
+ sqlite3 (1.3.6)
66
66
  sqlite3-ruby (1.3.3)
67
67
  sqlite3 (>= 1.3.3)
68
68
  term-ansicolor (1.0.7)
69
69
  timecop (0.3.5)
70
- tzinfo (0.3.32)
71
- yard (0.7.5)
70
+ tzinfo (0.3.33)
71
+ yard (0.8.1)
72
72
 
73
73
  PLATFORMS
74
74
  ruby
75
75
 
76
76
  DEPENDENCIES
77
- activerecord (~> 3.2)
77
+ activerecord (~> 3.2.0)
78
78
  appraisal (~> 0.4)
79
79
  aruba
80
80
  bluecloth
data/lib/factory_girl.rb CHANGED
@@ -1,14 +1,17 @@
1
- require "active_support/core_ext/module/delegation"
2
- require "active_support/notifications"
1
+ require 'set'
2
+ require 'active_support/core_ext/module/delegation'
3
+ require 'active_support/notifications'
3
4
 
5
+ require 'factory_girl/configuration'
4
6
  require 'factory_girl/errors'
5
7
  require 'factory_girl/factory_runner'
8
+ require 'factory_girl/strategy_syntax_method_registrar'
6
9
  require 'factory_girl/strategy_calculator'
7
- require "factory_girl/strategy/build"
8
- require "factory_girl/strategy/create"
9
- require "factory_girl/strategy/attributes_for"
10
- require "factory_girl/strategy/stub"
11
- require "factory_girl/strategy/null"
10
+ require 'factory_girl/strategy/build'
11
+ require 'factory_girl/strategy/create'
12
+ require 'factory_girl/strategy/attributes_for'
13
+ require 'factory_girl/strategy/stub'
14
+ require 'factory_girl/strategy/null'
12
15
  require 'factory_girl/disallows_duplicates_registry'
13
16
  require 'factory_girl/registry'
14
17
  require 'factory_girl/null_factory'
@@ -28,6 +31,7 @@ require 'factory_girl/attribute_list'
28
31
  require 'factory_girl/trait'
29
32
  require 'factory_girl/aliases'
30
33
  require 'factory_girl/definition'
34
+ require 'factory_girl/definition_list'
31
35
  require 'factory_girl/definition_proxy'
32
36
  require 'factory_girl/syntax'
33
37
  require 'factory_girl/syntax_runner'
@@ -36,8 +40,17 @@ require 'factory_girl/reload'
36
40
  require 'factory_girl/version'
37
41
 
38
42
  module FactoryGirl
39
- def self.factories
40
- @factories ||= DisallowsDuplicatesRegistry.new(Registry.new("Factory"))
43
+ def self.configuration
44
+ @configuration ||= Configuration.new
45
+ end
46
+
47
+ def self.reset_configuration
48
+ @configuration = nil
49
+ end
50
+
51
+ class << self
52
+ delegate :factories, :sequences, :traits, :strategies, :callback_names,
53
+ :to_create, :skip_create, :initialize_with, :constructor, to: :configuration
41
54
  end
42
55
 
43
56
  def self.register_factory(factory)
@@ -51,10 +64,6 @@ module FactoryGirl
51
64
  factories.find(name)
52
65
  end
53
66
 
54
- def self.sequences
55
- @sequences ||= DisallowsDuplicatesRegistry.new(Registry.new("Sequence"))
56
- end
57
-
58
67
  def self.register_sequence(sequence)
59
68
  sequence.names.each do |name|
60
69
  sequences.register(name, sequence)
@@ -66,10 +75,6 @@ module FactoryGirl
66
75
  sequences.find(name)
67
76
  end
68
77
 
69
- def self.traits
70
- @traits ||= DisallowsDuplicatesRegistry.new(Registry.new("Trait"))
71
- end
72
-
73
78
  def self.register_trait(trait)
74
79
  trait.names.each do |name|
75
80
  traits.register(name, trait)
@@ -81,22 +86,9 @@ module FactoryGirl
81
86
  traits.find(name)
82
87
  end
83
88
 
84
- def self.strategies
85
- @strategies ||= Registry.new("Strategy")
86
- end
87
-
88
89
  def self.register_strategy(strategy_name, strategy_class)
89
90
  strategies.register(strategy_name, strategy_class)
90
-
91
- FactoryGirl::Syntax::Methods.module_exec do
92
- define_method(strategy_name) do |name, *traits_and_overrides, &block|
93
- instrumentation_payload = { name: name, strategy: strategy_name }
94
-
95
- ActiveSupport::Notifications.instrument("factory_girl.run_factory", instrumentation_payload) do
96
- FactoryRunner.new(name, strategy_class, traits_and_overrides).run(&block)
97
- end
98
- end
99
- end
91
+ StrategySyntaxMethodRegistrar.new(strategy_name).define_strategy_methods
100
92
  end
101
93
 
102
94
  def self.strategy_by_name(name)
@@ -104,15 +96,25 @@ module FactoryGirl
104
96
  end
105
97
 
106
98
  def self.register_default_strategies
107
- FactoryGirl.register_strategy(:build, FactoryGirl::Strategy::Build)
108
- FactoryGirl.register_strategy(:create, FactoryGirl::Strategy::Create)
109
- FactoryGirl.register_strategy(:attributes_for, FactoryGirl::Strategy::AttributesFor)
110
- FactoryGirl.register_strategy(:build_stubbed, FactoryGirl::Strategy::Stub)
99
+ register_strategy(:build, FactoryGirl::Strategy::Build)
100
+ register_strategy(:create, FactoryGirl::Strategy::Create)
101
+ register_strategy(:attributes_for, FactoryGirl::Strategy::AttributesFor)
102
+ register_strategy(:build_stubbed, FactoryGirl::Strategy::Stub)
103
+ register_strategy(:null, FactoryGirl::Strategy::Null)
104
+ end
105
+
106
+ def self.register_default_callbacks
107
+ register_callback(:after_build)
108
+ register_callback(:after_create)
109
+ register_callback(:after_stub)
110
+ register_callback(:before_create)
111
111
  end
112
112
 
113
- def self.callback_names
114
- [:after_build, :after_create, :after_stub, :before_create].freeze
113
+ def self.register_callback(name)
114
+ name = name.to_sym
115
+ callback_names << name
115
116
  end
116
117
  end
117
118
 
118
119
  FactoryGirl.register_default_strategies
120
+ FactoryGirl.register_default_callbacks
@@ -1,6 +1,6 @@
1
1
  module FactoryGirl
2
2
  class << self
3
- attr_accessor :aliases #:nodoc:
3
+ attr_accessor :aliases
4
4
  end
5
5
 
6
6
  self.aliases = [
@@ -8,9 +8,8 @@ module FactoryGirl
8
8
  [/(.*)/, '\1_id']
9
9
  ]
10
10
 
11
- def self.aliases_for(attribute) #:nodoc:
12
- aliases.collect do |params|
13
- pattern, replace = *params
11
+ def self.aliases_for(attribute)
12
+ aliases.map do |(pattern, replace)|
14
13
  if pattern.match(attribute.to_s)
15
14
  attribute.to_s.sub(pattern, replace).to_sym
16
15
  end
@@ -1,11 +1,11 @@
1
- require "factory_girl/attribute/static"
2
- require "factory_girl/attribute/dynamic"
3
- require "factory_girl/attribute/association"
4
- require "factory_girl/attribute/sequence"
1
+ require 'factory_girl/attribute/static'
2
+ require 'factory_girl/attribute/dynamic'
3
+ require 'factory_girl/attribute/association'
4
+ require 'factory_girl/attribute/sequence'
5
5
 
6
6
  module FactoryGirl
7
-
8
- class Attribute #:nodoc:
7
+ # @api private
8
+ class Attribute
9
9
  attr_reader :name, :ignored
10
10
 
11
11
  def initialize(name, ignored)
@@ -29,11 +29,33 @@ module FactoryGirl
29
29
  private
30
30
 
31
31
  def ensure_non_attribute_writer!
32
- if @name.to_s =~ /=$/
33
- attribute_name = $`
34
- raise AttributeDefinitionError,
35
- "factory_girl uses 'f.#{attribute_name} value' syntax " +
36
- "rather than 'f.#{attribute_name} = value'"
32
+ NonAttributeWriterValidator.new(@name).validate!
33
+ end
34
+
35
+ class NonAttributeWriterValidator
36
+ def initialize(method_name)
37
+ @method_name = method_name.to_s
38
+ @method_name_setter_match = @method_name.match(/(.*)=$/)
39
+ end
40
+
41
+ def validate!
42
+ if method_is_writer?
43
+ raise AttributeDefinitionError, error_message
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def method_is_writer?
50
+ !!@method_name_setter_match
51
+ end
52
+
53
+ def attribute_name
54
+ @method_name_setter_match[1]
55
+ end
56
+
57
+ def error_message
58
+ "factory_girl uses '#{attribute_name} value' syntax rather than '#{attribute_name} = value'"
37
59
  end
38
60
  end
39
61
  end
@@ -1,6 +1,7 @@
1
1
  module FactoryGirl
2
- class Attribute #:nodoc:
3
- class Association < Attribute #:nodoc:
2
+ class Attribute
3
+ # @api private
4
+ class Association < Attribute
4
5
  attr_reader :factory
5
6
 
6
7
  def initialize(name, factory, overrides)
@@ -1,6 +1,7 @@
1
1
  module FactoryGirl
2
- class Attribute #:nodoc:
3
- class Dynamic < Attribute #:nodoc:
2
+ class Attribute
3
+ # @api private
4
+ class Dynamic < Attribute
4
5
  def initialize(name, ignored, block)
5
6
  super(name, ignored)
6
7
  @block = block
@@ -1,6 +1,6 @@
1
1
  module FactoryGirl
2
2
  class Attribute
3
-
3
+ # @api private
4
4
  class Sequence < Attribute
5
5
  def initialize(name, sequence, ignored)
6
6
  super(name, ignored)
@@ -12,6 +12,5 @@ module FactoryGirl
12
12
  -> { FactoryGirl.generate(sequence) }
13
13
  end
14
14
  end
15
-
16
15
  end
17
16
  end
@@ -1,6 +1,7 @@
1
1
  module FactoryGirl
2
- class Attribute #:nodoc:
3
- class Static < Attribute #:nodoc:
2
+ class Attribute
3
+ # @api private
4
+ class Static < Attribute
4
5
  def initialize(name, value, ignored)
5
6
  super(name, ignored)
6
7
  @value = value
@@ -1,4 +1,5 @@
1
1
  module FactoryGirl
2
+ # @api private
2
3
  class AttributeAssigner
3
4
  def initialize(evaluator, build_class, &instance_builder)
4
5
  @build_class = build_class
@@ -54,15 +55,15 @@ module FactoryGirl
54
55
  end
55
56
 
56
57
  def non_ignored_attribute_names
57
- @attribute_list.reject(&:ignored).map(&:name)
58
+ @attribute_list.non_ignored.names
58
59
  end
59
60
 
60
61
  def ignored_attribute_names
61
- @attribute_list.select(&:ignored).map(&:name)
62
+ @attribute_list.ignored.names
62
63
  end
63
64
 
64
65
  def association_names
65
- @attribute_list.associations.map(&:name)
66
+ @attribute_list.associations.names
66
67
  end
67
68
 
68
69
  def override_names
@@ -70,11 +71,11 @@ module FactoryGirl
70
71
  end
71
72
 
72
73
  def hash_instance_methods_to_respond_to
73
- @attribute_list.map(&:name) + override_names + @build_class.instance_methods
74
+ @attribute_list.names + override_names + @build_class.instance_methods
74
75
  end
75
76
 
76
77
  def alias_names_to_ignore
77
- @attribute_list.reject(&:ignored).map do |attribute|
78
+ @attribute_list.non_ignored.map do |attribute|
78
79
  override_names.map {|override| attribute.name if attribute.alias_for?(override) && attribute.name != override && !ignored_attribute_names.include?(override) }
79
80
  end.flatten.compact
80
81
  end
@@ -1,10 +1,11 @@
1
1
  module FactoryGirl
2
+ # @api private
2
3
  class AttributeList
3
4
  include Enumerable
4
5
 
5
- def initialize(name = nil)
6
+ def initialize(name = nil, attributes = [])
6
7
  @name = name
7
- @attributes = []
8
+ @attributes = attributes
8
9
  end
9
10
 
10
11
  def define_attribute(attribute)
@@ -18,8 +19,20 @@ module FactoryGirl
18
19
  @attributes.each(&block)
19
20
  end
20
21
 
22
+ def names
23
+ map(&:name)
24
+ end
25
+
21
26
  def associations
22
- @attributes.select(&:association?)
27
+ AttributeList.new(@name, select(&:association?))
28
+ end
29
+
30
+ def ignored
31
+ AttributeList.new(@name, select(&:ignored))
32
+ end
33
+
34
+ def non_ignored
35
+ AttributeList.new(@name, reject(&:ignored))
23
36
  end
24
37
 
25
38
  def apply_attributes(attributes_to_apply)
@@ -10,9 +10,9 @@ module FactoryGirl
10
10
 
11
11
  def run(instance, evaluator)
12
12
  case block.arity
13
- when 1 then block.call(instance)
14
- when 2 then block.call(instance, evaluator)
15
- else block.call
13
+ when 1 then syntax_runner.instance_exec(instance, &block)
14
+ when 2 then syntax_runner.instance_exec(instance, evaluator, &block)
15
+ else syntax_runner.instance_exec(&block)
16
16
  end
17
17
  end
18
18
 
@@ -32,5 +32,9 @@ module FactoryGirl
32
32
  "Valid callback names are #{FactoryGirl.callback_names.inspect}"
33
33
  end
34
34
  end
35
+
36
+ def syntax_runner
37
+ @syntax_runner ||= SyntaxRunner.new
38
+ end
35
39
  end
36
40
  end
@@ -1,4 +1,5 @@
1
1
  module FactoryGirl
2
+ # @api private
2
3
  class CallbacksObserver
3
4
  def initialize(callbacks, evaluator)
4
5
  @callbacks = callbacks
@@ -0,0 +1,24 @@
1
+ module FactoryGirl
2
+ # @api private
3
+ class Configuration
4
+ attr_reader :factories, :sequences, :traits, :strategies, :callback_names
5
+
6
+ def initialize
7
+ @factories = DisallowsDuplicatesRegistry.new(Registry.new('Factory'))
8
+ @sequences = DisallowsDuplicatesRegistry.new(Registry.new('Sequence'))
9
+ @traits = DisallowsDuplicatesRegistry.new(Registry.new('Trait'))
10
+ @strategies = Registry.new('Strategy')
11
+ @callback_names = Set.new
12
+ @definition = Definition.new
13
+
14
+ to_create {|instance| instance.save! }
15
+ initialize_with { new }
16
+ end
17
+
18
+ delegate :to_create, :skip_create, :constructor, to: :@definition
19
+
20
+ def initialize_with(&block)
21
+ @definition.define_constructor(&block)
22
+ end
23
+ end
24
+ end