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.
Related
So I am working on this rails project. I am trying to get an input from the view and pass it into the controller, so it can be saved into a variable for later use.
I have my view layer in /views/welcome/index.html.erb with the following :
<div class="locator-input">
<%= text_field_tag :user_input %>
<%= submit_tag "Get started" %>
</div>
and the controller in /controller/welcome_controller.rb
class WelcomeController < ApplicationController
def index
end
def locator
#user_input = params['user_input']
end
end
and routes.rb here
Rails.application.routes.draw do
root 'welcome#index'
end
so when I go ahead and hit submit, I get this error:
I know this error has something to do with routes.rb but I can't figure out how to fix it.
My ultimate goal is to get user input, pass it into the controller and save it into a variable to I can use it with my model later on.
I will greatly appreciate some guidance from our experts.
Thanks.
The route generate with root expects only GET requests. But your form sends a POST request.
To solve this just add the following to your config/routes.rb:
root 'welcome#index'
match '/', to: 'welcome#index', via: [:post]
Wrap the field in a form
<div class="locator-input">
<%= form_tag locator_welcome_path %>
<%= text_field_tag :user_input %>
<%= submit_tag "Get started" %>
<% end %>
</div>
You also need to create a route
Rails.application.routes.draw do
resource :welcome, controller: :welcome do
post :locator
end
root 'welcome#index'
end
This will generate
locator_welcome POST /welcome/locator(.:format) welcome#locator
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
I created a form to create articles, but I can only see the published articles on the index page, and, I'm unable to see individual articles.
Every time I click on 'show' for an individual article on the index, it opens a blank page with a URL like localhost:3000/articles.1, instead of localhost:3000/articles/1.
I don't know what's wrong with the code, it's similar to the code I have for creating and editing articles as admin and it works there, but I keep getting this error.
Here's the code:
views/articles/show.html.erb:
<h1><%= #article.name %></h1>
<%= #article.content %>
<%= image_tag #article.photo.url(:small) %>
<p>Tags: <%= raw article.tag_list.map { |t| link_to t, tag_path(t) }.join(', ') %></p>
<%= link_to 'Back', noticias_path %>
views/articles/index.html.erb:
<% #articles.each do |article| %>
<div>
<h2><%= article.name %></h2>
<%= article.content %>
<p><%= link_to 'Show', noticias_path(article) %></p>
<p>Tags: <%= raw article.tag_list.map { |t| link_to t, tag_path(t) }.join(', ') %></p>
</div>
<% end %>
articles_controller.rb:
# GET /articles/1
# GET /articles/1.json
def show
#article = Article.find(params[:id])
end
routes.rb:
Blog::Application.routes.draw do
root to: 'welcome#index'
get 'tags/:tag', to: 'noticias#index', as: :tag
get "noticias/index"
get "dashboard/index"
get "/sitemap" => "sitemap#index", :as => :sitemap, :defaults => {:format => :xml}
match '/noticias', to: 'noticias#index', via: 'get'
get 'login', to: 'sessions#new', as: 'login'
get 'logout', to: 'sessions#destroy', as: 'logout'
resources :users
resources :sessions
namespace :admin do
get '', to: 'dashboard#index', as: '/'
resources :noticias
end
end
It's more a problem with noticias_path, consider verify your routes with rake routes, but I think to change noticias_path to noticia_path, may can fixed it.
Based on your routes file, it looks like the problem is indeed incorrect routing. Presently, you are manually creating routes for RESTful resources, when you should simply let rails handle that for you properly.
Remove the manual get and match lines:
get "noticias/index"
match '/noticias', to: 'noticias#index', via: 'get'
And replace them with this:
resources :noticias
If noticias should be pointing to the ArticlesController (or any other controller), then simply do this:
resources :noticias, to: 'articles'
Also, Matheus Caceres was correct that the URL helper should in fact be noticia_path for the show action. The noticias_path points to the index action. Rails tries to be "helpful" by making routes, helpers, functions, etc, sound proper if read in English, but might not necessarily make sense for words in another language. I don't know if "noticia" makes any sense in Portuguese though.
Another quick side note, the two manual routing lines I indicated above are redundant; they would in fact both match a GET request and route them to noticias#index. However, keep in mind that routes are matched in the order they appear in the routing file, so the match line would never have been called, since the route would have matched on that get line.
In my small rails app I have a controller called say and two pages hello and goodbye in it. I installed devise in the app. Initially i was able to access the sing_in page as /users/sign_in and similarly for sign up. I was not able to sign out and due to not able to sign out i am not able to access sign up or sign in page again. Now I entered the following code int eh say/hello page
<h1>Say#hello</h1>
<% if user_signed_in? %>
Hey signed in as <%= current_user.email %>.Not you?
<%= link_to "Logout", destroy_user_session_path %>
<% else %>
Hey <%= link_to "Login", new_user_session_path %> or Hey <%= link_to "Logup", new_user_registration_path %>
<% end %>
</p>
This the routes page of the app.
Demo::Application.routes.draw do
devise_for :users
get "say/hello"
get "say/goodbye"
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
root :to => "say#hello"
end
Whenever I access the say/hello page, this is the output i get
Links
Hey signed in as x#gmail.com.Not you? Logout
When I click logout. It says
No route matches [GET] "/users/sign_out"
When I directly access users/sign_in I get routed to the say/hello page.
What mistake am I doing? How should I sign_out?
I have also tried
destroy_user_session_path, :method => :delete
Hope this could help
Try this in your routes.rb
devise_for :users do get '/users/sign_out' => 'devise/sessions#destroy' end
I have a rails 3 app, and when I click the link to my terms page, it routes to a completely different controller, than what the routes should use. Stranger still, the route works when I'm not logged in, and I'm using devise.
I get this error when clicking the link when I'm logged in.
No route matches {:action=>"edit", :controller=>"users", :id=>nil}
<%= link_to "Terms", terms_path %>
Routes (in the order they appear in routes.rb):
devise_for :users, :controllers => {:registrations => "registrations"}
resources :users do
member do
get :following, :followers
post :accept
end
end
match '/terms', to: 'static_pages#user_agreement'
Static Pages Controller
def user_agreement
end
Rake Routes
terms /terms(.:format) static_pages#user_agreement
This also happens for every other action that I've routed this way to the staticpages controller, but not for any other actions that route to different controller.
Update: Terms Page
Header:
<%= link_to "Follow", users_path %>
<%= link_to current_user.name, current_user %>
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
Footer:
<%= link_to "Welcome", welcome_path %>
<%= link_to "Settings", edit_user_path(#user) %>
<%= link_to "Terms", terms_path %>
All the content is pure html.
Thanks in advance
You have a link to edit_user_path with no #user as hinted in the comments.
You should almost certainly be using current_user anyway.