factory_girl 2.3.2 → 2.4.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 (58) hide show
  1. data/.travis.yml +5 -3
  2. data/Appraisals +4 -0
  3. data/CONTRIBUTION_GUIDELINES.md +1 -1
  4. data/Changelog +13 -0
  5. data/GETTING_STARTED.md +362 -286
  6. data/Gemfile.lock +1 -1
  7. data/README.md +8 -8
  8. data/features/factory_girl_steps.feature +4 -0
  9. data/features/support/factories.rb +19 -0
  10. data/gemfiles/2.1.gemfile.lock +1 -1
  11. data/gemfiles/2.3.gemfile.lock +1 -1
  12. data/gemfiles/3.0.gemfile.lock +1 -1
  13. data/gemfiles/3.1.gemfile.lock +1 -1
  14. data/gemfiles/3.2.gemfile +7 -0
  15. data/gemfiles/3.2.gemfile.lock +90 -0
  16. data/lib/factory_girl.rb +4 -0
  17. data/lib/factory_girl/attribute.rb +1 -9
  18. data/lib/factory_girl/attribute/association.rb +2 -2
  19. data/lib/factory_girl/attribute/dynamic.rb +2 -2
  20. data/lib/factory_girl/attribute/sequence.rb +1 -1
  21. data/lib/factory_girl/attribute/static.rb +1 -1
  22. data/lib/factory_girl/attribute_assigner.rb +73 -0
  23. data/lib/factory_girl/attribute_list.rb +6 -15
  24. data/lib/factory_girl/callback.rb +2 -2
  25. data/lib/factory_girl/evaluator.rb +57 -0
  26. data/lib/factory_girl/evaluator_class_definer.rb +34 -0
  27. data/lib/factory_girl/factory.rb +31 -80
  28. data/lib/factory_girl/null_factory.rb +2 -1
  29. data/lib/factory_girl/null_object.rb +19 -0
  30. data/lib/factory_girl/proxy.rb +6 -87
  31. data/lib/factory_girl/proxy/attributes_for.rb +2 -7
  32. data/lib/factory_girl/proxy/build.rb +4 -3
  33. data/lib/factory_girl/proxy/create.rb +6 -7
  34. data/lib/factory_girl/proxy/stub.rb +19 -18
  35. data/lib/factory_girl/step_definitions.rb +4 -3
  36. data/lib/factory_girl/version.rb +1 -1
  37. data/spec/acceptance/aliases_spec.rb +19 -0
  38. data/spec/acceptance/attributes_for_spec.rb +10 -1
  39. data/spec/acceptance/attributes_from_instance_spec.rb +53 -0
  40. data/spec/acceptance/build_spec.rb +8 -0
  41. data/spec/acceptance/build_stubbed_spec.rb +9 -0
  42. data/spec/acceptance/create_spec.rb +8 -0
  43. data/spec/factory_girl/attribute/association_spec.rb +5 -4
  44. data/spec/factory_girl/attribute/dynamic_spec.rb +9 -10
  45. data/spec/factory_girl/attribute/sequence_spec.rb +1 -2
  46. data/spec/factory_girl/attribute/static_spec.rb +1 -2
  47. data/spec/factory_girl/attribute_list_spec.rb +14 -4
  48. data/spec/factory_girl/evaluator_class_definer_spec.rb +54 -0
  49. data/spec/factory_girl/factory_spec.rb +23 -16
  50. data/spec/factory_girl/null_factory_spec.rb +2 -1
  51. data/spec/factory_girl/null_object_spec.rb +8 -0
  52. data/spec/factory_girl/proxy/attributes_for_spec.rb +8 -24
  53. data/spec/factory_girl/proxy/build_spec.rb +1 -7
  54. data/spec/factory_girl/proxy/create_spec.rb +2 -27
  55. data/spec/factory_girl/proxy/stub_spec.rb +14 -13
  56. data/spec/factory_girl/proxy_spec.rb +1 -33
  57. data/spec/support/shared_examples/proxy.rb +22 -45
  58. metadata +133 -177
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- factory_girl (2.3.2)
4
+ factory_girl (2.4.0)
5
5
  activesupport
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -1,16 +1,16 @@
1
- # factory_girl [![Build Status](https://secure.travis-ci.org/thoughtbot/factory_girl.png)](http://travis-ci.org/thoughtbot/factory_girl?branch=master)
1
+ # factory_girl [![Build Status](https://secure.travis-ci.org/thoughtbot/factory_girl.png)](http://travis-ci.org/thoughtbot/factory_girl?branch=master) [![Dependency Status](https://gemnasium.com/thoughtbot/factory_girl.png)](https://gemnasium.com/thoughtbot/factory_girl)
2
2
 
3
3
  factory_girl is a fixtures replacement with a straightforward definition syntax, support for multiple build strategies (saved instances, unsaved instances, attribute hashes, and stubbed objects), and support for multiple factories for the same class (user, admin_user, and so on), including factory inheritance.
4
4
 
5
5
  If you want to use factory_girl with Rails 3, see
6
- [factory_girl_rails](http://github.com/thoughtbot/factory_girl_rails).
6
+ [factory_girl_rails](https://github.com/thoughtbot/factory_girl_rails).
7
7
 
8
8
  Documentation
9
9
  -------------
10
10
 
11
- You should find the documentation for your version of factory_girl on [Rubygems](http://rubygems.org/gems/factory_girl).
11
+ You should find the documentation for your version of factory_girl on [Rubygems](https://rubygems.org/gems/factory_girl).
12
12
 
13
- See {file:GETTING_STARTED.md} for information on defining and using factories.
13
+ See [GETTING_STARTED](https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md) for information on defining and using factories.
14
14
 
15
15
  Install
16
16
  --------
@@ -28,15 +28,15 @@ and run `bundle install` from your shell.
28
28
  More Information
29
29
  ----------------
30
30
 
31
- * [Rubygems](http://rubygems.org/gems/factory_girl)
31
+ * [Rubygems](https://rubygems.org/gems/factory_girl)
32
32
  * [Mailing list](http://groups.google.com/group/factory_girl)
33
- * [Issues](http://github.com/thoughtbot/factory_girl/issues)
34
- * [GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS](http://giantrobots.thoughtbot.com)
33
+ * [Issues](https://github.com/thoughtbot/factory_girl/issues)
34
+ * [GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS](http://robots.thoughtbot.com/)
35
35
 
36
36
  Contributing
37
37
  ------------
38
38
 
39
- Please see the [contribution guidelines](http://github.com/thoughtbot/factory_girl/blob/master/CONTRIBUTION_GUIDELINES.md).
39
+ Please see the [contribution guidelines](https://github.com/thoughtbot/factory_girl/blob/master/CONTRIBUTION_GUIDELINES.md).
40
40
 
41
41
  Credits
42
42
  -------
@@ -215,3 +215,7 @@ Feature: Use step definitions generated by factories
215
215
  And the post "Tagged post" should not have the following tags:
216
216
  | name |
217
217
  | funky |
218
+
219
+ Scenario: step definitions work correctly with ORMs that have simple `columns`
220
+ Given a simple column exists
221
+ Then there should be 1 SimpleColumn
@@ -58,6 +58,21 @@ end
58
58
  class NonActiveRecord
59
59
  end
60
60
 
61
+ class SimpleColumn
62
+ def self.columns
63
+ [:name]
64
+ end
65
+
66
+ def save!
67
+ @@count ||= 0
68
+ @@count += 1
69
+ end
70
+
71
+ def self.count
72
+ @@count
73
+ end
74
+ end
75
+
61
76
  FactoryGirl.define do
62
77
  # To make sure the step defs work with an email
63
78
  sequence :email do |n|
@@ -90,6 +105,10 @@ FactoryGirl.define do
90
105
  # This is here to ensure that factory step definitions don't raise for a non-AR factory
91
106
  factory :non_active_record do
92
107
  end
108
+
109
+ # This is here to make FG work with ORMs that have `columns => [:name, :admin, :etc]` on the class (Neo4j)
110
+ factory :simple_column do
111
+ end
93
112
  end
94
113
 
95
114
  require 'factory_girl/step_definitions'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/joshuaclayton/dev/gems/factory_girl
3
3
  specs:
4
- factory_girl (2.3.2)
4
+ factory_girl (2.4.0)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/joshuaclayton/dev/gems/factory_girl
3
3
  specs:
4
- factory_girl (2.3.2)
4
+ factory_girl (2.4.0)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/joshuaclayton/dev/gems/factory_girl
3
3
  specs:
4
- factory_girl (2.3.2)
4
+ factory_girl (2.4.0)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/joshuaclayton/dev/gems/factory_girl
3
3
  specs:
4
- factory_girl (2.3.2)
4
+ factory_girl (2.4.0)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "activerecord", "~> 3.2.0.rc2"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,90 @@
1
+ PATH
2
+ remote: /Users/joshuaclayton/dev/gems/factory_girl
3
+ specs:
4
+ factory_girl (2.4.0)
5
+ activesupport
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ activemodel (3.2.0.rc2)
11
+ activesupport (= 3.2.0.rc2)
12
+ builder (~> 3.0.0)
13
+ activerecord (3.2.0.rc2)
14
+ activemodel (= 3.2.0.rc2)
15
+ activesupport (= 3.2.0.rc2)
16
+ arel (~> 3.0.0.rc1)
17
+ tzinfo (~> 0.3.29)
18
+ activesupport (3.2.0.rc2)
19
+ i18n (~> 0.6)
20
+ multi_json (~> 1.0)
21
+ appraisal (0.3.8)
22
+ bundler
23
+ rake
24
+ arel (3.0.0)
25
+ aruba (0.4.6)
26
+ bcat (>= 0.6.1)
27
+ childprocess (>= 0.2.0)
28
+ cucumber (>= 1.0.2)
29
+ rdiscount (>= 1.6.8)
30
+ rspec (>= 2.6.0)
31
+ bcat (0.6.2)
32
+ rack (~> 1.0)
33
+ bluecloth (2.2.0)
34
+ bourne (1.0)
35
+ mocha (= 0.9.8)
36
+ builder (3.0.0)
37
+ childprocess (0.2.9)
38
+ ffi (~> 1.0.6)
39
+ cucumber (1.0.6)
40
+ builder (>= 2.1.2)
41
+ diff-lcs (>= 1.1.2)
42
+ gherkin (~> 2.4.18)
43
+ json (>= 1.4.6)
44
+ term-ansicolor (>= 1.0.6)
45
+ diff-lcs (1.1.3)
46
+ ffi (1.0.11)
47
+ gherkin (2.4.21)
48
+ json (>= 1.4.6)
49
+ i18n (0.6.0)
50
+ json (1.6.4)
51
+ mocha (0.9.8)
52
+ rake
53
+ multi_json (1.0.4)
54
+ rack (1.4.0)
55
+ rake (0.9.2.2)
56
+ rcov (0.9.11)
57
+ rdiscount (1.6.8)
58
+ rspec (2.8.0)
59
+ rspec-core (~> 2.8.0)
60
+ rspec-expectations (~> 2.8.0)
61
+ rspec-mocks (~> 2.8.0)
62
+ rspec-core (2.8.0)
63
+ rspec-expectations (2.8.0)
64
+ diff-lcs (~> 1.1.2)
65
+ rspec-mocks (2.8.0)
66
+ sqlite3 (1.3.5)
67
+ sqlite3-ruby (1.3.3)
68
+ sqlite3 (>= 1.3.3)
69
+ term-ansicolor (1.0.7)
70
+ timecop (0.3.5)
71
+ tzinfo (0.3.31)
72
+ yard (0.7.4)
73
+
74
+ PLATFORMS
75
+ ruby
76
+
77
+ DEPENDENCIES
78
+ activerecord (~> 3.2.0.rc2)
79
+ appraisal (~> 0.3.8)
80
+ aruba
81
+ bluecloth
82
+ bourne
83
+ cucumber (~> 1.0.0)
84
+ factory_girl!
85
+ mocha
86
+ rcov
87
+ rspec (~> 2.0)
88
+ sqlite3-ruby
89
+ timecop
90
+ yard
@@ -3,7 +3,11 @@ require "active_support/core_ext/module/delegation"
3
3
  require 'factory_girl/proxy'
4
4
  require 'factory_girl/registry'
5
5
  require 'factory_girl/null_factory'
6
+ require 'factory_girl/null_object'
6
7
  require 'factory_girl/factory'
8
+ require 'factory_girl/attribute_assigner'
9
+ require 'factory_girl/evaluator'
10
+ require 'factory_girl/evaluator_class_definer'
7
11
  require 'factory_girl/attribute'
8
12
  require 'factory_girl/callback'
9
13
  require 'factory_girl/declaration_list'
@@ -14,15 +14,7 @@ module FactoryGirl
14
14
  ensure_non_attribute_writer!
15
15
  end
16
16
 
17
- def add_to(proxy)
18
- if @ignored
19
- proxy.set_ignored(self, to_proc(proxy))
20
- else
21
- proxy.set(self, to_proc(proxy))
22
- end
23
- end
24
-
25
- def to_proc(proxy)
17
+ def to_proc
26
18
  lambda { }
27
19
  end
28
20
 
@@ -9,10 +9,10 @@ module FactoryGirl
9
9
  @overrides = overrides
10
10
  end
11
11
 
12
- def to_proc(proxy)
12
+ def to_proc
13
13
  factory = @factory
14
14
  overrides = @overrides
15
- lambda { proxy.association(factory, overrides) }
15
+ lambda { association(factory, overrides) }
16
16
  end
17
17
 
18
18
  def association?
@@ -6,11 +6,11 @@ module FactoryGirl
6
6
  @block = block
7
7
  end
8
8
 
9
- def to_proc(proxy)
9
+ def to_proc
10
10
  block = @block
11
11
 
12
12
  lambda {
13
- value = block.arity == 1 ? block.call(proxy) : proxy.instance_exec(&block)
13
+ value = block.arity == 1 ? block.call(self) : instance_exec(&block)
14
14
  raise SequenceAbuseError if FactoryGirl::Sequence === value
15
15
  value
16
16
  }
@@ -7,7 +7,7 @@ module FactoryGirl
7
7
  @sequence = sequence
8
8
  end
9
9
 
10
- def to_proc(proxy)
10
+ def to_proc
11
11
  sequence = @sequence
12
12
  lambda { FactoryGirl.generate(sequence) }
13
13
  end
@@ -6,7 +6,7 @@ module FactoryGirl
6
6
  @value = value
7
7
  end
8
8
 
9
- def to_proc(proxy)
9
+ def to_proc
10
10
  value = @value
11
11
  lambda { value }
12
12
  end
@@ -0,0 +1,73 @@
1
+ module FactoryGirl
2
+ class AttributeAssigner
3
+ def initialize(build_class, evaluator)
4
+ @build_class = build_class
5
+ @evaluator = evaluator
6
+ @attribute_list = evaluator.class.attribute_list
7
+ @attribute_names_assigned = []
8
+ end
9
+
10
+ def object
11
+ @evaluator.instance = build_class_instance
12
+ build_class_instance.tap do |instance|
13
+ attributes_to_set_on_instance.each do |attribute|
14
+ instance.send("#{attribute}=", get(attribute))
15
+ @attribute_names_assigned << attribute
16
+ end
17
+ end
18
+ end
19
+
20
+ def hash
21
+ @evaluator.instance = NullObject.new
22
+
23
+ attributes_to_set_on_hash.inject({}) do |result, attribute|
24
+ result[attribute] = get(attribute)
25
+ result
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def build_class_instance
32
+ @build_class_instance ||= @build_class.new
33
+ end
34
+
35
+ def get(attribute_name)
36
+ @evaluator.send(attribute_name)
37
+ end
38
+
39
+ def attributes_to_set_on_instance
40
+ attribute_names_to_assign - @attribute_names_assigned
41
+ end
42
+
43
+ def attributes_to_set_on_hash
44
+ attribute_names_to_assign - association_names
45
+ end
46
+
47
+ def attribute_names_to_assign
48
+ non_ignored_attribute_names + override_names - ignored_attribute_names - alias_names_to_ignore
49
+ end
50
+
51
+ def non_ignored_attribute_names
52
+ @attribute_list.reject(&:ignored).map(&:name)
53
+ end
54
+
55
+ def ignored_attribute_names
56
+ @attribute_list.select(&:ignored).map(&:name)
57
+ end
58
+
59
+ def association_names
60
+ @attribute_list.associations.map(&:name)
61
+ end
62
+
63
+ def override_names
64
+ @evaluator.__overrides.keys
65
+ end
66
+
67
+ def alias_names_to_ignore
68
+ @attribute_list.reject(&:ignored).map do |attribute|
69
+ override_names.map {|override| attribute.name if attribute.alias_for?(override) && attribute.name != override }
70
+ end.flatten.compact
71
+ end
72
+ end
73
+ end
@@ -18,13 +18,12 @@ module FactoryGirl
18
18
  @attributes.each(&block)
19
19
  end
20
20
 
21
- def apply_attributes(attributes_to_apply)
22
- attributes_to_apply.each do |attribute|
23
- new_attribute = find_attribute(attribute.name) || attribute
24
- delete_attribute(attribute.name)
21
+ def associations
22
+ @attributes.select(&:association?)
23
+ end
25
24
 
26
- add_attribute new_attribute
27
- end
25
+ def apply_attributes(attributes_to_apply)
26
+ attributes_to_apply.each {|attribute| add_attribute(attribute) }
28
27
  end
29
28
 
30
29
  private
@@ -47,17 +46,9 @@ module FactoryGirl
47
46
  end
48
47
 
49
48
  def attribute_defined?(attribute_name)
50
- !!find_attribute(attribute_name)
51
- end
52
-
53
- def find_attribute(attribute_name)
54
- @attributes.detect do |attribute|
49
+ @attributes.any? do |attribute|
55
50
  attribute.name == attribute_name
56
51
  end
57
52
  end
58
-
59
- def delete_attribute(attribute_name)
60
- @attributes.delete_if {|attrib| attrib.name == attribute_name }
61
- end
62
53
  end
63
54
  end
@@ -10,10 +10,10 @@ module FactoryGirl
10
10
  check_name
11
11
  end
12
12
 
13
- def run(instance, proxy)
13
+ def run(instance, evaluator)
14
14
  case block.arity
15
15
  when 1 then block.call(instance)
16
- when 2 then block.call(instance, proxy)
16
+ when 2 then block.call(instance, evaluator)
17
17
  else block.call
18
18
  end
19
19
  end
@@ -0,0 +1,57 @@
1
+ require "active_support/core_ext/class/attribute"
2
+
3
+ module FactoryGirl
4
+ class Evaluator
5
+ class_attribute :callbacks, :attribute_lists
6
+
7
+ def self.attribute_list
8
+ AttributeList.new.tap do |list|
9
+ attribute_lists.each do |attribute_list|
10
+ list.apply_attributes attribute_list.to_a
11
+ end
12
+ end
13
+ end
14
+ undef_method(:id) if method_defined?(:id)
15
+
16
+ def initialize(build_strategy, overrides = {})
17
+ @build_strategy = build_strategy
18
+ @overrides = overrides
19
+ @cached_attributes = overrides
20
+
21
+ @build_strategy.add_observer(CallbackRunner.new(self.class.callbacks, self))
22
+ end
23
+
24
+ delegate :association, :to => :@build_strategy
25
+
26
+ def instance=(object_instance)
27
+ @instance = object_instance
28
+ end
29
+
30
+ def method_missing(method_name, *args, &block)
31
+ if @cached_attributes.key?(method_name)
32
+ @cached_attributes[method_name]
33
+ else
34
+ @instance.send(method_name, *args, &block)
35
+ end
36
+ end
37
+
38
+ def __overrides
39
+ @overrides
40
+ end
41
+
42
+ private
43
+
44
+ class CallbackRunner
45
+ def initialize(callbacks, evaluator)
46
+ @callbacks = callbacks
47
+ @evaluator = evaluator
48
+ end
49
+
50
+ def update(name, result_instance)
51
+ @callbacks.select {|callback| callback.name == name }.each do |callback|
52
+ callback.run(result_instance, @evaluator)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end