When I use this link:
<%= link_to "upvote", post_upvote_path(post), method: :put %>
I get error :
undefined method `liked_by' for nil:NilClass
Which is caused because variable @post inside method upvote is not properly assigned.
def upvote
@post = current_post
@post.liked_by current_user
redirect_to @post
end
private
def current_post
current_user.posts.find_by(id: params[:id])
end
private method current_post works fine in other methods inside this controller. However, inside this method it doesn't. For example If I used:
def upvote
@post = Post.first
@post.liked_by current_user
redirect_to @post
end
instead, it would work fine, except for the part it would upvote first post instead of the one where link is clicked. What is the right approach to this problem? How do I assign this variable properly to work for post where upvote link is clicked?
The rake routes | grep posts
output:
I noticed that this method has /posts/:post_id ... while others use :id . That might be the issue, how do I change it?
In your link_to you're passing post...is it in the context of an @posts loop? What page are you on when the voting is being done?
Try this:
def upvote
puts "params: #{params.inspect}"
@post = Post.find(params[:id]) # if this isn't working check out that puts statement in the stack trace
@post.liked_by current_user
redirect_to post_path(@post)
end
in your routes file there is
post_upvote /posts/:post_id/upvote
and not post_upvote /posts/:id/upvote
so actually
when you pass post to post_upvote_path method like that post_upvote_path( post)
in your controller you want to do params[:post_id]
and not params[:id]
because of what you wrote in your routes file
def current_post
current_user.posts.find_by(id: params[:post_id]) #post_upvote /posts/:post_id/upvote
end
I found where was the problem. In routes file I needed to nest member method like this:
resources :posts do
member do
put 'upvote', to: 'posts#upvote'
end
end
And then change view to this:
<%= link_to "upvote", upvote_post_path(post), method: :put %>
And this method in controller works just right:
def upvote
@post = Post.find(params[:id])
@post.liked_by current_user
end
This:
<%= link_to "upvote", post_upvote_path(post), method: :put %>
Should become:
<%= link_to "upvote", post_upvote_path(@post), method: :put %>