Wrong controller action in rails form with link - ruby-on-rails

I have a form...
= simple_form_for #form, :url => update_path, :method => :put do |form|
= form.input_field :name
= link_to image_tag asset_path("icon.png"),
{:controller => 'controller/name', :action => 'delete', :id => some.id}
= form.submit
As in above form I have a link/image/icon, which on click should fire delete action controller, but for some reason it goes to index controller action. Can someone point what's wrong here please?

When you define a resources routes, the delete action will be defined as the same url as the update action (which is accessed using PUT or PATCH HTTP verbs),
but it is accessed using the DELETE HTTP verb
All you need to do is set the link to the update path of your object and use the DELETE verb instead:
= link_to image_tag("icon.png"), update_path(id: some.id), method: :delete
Also, no need for #asset_path, I think

Try doing:
= link_to image_tag asset_path("icon.png"),
{:controller => 'controller_name', :action => 'delete_method_name', :id => some.id},
{:confirm => 'Are you sure?', :method => :delete}
Issue is that, you need to pass :method as :delete, :action should be the method name of your controller not the HTTP method.

Related

Share a partial among different resources

I have the following bit of code in my views:
- if admin?
.meta
Administrator options:
= link_to 'Edit This Post', edit_post_path(#post)
|
= link_to 'Delete This Post', #post, :method => 'delete', :confirm => 'Are you sure?'
I find that I use this same basic snippet a lot, but sometimes with different resources, and sometimes with more than one resource on a page. I'd like to extract this into a partial to DRY it up, but I need to write is so it could work with local or instance variables for any model. For instance, I need it to work with:
#post, post, #page, page
How do you do that?
You can cleanly write your partial to be independent of the given object:
- if admin?
.meta
Administrator options:
= link_to 'Edit', [:edit, object]
|
= link_to 'Delete', object, :method => 'delete', :confirm => 'Are you sure?'
And then you could do something like
render :partial => 'shared/admin_link', :locals => { :object => #post }
You can commit a variable to a partial using the :object or the :collection options in the render method. The :object option passes a single object to the partial that can contain anything. The :collection option is used to pass an Array of Objects that must be from the same Class.
For example you have your #post and pass it to the partial like this
<%= render :partial => 'layouts/my_partial', :object => #post, :as => :my_local_var %>
Then you can access the object by calling my_local_var in the partial. Using :collection is slightly different but you can read it on your own here: http://guides.rubyonrails.org/layouts_and_rendering.html
A Problem will be the usage of one partial in different Classes because of the routes names. Then you cant use the edit_modelname_path(#instance_var) you must use the routes Hash { :controller => params[:controller], :action => 'edit' } in the link_to method!
// For Link creation wihout params[:controller] :
Its just an Idea I didnt do this before but you can try this for example:
You render the partial and use :object => #instancevar, :as => :my_local_var you can use the following line for dynamic link creation:
<%= link_to "link text", { :controller => my_local_var.class.to_s.pluralize.downcase, :action => 'edit', :id => my_local_var.id } %>
Then you dont depend on the params[:controller] but are able to link to the vars edit link.

ROR ways of calling destroy action

I ask this question only because I'm curious.
The first line is standard, RESTful and of course invokes destroy method.
The second line returns a routing error.
The question is how to repair the second line to work like the first one. As I mentioned before, It's just for my curiosity and better ROR understanding.
<%= link_to 'delete', file, :method => :delete %></td>
<%= link_to 'delete', {:action => :destroy, :controller => 'files', :id => file.id.to_s}, :method => :delete %>
Bye
Disclaimer: I know this is not the way to do a delete. It is proof of concept on just how to access an action via a controller outside of REST.
You can do this:
<%= link_to 'delete', {:action => :destroy, :controller => 'files', :id => file.id} %>
You don't need the method destroy if you explicitly access the action. Also don't need the to_s for the file.id

How can I pass an extra parameter to a link_to remote?

Given the following:
<%= link_to "Add", group_request_path(gr), :confirm => "Are you sure?", :method=> :put, :remote => true %>
<%= link_to "Ignore", group_request_path(gr), :confirm => "Are you sure?", :method=> :put, :remote => true %>
How can I pass a decision param with either add or ignore in the link_to's above? Is there an option to add a URL param somehow with a link_to? I don't want to have to use forms.
the *_path helpers accept a hash of options to append to the path as a query string.
In your example, assuming group_request_path(gr) outputs something like /group_requests/123, you could add a query string with add/ignore actions like this:
group_request_path(gr, :action => 'add') # /groups_requests/123?action=add
or
group_request_path(gr, :add => 1) # /groups_requests/123?add=1
However this probably isn't the correct way of going about this. It looks like you should probably have distinct actions in your controller, and routes specific to adding or ignoring. You'll have to add something like the following to config/routes.rb:
put 'group_requests/:id/add' => 'groups_requests#add', :as => :add_group_request
put 'group_requests/:id/ignore' => 'groups_requests#ignore', :as => :ignore_group_request
Your links then become
<%= link_to "Add", add_group_request_path(gr), :confirm => "Are you sure?", :method=> :put, :remote => true %>
<%= link_to "Ignore", ignore_group_request_path(gr), :confirm => "Are you sure?", :method=> :put, :remote => true %>

How do properly delete this?

Something is seriously not adding up here.. My page just refreshes, nothing happens, it never touches any of my debuggers hanging out on all my methods except for index.
my html:
<%- for image in #images %>
<%= image.attachment_file_name %>
<%-# link_to_delete image, :url => destroy_image_admin_wysiwyg_path(image.id) %>
<%= link_to 'delete', { :url => destroy_image_image_path(image.id) },
#:confirm => 'Are you sure?',
:post => true
%>
<br />
<% end %>
my controller
def destroy_image
debugger
#img = Image.find(params[:id])
#img.destroy
respond_to do |format|
format.html { redirect_to admin_image_rotator_path }
end
end
My routes:
map.resources :images, :member => { :destroy_image => :post }
My disgusting hack that works that I will replace as soon as I find something better
I moved the action over to a simpler controller I built myself.
Changed my routes to :
admin.resources :wysiwygs, :member => { :destroy_image => :post }
Changed my html :
<%= link_to 'delete', :controller => "wysiwygs", :action => "destroy_image" %>
But when I clicked on the link..it brought up.. the show action ?? fffffffffuuuuuuu
I retaliated by just moving my action to the show action, and passing a hidden field in my html..
<%= link_to 'delete', :controller => "wysiwygs", :action => "destroy_image", :hidden_field => {:value => image.id} %>
def show
# this was previously in destroy_image
#img = Image.find(params[:hidden_field][:value])
#img.destroy
respond_to do |format|
format.html { redirect_to admin_image_rotator_path }
end
end
It seems you're going down the wrong path here. If a before_filter is blocking your action, figure out why. Use skip_before_filter :filter_name if the filter is not needed.
Don't use show actions or HTTP GET for deletes. Even if it works, it will confuse things down the road. Use a DELETE verb:
map.resources :images, :member => { :destroy_image => :delete }
pass it in the link helper:
<%= link_to "delete", destroy_image_image_path(image), :method => :delete %>
And use ImagesController#destroy_image to perform the action. Better yet, consider using the standard RESTful ImagesController#destroy which map.resources gives you for free.
Not sure what was wrong in the first place, but in your second, working solution, i think you should write your link_to as follows:
link_to 'delete', :controller => "wysiwygs", :action => "destroy_image", :id => image.id
That at least would send you to the correct action.
Depending on your routes, you will have to make this a method => :post or not.
Check your rake routes output, it will show you what are the possible routes, and also what names they got, which in turn you can use as a method (add _path or _url at the end). Then it should be even easier to write something like:
link_to 'delete', wysiwygs_destroy_image_path(image)
Good luck!
You're doing a POST but your resource says that :destroy_image is only available via GET. Try changing your route to:
map.resources :images, :member => { :destroy_image => :post }
Also, take a look at your link_to. The second parameter takes a URL, not a hash that has a :url key. As mentioned elsewhere, depending on your Rails version you may need :method => :post instead of :post => true. In Rails 2.3.8, you would want this line instead:
<%= link_to 'delete', destroy_image_image_path(image), :method => :post %>

Button_to uses POST Link_to uses GET, why? ROR

I've ran into a ror problem using the link_to. Why does my link to use the GET method and my button_to use the POST method, after I specified my "method"=>"post" within the link_to parameters?
View:
<%= button_to "pdf", :action => 'getquote' %>
<%= link_to 'pdf', {:controller => 'inventories', :action => 'getquote', :method => :post } %>
Controller Method:
def getquote
#cart = find_cart
respond_to do |format|
format.pdf
end
end
Terminal Output (Button/Link, respectively):
Processing InventoriesController#getquote (for 127.0.0.1 at 2010-01-30 01:38:02) [POST]
Parameters: {"action"=>"getquote", "authenticity_token"=>"D2cwnHyTHgomdUM3wXBBXlOe4NQLmv1Srn0paLbExpQ=", "controller"=>"inventories"}
Processing InventoriesController#show (for 127.0.0.1 at 2010-01-30 01:39:07) [GET]
Parameters: {"method"=>"post", "action"=>"show", "id"=>"getquote", "controller"=>"inventories"}
I think your html options have to be in a separate hash from your url options:
<%= link_to 'pdf', {:controller => 'inventories', :action => 'getquote'}, {:method => :post } %>
I looked all over for a proper example, with no luck. For my code, I've mostly given up and just use the new style:
<%= link_to 'Delete', custom_event, :confirm => 'Are you sure?', :method => :delete %>
Might be useful for someone who is visiting :)
By default, button_to performs POST action only.
to do make a GET the syntax is as follows:
<%= button_to 'pdf', { :action => 'getquote'}, :method => :get %>
One possibility is that you have Javascript disabled, in which case it will fall back to a GET.

Resources