Rails: Link to custom method with variables - ruby-on-rails

I have a simple custom method
def delete(foo, bar)
#foo = Foo.find(foo)
#bar = Bar.find(bar)
destroy
end
And I want to call it from a view with the link:
<%= link_to 'Delete', delete_articles_path(number: #number, tag: #tag), method: put, data: { confirm: 'Are you sure?' } %>
The route:
resources :articles do
collection do
put '/delete', to: "articles#delete", as: "delete_article"
end
end
I tried like here(Stack Overflow) But it says that we should pass data through params, while I want to pass it to the method as variables.

You don't need arguments. Simply pass the variables you need via the params hash.

Related

how to hide data from the user using delete function

I'm creating rails product controller to hide the product without deleting user grid panel using Boolean values, but I'm trying so many times, it's not working. I'm just show my code..please help where i'm missing...
I'm using ruby 2.4.1, rails 5.3.2 please help me.
rails route is,
post 'products/hide', to: 'products#hide'
products controller function is,
def hide
#product = Product.find(params[:id])
#product.hidden = true
flash[:notice] = 'you have successfully hide your product'
redirect_to suppliers_index_path
end
view form is,
<%= link_to 'delete', product, method: :hide, data: { confirm:
"Are you sure hide this #{product.Product_name} ?" } %>
products table migration are
class AddHiddenToProducts < ActiveRecord::Migration[5.2]
def change
add_column :products, :hidden, :boolean, :default => false
end
end
please help to resolve this issue.
There's a handful of things wrong with your code.
The most important issue is that you aren't saving your changes.
Your controller code which reads #product.hidden = true only assigns the value to the ruby object in memory. It does not save that change to the database. I believe this is the code you want in your controller action.
def hide
#product = Product.find(params[:id])
#product.update_attribute(:hidden, true)
flash[:notice] = 'you have successfully hide your product'
redirect_to suppliers_index_path
end
Your link_to is attempting to use a non-standard HTTP method ("hide"). I can tell that you're interpreting this as the controller method you want to hit, but that's not what method: means here. The method: parameter in link_to allows you to specify which HTTP method you want to send along with the request. HTTP methods are a standard that function as "verbs" that tell the server what you want to do to the resource you're requesting. Since you're only updating one attribute on the object, the Mozilla Foundation would instruct you to use the PATCH method for your request here.
NOTE: We'll be updating the route to match this in the next point.
COMMENT: Whoever named the product's "name" column products.Product_name needs to have a code review meeting with someone. But anyway...
<%= link_to 'delete', product, method: :patch, data: { confirm:
"Are you sure hide this #{product.Product_name} ?" } %>
Your routes need to be mapped to respond to a PATCH method request. You could use the format you use in your example, but most of the time you want to use "resourceful" routes.
resources :products do
member do
patch :hide
end
end
I will add that you don't have to use the PATCH method at all. You could also use put :hide + method: :put or post :hide + method: :post. They just need to match.
The key method passed to link_to call doesn't define controller method, but HTTP method, so it should be :post actually. You specify controller method by setting correct path/http method. You can achieve your goal by:
<%= link_to 'delete', { controller: products, action: :hide, id: product }, method: :post, data: { confirm: "Your confirmation" } %>
But I would go a little bit further and provide correct named route, assuming you have resources :products somewhere in your routes:
resources :products do
member do
post :hide
end
end
and in your view:
<%= link_to 'delete', [:hide, product], method: :post, data: { confirm: "Confirmation text" } %>

No route matches [DELETE] "/todo_lists/1/todo_items.9"

I've been following a tutorial to create a Todo list app using Ruby on Rails. Click to view Todo app tutorial here
As of now, I have created the TodoLists controller, TodoItems Controller and actions along with the respective models.
Here is my code:
todo_items_controller.rb:
class TodoItemsController < ApplicationController
before_action :set_todo_list
def create
#todo_item = #todo_list.todo_items.new(todo_item_params)
if #todo_item.save
redirect_to todo_list_path(#todo_list)
end
end
def destroy
#todo_item = #todo_list.todo_items.find(params[:id])
if #todo_item.destroy
flash[:success] = "Todo List item was deleted."
else
flash[:danger] = "Todo List item could not be deleted."
end
redirect_to #todo_list
end
private
def todo_item_params
params.require(:todo_item).permit(:content)
end
def set_todo_list
#todo_list = TodoList.find(params[:todo_list_id])
end
end
Here is my routes.rb:
rails routes
Prefix Verb URI Pattern Controller#Action
root GET / todo_lists#index
todo_list_todo_items GET /todo_lists/:todo_list_id/todo_items(.:format) todo_items#index
POST /todo_lists/:todo_list_id/todo_items(.:format) todo_items#create
new_todo_list_todo_item GET /todo_lists/:todo_list_id/todo_items/new(.:format) todo_items#new
edit_todo_list_todo_item GET /todo_lists/:todo_list_id/todo_items/:id/edit(.:format) todo_items#edit
todo_list_todo_item GET /todo_lists/:todo_list_id/todo_items/:id(.:format) todo_items#show
PATCH /todo_lists/:todo_list_id/todo_items/:id(.:format) todo_items#update
PUT /todo_lists/:todo_list_id/todo_items/:id(.:format) todo_items#update
DELETE /todo_lists/:todo_list_id/todo_items/:id(.:format) todo_items#destroy
todo_lists GET /todo_lists(.:format) todo_lists#index
POST /todo_lists(.:format) todo_lists#create
new_todo_list GET /todo_lists/new(.:format) todo_lists#new
edit_todo_list GET /todo_lists/:id/edit(.:format) todo_lists#edit
todo_list GET /todo_lists/:id(.:format) todo_lists#show
PATCH /todo_lists/:id(.:format) todo_lists#update
PUT /todo_lists/:id(.:format) todo_lists#update
DELETE /todo_lists/:id(.:format) todo_lists#destroy
I think the problem is here in the following code in _todo_item.html.erb
with "todo_item.id". Also, as I'm usually acquainted with simple link_tos such as <%= link_to "Delete", article_path(#article), method: :delete, data: { confirm: "Are you sure? } %>, I'm not sure how the more complicated link_to is constructed especially todo_list_todo_items_path(#todo_list, todo_item.id)
_todo_item.html.erb:
<p><%= todo_item.content %></p>
<%= link_to "Delete", todo_list_todo_items_path(#todo_list, todo_item.id), method: :delete, data: { confirm: "Are you sure?" } %>
Could someone point out the error in my code?
Explain the second part of the link_to tag that I mentioned above?
Thank you very much.
Your routes show:
todo_list_todo_item GET /todo_lists/:todo_list_id/todo_items/:id(.:format) todo_items#show
PATCH /todo_lists/:todo_list_id/todo_items/:id(.:format) todo_items#update
PUT /todo_lists/:todo_list_id/todo_items/:id(.:format) todo_items#update
DELETE /todo_lists/:todo_list_id/todo_items/:id(.:format) todo_items#destroy
So, the helper for the DELETE route is:
todo_list_todo_item_path
not
todo_list_todo_items_path
(note the change in 'item' vs 'items')
Your link code should be:
<%= link_to "Delete", todo_list_todo_item_path(#todo_list, todo_item.id), method: :delete, data: { confirm: "Are you sure?" } %>
To answer your second question part:
Your routes show:
DELETE /todo_lists/:todo_list_id/todo_items/:id(.:format)
This route requires two parameters: the id of the TodoList and the id of the TodoItem. These are shown in the route as :todo_list_id and :id.
Note how in your controller you are first finding a TodoList by params[:todo_list_id] in the before_action, and then you are finding a TodoItem on the association by params[:id] in the action.
In your link_to, you have to pass both parameters.
The Rails guide on Routing is probably something you should read to gain a better understanding of how it all works: https://guides.rubyonrails.org/routing.html
You have more errors in your projects. Here is your project fixed and pushed on my git repo: https://github.com/nezirz/todo-list
<%= link_to "DELETE - #{todo_item.content}", todo_list_todo_item_path(#todo_list, todo_item.id), method: :delete, data: { confirm: "Are you sure?" } %>

undefined method `update_attributes' in ruby on rails

This update process something different I need update query inside loop, but showing this error:
undefined method `update_attributes'
This is code:
<%= link_to "Accept", apply_path(accept:{:accept => 1}), :method => :put, class: "btn btn-success" %>
Controller:
def update
#accept = Applied.where(params[:applied_id])
params.permit!
if #accept.update_attributes(params[:applied_id])
#flash[:notice] = "updated"
render 'apply'
else
render 'apply'
end
end
request parameters:
{"_method"=>"put",
"authenticity_token"=>"Yk26LKrW9ulRVV6p8GWhqTP7coSg96JiAmU4CUYYFugBgTDR2iRZZlyY1SQ7TbA7B2YVmgulgcWTosXvjnPXZw==",
"accept"=>{"accept"=>"1"}}
How can I reach solution?
You can call update_attributes for a single model instance (a record) only not for an ActiveRecord::Relation object (it's like an array of records).
Use:
#accept = Applied.where({applied_id:params[:applied_id]}).first
or
#accept = Applied.find(params[:applied_id])
Be aware, find looks for your applied_id in the id field of your model table, if you haven't another config in place.
And note that update_attributes consumes a hash of "field:value" pairs ({field_1_name:field_1_value, field_2_name:field_2_value}) you want to update, not a single applied_id only.
You line
#accept = Applied.where(params[:applied_id])
returns an ActiveRecord relation which obviously does not have a method update_attributes. To fetch single record, use first of find instead:
#accept = Applied.find(params[:applied_id])
Continuing from our comments.
I am not sure what actually accept is and what actually you want to do specically, however, just as per my understanding, try to update your link href. It should look like:
apply_path(accept:{:accept => 1, applied_id: YOUR_APPLIED_ID})
Update your action as follow:
def update
accept = params[:accept] # Recommendation: you should use strong parameter
#accept = Applied.where(accept[:applied_id])
params.permit!
#accept.update_attributes(accept)
render 'apply' # You don't need any condition, as you are rendering same template in every case.
end
The issue is that you're trying to update a collection (where) which does not have the update_attributes method available.
What you need is .find:
def update
#accept = Applied.find params[:applied_id]
#accept.update applied_params
render 'apply'
end
private
def applied_params
params.require(:accept).permit(:accept)
end
However, you're not passing any applied_id parameter (so the find won't work); you need to use the following route:
#config/routes.rb
resources :applied do
put :apply, action: :update #-> url.com/applied/:applied_id/apply
end
<%= link_to "Accept", apply_path([[[applied.id]]], accept:{:accept => 1}), :method => :put, class: "btn btn-success" %>
A much better way would be to use button_to:
<%= button_to "Accept", apply_path([[applied_id]]), method: :put, params: {accept: 1} %>
If you used the above, you'd have to change your params method in your controller.
--
If you wanted to use .where (for multiple records), you'll need to use update_all:
def update
#accept = Applied.where id: params[:applied_id]
#accept.update_all applied_params
render 'apply'
end
private
def applied_params
params.require(:accept).permit(:accept)
end

RoR how to get button_to path to /needs/4 instead of /needs.4?

I am still fairly new to RoR and I am trying to delete an object with a button_to delete button.
With the code I wrote though, it gets me to /needs.4 instead of /needs/4 when I try to get it to /needs/:id for the destroy method.
A "need" is created via the needs-controller and a needs new.html.erb page, and then shows up in the user's show page. from there, a user is supposed to be able to delete his/her need.
This is the error I get:
ActiveRecord::RecordNotFound in NeedsController#destroy
Couldn't find Need with id=#userneed
Rails.root: /Users/mcn/Dropbox/Code/GA/Projects/GA_projects/p4_final/flatcircle
Application Trace | Framework Trace | Full Trace
app/controllers/needs_controller.rb:20:in `destroy'
Request
Parameters:
{"_method"=>"delete",
"authenticity_token"=>"Fv6EcMNJQEjtw1naQVMw77lkCGjTJR7ui2FD53aoZfc=",
"id"=>"#userneed"}
And this is my code:
Needs_controller:
def destroy
Need.find(params[:id]).destroy
redirect_to :controller => :users, :action => :show, :id => current_user.id, :flash => { :success => "Your search post was deleted." }
end
User's show page button_to line:
<%= button_to "delete", '/needs/#userneed', method: :delete, data: { confirm: "You sure?"} %>
and on same page:
#userneed = #current_user.needs.last
Routes.rb
delete "/needs/:id", to: "needs#destroy"
get "/needs/:id", to: "needs#show"
Super confused, let me know if you know how to solve it!
Ok so this is how I fixed it:
<%= button_to "delete", {:controller => :needs, :action => "destroy", :id => current_user.needs.last.id}, :method => :delete, data: { confirm: "You sure?"} %>
So I guess it was two things:
1) the curly braces in the right places (I need them because there are still arguments to come after the stuff in the curly braces
2) specifying the id this way instead of with the _path() way
try <%= button_to "delete", '/needs/<%= #userneed %>', method: :delete, data: { confirm: "You sure?"} %>
and #userneed = #current_user.needs.last.id
But I think its best to use a link instead a button...something like delete
You need to run rake routes and then see which path you need. Example...
schemas GET /schemas(.:format) schemas#index
POST /schemas(.:format) schemas#create
new_schema GET /schemas/new(.:format) schemas#new
edit_schema GET /schemas/:id/edit(.:format) schemas#edit
schema GET /schemas/:id(.:format) schemas#show
PUT /schemas/:id(.:format) schemas#update
DELETE /schemas/:id(.:format) schemas#destroy
Take the route name on the left, so for me to get to the SchemasController and it's destroy action I need to use one of the route path helpers...
schemas_path(#schema)
That would automatically be replaced with at runtime (if the object's ID was 1)...
/schemas/1
So to use that in a button...
<%= button_to "delete", schemas_path(#schema), method: :delete, data: { confirm: "You sure?"} %>
You should always use the route helpers when referencing routes as it allows you to change all of them by adjusting the routes.rb file. If you need to read more on Rails Routing, the guide can be found here...
http://guides.rubyonrails.org/routing.html

rails, how to pass hidden field in link_to for a delete request

i was wondering how someone can pass hidden fields in a link_to performing a delete request. i have..
<%= link_to "delete", feed_item, method: :delete,
confirm: "You sure?",
title: feed_item.content,
user_id: user_id %>
<% end %>
ive been trying to pass user_id into my controller's destroy action but it cant seem to find params[:user_id]
it seems like its possible to pass hidden values when the method is a :post, but how can i do so in a :delete?
i essentially just want the user_id in my destroy action, so it can redirect back to the users profile page.
thank you
The proper way would be to either put feed_item under user resource or user current_user method in the controller
if you decide to put it under user resource the modify your routes file as
resources :users do
resources feed_items, :only=>[:destroy]
end
and than in your link to delete change the path to
user_feed_item_path
Alternatively if you have current_user method from using any sort of authentication solution you can just use that in your redirect path

Resources