开发者

Rails' link_to method: GETing when it should DELETE

I'm following Michael Hartl's Rails Tutorial, and for some reason the following code:

<%= link_to 'delete', user, :method => :delete, :confirm => "You sure?",
                                :title => "Delete #{user.name}" %>

Issues a GET request (as I verified by checking the rails server log). I also verified that the following line is in my applicat开发者_如何学JAVAion view:

<%= javascript_include_tag :all %>

One thing I didn't quite understand, and it's probably the source of my problem: where is the "delete" method defined? I verified in Hartl's source code that he defines a "destroy" method in the controller, not "delete". But even if I change the link_to to :method => :destroy, it just issues a GET.

I'm using Rails 3.1. Any tips?


Also check that this is in your application.js:

//= require jquery
//= require jquery_ujs 

Apparently I had the jquery without the jquery_ujs and I had the same problem until I added that.

Note that you may need to add these lines above any import statements within application.js.


Most browsers don't actually support the DELETE verb, so Rails fakes it by modifying the HTML it generates. Rails tacks on a HTML5 attribute called data-method and sets it to "delete". So when a user clicks on the link, it is actually issued as a GET request, but the data-method attribute allows for some Rails magic and means your routing code should recognize it as a DELETE request.

edit:

You can test it yourself in the console. Run bundle exec rails c to get into the console, and look at the HTML that this generates:

helper.link_to "delete", "foobar/delete", :method => 'delete'

The HTML should look like this:

<a href="foobar/delete" data-method="delete" rel="nofollow">delete</a>


You should use the following code

<%= button_to "delete", @user_current, :method => "delete" %>

It will solve the problem or add this line //= require jquery_ujs to application.js and use:

 <%= link_to 'delete', user, :method => :delete, data: {:confirm => "You sure?" } ,
                            :title => "Delete #{user.name}" %>


As browsers don't support the DELETE verb, Rails creates a workaround for this problem by simulating a DELETE request through a standard GET or POST. The way method: :delete works is with a JavaScript handler for all links with data-method="delete" which modifies the request so Rails processes it as a DELETE. This JavaScript handler is provided by the jquery_ujs library.

There are several things that could have gone wrong:

  1. Make sure you have both jquery and jquery_ujs included in your application.js. Without both nothing will process the data attributes.
  2. Make sure the link in question really has the method: :delete option specified.
  3. Make sure for some reason you haven't stopped the event propagation of the link in question, like so for example:
$( 'a' ).click( function( event ) {
    event.stopPropagation()
})

As this would prevent the jquery_ujs handlers from being executed and the request will never be modified and will remain just a standard GET.


I faced the same problem with Michael's tutorial. The data-method="delete" actually works as expected - it does call the destroy action in the controller. The reason it tries to GET (and eventually fail) is the following:

You'll notice that one of the before_filter's in the controller is set to signed_in_user, and in session_helper.rb, you'll notice that signed_in_user calls store_location (private method), which updates session[:return_to] to the current URL.

So, back in your controller's destroy action, it tries to redirect_back_or which results in GET current_url. I modified the signed_in_user helper to only call store_location when user is not signed in already.


On rails 5 :

Have the same problem, all 'DELETE' posts were compromised, affecting my crud pages AND devise signout... to solve the problem all I had to do was :

//= require rails-ujs


All we need is add the below line of code

//= require jquery_ujs 

It seems like a bug:))


You want to do this in Rails 6+:

 link_to(
  'Delete Me',
   some_controller_path(model),
   data: { method: :delete }
 )


Use button_to instead of link_to.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜