So I have a simple list of messages that users can submit. I'm trying to put a delete button (that works) for each message. But as you can see here you get an error about an entirely different action if you click the button. I'm not totally sure about where I went wrong. My guess is that I'm out of my depth in the controller area. Here are all the applicable files.
Routes.rb:
Rails.application.routes.draw do
root 'messages#index', as: :home
get '/new' => 'messages#new', as: :edit
resources :messages
post '/new' => 'messages#create', as: :create
delete 'messages/:id' => 'messages#destroy', as: :delete
The relevant controller:
class MessagesController < ApplicationController
def index
#messages=Message.all
end
def new
#messages=Message.new
end
def destroy
#messages=Message.find(params[:id])
#messages.destroy
end
def create
#messages = Message.new(message_params)
if #messages.save
redirect_to '/'
else
render 'new'
end
end
private
def message_params
params.require(:message).permit(:content, :subject)
end
end
The Relevant View:
<div class="main">
<div="messages">
<%#messages.each do |t|%>
<h2 class="subject"><%=t.subject%></h2>
<p class="content"><%=t.content%></p>
<%=link_to "Delete Message", delete_path(t)%>
<% end %>
<%=link_to "Create Message", edit_path%>
</div>
</div>
You need to pass the method DELETE as well, otherwise it will perform the simply GET request. Here's how:
<%=link_to "Delete Message", delete_path(t), :method => 'delete' %>
Remember if you do not mention any method in link_to, the default will be taken as GET. So you have to be explicit about other HTTP methods.
Edit:
Either use resources :messages, or use the routes that you wrote yourself. Using resources :messages is a bit easier, and it is the preferred way.
Using resources :messages, you'd have to write:
<%= link_to "Delete Message", t, :method => 'delete' %>
Edit 2:
You are getting the error Template is missing, because in your destroy method, neither you are rendering anything, nor you are redirect_toing anything. After you destroy the object, you will have to tell where should it go. Like if you want the user to go all messages page after he/she destroys the record, you need to add the following line to the end of the method:
redirect_to messages_path
Related
I am developing a project in Ruby on rails 5.2, and in this route it tells me that I have an error and that the specified route is not found. but when checking, the route is there or at least I think so.
Here's my routes.rb:
resources :checkin do
post :get_barcode, on: :collection
end
checkin_controller.rb:
class CheckinController < ApplicationController
def index
#checkin = CheckIn.all
end
def show
end
def new
#checkin = CheckIn.new
#checkin.upc = params[:upc]
end
def edit
end
def update
end
def destroy
end
def get_barcode
#checkin = Merchant.find_or_initialize_by(upc: params[:upc])
unless #checkin.new_record?
redirect_to #checkin
else
redirect_to new_product_path(upc: params[:upc])
end
end
end
And my link in my view:
<%= link_to "Check-In", checkin_path, :class => "nav-link" %>
here's a image of my error page:
If you run rake routes in your console, you'll see that your routes are:
get_barcode_checkin_index POST /checkin/get_barcode(.:format) checkin#get_barcode
checkin_index GET /checkin(.:format) checkin#index
POST /checkin(.:format) checkin#create
new_checkin GET /checkin/new(.:format) checkin#new
edit_checkin GET /checkin/:id/edit(.:format) checkin#edit
checkin GET /checkin/:id(.:format) checkin#show
PATCH /checkin/:id(.:format) checkin#update
PUT /checkin/:id(.:format) checkin#update
DELETE /checkin/:id(.:format) checkin#destroy
As you can see, the checkin_path expects an id, which you are not providing here:
<%= link_to "Check-In", checkin_path, :class => "nav-link" %>
Your error probably says something about missing id, but you don't provide the error in your question, so we can't see exactly what it says.
BTW, by convention, CheckinController should probably be CheckinsController. And your routes should probably be:
resources :checkins do
post :get_barcode, on: :collection
end
As you said in one of your comments, you're expecting the URL for the index page?
Then instead of
<%= link_to "Check-In", checkin_path, :class => "nav-link" %>`
you need to use
<%= link_to "Check-In", checkin_index_path, :class => "nav-link" %>
I am trying to link to a custom controller route action and I'm doing something wrong. I have a Document model that handles uploading documents to my CRUD app. I want users to be able to 'delete' something, but not actually delete it from the system, but rather update the column 'active' to false. Then if someone with admin privileges can go ahead an complete the deletion. This process is needed because the app gets audited and we do not want to accidentally delete uploaded files.
I can't get the custom update action (remove) to work. When I rake routes I see:
remove_documents PUT /documents/remove(.:format) document#remove
In my routes file (I'll a couple similar routes I'll want to add later so I used collection it up this way):
resources :documents do
collection do
put "remove", to: "document#remove", as: :remove
end
end
In the Documents index view:
<%= link_to remove_documents_url(document), :method => :put do %>
<span class="fa fa-trash text-danger"></span>
<% end %>
My Controller:
def remove
#document = Document.find(params[:id])
#document.active = false
#document.save
html { redirect_to(:back, :notice => 'Document was successfully removed.')}
end
The link works, but then I get the following error:
NameError at /documents/remove.75 uninitialized constant DocumentController
raise unless e.missing_name? qualified_name_for(parent, const_name)
end
end
name_error = NameError.new("uninitialized constant #{qualified_name}", const_name)
name_error.set_backtrace(caller.reject {|l| l.starts_with? __FILE__ })
raise name_error
end
# Remove the constants that have been autoloaded, and those that have been
# marked for unloading. Before each constant is removed a callback is sent
If you want the remove action on a specific Document, change the routes to :
resources :documents do
member do
put "remove", to: "documents#remove", as: :remove
end
end
which gives you : remove_document PUT /documents/:id/remove(.:format)
and use it like :
<%= link_to remove_document_path(document), :method => :put do %>
<span class="fa fa-trash text-danger"></span>
<% end %>
I am working on a rails 3 app, and i am trying to link_to a delete path. It seems pretty straightforward, and my routes look like this
namespace :admin do
resources :users, :except => :destroy do
...
delete :delete_contacts, :on => :collection
end
end
and my controller looks like this
class Admin::UsersController < ApplicationController
...
def delete_contacts
user = User.find(params[:user_id])
user.contacts.destroy_all
redirect_to edit_admin_user_path(current_user.id)
flash[:notice] = "Successfully deleted #{user.name} contacts"
end
end
and my current link_to looks like this
<%= link_to delete_contacts_admin_users_path(user_id: #user.id), method: :delete, data: { confirm: 'Are you sure you want to delete this users Contacts?' }, remote: true do %>
<h4 style="color: #BF3430;"><i class="material-icons">delete_forever</i> Delete Contacts</h4>
<% end %>
I have tried the routes both with and without the :on => :collection, and i seem to keep getting the same error:
ERROR
Started DELETE "/admin/users/955/delete_properties/" for 127.0.0.1 at 2018-01-17 17:58:34 -0800
Processing by Admin::UsersController#delete_properties as JS
Parameters: {"id"=>"955"}
But the link that is made, /admin/users/delete_properties/?user_id=955 , seems like just the link needed?
Does anyone see what I'm doing wrong here? this is pretty straightforward, I'm not sure why it's not behaving the way i'm thinking it should. Any help is much appreciated!
Personally, I think I would have done:
namespace :admin do
resources :users, :except => :destroy do
delete :delete_contacts, :on => :member
end
end
Which would give you:
delete_contacts_admin_user DELETE /admin/users/:id/delete_contacts(.:format) admin/users#delete_contacts
Then, you could do:
<%= link_to delete_contacts_admin_user_path(#user) ... %>
My thinking is that you're working with a particular user and so using a member path instead of a collection path, IMO, seems a little more natural.
Of course, you'd have to change your action slightly:
class Admin::UsersController < ApplicationController
...
def delete_contacts
user = User.find(params[:id])
user.contacts.destroy_all
redirect_to edit_admin_user_path(current_user.id)
flash[:notice] = "Successfully deleted #{user.name} contacts"
end
...
end
That edit_admin_user_path may be munged based on this, so you might have to look at the route for that, too (and possibly others, as well).
I am working with rails I have a controller name books and has a user defined method in it .I need to call this method so that i can see the output on console.And I dont want to call this method in helpers.
def approve
#user=current_user.users.find params[:id]
puts '#{#usery}'
end
Also I Have a link
<%= link_to 'approve',users_path,data: { :confirm => 'Are you sure to delete the folder and all of its contents?'} %>
.When i click on this link I want to call the above method on it .
You'll just need to define a route and call it through that:
#config/routes.rb
resources :users do
get :approve, on: :member
end
<%= link_to "Approve", users_approve_path(#user) %>
As #Rich suggested that, you can achieve it by member. Please note that when you'll create a member route in member block
resources :users do
member do
get 'approve'
end
end
then you'll get the params[:id]. Like
def approve
#user = User.find params[:id]
puts '#{#user}'
end
and when create a member route using :on then you'll get params[:user_id]. Like
def approve
#user = User.find params[:user_id]
puts '#{#user}'
end
Path will be same in both cases that is
<%= link_to "Approve", users_approve_path(#user) %>
Source Rails - Adding More RESTful Actions
Happy coding !!!
Route
resources :cars do
collection do
get :f01a
end
end
Controller
class CarsController < ApplicationController
def f01a
#user = User.find(params[:id])
#count = Count.find_by_user_id(#user)
#count.increment!(:f02)
redirect_to #user
end
end
View
<%= button_to "add f01", f01a_cars_path %>
I can't get this to work. I need to execute this code from a button.
button_to sends a POST request, but your routing is setup to only accept GET requests. You should change it to:
resources :cars do
collection do
post :f01a
end
end
Since you're using params[:id] in your action, but not sending it in at all, you'll need to pass it in your button_to:
<%= button_to "add f01", f01a_cars_path(:id => something)
(Replace something with whatever ID you want to pass.)