Search code examples
ruby-on-railsrenderpartial

Rails partial works when invoked at the end of a page, not in the middle


I have the following code section:

<%= link_to 'Edit', edit_computer_path(@computer) %> |
<%= link_to 'Back', computers_path %>

<div>
  <h2>New config</h2>
  <%= render "kernel_configs/computerkernelconfig", :locals => { :computer => @computer } %>
</div>

<div>
  <h2>Submitted Configs</h2>
  <table>
    <tr>
      <th>Rating</th>
      <th>Title</th>
      <th>Contributor</th>
      <th>Features</th>
      <th>Config file</th>
      <th></th>
    </tr>

    <%= render @computer.kernel_configs %>

  </table>
</div>

which complains there is no route:

ActionController::RoutingError (No route matches {:action=>"edit", :controller=>"kernel_configs", :id=>#}):
app/views/kernel_configs/_kernel_config.html.erb:13:in _app_views_kernel_configs__kernel_config_html_erb___3252059691242213705_26424640' app/views/computers/show.html.erb:34:in _app_views_computers_show_html_erb___4341746115390966607_23819760'
app/controllers/computers_controller.rb:18:in `show'

If I move the first render after the second, then the page renders fine without errors. So I'm pretty sure there is a route, in fact one of these probably:

 edit_kernel_config GET    /kernel_configs/:id/edit(.:format)   kernel_configs#edit
 edit_computer_kernel_config GET    /computers/:computer_id/kernel_configs/:id/edit(.:format)    kernel_configs#edit

For reference, the partial is here:

<%= form_for( [@computer,@computer.kernel_configs.build], :multipart => true ) do |form| %>

  <div class="field">
    <%= form.label :title %>
    <%= form.text_field :title %>
  </div>

  <div class="field">
    <%= form.label :contributed_by %>
    <%= form.text_field :contributed_by %>
  </div>

  <div class="field">
    <%= form.label :features %><br />
    <%= form.text_area :features %>
  </div>

  <div class="field">
    <%= form.label "Upload File" %><br />
    <%= form.file_field :kernelconfig %>
  </div>

  <div class="field">
    <%= form.submit %>
  </div>

<% end %>

_kernel_congif partial:

<tr>

  <td><%= kernel_config.rating %></td>

  <td><%= kernel_config.title %></td>

  <td><%= kernel_config.contributed_by %></td>

  <td><%= kernel_config.features %></td>

  <td><%= truncate kernel_config.kernelconfig %></td>

  <td><%= link_to 'Edit', edit_kernel_config_path(kernel_config) %></td>

</tr>

Solution

  • What is happening is that since you have the form before the list, you are calling @computer.kernel_configs.build which adds a new empty record to @computer.kernel_configs.

    Your partial is probably crashing because you are trying to display this new empty record.

    This is why when you move the form partial below the collection partial, it works just fine.

    EDIT:

    As expected, you have are trying to create a link to an empty object.

    The error is happening at the following line:

    # _kernel_config.html.erb
    <td><%= link_to 'Edit', edit_kernel_config_path(kernel_config) %></td>
    

    The edit_kernel_config_path cannot find a path to an empty kernel_config.