I am working on an invoice tracking system for my business and have
gotten so close to getting this portion to work!

I have an Invoice model with many InvoiceItems.

I am following this example (which is based off of ryan daigle's post)
http://transfs.com/devblog/2009/06/26/nested-forms-with-rails-2-3-helpers-and-javascript-tricks/
and I've looked at a couple of other similar examples as well.

I can generate the fields just fine, but when I try to add more fields
and save, I get the following message:

ActiveRecord::UnknownAttributeError in InvoicesController#update

unknown attribute: invoice_items

Parameters:
{"commit"=>"Submit",
 "invoice"=>{"invoice_items_attributes"=>{"1248641854778"=>
{"invoice_items"=>{"project_id"=>"9",
 "_delete"=>"0",
 "amount_billed"=>"48"}},
 "0"=>{"project_id"=>"8",
 "_delete"=>"0",
 "id"=>"29",
 "amount_billed"=>"32.00"}},
 "date_due(1i)"=>"2009",
 "date_due(2i)"=>"8",
 "date_due(3i)"=>"9"},
 "client_id"=>"1",
 "_method"=>"put",
 "authenticity_token"=>"WiwqytxYy/KZSrO76kWKGCH2hMlgiCj1lSedQV3h6KA=",
 "id"=>"17"}

The second line of parameters looks like it goes one level too deep
with the Hash key "invoice_items". If you go further down to where the
project_id is 8, that is the record that was already in existance.
Below is the yaml output of the request.

Here is the same request converted to yaml:

--- !map:HashWithIndifferentAccess
commit: Submit
invoice: !map:HashWithIndifferentAccess
  invoice_items_attributes: !map:HashWithIndifferentAccess
    "1248641854778": !map:HashWithIndifferentAccess
      invoice_items: !map:HashWithIndifferentAccess
        project_id: "9"
        _delete: "0"
        amount_billed: "48"
    "0": !map:HashWithIndifferentAccess
      project_id: "8"
      _delete: "0"
      id: "29"
      amount_billed: "32.00"
  date_due(1i): "2009"
  date_due(2i): "8"
  date_due(3i): "9"
authenticity_token: WiwqytxYy/KZSrO76kWKGCH2hMlgiCj1lSedQV3h6KA=
_method: put
client_id: "1"
action: update
id: "17"
controller: invoices

My form basically looks like this:


<% form_for [...@client, @invoice], setup_invoice(@invoice) do |f| %>
  <%= f.error_messages %>

<h2>Add Projects:</h2>
  <ul id="invoice_items">
    <li class="invoice_item">

      <% f.fields_for :invoice_items do |invoice_item| %>
        <%= invoice_item.collection_select :project_id,
@client.projects, :id, :title, { :include_blank => true } %>
        <%= invoice_item.label :amount_billed, "Amount to bill" %>
        <%= invoice_item.text_field :amount_billed %>

        <% if invoice_item.object.new_record? %>
                <%= link_to_function "clear", "this.up('.invoice_item').remove
()" %>
        <% else %>
                <%= invoice_item.check_box '_delete' %>
                <%= invoice_item.label '_delete', 'Remove' %>
        <% end %>
      <% end %>

    </li>
  </ul>
  <%= link_to_new_nested_form "Add a Project", f, :invoice_items %>
  <hr />
  <p>
    <%= f.label :date_due %><br />
    <%= f.date_select :date_due,  :default => 15.days.from_now,
                                  :order => [:day, :month, :year],
                                  :start_year => Time.now.year

                                   %>
  </p>
  <p><%= f.submit "Submit" %></p>
<% end %>

I'm just not sure how to change the code to make it work!

Here is what I have in my application_helper.rb:

   def generate_html(form_builder, method, options = {})
     options[:object] ||=
form_builder.object.class.reflect_on_association(method).klass.new
     options[:partial] ||= method.to_s.singularize
     options[:form_builder_local] ||= :f
     form_builder.fields_for(method, options[:object], :child_index =>
'NEW_RECORD') do |f|
       render(:partial => options[:partial], :locals => { options
[:form_builder_local] => f })
     end
   end

   def link_to_new_nested_form(name, form_builder, method, options =
{})
     options[:object] ||=
form_builder.object.class.reflect_on_association(method).klass.new
     options[:partial] ||= method.to_s.singularize
     options[:form_builder_local] ||= :f
     options[:element_id] ||= method.to_s
     options[:position] ||= :bottom
     link_to_function name do |page|
       html = generate_html(form_builder,
                           method,
                           :object => options[:object],
                           :partial => options[:partial],
                           :form_builder_local => options
[:form_builder_local]
                          )
             page << %{
               $('#{options[:element_id]}').insert({ #{options
[:position]}: "#{ escape_javascript html }".replace(/NEW_RECORD/g, new
Date().getTime()) });
             }
     end
   end

I've had other problems with this approach as well, but if I can at
least get it to save to the db I should be okay.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to