adding delete option for product rails member routes - ruby-on-rails

My problem is that I need to add the option for delete product and I'm stock with that....
First I added this line in the index.html.erb:
<% glyph_to "Delete", product, method: :delete, data: (confirm: "Are you sure that product" ##(product.id) is not used?") if can? (:destroy, product)%>
but I don't now in that line what is the difference between "method: :delete" and "if can? (:destroy, product)", destroy is the controller action I guess and delete? I don't know....
another thing is my controller definition for that action:
def destroy
#product = Product.find(params[:id])
#product.destroy
redirect_to product_path
end
but when I press "delete" it doesn't redirect to product_path
and my routes definition are the following:
resources products do
member do
get :destroy
end
end
I will be very grateful of any help with this,
thank you for your time :D!

Yes , destroy is controller's delete method , to redirect to the product listing page you should use redirect_to action: 'index'. You can check all actions and method through command rake routes

You should redirect_to products_path(this translates to index) since currently it says redirect_to product path(translating to show) which will throw error
method: :delete is for posting to destroy action and can? is a cancan gem method by Ryan Bates. The if checks if user has the permissions to delete the product or not.
The permissions can be set in app/models/ability.rb
Lastly change your routes to:
resources: :products

destroy action must be called on HTTP DELETE request and never on GET. You should definitely fix the following code from your routes:
resources products do ## missing : here, it should be :products
## member block not required
member do
get :destroy ## destroy should never be GET request
end
end
You just need to define your routes as:
resources :products ## Notice :products and not products
This will generate following routes for you which you can check by running command rake routes
products GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:id/edit(.:format) products#edit
product GET /products/:id(.:format) products#show
PATCH /products/:id(.:format) products#update
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy
Notice the last route generated.
destroy action should be called as HTTP Delete method which is why on your link you need to specify method: :delete as
<% glyph_to "Delete", product, method: :delete, data: (confirm: "Are you sure that product" ##(product.id) is not used?") if can? (:destroy, product)%>
so when you click on this link a DELETE request would be sent which would be mapped to your route for products#destroy, i.e.,
DELETE /products/:id(.:format) products#destroy
Also, you need to update the destroy action as below:
def destroy
#product = Product.find(params[:id])
#product.destroy
redirect_to products_url ## products_url notice plural products
end
products_url would redirect you to index page of products.
As product_path is for show, i.e., to show a particular product. You can't show a deleted product that too without providing an id to product_path. So, logically you should be redirecting to index action with products_url (NOTE using **_url for redirection is advisable but you could also use products_path)

Related

How can I redirect to a Create action?

Ruby Version: 2.0.0
Rails Version: 4.0.1
I have a controller to handle the Paypal Express Checkout workflow. When paypal reports a successful payment, I want to go ahead and create an order. This is my current attempt:
def do_express_checkout
##
# Paypal logic ommited to keep this from being lengthy....
##
#do_express_checkout_payment_response = api.do_express_checkout_payment(#do_express_checkout_payment) if request.post?
if #do_express_checkout_payment_response.success?
redirect_to controller: :orders, action: :create, method: :post
end
end
The routing is the default rails routing:
resources :orders
Right now, this is just redirecting to /orders (the index method). What should I do?
You cannot redirect to a POST action. redirect_to works only for GET requests.
With resources :orders , routes for create and index look exactly same except the HTTP verb :
orders GET /orders(.:format) orders#index
POST /orders(.:format) orders#create
When you do
redirect_to controller: :orders, action: :create, method: :post
it generates a GET request for /orders which goes to index action. method is not a valid option for redirect_to so it is ignored.
An ugly workaround would be, to create a duplicate route for create action with a GET verb:
resources :orders
get "create", to: "orders#create", as: :create_order
This will create a route as:
create_order GET /create(.:format) orders#create
Then you can update do_express_checkout method as below:
if #do_express_checkout_payment_response.success?
redirect_to create_order_path
end

Unable to delete all records in Rails 4 through link_to

I was originally getting a routing error posted in Routing Errors on attempts to delete all records in a table using Rails 4 through a link_to, and that has been resolved.
Now I am having problems with "id=remove_all" being passed. I'm using Rails 4, and am trying to delete all the assessments using a link_to helper. The pertinent code is below:
routes.rb
resources :assessments do
collection do
delete :remove_all
end
end
assessment index.html.erb
<p>To delete all assessments in one swoop, click <%= link_to 'Remove ALL Assessments', remove_all_assessments_path, method: :destroy, data: { confirm: 'Are you sure?' } %>
assessments_controller.rb
def remove_all
#assessments = Assessment.all
#assessments.each do |assessment|
assessment.destroy(assessment.id)
end
flash[:notice] = "All assessments have been deleted."
redirect_to assessments_url
end
I run rake routes and
Prefix Verb URI Pattern Controller#Action
remove_all_assessments DELETE /assessments/remove_all(.:format) assessments#remove_all
The HTML source generated for the link:
<p>To delete all assessments in one swoop, click <a data-confirm="Are you sure?" data-method="destroy" href="/assessments/remove_all" rel="nofollow">Remove ALL Assessments</a>
When I click on the 'Remove All Assessments' link, I expect to have the remove_all action run in the AssessmentsController, and delete all the assessments in #assessments, then redirect me to the assessments_url. However, when I click on the 'Remove ALL Assessments', link, I am brought to the url: http://localhost:3000/assessments/remove_all
ActiveRecord::RecordNotFound in AssessmentsController#destroy
Couldn't find Assessment with id=remove_all
# Use callbacks to share common setup or constraints between actions.
def set_assessment
#assessment = Assessment.find(params[:id])
end
The logs show:
Started DELETE "/assessments/remove_all" for 127.0.0.1 at 2014-01-31 15:41:41 -0500
Processing by AssessmentsController#destroy as HTML
Parameters: {"authenticity_token"=>"fooBarBaz=", "id"=>"remove_all"}
How do pass the collection of #assessments to the remove_all action using the Delete verb? Is this possible?
It is Because
resources :assessments
already have route to destroy
like /assessment/:id with method :delete
so your remove_all_assessments_path will hit to that url bcoz it comes first in in your routes.rb file
To solve your problem u have to do something like this:-
resources :assessments, except: [:destroy] do
collection do
delete :remove_all
end
end
or define your remove_all_assessments url above it.
like
match "/assessments/remove_all", to: "assessments#remove_all", via: [:delete], as: :remove_all_assessments
resources :assessments do
collection do
delete :remove_all
end
end

Editing a comment that belongs to a post

So I have created a blog that users can create posts and others can comment on that post.
I want users to be able to edit the comments.
What I did so far is the following:
My routes are like this:
resources :posts do
resources :comments
end
and when I rake route I get this:
new_post_comment GET /posts/:post_id/comments/new(.:format) comments#new
edit_post_comment GET /posts/:post_id/comments/:id/edit(.:format) comments#edit
post_comment GET /posts/:post_id/comments/:id(.:format) comments#show
on my view file I use this which is obviously wrong
<%= link_to 'Edit Comment', edit_post_comment_path(#comment) %>
and my controller is like that:
def edit
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
end
def update
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
if #comment.update(comments_params)
redirect_to post_path(#post)
else
render 'edit'
end
end
When I try to visit the page (of the post) I get this error:
No route matches {:action=>"edit", :controller=>"comments", :id=>nil, :post_id=>nil, :format=>nil} missing required keys: [:post_id, :id]
That's the first time I work on nested routes. I read some tutorials but had nothing really helped me to fix this. I am not sure how can I pass these keys...
(if you need any other info please let me know and I will provide them)
Any help is greatly appreciated!
You need to pass both the #post and #comment instance.
edit_post_comment_path(#post, #comment)
Generally speaking, you need to pass every instance matching the resource the route is part of. So, in a single route like
edit_post_path(#post)
you pass only the post. In a post/comment nested route you pass both. In a post/comment/whatever you will need to pass the three resources, etc.

Creating a page that is dependant on the model id

I have a create product page that takes infomation like name description. I want to make another page that allows the user to add a photo. To that product page. So i created a method for this page.
def pics
#product = Product.find(params[:id])
#photo = Photo.new
#product.photos.build
end
And also i added this to the config file
resources :products do
collection do
get :pics
end
end
And my rake routes look like this.
pics_products GET /products/pics(.:format) products#pics
products GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:id/edit(.:format) products#edit
product GET /products/:id(.:format) products#show
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy
Right now it's not taking the ID of the product it's in. How can i turn it into pics_products GET /products/:id/pics(.:format)?
You should change you routes like this:
resources :products do
member do
get :pics
end
end

Rails: What's the proper RESTful way to make this route?

So I have a Carts model which has_many Items. When I'm on the Carts#show page I want to have a link to an action that removes an item from that cart, in other words something that will find the item and set its cart_id to nil.
What should I name this action? Which controller should it be in -- CartsController or ItemsController? And lastly... how do I specify this route in my routes.rb (CODE PLEASE FOR THIS ONE)
Edit
I should be a bit more explicit: I don't want to destroy an item when I remove it from a person's cart. Each item is unique, and thus destroying it would destroy the listing... which is undesirable. Note that this also implies that this isn't a HABTM relationship... items can't belong to more than one cart.
Route:
resources :carts do
resources :items
end
This generates the following routes:
cart_items GET /carts/:cart_id/items(.:format) items#index
POST /carts/:cart_id/items(.:format) items#create
new_cart_item GET /carts/:cart_id/items/new(.:format) items#new
edit_cart_item GET /carts/:cart_id/items/:id/edit(.:format) items#edit
cart_item GET /carts/:cart_id/items/:id(.:format) items#show
PUT /carts/:cart_id/items/:id(.:format) items#update
DELETE /carts/:cart_id/items/:id(.:format) items#destroy
carts GET /carts(.:format) carts#index
POST /carts(.:format) carts#create
new_cart GET /carts/new(.:format) carts#new
edit_cart GET /carts/:id/edit(.:format) carts#edit
cart GET /carts/:id(.:format) carts#show
PUT /carts/:id(.:format) carts#update
DELETE /carts/:id(.:format) carts#destroy
So you're really explicit in describing items - carts relationship.
You use your controllers like you normally would.
I don't know why would you want to set the cart_id to nil instead of removing it, but this is how you would do it:
# in items_controller.rb
def destroy
#item = Item.find(params[:id])
#item.update_attributes(:cart_id => params[:cart_id])
respond_to do |format|
format.html { redirect_to items_url }
format.json { head :no_content }
end
end

Resources