adding nested fields dynamically with parent.send(association).build instead of reflect_on_association(association).klass.new

StackOverflow https://stackoverflow.com/questions/18980282

Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top