factory_girl 2.3.1 → 2.3.2

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 (36) hide show
  1. data/Changelog +9 -0
  2. data/Gemfile.lock +1 -1
  3. data/gemfiles/2.1.gemfile.lock +1 -1
  4. data/gemfiles/2.3.gemfile.lock +1 -1
  5. data/gemfiles/3.0.gemfile.lock +1 -1
  6. data/gemfiles/3.1.gemfile.lock +1 -1
  7. data/lib/factory_girl/attribute.rb +10 -24
  8. data/lib/factory_girl/attribute/association.rb +4 -2
  9. data/lib/factory_girl/attribute/dynamic.rb +7 -6
  10. data/lib/factory_girl/attribute/sequence.rb +3 -3
  11. data/lib/factory_girl/attribute/static.rb +3 -16
  12. data/lib/factory_girl/attribute_list.rb +3 -27
  13. data/lib/factory_girl/definition.rb +1 -1
  14. data/lib/factory_girl/factory.rb +1 -1
  15. data/lib/factory_girl/proxy.rb +80 -21
  16. data/lib/factory_girl/proxy/attributes_for.rb +2 -12
  17. data/lib/factory_girl/proxy/build.rb +2 -20
  18. data/lib/factory_girl/proxy/create.rb +2 -3
  19. data/lib/factory_girl/proxy/stub.rb +3 -16
  20. data/lib/factory_girl/version.rb +1 -1
  21. data/spec/acceptance/attributes_for_spec.rb +17 -0
  22. data/spec/acceptance/traits_spec.rb +23 -0
  23. data/spec/factory_girl/attribute/association_spec.rb +14 -13
  24. data/spec/factory_girl/attribute/dynamic_spec.rb +6 -9
  25. data/spec/factory_girl/attribute/sequence_spec.rb +1 -3
  26. data/spec/factory_girl/attribute/static_spec.rb +2 -4
  27. data/spec/factory_girl/attribute_list_spec.rb +2 -14
  28. data/spec/factory_girl/attribute_spec.rb +0 -15
  29. data/spec/factory_girl/declaration/implicit_spec.rb +10 -29
  30. data/spec/factory_girl/definition_spec.rb +7 -1
  31. data/spec/factory_girl/factory_spec.rb +1 -1
  32. data/spec/factory_girl/proxy/attributes_for_spec.rb +10 -5
  33. data/spec/factory_girl/proxy/create_spec.rb +1 -7
  34. data/spec/factory_girl/proxy_spec.rb +2 -5
  35. data/spec/support/shared_examples/proxy.rb +13 -12
  36. metadata +174 -115
data/Changelog CHANGED
@@ -1,3 +1,12 @@
1
+ 2.3.2 (November 26, 2011)
2
+ Move logic of where instance.save! is set to Definition
3
+ Fix method name from aliases_for? to alias_for?
4
+ Refactor internal attribute handling to use an anonymous class instead of
5
+ faking Ruby's variable resolution. This allows for more sane usage of
6
+ attributes without having to manage sorting priority because attributes
7
+ can turn themselves into procs, which are used with define_method on a
8
+ class so attributes work correctly all the time.
9
+
1
10
  2.3.1 (November 23, 2011)
2
11
  Remove internally-used associate method from all the FactoryGirl::Proxy subclasses
3
12
  Move around requiring of files
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- factory_girl (2.3.1)
4
+ factory_girl (2.3.2)
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.1)
4
+ factory_girl (2.3.2)
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.1)
4
+ factory_girl (2.3.2)
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.1)
4
+ factory_girl (2.3.2)
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.1)
4
+ factory_girl (2.3.2)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -6,8 +6,6 @@ require "factory_girl/attribute/sequence"
6
6
  module FactoryGirl
7
7
 
8
8
  class Attribute #:nodoc:
9
- include Comparable
10
-
11
9
  attr_reader :name, :ignored
12
10
 
13
11
  def initialize(name, ignored)
@@ -17,29 +15,25 @@ module FactoryGirl
17
15
  end
18
16
 
19
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
20
23
  end
21
24
 
22
- def association?
23
- false
25
+ def to_proc(proxy)
26
+ lambda { }
24
27
  end
25
28
 
26
- def priority
27
- 1
29
+ def association?
30
+ false
28
31
  end
29
32
 
30
- def aliases_for?(attr)
33
+ def alias_for?(attr)
31
34
  FactoryGirl.aliases_for(attr).include?(name)
32
35
  end
33
36
 
34
- def <=>(another)
35
- return nil unless another.is_a? Attribute
36
- self.priority <=> another.priority
37
- end
38
-
39
- def ==(another)
40
- self.object_id == another.object_id
41
- end
42
-
43
37
  private
44
38
 
45
39
  def ensure_non_attribute_writer!
@@ -50,13 +44,5 @@ module FactoryGirl
50
44
  "rather than 'f.#{attribute_name} = value'"
51
45
  end
52
46
  end
53
-
54
- def set_proxy_value(proxy, value)
55
- if @ignored
56
- proxy.set_ignored(self, value)
57
- else
58
- proxy.set(self, value)
59
- end
60
- end
61
47
  end
62
48
  end
@@ -9,8 +9,10 @@ module FactoryGirl
9
9
  @overrides = overrides
10
10
  end
11
11
 
12
- def add_to(proxy)
13
- proxy.set(self, proxy.association(@factory, @overrides))
12
+ def to_proc(proxy)
13
+ factory = @factory
14
+ overrides = @overrides
15
+ lambda { proxy.association(factory, overrides) }
14
16
  end
15
17
 
16
18
  def association?
@@ -6,13 +6,14 @@ module FactoryGirl
6
6
  @block = block
7
7
  end
8
8
 
9
- def add_to(proxy)
10
- value = @block.arity == 1 ? @block.call(proxy) : proxy.instance_exec(&@block)
11
- if FactoryGirl::Sequence === value
12
- raise SequenceAbuseError
13
- end
9
+ def to_proc(proxy)
10
+ block = @block
14
11
 
15
- set_proxy_value(proxy, value)
12
+ lambda {
13
+ value = block.arity == 1 ? block.call(proxy) : proxy.instance_exec(&block)
14
+ raise SequenceAbuseError if FactoryGirl::Sequence === value
15
+ value
16
+ }
16
17
  end
17
18
  end
18
19
  end
@@ -7,9 +7,9 @@ module FactoryGirl
7
7
  @sequence = sequence
8
8
  end
9
9
 
10
- def add_to(proxy)
11
- value = FactoryGirl.generate(@sequence)
12
- set_proxy_value(proxy, value)
10
+ def to_proc(proxy)
11
+ sequence = @sequence
12
+ lambda { FactoryGirl.generate(sequence) }
13
13
  end
14
14
  end
15
15
 
@@ -1,27 +1,14 @@
1
1
  module FactoryGirl
2
2
  class Attribute #:nodoc:
3
-
4
3
  class Static < Attribute #:nodoc:
5
-
6
- attr_reader :value
7
-
8
4
  def initialize(name, value, ignored)
9
5
  super(name, ignored)
10
6
  @value = value
11
7
  end
12
8
 
13
- def add_to(proxy)
14
- set_proxy_value(proxy, @value)
15
- end
16
-
17
- def priority
18
- 0
19
- end
20
-
21
- def ==(another)
22
- self.name == another.name &&
23
- self.value == another.value &&
24
- self.ignored == another.ignored
9
+ def to_proc(proxy)
10
+ value = @value
11
+ lambda { value }
25
12
  end
26
13
  end
27
14
  end
@@ -15,19 +15,16 @@ module FactoryGirl
15
15
  end
16
16
 
17
17
  def each(&block)
18
- sorted_attributes.each(&block)
18
+ @attributes.each(&block)
19
19
  end
20
20
 
21
21
  def apply_attributes(attributes_to_apply)
22
- new_attributes = []
23
-
24
22
  attributes_to_apply.each do |attribute|
25
23
  new_attribute = find_attribute(attribute.name) || attribute
26
24
  delete_attribute(attribute.name)
27
- new_attributes << new_attribute
28
- end
29
25
 
30
- prepend_attributes new_attributes
26
+ add_attribute new_attribute
27
+ end
31
28
  end
32
29
 
33
30
  private
@@ -37,19 +34,6 @@ module FactoryGirl
37
34
  attribute
38
35
  end
39
36
 
40
- def prepend_attributes(new_attributes)
41
- @attributes.unshift *new_attributes
42
- end
43
-
44
- def sorted_attributes
45
- attributes_hash = attributes_hash_by_priority
46
-
47
- attributes_hash.keys.sort.inject([]) do |result, key|
48
- result << attributes_hash[key]
49
- result
50
- end.flatten
51
- end
52
-
53
37
  def ensure_attribute_not_defined!(attribute)
54
38
  if attribute_defined?(attribute.name)
55
39
  raise AttributeDefinitionError, "Attribute already defined: #{attribute.name}"
@@ -75,13 +59,5 @@ module FactoryGirl
75
59
  def delete_attribute(attribute_name)
76
60
  @attributes.delete_if {|attrib| attrib.name == attribute_name }
77
61
  end
78
-
79
- def attributes_hash_by_priority
80
- @attributes.inject({}) do |result, attribute|
81
- result[attribute.priority] ||= []
82
- result[attribute.priority] << attribute
83
- result
84
- end
85
- end
86
62
  end
87
63
  end
@@ -6,7 +6,7 @@ module FactoryGirl
6
6
  @declarations = DeclarationList.new(name)
7
7
  @callbacks = []
8
8
  @defined_traits = []
9
- @to_create = nil
9
+ @to_create = lambda {|instance| instance.save! }
10
10
  @traits = []
11
11
  end
12
12
 
@@ -180,7 +180,7 @@ module FactoryGirl
180
180
  end
181
181
 
182
182
  def overrides_for_attribute(attribute)
183
- @overrides.select { |attr, val| attribute.aliases_for?(attr) }
183
+ @overrides.select { |attr, val| attribute.alias_for?(attr) }
184
184
  end
185
185
 
186
186
  def handle_attribute_with_overrides(attribute)
@@ -7,29 +7,16 @@ require "factory_girl/proxy/stub"
7
7
  module FactoryGirl
8
8
  class Proxy #:nodoc:
9
9
  def initialize(klass, callbacks = [])
10
- @callbacks = callbacks.inject({}) do |result, callback|
11
- result[callback.name] ||= []
12
- result[callback.name] << callback
13
- result
14
- end
15
-
16
- @ignored_attributes = {}
17
- end
18
-
19
- def get(attribute)
10
+ @callbacks = process_callbacks(callbacks)
11
+ @proxy = ObjectWrapper.new(klass)
20
12
  end
21
13
 
22
- def set(attribute, value)
23
- end
24
-
25
- def set_ignored(attribute, value)
26
- @ignored_attributes[attribute.name] = value
27
- end
14
+ delegate :get, :set, :set_ignored, :to => :@proxy
28
15
 
29
16
  def run_callbacks(name)
30
17
  if @callbacks[name]
31
18
  @callbacks[name].each do |callback|
32
- callback.run(@instance, self)
19
+ callback.run(result_instance, self)
33
20
  end
34
21
  end
35
22
  end
@@ -69,10 +56,6 @@ module FactoryGirl
69
56
  def association(name, overrides = {})
70
57
  end
71
58
 
72
- def method_missing(method, *args, &block)
73
- get(method)
74
- end
75
-
76
59
  def result(to_create)
77
60
  raise NotImplementedError, "Strategies must return a result"
78
61
  end
@@ -82,5 +65,81 @@ module FactoryGirl
82
65
  raise ArgumentError, "Unknown strategy: #{strategy}"
83
66
  end
84
67
  end
68
+
69
+ private
70
+
71
+ def method_missing(method, *args, &block)
72
+ get(method)
73
+ end
74
+
75
+ def process_callbacks(callbacks)
76
+ callbacks.inject({}) do |result, callback|
77
+ result[callback.name] ||= []
78
+ result[callback.name] << callback
79
+ result
80
+ end
81
+ end
82
+
83
+ def result_instance
84
+ @proxy.object
85
+ end
86
+
87
+ def result_hash
88
+ @proxy.to_hash
89
+ end
90
+
91
+ class ObjectWrapper
92
+ def initialize(klass)
93
+ @klass = klass
94
+ @attributes = []
95
+ @cached_attribute_values = {}
96
+ end
97
+
98
+ def to_hash
99
+ @attributes.inject({}) do |result, attribute|
100
+ result[attribute] = get(attribute)
101
+ result
102
+ end
103
+ end
104
+
105
+ def object
106
+ @object ||= @klass.new
107
+ assign_object_attributes
108
+ @object
109
+ end
110
+
111
+ def set(attribute, value)
112
+ define_attribute(attribute, value)
113
+ @attributes << attribute.name
114
+ end
115
+
116
+ def set_ignored(attribute, value)
117
+ define_attribute(attribute, value)
118
+ end
119
+
120
+ def get(attribute)
121
+ @cached_attribute_values[attribute] ||= anonymous_instance.send(attribute)
122
+ end
123
+
124
+ private
125
+
126
+ def define_attribute(attribute, value)
127
+ anonymous_class.send(:define_method, attribute.name, value)
128
+ end
129
+
130
+ def assign_object_attributes
131
+ (@attributes - @cached_attribute_values.keys).each do |attribute|
132
+ @object.send("#{attribute}=", get(attribute))
133
+ end
134
+ end
135
+
136
+ def anonymous_class
137
+ @anonymous_class ||= Class.new
138
+ end
139
+
140
+ def anonymous_instance
141
+ @anonymous_instance ||= anonymous_class.new
142
+ end
143
+ end
85
144
  end
86
145
  end
@@ -1,23 +1,13 @@
1
1
  module FactoryGirl
2
2
  class Proxy #:nodoc:
3
3
  class AttributesFor < Proxy #:nodoc:
4
- def initialize(klass, callbacks = [])
5
- super
6
- @hash = {}
7
- end
8
-
9
- def get(attribute)
10
- @ignored_attributes[attribute] || @hash[attribute]
11
- end
12
-
13
4
  def set(attribute, value)
14
5
  return if attribute.is_a? Attribute::Association
15
-
16
- @hash[attribute.name] = value
6
+ super
17
7
  end
18
8
 
19
9
  def result(to_create)
20
- @hash
10
+ result_hash
21
11
  end
22
12
  end
23
13
  end
@@ -1,32 +1,14 @@
1
1
  module FactoryGirl
2
2
  class Proxy #:nodoc:
3
3
  class Build < Proxy #:nodoc:
4
- def initialize(klass, callbacks = [])
5
- super
6
- @instance = klass.new
7
- end
8
-
9
- def get(attribute)
10
- if @ignored_attributes.has_key?(attribute)
11
- @ignored_attributes[attribute]
12
- else
13
- @instance.send(attribute)
14
- end
15
- end
16
-
17
- def set(attribute, value)
18
- @instance.send(:"#{attribute.name}=", value)
19
- end
20
-
21
4
  def association(factory_name, overrides = {})
22
- method = get_method(overrides[:method])
23
5
  factory = FactoryGirl.factory_by_name(factory_name)
24
- factory.run(method, overrides.except(:method))
6
+ factory.run(get_method(overrides[:method]), overrides.except(:method))
25
7
  end
26
8
 
27
9
  def result(to_create)
28
10
  run_callbacks(:after_build)
29
- @instance
11
+ result_instance
30
12
  end
31
13
 
32
14
  private