Ruby-on-rails – Form Submit button only works after reload

ruby-on-railsruby-on-rails-4

I have an index page that builds a table, and I am trying to allow users to edit line's in the table. I am trying to do this in the most basic way possible – no javascript, ajax, etc, unless Rails is supplying it.

I have my table displaying fine in the index method, and there is a form as the last row in the table that can be used to add a new row. The new form works fine. Each row has an edit link that routes to the controller's edit method. The controller sets the object to be edited, and renders index, this time with a form in the row that is to be edited. My problem is that this form will not submit, but if I refresh the page it will submit.

The fact that the page will submit after a refresh is very confusing. I don't see how a refresh would do anything different then clicking the link (it should still go through the same routing, with the same variables right?) and I can't see any difference in the form html before and after the refresh. Any have ideas on what might be happening?

I am not sure what code to even start looking in, but here goes;

index.html.erb

...
<tbody>
  <% @boms.each do |line| %>
   <% if line == @bom %>
     <%= render("form_in_table", form_objects: @bom , button_text: "Update") %>
    <% else %>
      <%= render("bom_in_table", line: line) %>
    <% end %>
  <% end %>
  <% if @bom.new_record? %>
    <%= render("form_in_table", form_objects: [@li, @bom] , button_text: "Add") %>
  <% end %>
</tbody>
...

_form_in_table.html.erb

<%= form_for(form_objects, html: {class: "form-in-table"}) do |f| %>
  <tr>
    <td><%= f.text_field :quantity %></td>
    <td colspan="2">
      <%= f.select(:part_id,
                   options_from_collection_for_select(@parts, :id, :pricebook_name),
                   prompt: "Select a Part",) %></td>
    <td></td>
    <td></td>
    <td></td>
    <td><%= f.submit(button_text, class: "btn btn-primary btn-mini") %></td>
  </tr>
<% end %>

_bom_in_table.html.erb

<tr>
  <td><%= line.quantity%></td>
  <td><%= line.part_number %></td>
  <td><%= line.part_description %></td>
  <td><%= number_to_currency(line.part_cost) %></td>
  <td><%= line.part_unit %></td>
  <td><%= number_to_currency(line.extension) %></td>
  <td><%= link_to('Edit', edit_bom_path(line)) %></td>
</tr>

boms_controller.rb

...
def edit
  @bom = Bom.find(params[:id])
  @li = @bom.line_item
  @boms = @li.boms.sorted_by_part_number
  @parts = Part.sorted_by_number
  render 'index'
end
...

In case this is useful to deciphering the code/intent, I have collections of line_items, parts, and boms; line_item has many boms, and line_item has many parts through boms. In addition to the part/line item relationship, boms have a quantity. Bom is short for bill of materials. @li is the line_item that is being manipulated. The form I having trouble with is for viewing/adding/editing the collection of boms (quantitys and parts) that belong to a line item.

ADDING LOGS

Started GET "/line_items/8/boms" for 127.0.0.1 at 2013-10-14 14:27:27 -0400
Processing by BomsController#index as HTML
  Parameters: {"line_item_id"=>"8"}
  [1m[35mLineItem Load (0.0ms)[0m  SELECT "line_items".* FROM "line_items" WHERE "line_items"."id" = ? LIMIT 1  [["id", "8"]]
  [1m[36mLineItemSubClass Load (1.0ms)[0m  [1mSELECT "line_item_sub_classes".* FROM "line_item_sub_classes" WHERE "line_item_sub_classes"."id" = ? ORDER BY "line_item_sub_classes"."id" ASC LIMIT 1[0m  [["id", 8]]
  [1m[35mLineItemClass Load (4.0ms)[0m  SELECT "line_item_classes".* FROM "line_item_classes" WHERE "line_item_classes"."id" = ? ORDER BY "line_item_classes"."id" ASC LIMIT 1  [["id", 1]]
  Rendered shared/_error_messages.html.erb (3.0ms)
  [1m[36mBom Load (1.0ms)[0m  [1mSELECT "boms".* FROM "boms" INNER JOIN "parts" ON "parts"."id" = "boms"."part_id" WHERE "boms"."line_item_id" = ? ORDER BY "parts".number ASC[0m  [["line_item_id", 8]]
  [1m[35mPart Load (0.0ms)[0m  SELECT "parts".* FROM "parts" WHERE "parts"."id" = ? ORDER BY "parts"."id" ASC LIMIT 1  [["id", 1]]
  Rendered boms/_bom_in_table.html.erb (96.0ms)
  [1m[36mPart Load (1.0ms)[0m  [1mSELECT "parts".* FROM "parts" ORDER BY "parts".number ASC[0m
  Rendered boms/_form_in_table.html.erb (103.0ms)
  [1m[35m (24.0ms)[0m  SELECT SUM(quantity * cost) AS sum_id FROM "parts" INNER JOIN "boms" ON "boms"."part_id" = "parts"."id" WHERE "boms"."line_item_id" = 8
  Rendered boms/index.html.erb within layouts/boms (477.0ms)
  Rendered layouts/_shim.html.erb (1.0ms)
  Rendered layouts/_header.html.erb (0.0ms)
  Rendered layouts/_footer.html.erb (0.0ms)
  Rendered layouts/application.html.erb (69.0ms)
Completed 200 OK in 671ms (Views: 601.0ms | ActiveRecord: 31.0ms)


Started GET "/boms/22/edit" for 127.0.0.1 at 2013-10-14 14:28:13 -0400
Processing by BomsController#edit as HTML
  Parameters: {"id"=>"22"}
  [1m[36mBom Load (0.0ms)[0m  [1mSELECT "boms".* FROM "boms" WHERE "boms"."id" = ? LIMIT 1[0m  [["id", "22"]]
  [1m[35mLineItem Load (1.0ms)[0m  SELECT "line_items".* FROM "line_items" WHERE "line_items"."id" = ? ORDER BY "line_items"."id" ASC LIMIT 1  [["id", 8]]
  [1m[36mLineItemSubClass Load (1.0ms)[0m  [1mSELECT "line_item_sub_classes".* FROM "line_item_sub_classes" WHERE "line_item_sub_classes"."id" = ? ORDER BY "line_item_sub_classes"."id" ASC LIMIT 1[0m  [["id", 8]]
  [1m[35mLineItemClass Load (0.0ms)[0m  SELECT "line_item_classes".* FROM "line_item_classes" WHERE "line_item_classes"."id" = ? ORDER BY "line_item_classes"."id" ASC LIMIT 1  [["id", 1]]
  Rendered shared/_error_messages.html.erb (0.0ms)
  [1m[36mBom Load (1.0ms)[0m  [1mSELECT "boms".* FROM "boms" INNER JOIN "parts" ON "parts"."id" = "boms"."part_id" WHERE "boms"."line_item_id" = ? ORDER BY "parts".number ASC[0m  [["line_item_id", 8]]
  [1m[35mPart Load (0.0ms)[0m  SELECT "parts".* FROM "parts" ORDER BY "parts".number ASC
  Rendered boms/_form_in_table.html.erb (25.0ms)
  [1m[36m (0.0ms)[0m  [1mSELECT SUM(quantity * cost) AS sum_id FROM "parts" INNER JOIN "boms" ON "boms"."part_id" = "parts"."id" WHERE "boms"."line_item_id" = 8[0m
  Rendered boms/index.html.erb within layouts/boms (41.0ms)
  Rendered layouts/_shim.html.erb (0.0ms)
  Rendered layouts/_header.html.erb (1.0ms)
  Rendered layouts/_footer.html.erb (0.0ms)
  Rendered layouts/application.html.erb (54.0ms)
Completed 200 OK in 113ms (Views: 104.0ms | ActiveRecord: 3.0ms)


Started GET "/boms/22/edit" for 127.0.0.1 at 2013-10-14 14:28:37 -0400
Processing by BomsController#edit as HTML
  Parameters: {"id"=>"22"}
  [1m[35mBom Load (0.0ms)[0m  SELECT "boms".* FROM "boms" WHERE "boms"."id" = ? LIMIT 1  [["id", "22"]]
  [1m[36mLineItem Load (0.0ms)[0m  [1mSELECT "line_items".* FROM "line_items" WHERE "line_items"."id" = ? ORDER BY "line_items"."id" ASC LIMIT 1[0m  [["id", 8]]
  [1m[35mLineItemSubClass Load (0.0ms)[0m  SELECT "line_item_sub_classes".* FROM "line_item_sub_classes" WHERE "line_item_sub_classes"."id" = ? ORDER BY "line_item_sub_classes"."id" ASC LIMIT 1  [["id", 8]]
  [1m[36mLineItemClass Load (1.0ms)[0m  [1mSELECT "line_item_classes".* FROM "line_item_classes" WHERE "line_item_classes"."id" = ? ORDER BY "line_item_classes"."id" ASC LIMIT 1[0m  [["id", 1]]
  Rendered shared/_error_messages.html.erb (0.0ms)
  [1m[35mBom Load (1.0ms)[0m  SELECT "boms".* FROM "boms" INNER JOIN "parts" ON "parts"."id" = "boms"."part_id" WHERE "boms"."line_item_id" = ? ORDER BY "parts".number ASC  [["line_item_id", 8]]
  [1m[36mPart Load (0.0ms)[0m  [1mSELECT "parts".* FROM "parts" ORDER BY "parts".number ASC[0m
  Rendered boms/_form_in_table.html.erb (5.0ms)
  [1m[35m (0.0ms)[0m  SELECT SUM(quantity * cost) AS sum_id FROM "parts" INNER JOIN "boms" ON "boms"."part_id" = "parts"."id" WHERE "boms"."line_item_id" = 8
  Rendered boms/index.html.erb within layouts/boms (27.0ms)
  Rendered layouts/_shim.html.erb (1.0ms)
  Rendered layouts/_header.html.erb (8.0ms)
  Rendered layouts/_footer.html.erb (0.0ms)
  Rendered layouts/application.html.erb (60.0ms)
Completed 200 OK in 131ms (Views: 94.0ms | ActiveRecord: 2.0ms)


Started GET "/assets/application.css?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400


Started GET "/assets/custom.css?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400


Started GET "/assets/jquery.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400


Started GET "/assets/jquery_ujs.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400


Started GET "/assets/bootstrap-transition.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400


Started GET "/assets/bootstrap-affix.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400


Started GET "/assets/bootstrap-alert.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400


Started GET "/assets/bootstrap-collapse.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400


Started GET "/assets/bootstrap-modal.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400


Started GET "/assets/bootstrap-carousel.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400


Started GET "/assets/bootstrap-button.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400


Started GET "/assets/bootstrap-dropdown.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400


Started GET "/assets/bootstrap-scrollspy.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400


Started GET "/assets/bootstrap-tab.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400


Started GET "/assets/bootstrap-typeahead.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400


Started GET "/assets/bootstrap-tooltip.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400


Started GET "/assets/bootstrap-popover.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400


Started GET "/assets/bootstrap.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400


Started GET "/assets/turbolinks.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400


Started GET "/assets/parts.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400


Started GET "/assets/application.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400

Best Answer

I believe this is an HTML issue, not a Rails issue. Per this discussion Form inside a table, <form> can not be placed inside <table> or <tbody> or <tr>. After moving the <form> to wrap the table and putting the controls inside the respective <td> the form works.

I still don't understand why refreshing the page made the form work, but...

Related Topic