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?" } %>
Related
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" } %>
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.
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
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
I have the following code in my Users controller in Rails to let users delete themselves:
def delete_account
User.find(params[:id]).destroy
flash[:success] = "Your account has been deleted."
redirect_to root_path
end
Now, I'm unsure of how to add the proper route to my route.rb file and then add the button correctly into my user settings view.
For my route file I have the following code:
match '/delete_account' to: 'users#delete_account'
And in my settings view file I have the following code to add a button for the delete_account action in the view:
<%= link_to class: "btn btn-danger", delete_account_path %>\
Any help you can provide in implementing the correct route and embedded ruby in my view would be greatly appreciated. Sorry if this is an easy error to fix; I'm a beginner developer, and this has been giving me some trouble.
I think it's better to use RESTful way.
Rename your method to destroy in controller.
In your routes.rb,
resources :users or match '/delete_account', to: 'users#destroy'
In the view, say in show.html.erb,
<%= link_to 'Delete', #user, confirm: 'Are you sure?', method: :delete %>
And obvious your show action should find the right user,
#user = User.find(params[:id])