Avoid recursive call to AttributeHash#attributes
Fixes 1155 Defining an attribute called 'attributes', then referring to that attribute in `initialize_with` was causing `AttributeHash#attributes` to call itself recursively.
This commit is contained in:
parent
ef5c4ba49a
commit
0c17434b4a
|
@ -31,7 +31,10 @@ module FactoryBot
|
||||||
private
|
private
|
||||||
|
|
||||||
def method_tracking_evaluator
|
def method_tracking_evaluator
|
||||||
@method_tracking_evaluator ||= Decorator::AttributeHash.new(decorated_evaluator, attribute_names_to_assign)
|
@method_tracking_evaluator ||= Decorator::AttributeHash.new(
|
||||||
|
decorated_evaluator,
|
||||||
|
attribute_names_to_assign,
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def decorated_evaluator
|
def decorated_evaluator
|
||||||
|
|
|
@ -8,7 +8,7 @@ module FactoryBot
|
||||||
|
|
||||||
def attributes
|
def attributes
|
||||||
@attributes.each_with_object({}) do |attribute_name, result|
|
@attributes.each_with_object({}) do |attribute_name, result|
|
||||||
result[attribute_name] = send(attribute_name)
|
result[attribute_name] = @component.send(attribute_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -178,7 +178,7 @@ describe "initialize_with doesn't duplicate assignment on attributes accessed fr
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "initialize_with has access to all attributes for construction" do
|
describe "initialize_with has access to all attributes for construction" do
|
||||||
before do
|
it "assigns attributes correctly" do
|
||||||
define_class("User") do
|
define_class("User") do
|
||||||
attr_reader :name, :email, :ignored
|
attr_reader :name, :email, :ignored
|
||||||
|
|
||||||
|
@ -204,9 +204,7 @@ describe "initialize_with has access to all attributes for construction" do
|
||||||
initialize_with { new(attributes) }
|
initialize_with { new(attributes) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
it "assigns attributes correctly" do
|
|
||||||
user_with_attributes = FactoryBot.build(:user)
|
user_with_attributes = FactoryBot.build(:user)
|
||||||
expect(user_with_attributes.email).to eq "person1@example.com"
|
expect(user_with_attributes.email).to eq "person1@example.com"
|
||||||
expect(user_with_attributes.name).to eq "person1"
|
expect(user_with_attributes.name).to eq "person1"
|
||||||
|
@ -214,6 +212,29 @@ describe "initialize_with has access to all attributes for construction" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "initialize_with with an 'attributes' attribute" do
|
||||||
|
it "assigns attributes correctly" do
|
||||||
|
define_class("User") do
|
||||||
|
attr_reader :name
|
||||||
|
|
||||||
|
def initialize(attributes:)
|
||||||
|
@name = attributes[:name]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
FactoryBot.define do
|
||||||
|
factory :user do
|
||||||
|
attributes { { name: "Daniel" } }
|
||||||
|
initialize_with { new(attributes) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
user = FactoryBot.build(:user)
|
||||||
|
|
||||||
|
expect(user.name).to eq("Daniel")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "initialize_with for a constructor that requires a block" do
|
describe "initialize_with for a constructor that requires a block" do
|
||||||
it "executes the block correctly" do
|
it "executes the block correctly" do
|
||||||
define_class("Awesome") do
|
define_class("Awesome") do
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
describe FactoryBot::Decorator::AttributeHash do
|
||||||
|
describe "#attributes" do
|
||||||
|
it "returns a hash of attributes" do
|
||||||
|
attributes = { attribute_1: :value, attribute_2: :value }
|
||||||
|
component = double(:component, attributes)
|
||||||
|
|
||||||
|
decorator = described_class.new(component, [:attribute_1, :attribute_2])
|
||||||
|
|
||||||
|
expect(decorator.attributes).to eq(attributes)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with an attribute called 'attributes'" do
|
||||||
|
it "does not call itself recursively" do
|
||||||
|
attributes = { attributes: :value }
|
||||||
|
component = double(:component, attributes)
|
||||||
|
|
||||||
|
decorator = described_class.new(component, [:attributes])
|
||||||
|
|
||||||
|
expect(decorator.attributes).to eq(attributes)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue