The code is confusing because it’s written to be useful in all settings. If you translate it to your models, it should become more clear.
f is your form builder.
f.object is the object that the form is for. In your case, @job_sheet.
f.object.send(association) is then equivalent to @job_sheet.products, which this code then calls klass.new on, which says “get me the class of that association and call the initializer”.
So all of the above lines just gave you a new object for the association and assigns it to new_object. Then the code goies about the call to fields_for. It sets the child_index to new_object.object_id simply because it’s a convenient unique identifier. Within the fields_for block there’s the call to render a partial which will follow the convention of the association singularized appended with _fields. So in your case, it’d be _product_fields.html.erb.
The code ends with the call to link_to to tie all of this together.
As I said, it’s a bit opaque because it’s written to be generally useful. I think it’s interesting to try to understand this code but if I were doing this today I’d probably go with cocoon. It’s API might be a bit easier to read too.
Thanks @derekprior things are a little more clear to me now. Is it possible to do this in a Rails console or IRB session, so I can see what each step is doing?
You can play with the non-form related things in a console without a problem. To use the form stuff (form_for, fields_for, etc), you’ll need to include ActionView::Helpers in your console session.
Not that I’m aware of. I’m no longer a pro subscriber to RailsCasts, but from what I can remember it lays out the ways you would go about building this yourself. You could eliminate some of the misdirection in the RailsCasts sample and hardwire it to your use case - that is - render a specific partial, call new on a specific relation rather than going through send, etc).
The one part of the code I didn’t explain yet is the link itself. It’s creating an HTML link that has as a data attribute HTML that represents the fields needed for the nested model. When the link is clicked, JavaScript grabs that html from the data attribute and puts it into the form (incrementing the id, I believe, so that it’s always unique as you keep clicking ‘add’).
Cocoon does something very similar. Last I checked instead of using a data attribute it uses a hidden div to the same effect.
def link_to_add_fields(name, job_sheet)
new_object = job_sheet.products.new
id = new_object.object_id
**not to sure what to do with the fields part**
link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
end
Also my form is a nested resource so my main form is <%= form_for([@company, @job_sheet]) do |form| %>
That looks like a start. Then you need to do the same fields_for stuff done above (but you can hardcode your partial) and add the javascript, etc.
THis is really rather complicated. As I said, I think it’s great to try and figure out what’s going on here, but in production I’d probably rely on cocoon.