views:

160

answers:

2

I have a nested form in a rails view that is called like this

<% f.fields_for :invoice_item_numbers do |item_no_form| %>
    <%= render 'invoice_item_number', :f => item_no_form %>
<% end %>

and the partial (_invoice_item_number.html.erb) looks like this

<div class='invoice_item_numbers'>
<% if f.object.new_record? %>
        <li><%= f.label :item_number %><%= f.text_field :item_number %>
    <%= link_to_function "remove", "$(this).parent().remove()", :class => 'remove_link' %></li>
<% else %>
    <li class="inline"><%= f.label :item_number %><%= f.text_field :item_number %>
    </li><li class="inline"><%= f.label :description %><%= invoice_item_number.description %></li><li><%= f.label :amount %><%= f.text_field :amount %>
    <%= f.check_box '_destroy', :class => 'remove_checkbox' %>
    <%= f.label '_destroy', 'remove', :class => 'remove_label' %></li>
<% end %>
</div>

This fails with the error message

undefined method `description' for nil:NilClass

Why does invoice_item_number return a nil object in this partial? It is obviously being defined somehow because if I change it to something else (e.g. item_number.description then the error message becomes undefined local variable or methoditem_number' for #instead. The invoice_item_number object that is being displayed by this partial is being used perfectly well by the form helpers as<%= f.text_field :item_number %>and<% f.text_field :amount %>both work perfectly well. I have tried a number of solutions such as using@invoice_item_number` and explicitly defining an object in the render method but these have not worked.

Presumably there is a very simple answer to this.

+2  A: 

how about changing:

<%= invoice_item_number.description %>

to

<%= f.label :description %>

or if you need a field:

<%= f.text_field :description %>
ohho
Well, I've already got f.label :description in there. Interestingly, if I do put in f.text_field :description this accesses the description method exactly as I want, but I don't want a text field, I just want the text. Thanks though.
brad
invoice_item_number is nil (not defined yet) in the partial. if you want to access the model data, you needed to define @invoice_item_number in the controller and access by @invoice_item_number.description
ohho
Hmm, but invoice_item_number is a nested attribute in this case. The parent attribute (invoice) is defined in the controller with @invoice=Invoice.find(params[:id]). What I really want to access is invoice.invoice_item_number.description but I'm not sure how to in my partial.
brad
you can pass multiple parameters to a partial, the syntax is: <%= render :partial => 'invoice_item_number', :locals => { :f => item_no_form, :x => 123 } %>then you can use x as a local variable inside the partial.
ohho
+2  A: 

Just re-read the Ryan's scraps post on nested forms at http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes and found the answer. It was sort of in my code already but I didn't understand what was happening. I can access the invoice_item_number object with f.object so replacing <%= invoice_item_number.description %> with <%= f.object.description %> solved my problem.

brad
sweet. (I misread your question, sorry ;-)
ohho
No problem. I'm grateful you took the time to read it. Thanks.
brad