Permalink
Browse files

Initial work on DeclarationList and cleaning up AttributeList

  • Loading branch information...
1 parent cddfa92 commit f721bc6b83f86f566398439acf1067d5020d4ae5 @joshuaclayton joshuaclayton committed Oct 28, 2011
View
@@ -1,3 +1,5 @@
+require "active_support/core_ext/module/delegation"
+
require 'factory_girl/proxy'
require 'factory_girl/proxy/build'
require 'factory_girl/proxy/create'
@@ -11,6 +13,7 @@
require 'factory_girl/attribute/association'
require 'factory_girl/attribute/sequence'
require 'factory_girl/callback'
+require 'factory_girl/declaration_list'
require 'factory_girl/declaration'
require 'factory_girl/declaration/static'
require 'factory_girl/declaration/dynamic'
@@ -2,14 +2,12 @@ module FactoryGirl
class AttributeList
include Enumerable
- attr_reader :callbacks, :declarations
-
def initialize(name = nil)
@name = name
@attributes = {}
- @declarations = []
- @callbacks = []
+ @declarations = DeclarationList.new
@overridable = false
+ @compiled = false
end
def declare_attribute(declaration)
@@ -18,24 +16,21 @@ def declare_attribute(declaration)
end
def define_attribute(attribute)
- if attribute.respond_to?(:factory) && attribute.factory == @name
- raise AssociationDefinitionError, "Self-referencing association '#{attribute.name}' in '#{attribute.factory}'"
- end
-
+ ensure_attribute_not_self_referencing! attribute
ensure_attribute_not_defined! attribute
- add_attribute attribute
- end
- def add_callback(callback)
- @callbacks << callback
+ add_attribute attribute
end
def each(&block)
flattened_attributes.each(&block)
end
- def apply_attributes(attributes_to_apply)
- attributes_to_apply.callbacks.reverse.each { |callback| prepend_callback(callback) }
+ def ensure_compiled
+ compile unless @compiled
+ end
+
+ def apply_attribute_list(attributes_to_apply)
new_attributes = []
attributes_to_apply.each do |attribute|
@@ -53,19 +48,19 @@ def apply_attributes(attributes_to_apply)
end
def overridable
+ @compiled = false
@overridable = true
end
- def overridable?
- @overridable
- end
+ private
- def size
- to_a.size
+ def compile
+ @declarations.to_attributes.each do |attribute|
+ define_attribute(attribute)
+ end
+ @compiled = true
end
- private
-
def add_attribute(attribute)
delete_attribute(attribute.name) if overridable?
@@ -74,10 +69,6 @@ def add_attribute(attribute)
attribute
end
- def prepend_callback(callback)
- @callbacks.unshift(callback)
- end
-
def prepend_attributes(new_attributes)
new_attributes.group_by {|attr| attr.priority }.each do |priority, attributes|
@attributes[priority] ||= []
@@ -98,6 +89,12 @@ def ensure_attribute_not_defined!(attribute)
end
end
+ def ensure_attribute_not_self_referencing!(attribute)
+ if attribute.respond_to?(:factory) && attribute.factory == @name
+ raise AssociationDefinitionError, "Self-referencing association '#{attribute.name}' in '#{attribute.factory}'"
+ end
+ end
+
def attribute_defined?(attribute_name)
!!find_attribute(attribute_name)
end
@@ -115,5 +112,9 @@ def delete_attribute(attribute_name)
end
end
end
+
+ def overridable?
+ @overridable
+ end
end
end
@@ -0,0 +1,15 @@
+module FactoryGirl
+ class DeclarationList
+ def initialize
+ @definitions = []
+ end
+
+ def to_attributes
+ @definitions.inject([]) {|result, definition| result += definition.to_attributes }
+ end
+
+ def method_missing(name, *args, &block)
+ @definitions.send(name, *args, &block)
+ end
+ end
+end
@@ -1,5 +1,4 @@
require "active_support/core_ext/hash/keys"
-require "active_support/core_ext/module/delegation"
require "active_support/inflector"
module FactoryGirl
@@ -16,16 +15,20 @@ def initialize(name, options = {}) #:nodoc:
@default_strategy = options[:default_strategy]
@defined_traits = []
@attribute_list = build_attribute_list
- @compiled = false
+ @callbacks = []
end
- delegate :overridable?, :declarations, :declare_attribute, :define_attribute, :add_callback, :to => :@attribute_list
+ delegate :declare_attribute, :to => :@attribute_list
def factory_name
$stderr.puts "DEPRECATION WARNING: factory.factory_name is deprecated; use factory.name instead."
name
end
+ def add_callback(callback)
+ @callbacks << callback
+ end
+
def build_class #:nodoc:
@build_class ||= class_name.to_s.camelize.constantize
end
@@ -35,7 +38,6 @@ def default_strategy #:nodoc:
end
def allow_overrides
- @compiled = false
@attribute_list.overridable
self
end
@@ -45,8 +47,6 @@ def define_trait(trait)
end
def run(proxy_class, overrides, &block) #:nodoc:
- ensure_compiled
-
runner_options = {
:attributes => attributes,
:callbacks => callbacks,
@@ -111,8 +111,9 @@ def to_create(&block)
@to_create_block = block
end
- def ensure_compiled
- compile unless @compiled
+ def compile
+ parent.compile if parent
+ @attribute_list.ensure_compiled
end
protected
@@ -122,39 +123,24 @@ def class_name #:nodoc:
end
def attributes
- ensure_compiled
+ compile
build_attribute_list.tap do |list|
- @traits.reverse.map { |name| trait_by_name(name) }.each do |trait|
- list.apply_attributes(trait.attributes)
+ traits.each do |trait|
+ list.apply_attribute_list(trait.attributes)
end
- list.apply_attributes(@attribute_list)
- list.apply_attributes(parent.attributes) if parent
+ list.apply_attribute_list(@attribute_list)
+ list.apply_attribute_list(parent.attributes) if parent
end
end
- private
-
def callbacks
- attributes.callbacks
+ [@callbacks].tap do |result|
+ result.unshift(*parent.callbacks) if parent
+ end.flatten
end
- def compile
- inherit_factory(parent) if parent
-
- declarations.each do |declaration|
- declaration.to_attributes.each do |attribute|
- define_attribute(attribute)
- end
- end
-
- @compiled = true
- end
-
- def inherit_factory(parent) #:nodoc:
- parent.ensure_compiled
- allow_overrides if parent.overridable?
- end
+ private
def assert_valid_options(options)
options.assert_valid_keys(:class, :parent, :default_strategy, :aliases, :traits)
@@ -166,6 +152,10 @@ def assert_valid_options(options)
end
end
+ def traits
+ @traits.reverse.map { |name| trait_by_name(name) }
+ end
+
def trait_for(name)
@defined_traits.detect {|trait| trait.name == name }
end
@@ -95,7 +95,7 @@ def initialize(human_hash_to_attributes_hash, key, value)
World(FactoryGirlStepHelpers)
FactoryGirl.factories.each do |factory|
- factory.ensure_compiled
+ factory.compile
factory.human_names.each do |human_name|
Given /^the following (?:#{human_name}|#{human_name.pluralize}) exists?:$/i do |table|
table.hashes.each do |human_hash|
@@ -46,7 +46,7 @@ def factory(name, options = {}, &block)
factory = FactoryGirl.factory_by_name(name).allow_overrides
proxy = FactoryGirl::DefinitionProxy.new(factory)
proxy.instance_eval(&block)
- factory.ensure_compiled
+ factory.compile
end
end
end
View
@@ -11,24 +11,11 @@ def initialize(name, &block) #:nodoc:
proxy.instance_eval(&@block) if block_given?
end
- def declare_attribute(declaration)
- @attribute_list.declare_attribute(declaration)
- declaration
- end
-
- def add_callback(name, &block)
- @attribute_list.add_callback(Callback.new(name, block))
- end
+ delegate :declare_attribute, :to => :@attribute_list
def attributes
- AttributeList.new.tap do |list|
- @attribute_list.declarations.each do |declaration|
- declaration.to_attributes.each do |attribute|
- list.define_attribute(attribute)
- end
- end
- list.apply_attributes @attribute_list
- end
+ @attribute_list.ensure_compiled
+ @attribute_list
end
def names
@@ -60,19 +60,7 @@
end
end
-describe FactoryGirl::AttributeList, "#add_callback" do
- let(:proxy_class) { mock("klass") }
- let(:proxy) { FactoryGirl::Proxy.new(proxy_class) }
-
- it "allows for defining adding a callback" do
- subject.add_callback(FactoryGirl::Callback.new(:after_create, lambda { "Called after_create" }))
-
- subject.callbacks.first.name.should == :after_create
- subject.callbacks.first.run(nil, nil).should == "Called after_create"
- end
-end
-
-describe FactoryGirl::AttributeList, "#apply_attributes" do
+describe FactoryGirl::AttributeList, "#apply_attribute_list" do
let(:full_name_attribute) { FactoryGirl::Attribute::Static.new(:full_name, "John Adams", false) }
let(:city_attribute) { FactoryGirl::Attribute::Static.new(:city, "Boston", false) }
let(:email_attribute) { FactoryGirl::Attribute::Dynamic.new(:email, false, lambda {|model| "#{model.full_name}@example.com" }) }
@@ -86,28 +74,28 @@ def list(*attributes)
it "prepends applied attributes" do
subject.define_attribute(full_name_attribute)
- subject.apply_attributes(list(city_attribute))
+ subject.apply_attribute_list(list(city_attribute))
subject.to_a.should == [city_attribute, full_name_attribute]
end
it "moves non-static attributes to the end of the list" do
subject.define_attribute(full_name_attribute)
- subject.apply_attributes(list(city_attribute, email_attribute))
+ subject.apply_attribute_list(list(city_attribute, email_attribute))
subject.to_a.should == [city_attribute, full_name_attribute, email_attribute]
end
it "maintains order of non-static attributes" do
subject.define_attribute(full_name_attribute)
subject.define_attribute(login_attribute)
- subject.apply_attributes(list(city_attribute, email_attribute))
+ subject.apply_attribute_list(list(city_attribute, email_attribute))
subject.to_a.should == [city_attribute, full_name_attribute, email_attribute, login_attribute]
end
it "doesn't overwrite attributes that are already defined" do
subject.define_attribute(full_name_attribute)
attribute_with_same_name = FactoryGirl::Attribute::Static.new(:full_name, "Benjamin Franklin", false)
- subject.apply_attributes(list(attribute_with_same_name))
+ subject.apply_attribute_list(list(attribute_with_same_name))
subject.to_a.should == [full_name_attribute]
end
@@ -116,28 +104,28 @@ def list(*attributes)
it "prepends applied attributes" do
subject.define_attribute(full_name_attribute)
- subject.apply_attributes(list(city_attribute))
+ subject.apply_attribute_list(list(city_attribute))
subject.to_a.should == [city_attribute, full_name_attribute]
end
it "moves non-static attributes to the end of the list" do
subject.define_attribute(full_name_attribute)
- subject.apply_attributes(list(city_attribute, email_attribute))
+ subject.apply_attribute_list(list(city_attribute, email_attribute))
subject.to_a.should == [city_attribute, full_name_attribute, email_attribute]
end
it "maintains order of non-static attributes" do
subject.define_attribute(full_name_attribute)
subject.define_attribute(login_attribute)
- subject.apply_attributes(list(city_attribute, email_attribute))
+ subject.apply_attribute_list(list(city_attribute, email_attribute))
subject.to_a.should == [city_attribute, full_name_attribute, email_attribute, login_attribute]
end
it "overwrites attributes that are already defined" do
subject.define_attribute(full_name_attribute)
attribute_with_same_name = FactoryGirl::Attribute::Static.new(:full_name, "Benjamin Franklin", false)
- subject.apply_attributes(list(attribute_with_same_name))
+ subject.apply_attribute_list(list(attribute_with_same_name))
subject.to_a.should == [attribute_with_same_name]
end
end
Oops, something went wrong.

0 comments on commit f721bc6

Please sign in to comment.