2

I was working with Devise in Rails and while setting up the sign_out function I run into errors. I noticed than, it happened because pages which have sign_out link skipped layouts so Javascript was inactive. By enabling javascript with:`

<%= javascript_include_tag :defaults %>

everything just worked fine.

Why does it work like that?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Barbared
  • 800
  • 1
  • 8
  • 25

2 Answers2

4

links are (normally) always get requests. In order for a link to send a non-get request you need some javascript that modifies the behaviour of the link.

In addition browsers typically only support GET/POST requests so rails fakes up the other methods (DELETE, PUT,...) by adding a _method field to the post.

Frederick Cheung
  • 83,189
  • 8
  • 152
  • 174
2

Here's excerpt from jquery_ujs.js. It'll shed some light on how it is done:

// Handles "data-method" on links such as:
// <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
handleMethod: function(link) {
  var href = link.attr('href'),
    method = link.data('method'),
    target = link.attr('target'),
    csrf_token = $('meta[name=csrf-token]').attr('content'),
    csrf_param = $('meta[name=csrf-param]').attr('content'),
    form = $('<form method="post" action="' + href + '"></form>'),
    metadata_input = '<input name="_method" value="' + method + '" type="hidden" />';

  if (csrf_param !== undefined && csrf_token !== undefined) {
    metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />';
  }

  if (target) { form.attr('target', target); }

  form.hide().append(metadata_input).appendTo('body');
  form.submit();
},

So, by clicking on such a link you're basically trigger sending of a hidden form (that is being created during the click) with some parameters that simulate DELETE HTTP verb.

jdoe
  • 15,665
  • 2
  • 46
  • 48
  • And does this function get called in every REST form? I explain better: what if instead of using "form_for @resource" I just use "form tag ..." with REST resource? Would the behaviour be just the same? – Barbared Jun 05 '12 at 12:52
  • 1
    It's for handling links. This code creates hidden form on the fly and submits it. If you have some form_xxx (or button_to) then you can use them to trigger non-GET actions even w/o javascript enabled. That's why some sources don't recommend using links for non-GET actions if you're afraid to meet some user w/o javascript. Can be the case for mobile users. – jdoe Jun 05 '12 at 13:00