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 !!!
Related
I have this setup where it destroys all users but i want it not to destroy current user which is admin.
controller.
def remove_all
User.destroy_all
redirect_to(admin_users_path, { flash: { success: 'You have wiped all the data on the website!' } })
end
navigation.html
<%= link_to "Nuke Button", remove_all_profiles_path, :method => :get %>
route:
resources :profiles do
member do
get :delete
end
collection do
get 'remove_all'
end
end
I know I have to add something to the controller just don't know what to add
I'm assuming you have access to the current_user in your controller (or if not that, you know the id of the current user somehow
User.where.not(id: current_user.id).destroy_all
Note: In Rails 7 you will also be able to do
User.excluding(current_user).destroy_all
Which is a bit nicer maybe, but this doesn't work yet.
https://blog.saeloun.com/2021/03/08/rails-6-1-adds-excluding-to-active-record-relation.html
I have an Approved column in a database which is false by default and might become true on "Approve" button click.
That's what this button look like at the moment:
<%= link_to('Approve It', #comment_path, method: :update) %>
But it raises an exception:
No route matches [POST] "/books/4/comments/6
# app/controllers/comments_controller.rb
def update
#comment = Comment.find(params[:id])
#comment.approve = true
redirect_to '/dashboard'
end
# config/routes.rb
resources :books do
resources :comments
end
How can I fix it?
link_to has to point to an existing route/action, with a proper method name. There is no :update HTTP method.
FYI: Approve action doesn't seem like it belongs to the #update method/action. You might want to extract it to a separate route like so:
resources :books do
resources :comments do
post :approve, on: :member
end
end
this is more idiomatic/common approach in Ruby because #update is usually preserved for more general object updates.
For this you will need to change :method argument value to :post and update your route/#comment_path.
Rails-ujs event handlers - this link might be useful for understanding how it works behind the scenes.
Controller Namespaces and Routing
Post / Update actions require forms
You're using a link_to. This is good for GET requests, but is no good for POST/PATCH/UPDATE requests. For that you'll have to use a form in HTML. Luckily Rails offers some short cut. You can use something like button_to:
<%= button_to "Approve", { controller: "comments", action: "update" }, remote: false, form: { "id" => #comment.id, "approved" => true } %>
This creates a form for you. Which will come with CSRF protection automatically. You can style the button however you like.
or you could use a link to:
<%= link_to comment_approved_path(#comment), method: :put %>
but then you would need to create a separate "approved" action in your controller, and a separate route to reach it.
(The above code has not been tested).
#html
<%= link_to "Approve It", book_comment_path(#comment), method: 'put' %>
# app/controllers/comments_controller.rb
def update
#comment = Comment.find(params[:id])
#comment.approve = true
#comment.save
redirect_to '/dashboard'
end
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
I have something like this in view:
<% if actions.include? "delete" %>
<%= link_to 'UsuĊ', asset_path(asset), :method => :delete, :data => { :confirm => "Want to delete it?" }, :role => "link" %>
<% end %>
and this in assetcontroller:
def destroy
#asset = current_user.assets.find(params[:id])
#asset.destroy
redirect_to assets_path
end
the question is, why it "use" destroy method when action in view is "delete" ?
delete is method of HTTP protocol. destroy is the action of your controller.
Route with delete HTTP method leads to destroy action.
To edit this routes and make delete HTTP method lead to delete action (for example), you should edit config/routes.rb file.
This is because in your routes.rb file you have defined the model as a resource (or a generator like scaffold did). This means that the default CRUD routes are generated. If you want to do it another way, use your own routes instead of generating them.
http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
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.)