Permalink
Browse files

Add DefinitionHierarchy to handle inheritance of some definition attr…

…ibutes

This includes #callbacks, #constructor, and #to_create. The reasoning
behind this is that we were mimicing an inheritance chain via methods;
now, we actually generate classes, which Factory maintains, who inherit
from their parent's hierarchy. We build the hierarchy during compilation
to conditionally define methods based on whether what we're dealing
with from the definition is actually meaningful. The base class
(DefinitionHierarchy) uses the defaults (an empty array for #callbacks
and the global #to_create and #constructor) so once we hit the top
level, if the definition doesn't set any overrides, we have a list of
sensible values.
  • Loading branch information...
joshuaclayton committed Jul 12, 2012
1 parent b6692b6 commit 0c165ec993759881bcb8ea9c1c58ff2ed7cf2c8c
Showing with 62 additions and 5 deletions.
  1. +1 −0 lib/factory_girl.rb
  2. +39 −0 lib/factory_girl/definition_hierarchy.rb
  3. +21 −3 lib/factory_girl/factory.rb
  4. +1 −2 lib/factory_girl/null_factory.rb
View
@@ -2,6 +2,7 @@
require 'active_support/core_ext/module/delegation'
require 'active_support/notifications'
+require 'factory_girl/definition_hierarchy'
require 'factory_girl/configuration'
require 'factory_girl/errors'
require 'factory_girl/factory_runner'
@@ -0,0 +1,39 @@
+module FactoryGirl
+ class DefinitionHierarchy
+ def callbacks
+ []
+ end
+
+ def constructor
+ FactoryGirl.constructor
+ end
+
+ def to_create
+ FactoryGirl.to_create
+ end
+
+ def self.add_callbacks(callbacks)
+ if callbacks.any?
+ define_method :callbacks do
+ super() + callbacks
+ end
+ end
+ end
+
+ def self.build_constructor(&block)
+ if block
+ define_method(:constructor) do
+ block
+ end
+ end
+ end
+
+ def self.build_to_create(&block)
+ if block
+ define_method(:to_create) do
+ block
+ end
+ end
+ end
+ end
+end
@@ -84,6 +84,7 @@ def compile
parent.compile
parent.defined_traits.each {|trait| define_trait(trait) }
@definition.compile
+ build_hierarchy
@compiled = true
end
end
@@ -111,16 +112,30 @@ def attributes
end
end
+ def hierarchy_class
+ @hierarchy_class ||= Class.new(parent.hierarchy_class)
+ end
+
+ def hierarchy_instance
+ @hierarchy_instance ||= hierarchy_class.new
+ end
+
+ def build_hierarchy
+ hierarchy_class.build_to_create &definition.to_create
+ hierarchy_class.build_constructor &definition.constructor
+ hierarchy_class.add_callbacks definition.callbacks
+ end
+
def callbacks
- parent.callbacks + definition.callbacks
+ hierarchy_instance.callbacks
end
def compiled_to_create
- @definition.to_create || parent.compiled_to_create || FactoryGirl.to_create
+ hierarchy_instance.to_create
end
def compiled_constructor
- @definition.constructor || parent.compiled_constructor || FactoryGirl.constructor
+ hierarchy_instance.constructor
end
private
@@ -141,6 +156,9 @@ def initialize_copy(source)
super
@definition = @definition.clone
@evaluator_class = nil
+ @hierarchy_class = nil
+ @hierarchy_instance = nil
+ @compiled = false
end
end
end
@@ -10,10 +10,9 @@ def initialize
delegate :defined_traits, :callbacks, :attributes, :constructor,
:to_create, to: :definition
- def compiled_to_create; to_create; end
- def compiled_constructor; constructor; end
def compile; end
def class_name; end
def evaluator_class; FactoryGirl::Evaluator; end
+ def hierarchy_class; FactoryGirl::DefinitionHierarchy; end
end
end

0 comments on commit 0c165ec

Please sign in to comment.