factory_girl 2.3.1 → 2.3.2

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