Permalink
Browse files

Attribute lists can be named

This allows us to move self-referencing logic into AttributeList and
just delegate to define_attribute from Factory. This means that once
define_attribute is private, Factory will only need to remove the
delegation.
  • Loading branch information...
joshuaclayton committed Oct 20, 2011
1 parent a09ec68 commit e3bf491dd6af2b6c5c110c4a795db65bb458e3da
@@ -4,7 +4,8 @@ class AttributeList
attr_reader :callbacks, :declarations
- def initialize
+ def initialize(name = nil)
+ @name = name
@attributes = {}
@declarations = []
@callbacks = []
@@ -17,6 +18,10 @@ 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_defined! attribute
add_attribute attribute
end
@@ -15,11 +15,11 @@ def initialize(name, options = {}) #:nodoc:
@class_name = options[:class]
@default_strategy = options[:default_strategy]
@defined_traits = []
- @attribute_list = AttributeList.new
+ @attribute_list = build_attribute_list
@compiled = false
end
- delegate :overridable?, :declarations, :declare_attribute, :add_callback, :to => :@attribute_list
+ delegate :overridable?, :declarations, :declare_attribute, :define_attribute, :add_callback, :to => :@attribute_list
def factory_name
$stderr.puts "DEPRECATION WARNING: factory.factory_name is deprecated; use factory.name instead."
@@ -123,7 +123,7 @@ def class_name #:nodoc:
def attributes
ensure_compiled
- AttributeList.new.tap do |list|
+ build_attribute_list.tap do |list|
@traits.reverse.map { |name| trait_by_name(name) }.each do |trait|
list.apply_attributes(trait.attributes)
end
@@ -156,14 +156,6 @@ def inherit_factory(parent) #:nodoc:
allow_overrides if parent.overridable?
end
- def define_attribute(attribute)
- if attribute.respond_to?(:factory) && attribute.factory == self.name
- raise AssociationDefinitionError, "Self-referencing association '#{attribute.name}' in factory '#{self.name}'"
- end
-
- @attribute_list.define_attribute(attribute)
- end
-
def assert_valid_options(options)
options.assert_valid_keys(:class, :parent, :default_strategy, :aliases, :traits)
@@ -183,6 +175,10 @@ def parent
FactoryGirl.factory_by_name(@parent)
end
+ def build_attribute_list
+ AttributeList.new(@name)
+ end
+
class Runner
def initialize(options = {})
@attributes = options[:attributes]
@@ -45,6 +45,21 @@
end
end
+describe FactoryGirl::AttributeList, "#define_attribute with a named attribute list" do
+ subject { FactoryGirl::AttributeList.new(:author) }
+
+ let(:association_with_same_name) { FactoryGirl::Attribute::Association.new(:author, :author, {}) }
+ let(:association_with_different_name) { FactoryGirl::Attribute::Association.new(:author, :post, {}) }
+
+ it "raises when the attribute is a self-referencing association" do
+ expect { subject.define_attribute(association_with_same_name) }.to raise_error(FactoryGirl::AssociationDefinitionError, "Self-referencing association 'author' in 'author'")
+ end
+
+ it "does not raise when the attribute is not a self-referencing association" do
+ expect { subject.define_attribute(association_with_different_name) }.to_not raise_error
+ end
+end
+
describe FactoryGirl::AttributeList, "#add_callback" do
let(:proxy_class) { mock("klass") }
let(:proxy) { FactoryGirl::Proxy.new(proxy_class) }
@@ -48,14 +48,6 @@
factory.associations.size.should == 3
end
- it "raises for a self referencing association" do
- factory = FactoryGirl::Factory.new(:post)
- lambda {
- factory.declare_attribute(FactoryGirl::Declaration::Association.new(:parent, { :factory => :post }))
- factory.ensure_compiled
- }.should raise_error(FactoryGirl::AssociationDefinitionError)
- end
-
describe "when overriding generated attributes with a hash" do
before do
@name = :name

0 comments on commit e3bf491

Please sign in to comment.