Skip to content

Commit

Permalink
Attribute lists can be named
Browse files Browse the repository at this point in the history
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 e3bf491
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 20 deletions.
7 changes: 6 additions & 1 deletion lib/factory_girl/attribute_list.rb
Expand Up @@ -4,7 +4,8 @@ class AttributeList

attr_reader :callbacks, :declarations

def initialize
def initialize(name = nil)
@name = name
@attributes = {}
@declarations = []
@callbacks = []
Expand All @@ -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
Expand Down
18 changes: 7 additions & 11 deletions lib/factory_girl/factory.rb
Expand Up @@ -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."
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand All @@ -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]
Expand Down
15 changes: 15 additions & 0 deletions spec/factory_girl/attribute_list_spec.rb
Expand Up @@ -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) }
Expand Down
8 changes: 0 additions & 8 deletions spec/factory_girl/factory_spec.rb
Expand Up @@ -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
Expand Down

0 comments on commit e3bf491

Please sign in to comment.