Acts as votable routing error - ruby-on-rails

I'm trying to use acts as votable gem and can't understand how it actually works. I couldn't find any good workarounds or tutorials for it. I tried implementing the accepted solution mentioned here but got Routing Error. Can anyone help me out with a good tutorial or point me out how to get it to work editing the following code.
routes.rb
resources :posts do
member do
put "like", to: "posts#upvote"
end
end
posts controller
def upvote
#post = Post.find(params[:id])
#post.liked_by current_user
redirect_to #post
end
show.html.erb
<%= link_to "Bookmark Post", like_post_path(#post, method: :put), class: "button tiny" %>

method attribute should be passed to the link_to method, not the path helper, like this
<%= link_to "Bookmark Post", like_post_path(#post), method: :put, class: "button tiny" %>

Related

RoR - how to make an .each loop on views pass a variable to the controller

Im trying to add votes to comments on my blog application. But i cant seem to be able to send the variable within the below loop to the controller:
<% #comments.each do |c| %>
<h1><%= c.title %></h1>
<p><%= c.content %></p>
<p><%= c.user.username %></p>
<% if current_user.id == c.user_id %>
<%= link_to "Edit", edit_comment_path(#post, c)%>
<%= link_to "Delete", delete_comment_path(#post, c), method: :delete, data: { confirm: "Are you sure?" }%>
<% end %>
<% if current_user.id != c.user_id %>
<p>Review this comment</p>
<%= link_to like_path(c), method: :put do %>
Upvote
<%= c.upvote %>
<% end %>
<%= link_to dislike_path(c), method: :put do %>
Downvote
<%= c.downvote %>
<% end %>
<% end %>
<% end %>
controller:
...
def upvote
object_comment = Comment.find(#comment.id)
object_comment.increment!(:upvote)
redirect_to show_path(#post)
end
def downvote
object_comment = Comment.find(#comment.id)
object_comment.increment!(:downvote)
redirect_to show_path(#post)
end
....
Routes:
Rails.application.routes.draw do
....
#Comments
post '/post/:post_id', to: 'comment#create', as: 'new_comments'
get '/post/:post_id/:comment_id/edit', to: 'comment#edit', as: 'edit_comment'
put '/post/:post_id/comment/:comment_id', to: 'comment#update', as: 'update_comment'
delete '/post/:id/:comment_id/', to: 'comment#destroy', as: 'delete_comment'
put 'like', to: "comment#upvote", as: 'like'
put 'dislike', to: "comment#downvote", as: 'dislike'
end
I would like to receive the 'c' stated on the each loop as a variable on the upvote and downvote methods to replace the #comment within object_comment = Comment.find(#comment.id), in order to increment the votes. is this possible?
As it is right i obviously receive the following error:
NoMethodError (undefined method `id' for nil:NilClass):
Your *_path methods do not know what to do with that single argument. (If you want to pass an object to your links, you might want to research RESTful routing. However, to solve it with your current routes, I suggest
<%= link_to "Downvote #{c.downvote}" dislike_path(id: c.id) %>
It should then be possible to access this id attribute in the controller via params.
def dislike
#comment = Comment.find(params[:id])
...
end
A couple of other things to think about:
It's very unusual to perform a put action on clicking a link. You might want to consider doing this as a get action instead.
Does the downvote method return something which is different for each comment? If not, it's standard practise to include it in the controller's helper.
You can get id in parameters, please check below methods
def upvote
object_comment = Comment.find(params[:id])
object_comment.increment!(:upvote)
redirect_to show_path(#post)
end
def downvote
object_comment = Comment.find(params[:id])
object_comment.increment!(:downvote)
redirect_to show_path(#post)
end
....
I think you're doing it wrong. You'll need to save the user's action on the comment with a model CommentVote for example that belongs to user and comment.
Then you'll need to do something like:
class CommentVote
belongs_to :comment
belongs_to :user
enum type: [:upvote, :downvote]
def self.vote(type:, comment_id:, user_id:)
comment_vote = CommentVote.where(comment_id: comment_id, user_id: user_id).first_or_initialize
comment_vote.type = type
comment_vote.save
end
end
And then do a after_save :update_counts in the CommentVote model:
def update_counts
self.comment.upvote = self.comment.comment_votes.upvote.count
self.comment.downvote = self.comment.comment_votes.downvote.count
self.comment.save
end
and you'll call it like: CommentVote.vote(type: :upvote, comment_id: 1, user_id: 1)

Rails destroy does not work and forwards to a wrong link

I am totally new to rails and struggle with the easiest stuff. I have the following problem:
When I try to destroy a search (from my model search) it does not work and I get redirected to "/search.48 (the search with id 48). It gives me the notice "We're sorry, but something went wrong." and in the console it says something with POST. Neither the search is deleted nor the redirect_to search_path is working. What am I doing wrong?
This is my controller:
def show
#searches = current_user.searches
end
def destroy
#search = Search.find(params[:id])
#search.destroy
flash[:success] = "Search deleted"
redirect_to search_path
end
This is my view show:
<% #searches.each do |search| %>
<%= search.title %>
<%= search.description %>
<%= button_to "delete", search, method: :destroy %>
My routes.rb:
get 'search' => 'searches#show'
resources :searches
And I also included <%= javascript_include_tag 'application' %> in the application.html.erb as well as //= require jquery and //= require jquery_ujs in the application.js file.
So I really can't find my mistake. Can someone help me?
In your view file, the code for the button should look like:
<%= button_to "delete", search, method: :delete %>
Note the method is :delete, not :destroy. It's a little confusing, because 'delete' is the REST verb, but 'destroy' is the controller action name.
have you tried:
<%= button_to "Delete", { action: "delete", id: search.id },
method: :delete %>
in you view. Also it appears you are redirecting to search_path but I am guessing you want searches_path.
I got it! In my router I wrote get 'search' => 'searches#show' and somehow my controller was confused with the search_path. Since I renamed it to get 'mysearches' => 'searches#show' and mysearches_path it works perfectly

No route matches [GET] "/links/1/like" with acts_as_votable

I'm trying to implement acts_as_votable gem as shown in this this tutorial
https://www.youtube.com/watch?v=7-1HCWbu7iU
Seems everything is workigng fine, except when I click on upvote or downvote, I get this error:
No route matches [GET] "/links/1/like"
This is the code for upvote / downvote function
<span class="upvote">
<%= link_to like_link_path(link), method: :put, class: "upvote-image" do %>
<% end %>
</span>
This is the routes.rb file:
resources :links do
member do
put "like", to: "links#upvote"
put "dislike", to: "links#downvote"
end
resources :comments
end
Here are the upvote and downvote actions in links_controller
def upvote
#link = Link.find(params[:id])
#link.upvote_by current_user
redirect_to :back
end
def downvote
#link = Link.find(params[:id])
#link.downvote_by current_user
redirect_to :back
end
Any idea on how to resolve this?
Looks like the problem is down to your link having a GET method, rather than PUT:
No route matches [GET] "/links/1/like"
I can only surmise that your link_to code is not written correctly:
<span class="upvote">
<%= link_to like_link_path(link), method: :put, class: "upvote-image" %>
</span>
Your other code looks good. If you test this, the best thing to do will be to show the pure HTML for the link in your question - this will give us the ability to see whether it's being rendered correctly.
I found an answer for this, and I'm posting it here in case there are others with the same problem.
I'm developing on Windows. I had problems with javascript, and followed this solution here:
https://stackoverflow.com/a/31972253/1690091
This removed the javascript related errors that were popping all over the place, but this is NOT the solution. This simply removed js from my app.
The real solution is here:
https://stackoverflow.com/a/28331807/1690091
You need to use a proper version of coffee script, that's compatible with Windows.
To sum things up:
js file was missing from my app, and therefore //= require jquery_ujs was also missing, and that's why all of my links were being called as GET.
#Rich Peck,
Thanks for your help.
Try this
<span class="upvote">
<%= link_to like_path, method: :put, class: "upvote-image" do %>
<% end %>
</span>

No route matches [POST] - Rails destroy

I am new to RoR and still don't have enough experience on solving the different errors that may appear to me. In this case I am designing a blog where I can post articles. More specifically, my problem is related to deleting these articles.
As far as I know, writing:
resources :articles
in the routes file is an alternative for writing:
get "/articles" #index
post "/articles" #create
delete "/articles/:id" #delete
get "/articles/:id" #show
get "/articles/new" #new
get "/articles/:id/edit" #edit
patch "/articles/:id" #update
put "/articles/:id" #update
When I try to delete an article I get the following error:
No route matches [POST] "/articles/1"
The code I wrote was:
View
<% #articles.each do |art| %>
<%= art.title %>
<div>
<%= art.body %> - <%= link_to "Delete", art, method: :delete %>
</div>
<% end %>
Controller
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
It sounds like you have this in your view:
<%= art.body %> - <%= link_to "Delete", art, method: :destroy %>
But you actually need:
<%= art.body %> - <%= link_to "Delete", art, method: :delete %>
I'd advise double-checking this in your app based on your reply to a comment from #GonzaloRobaina.
It looks to me like you're missing the correct path in your code. It should work with something like this :)
<%= link_to "Delete, article_path(art), method: :delete %>

Deleting with link_to from within a Rails 4 view

The following Rails 4 link_to is wrong, and thus I'm unable to delete and not sure why. In this project, "bookmarks" is a nested resource under "users" so rake routes gives me:
DELETE /users/:user_id/bookmarks/:id(.:format) bookmarks#destroy
View:
<% #bookmarks.each do |bookmark| %>
<%= link_to "delete", user_bookmarks_path(#user, bookmark.id), method: :delete %>
<% end %>
Controller:
def destroy
#user.bookmarks.find(params[:id]).destroy
redirect_to root_path
end
private
def bookmark_params
params.require(:bookmark).permit(:title, :bookmark_url)
end
def get_user
#user = User.friendly.find(params[:user_id])
end
The result is a link that looks like http://www.example.com/users/jane-doe/bookmarks.6 where 6 is the correct ID of the bookmark to be deleted. But I don't understand why it's not creating /bookmarks/6, which I think would then work fine with destroy in my controller. It feels like there's some big conceptual piece I'm just not understanding. Any tips are appreciated.
Your view should look something like this. It appears your path name is incorrect:
<% #bookmarks.each do |bookmark| %>
<%= link_to "delete", user_bookmark_path(#user, bookmark.id), method: :delete %>
<% end %>

Resources