问题
I have two models that can be commented on, Books and Movies.
The comments are votable
In my routes file:
resources :books, :path => '' do
resources :comments do
member do
post :vote_up
end
end
In my comments controller:
class CommentsController < ApplicationController
def create
book.comments.create(new_comment_params) do |comment|
comment.user = current_user
end
redirect_to book_path(book)
end
private
def new_comment_params
params.require(:comment).permit(:body)
end
def book
@book = Book.find(params[:book_id])
end
def vote_up
begin
current_user.vote_for(@comment = Comment.find(params[:id]))
render :nothing => true, :status => 200
rescue ActiveRecord::RecordInvalid
render :nothing => true, :status => 404
end
end
end
In my view:
<%= link_to('vote for this post!', vote_up_book_comment_path(comment),
:method => :post) %>
I keep on getting this error:
No route matches {:action=>"vote_up", :controller=>"comments", :id=>nil, :book_id=>#<Comment id:
3, body: "fantastic read!", book_id: 113, created_at: "2014-02-15 17:08:10", updated_at:
"2014-02-15 17:08:10", user_id: 8>, :format=>nil} missing required keys: [:id]
This is the gem I am using for the voting: https://github.com/bouchard/thumbs_up
The comments can belong to either the books or movies, how do I set this up in the routes? Also, how do I set up the votes in the routes? (all the comments are votable)
回答1:
If you run rake routes
, you'll probably get a line in the output that reads like this:
vote_up_book_comment POST /:book_id/comments/:id/vote_up(.:format) comments#vote_up
Pay special attention to this part — it's telling you what the vote_up_book_comment_path
method expects as arguments:
/:book_id/comments/:id/vote_up(.:format)
Also, your error message is giving you a few hints:
No route matches ...
:id=>nil, :book_id=>#<Comment id: 3 ...
missing required keys: [:id]
The path helper expects an id (for the comment) and a book_id, and the order in which they are required is shown in rake routes
(book_id first, then id).
So, in sum, you need to pass a book
to vote_up_book_comment_path
:
<%= link_to('vote for this post!', vote_up_book_comment_path(@book, comment), :method => :post) %>
回答2:
Because you are using member
in your routes, rails requires an id in the url. In vote_up_book_comment_path(comment)
you supply a book
id, but no comment
id. It interpreted the comment
argument as a book. To fix this, include a book object, changing vote_up_book_comment_path(comment)
to vote_up_book_comment_path(@book, comment)
. In your new
method of your controller, include the book
variable also so your view template can access it.
To set up comments in either the books or movies:
Because comments are separate from books or videos, you do not want to nest them under books. Instead, have comments be a separate route, and only have the route nested under books or videos when you are new
ing or edit
ing. That way you can have a hidden field in your view template that stores whether it's a book or a video, and then pass it along to the controller. Now the controller has the necessary information to know whether it's a book_id
or a movie_id
.
It would look something like this in the code:
resources :books do
resources :comments, only: [:new, :edit]
end
You would do this for all resources you want. Finally for comments you would do something like this:
resources :comments, except: [:new, :edit]
来源:https://stackoverflow.com/questions/21801836/routes-on-comments-and-votes