Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete / Destroy is not working in rails 3 with jQuery

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.

like image 426
Mohit Jain Avatar asked Sep 24 '10 06:09

Mohit Jain


2 Answers

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.

like image 90
Justin Houk Avatar answered Sep 28 '22 01:09

Justin Houk


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
like image 26
Mohit Jain Avatar answered Sep 28 '22 00:09

Mohit Jain