I'm using simple_form's fields_for and add fields dynamically with the link_to_add_fields
method proposed by Ryan Bates (Railscast).
The Problem I have is that
f.object.class.reflect_on_association(association).klass.new
, which is used to instantiate the model for the additional fields, creates a completely empty record (order_id is not being set), thus my delegated method results in an error.
If you instead use
send(:line_items).build
to instantiate the new record, it already has the parent's id
set:
# order.rb
class Order < ActiveRecord::Base
has_many :line_items
def price_currency
"USD"
end
end
# line_item.rb
class LineItem < ActiveRecord::Base
belongs_to :order
delegate :price_currency, :to => :order
end
# rails console
> order = Order.last # must be persisted
> line_item1 = order.class.reflect_on_association(:line_items).klass.new #=> #<LineItem id: nil, order_id: nil, created_at: nil, updated_at: nil>
> line_item2 = order.send(:line_items).build #=> #<LineItem id: nil, order_id: 1, created_at: nil, updated_at: nil>
> line_item1.price_currency #=> RuntimeError: LineItem#price_currency delegated to order.price_currency, but order is nil
> line_item2.price_currency #=> "USD"
My questions: Why does Ryan Bates use
f.object.class.reflect_on_association(association).klass.new
to instantiate the model? Is using #send
a bad thing, or is there something else I missed about the send(association)
way?
TL;DR:
Can I savely replace
f.object.class.reflect_on_association(association).klass.new
with
f.object.send(association).build
without problems?
Why does Ryan Bates use
f.object.class.reflect_on_association(association).klass.new
to instantiate the model?
Because an object that .accepts_nested_attributes
for a collection does not need to have the collection elements linked to it at the time of building the form. This will happen automatically later on (if you use fields_for
). If you need the link, I don't see anything wrong with using order.line_items.build
or order.send(:line_items).build
.
So
Can I safely replace
f.object.class.reflect_on_association(association).klass.new
with
f.object.send(association).build
without problems?
Yes, you can.