1

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
2
  • 1
    For what it's worth, you do not need to create a special method for this. Simply pass your attributes in a put/patch link to your controller's normal update method and it will work. Commented Dec 28, 2015 at 22:17
  • Thanks for the advice. I've come back to this app after being away awhile. Can't honestly remember why I did it the way I did. Commented Dec 29, 2015 at 2:34

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Good advice. I was thinking I had already tried that and after looking at your example I realized I had forgotten the 'do' after 'resources :books'. Dang, always the smallest things. Appreciate the help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.