The other solutions here did not work, so I am posting a new question. I am using acts_as_votable for up and down voting on links, but when I try to actually vote I get the error:
No route matches [GET] "/links/1/like"
This is what my view looks like:
<%= link_to like_link_path(link), method: :put, class: "btn btn-default btn-sm" do %>
<span class="glyphicon glyphicon-chevron-up"></span>
Upvote
<%= link.get_upvotes.size %>
<% end %>
<%= link_to dislike_link_path(link), method: :put, class: "btn btn-default btn-sm" do %>
<span class="glyphicon glyphicon-chevron-down">
Downvote
<%= link.get_downvotes.size %>
<% end %>
And this is what my routes look like:
resources :links do
member do
put "like", to: "links#upvote"
put "dislike", to: "links#downvote"
end
end
I see that my client is trying to access the get method, but I explicitly call method: :put in my index.html.erb file.
Do you know why it is trying to access get and how I can override that?
This problem is almost always to do with JQuery, although in this instance I'm not sure why.
You can even see it here:
Note that if the user has JavaScript disabled, the request will fall back to using GET
I would firstly check that you have JQuery in your app, and then that it's getting called okay. If it isn't loading, then the best course of action is to see why JQuery is not being called (it's either going to because it won't be referenced, or you'll have an error preventing it from loading).
Your code actually looks valid, so I'd have to say that JQuery would be the likely issue here.
You could polish up your routes etc:
#config/routes.rb
resources :links do
match "vote", action: :vote, via: [:put,:delete], on: :member
end
This will send both types of request to an action called vote, which you can then split up as follows:
#app/controllers/links_controller.rb
class LinksController < ApplicationController
def vote
if request.put?
# Code to vote
elsif request.delete?
# Code to downvote
end
# Redirect back
end
end
Much DRYer and more efficient (only calling a single action etc)
It turns out that the answer was related to JQuery. I was getting an Uncaught ReferenceError: jQuery is not defined error and so what I did was include JQuery outright in my application.html.erb file.
You have to put this ahead of all your other scripts.
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
After that, the voting began to work
Related
Working on versions:
Ruby: 3.0.2
Rails 6.1.4
I'm trying to put a button in my View template for "Users" that will set the :mod attribute to false, with the button just being "Demote User".
I had it working SOMEHOW using a helper method, demote_user, and some variation of
<% if logged_in? && current_user.admin? %>
<%= link_to "Demote User", user_path(#user), onclick: demote_user(#user), class: "btn btn-info" %>
<% end %>
I messed up however it was working when trying to move this method into a controller for best practice. I'm not sure what format worked out, but I've tried many such as
:onclick => demote_user(#user)
onclick: 'demote_user(#user)'
onclick=demote_user(#user)
onclick='demote_user(#user)
and etc. Somehow, it did eventually work but I busted it. Now, every time I load the User's page, it's just executing demote_user(#user) without even needing to click the button, so refreshing a User's page is demoting them.
I am now trying to do this properly by creating a demote method in the UserController, but I have NO IDEA how to make the route, or make it work properly. Up until now, all my routes have been working using resources, and the basic new, create, destroy, etc.
I've been trying many different routes, and view formatting, with no luck and usually ending up with just: Routing Error
No route matches [GET] "/demote.3"
I'd like to be able to avoid using the Javascript onClick functionality and do it properly with the controller even if I could remember how to make it work, but I think my route, or view page, or controller is incorrect. Here are the contents of each file:
Controller
def demote
byebug
#user = User.find(params[:id])
#user.mod = false
redirect_to user_path(#user)
end
View
div class="container text-center mt-4">
<% if logged_in? && current_user.admin? %>
<%= link_to "Demote User", demote_path(#user), class: "btn btn-info" %>
<% end %>
</div>
Routes
Rails.application.routes.draw do
root 'pages#home'
get 'about', to: 'pages#about'
resources :articles
get 'signup', to: 'users#new'
resources :users, except: [:new]
get 'login', to: 'sessions#new'
post 'login', to: 'sessions#create'
delete 'logout', to: 'sessions#destroy'
resources :categories
post 'demote', to: 'users#demote'
end
Up until now, I've been following a course, and I've nailed everything in it and have added some of my own functionality, but I'm still not quite sure how to make sense of routes, or what paths it creates.
I'd like to make other similar custom controller functions beyond show, index, create, delete, update which are all I really understand how to build. I'm not even sure if POST is the correct call in the route.
I would just setup an additional RESTful action for the resource:
resources :users do
patch :demote
end
<% if logged_in? && current_user.admin? %>
<%= button_to "Demote User", demote_user_path(#user), method: :patch %>
<% end %>
You can use link_to instead of button_to but you need to use the correct method: :patch or data: { turbo_method: :patch } option depending on your version of Rails to get the javascript driver to do its trickery.
Not sure why i am getting this error message when implementing gem x_editable_rails to allow comments to be edited without users being brought to a separate edit page.
x_editable_rails demo app shows that perhaps the right way should be <%= editable #comment, :content %>, but because I am looping all comments in the #comments instance variable, doing that throws an error too.
EDIT
I changed the line of code from <%= editable #comments.comment %> to <%= editable [comment.article, comment], :content, url: edit_article_comment_path(comment.article, comment) %> and now, its showing
undefined method `xeditable?' error.
I have added the below helper method and added this (helper_method :xeditable?) to application controller. (I don't use cancan so i have added a dummy can? as suggested on this stackoverflow post.
module ApplicationHelper
def xeditable?
current_user.xeditable?
end
def can?(role, object)
true
end
end
_comments.html.erb
<% #comments.each do |comment| %>
<%= editable [comment.article, comment], :content, url: edit_article_comment_path(comment.article, comment) %>
<%= link_to "Delete comment", [comment.article, comment], method: :delete %>
<%= link_to "Edit comment", edit_article_comment_path(comment.article, comment) %>
<% end %>
routes.rb
resources :articles do
resources :comments
end
Routing
The original error you posted indicates you do not have a route for APP_DOMAIN/comments/:id, and that's confirmed by your routes -- comment is a nested resource in your routing, routed like APP_DOMAIN/articles/:id/comments/:id.
Note that for unusual routing (i.e. not a typical Rails naming pattern), x-editable-rails allows you to specify your path. Maybe comments are routed through another name, like url: post_critique_path(#comment.post, #comment). I see you have now done this, though I'm not sure if it is necessary since your routing is standard pratice.
Note that I have not tested this myself. The README is not super clear on what are the allowed or expected values for :url. And, confusingly, the gem has a :nested option – which appears to be about setting the title HTML attribute.
Application helper methods
For your next error, it appears you are implementing the advice from this answer. But I believe you have missed a line, and your ApplicationHelper module should look like this:
module ApplicationHelper
helper_method :xeditable?, :can
def xeditable?
current_user.xeditable?
end
def can?(role, object)
true
end
end
Using a member route like this similar to one I have used for deleting tags:
resources 'factory' do
resources 'tags' do
member do
delete :remove
end
end
resources 'project_files' do
member do
delete :remove
end
end
end
I (should) invoke in the projects controller:
class ProjectFilesController < ApplicationController
def remove
#factory = Factory.find(params[:fabmoment_id])
#project_file = ProjectFile.find(params[:id])
authorize #factory, :project_file?
#project_file.remove!
head :ok
end
end
Which I can't check for correctness (yet). The partial _project_files looks like:
<li class="project_file">
<% if policy(factory).project_file? %>
<%= link_to "<span></span>".html_safe,
remove_factory_project_file_path(factory, project_file), method: :delete, remote: true,
class: "remove",
title: "remove" %>
<% end %>
<%= link_to File.basename(project_file.url), project_file.url %>
(<%= number_to_human_size(project_file.file.size) %>)
</li>
Which is invoked by passing locales with a render method in the factory#show view. (Could also add an index.)
Like this it is mostly equal to the tags remove action though and I like to keep things consequent and simple.
The error I receive from my spec:
No route matches [DELETE] "/factories/1/project_files/%2Fuploads%2Ffactory%2Fproject_files%2F1%2Fthe_puritan_1st_floor.stl/remove"
My Factory model only contains mount_uploaders :project_files, ProjectFileUploader
Any ideas on how to make this work?
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>
I am trying to use link_to in rails 4 with controller and html options and a do..end block. I have seen similar posts but have not been able to use any of the answers successfully.
Working code without a do..end block:
<%= link_to 'recommend', { controller: 'recommendations', id: offer.id }, method: :post %>
When I try to use some embedded ruby to add extra information to the link, I cannot get it to work:
<%= link_to( { controller: 'recommendations', id: offer.id }, method: :post) do %>
<p>Some Html</p><%= offer.recommendations %>
<% end %>
The code compiles but in the rendered, the link that is generated is the following:
<a controller="recommendations" id="38">
<p>Some Html</p>0
</a>
Any help would be appreciated. I think that it is a small problem with the syntax but I have tried all manner of brackets, spaces etc that I could think of without luck.
UPDATE: I have tried the following code without success:
<%= link_to( { controller: 'recommendations', action: 'create', id: offer.id }, method: :post) do %>
<p>Some Html</p><%= offer.recommendations %>
<% end %>
The HTML output is:
<a action="create" controller="recommendations" id="39">
<p>Some Html</p>0
</a>
This might not be important but as a side note, the create action doesn't have a helper function for links. When I run the
rake routes
command I get the following
...
recommendations GET /recommendations(.:format) recommendations#index
POST /recommendations(.:format) recommendations#create
new_recommendation GET /recommendations/new(.:format) recommendations#new
...
In my opinion this isn't a problem but it is a reason why code such as:
link_to create_recommendation_path
won't work. Finally, the intention of the link is to act as a 'like' button. It creates a recommendation and then displays the current page again. Once again, thanks for the help in advance.
The reason link_to create_recommendation_path doesn't work is because there is no named route for create_recommendation_path, only for recommendations_path. You can see the named routes in your routes list (which you have in your post above). The left most column that comes out of routes shows the named routes. Notice that recommendations#create doesn't have an entry in the list.
You could probably get the path you want with
<%= link_to recommendations_path(:offer_id => offer.id), :method => :post do %>
html stuff
<% end %>
This should post to a path that looks like
/recommendations?offer_id=<the offer id>
(except the post data will be in the headers not on the URL)
This will work if the create method going to do something like
Recommendation.create(params)
and the only parameter you need to create a new Recommendation is an offer_id
What I don't understand is why you're trying to POST with a link? Does creating a recommendation only require an offer id?
In your link_to you're only specifying a controller, you need to also specify the action otherwise it doesn't know where to route it to. Either use:
<%= link_to({ controller: 'recommendations', action: 'show', id: offer.id }) do %>
<p>Some Html</p><%= offer.recommendations %>
<% end %>
Or
<%= link_to({ show_recommendations_path(id: offer.id) }) do %>
<p>Some Html</p><%= offer.recommendations %>
<% end %>