Delete / Destroy is not working in rails 3 with jQuery
Asked Answered
C

4

6

My delete/destroy is not working for Rails 3.

Not for any scaffold or even for new projects.

<%= link_to 'Destroy', card, :confirm => 'Are you sure?', :method => :delete %> 

From this question. Solution is Firefox reinstalation. But mine is also not working in chrome, safari or opera.

Html code generated:--

 <a href="/categories/1" data-confirm="Are you sure?" data-method="delete" rel="nofollow">Destroy</a>

PS: Please don't say include default JS files or something. Because I am not interested in prototype all together, as I am using jQuery.

EDIT/Update, Important: this is the solution when you don't want to use prototype at all. I am using only jQuery and respective plugins in my project.

People are answering: First include prototype etc and then install some gem etc to remove conflicts between prototype and jQuery. That's rubbish.

I have posted an answer. Please check that once before you go for the option. Worked for me for more than 10 projects without any issues. All you need to do is:

Remove all the js files from your javascript directory except application.js. Then Paste the code i specified in my answer in a new file and include that file. Include Jquery.js and then you are all set. You don't need to add default javascript (ie: prototype) or some other gem to remove conflicts etc.

Carlyncarlynn answered 24/9, 2010 at 6:11 Comment(0)
C
8

I ran into the same issue Mohit had and also needed to include the 'Unobtrusive JavaScript Library' (or 'ujs') in my JavaScript assets. In my current Rails (v3.2.5), the UJS library will be provided automatically. You can verify this by seeing the following line in your Gemfile:

gem 'jquery-rails'

and the following line in your app/assets/javascripts/application.js file:

//= require jquery_ujs

Since I didn't know any better, I had removed the require jquery_ujs line from my own application.js file, and it took me a while to figure out why my link_to ..., :method => :delete calls weren't working any more!

Once I understood the problem, it was easy to add the above two lines back to their respective files and everything started working as expected again.

Chatter answered 22/6, 2012 at 17:47 Comment(0)
C
8

If you are using jQuery not Prototype then you need to add Jquery.rails.js in your project, otherwise every time you try to delete anything it will take you to show page.

I don't remember from where I got the solution and this Jquery.rails.js file. But sure from some trustworthy source.

Here is the code for that file:

jQuery(function ($) {
    var csrf_token = $('meta[name=csrf-token]').attr('content'),
        csrf_param = $('meta[name=csrf-param]').attr('content');

    $.fn.extend({
        /**
         * Triggers a custom event on an element and returns the event result
         * this is used to get around not being able to ensure callbacks are placed
         * at the end of the chain.
         *
         * TODO: deprecate with jQuery 1.4.2 release, in favor of subscribing to our
         *       own events and placing ourselves at the end of the chain.
         */
        triggerAndReturn: function (name, data) {
            var event = new $.Event(name);
            this.trigger(event, data);

            return event.result !== false;
        },

        /**
         * Handles execution of remote calls firing overridable events along the way
         */
        callRemote: function () {
            var el      = this,
                data    = el.is('form') ? el.serializeArray() : [],
                method  = el.attr('method') || el.attr('data-method') || 'GET',
                url     = el.attr('action') || el.attr('href');

            if (url === undefined) {
              throw "No URL specified for remote call (action or href must be present).";
            } else {
                if (el.triggerAndReturn('ajax:before')) {
                    $.ajax({
                        url: url,
                        data: data,
                        dataType: 'script',
                        type: method.toUpperCase(),
                        beforeSend: function (xhr) {
                            el.trigger('ajax:loading', xhr);
                        },
                        success: function (data, status, xhr) {
                            el.trigger('ajax:success', [data, status, xhr]);
                        },
                        complete: function (xhr) {
                            el.trigger('ajax:complete', xhr);
                        },
                        error: function (xhr, status, error) {
                            el.trigger('ajax:failure', [xhr, status, error]);
                        }
                    });
                }

                el.trigger('ajax:after');
            }
        }
    });

    /**
     *  confirmation handler
     */
    $('a[data-confirm],input[data-confirm]').live('click', function () {
        var el = $(this);
        if (el.triggerAndReturn('confirm')) {
            if (!confirm(el.attr('data-confirm'))) {
                return false;
            }
        }
    });


    /**
     * remote handlers
     */
    $('form[data-remote]').live('submit', function (e) {
        $(this).callRemote();
        e.preventDefault();
    });
    $('a[data-remote],input[data-remote]').live('click', function (e) {
        $(this).callRemote();
        e.preventDefault();
    });

    $('a[data-method]:not([data-remote])').live('click', function (e){
        var link = $(this),
            href = link.attr('href'),
            method = link.attr('data-method'),
            form = $('<form method="post" action="'+href+'">'),
            metadata_input = '<input name="_method" value="'+method+'" type="hidden" />';

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

        form.hide()
            .append(metadata_input)
            .appendTo('body');

        e.preventDefault();
        form.submit();
    });

    /**
     * disable-with handlers
     */
    var disable_with_input_selector = 'input[data-disable-with]';
    var disable_with_form_selector = 'form[data-remote]:has(' + disable_with_input_selector + ')';

    $(disable_with_form_selector).live('ajax:before', function () {
        $(this).find(disable_with_input_selector).each(function () {
            var input = $(this);
            input.data('enable-with', input.val())
                 .attr('value', input.attr('data-disable-with'))
                 .attr('disabled', 'disabled');
        });
    });

    $(disable_with_form_selector).live('ajax:after', function () {
        $(this).find(disable_with_input_selector).each(function () {
            var input = $(this);
            input.removeAttr('disabled')
                 .val(input.data('enable-with'));
        });
    });
});

Update

You can get latest copy of Jquery.rails.js from here.

   https://raw.github.com/rails/jquery-ujs/master/src/rails.js
Carlyncarlynn answered 7/5, 2011 at 19:7 Comment(4)
This isn't the best way to this if you are using the asset pipeline. Justin Houk answer is a better one if you use the asset pipeline.Bookbinder
@Justin houk answer is better, well I don't understand why this answer is higher vote then him. Anyway, thank you Mab879 you save my hours time and thank yo Justin houk tooGland
@Gland cause the time I posted this answer. Jquery-rails gem was not released. I have changed the accepted answer now..Carlyncarlynn
I can understand that keep something update is not an easy things... Anyway, Happy codingGland
C
8

I ran into the same issue Mohit had and also needed to include the 'Unobtrusive JavaScript Library' (or 'ujs') in my JavaScript assets. In my current Rails (v3.2.5), the UJS library will be provided automatically. You can verify this by seeing the following line in your Gemfile:

gem 'jquery-rails'

and the following line in your app/assets/javascripts/application.js file:

//= require jquery_ujs

Since I didn't know any better, I had removed the require jquery_ujs line from my own application.js file, and it took me a while to figure out why my link_to ..., :method => :delete calls weren't working any more!

Once I understood the problem, it was easy to add the above two lines back to their respective files and everything started working as expected again.

Chatter answered 22/6, 2012 at 17:47 Comment(0)
C
4

Make sure that you include default Rails javascript files in your layout.

<%= javascript_include_tag :defaults %>
Clouet answered 24/9, 2010 at 7:40 Comment(3)
Why should I, when i am using Jquery. Still for testing purpose i did that. Still no working.Carlyncarlynn
Rails 3 uses unobtrusive javascript to make it work. So you have to include some javascript framework (Prototype or JQuery) and proper rails.js for it. See the screencast by Ryan Bates for more information.Clouet
If you use jquery-rails instead of prototype-rails gem (which is by default) you should get jquery javascripts here. This answer is for Rails 3.0 only.Clouet
D
2

Make sure that you include default Rails javascript files in your layout.

<%= javascript_include_tag "application" %>
Darrondarrow answered 13/3, 2012 at 21:13 Comment(1)
application.js is a blank js file :P Check my answer.Carlyncarlynn

© 2022 - 2024 — McMap. All rights reserved.