Search code examples
jqueryruby-on-railsnested-resourcesnested-routes

Rails JQUERY Toggle with Nested Resources


I'm trying to figure out how to toggle a "finish" action with nested resources in rails. For whatever reason I can't get it to do what I want. I keep getting 'Couldn't find List without an ID'. Which makes sense but I can't configure it so that it will work. Was curious if anyone knew how to configure things as to get this to function properly. I'm assuming it probably has something to do with my routes file or the each block maybe?? in the partial. Thanks.

Code Below.

Books Controller

def finish
  @list = List.find(params[:list_id])
  @book = @list.books.find(params[:id])
  @book.update(finished: true)
    respond_to do |format|
        format.html {redirect_to list_path(@list)}
        format.js {}
    render @list
end
end

def unfinish
  @list = List.find(params[:list_id])
  @book = @list.books.find(params[:id])
  @book.update(finished: false)
    respond_to do |format|
        format.html {redirect_to list_path(@list)}
        format.js {}
    render @list
 end
end

Books Partial

 <table class="table table-hover">
<thead>
  <tr>
    <th>Title</th>
    <th>Author</th>
    <th>Pages</th>
    <th>Did you finish the book?</th>
    <th>Remove book from list</th>
  </tr>
</thead>
  <tbody>
    <% @books.each do |book| %>
      <tr>
        <td><%=book.name %></td>
        <td><%=book.author %></td>
        <td><%=book.pages %></td>
        <% if book.finished? %>
        <td class="unfinish-book"><%=link_to 'Finished',      unfinish_book_path(book), :method => :put, remote: true %></td>
    <% else %>
    <td class="finish-book"><%=link_to 'Mark as Finished', finish_book_path(book), :method => :put, remote: true %></td>
    <% end %>
    <td class><%= link_to '|Remove Book|', list_book_path(@list, book), method: :delete, data: { confirm: 'Are you sure?'} %></td>
<% end %>
  </tr>
  </tbody>
  </table>

Routes

 Rails.application.routes.draw do
   root 'lists#index'

   resources :lists do
     resources :books
   end

  resources :books do
    member do
      put :finish
      put :unfinish
    end
  end
 end

Solution

  • If you look at your rake routes output then you'll see the following finish/unfinish routes:

      finish_book PUT    /books/:id/finish(.:format)   books#finish
    unfinish_book PUT    /books/:id/unfinish(.:format) books#unfinish
    

    As you can see, there is no :list_id parameter in those URLs, only the :id parameter, so params[:list_id] in your controller code will have no value, hence the error you're getting.

    You should probably have those finish/unfinish routes inside the nested books resource, like so:

    resources :lists do
      resources :books do
        member do
          put :finish
          put :unfinish
        end
      end
    end
    

    Then adjust your link_to calls to send: finish_list_book_path(@list, book) and the unfinish equivalent.