在Rails 3中,使用jQuery删除/销毁功能无效。

6
我的Rails 3中的删除/销毁功能无法正常工作。不仅是在脚手架上,就连新项目也是如此。请帮我解决这个问题。
<%= link_to 'Destroy', card, :confirm => 'Are you sure?', :method => :delete %> 

来自这个问题。解决方案是重新安装Firefox浏览器。但我在Chrome、Safari或Opera中也无法正常工作。

生成的HTML代码如下:

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

PS:请不要说包含默认的JS文件或其他。因为我完全不感兴趣Prototype,我正在使用jQuery。

编辑/更新,重要提示:这是当你不想使用Prototype时的解决方案。我的项目只使用了jQuery和相应的插件。

有人回答说:首先包含Prototype等,然后安装一些gem来消除Prototype和jQuery之间的冲突。这是废话。

我已经发布了一个答案。在你选择选项之前,请检查一下。对于我超过10个项目,没有任何问题。你需要做的就是:

从javascript目录中删除所有js文件,除了application.js。然后将我在答案中指定的代码粘贴到一个新文件中,并包含该文件。包含Jquery.js,然后你就完成了。你不需要添加默认的Javascript(即:Prototype)或某些其他的gem来消除冲突等。

4个回答

8
如果您正在使用 jQuery 而不是 Prototype,则需要在项目中添加 Jquery.rails.js。否则,每次尝试删除任何内容时,它将带您到展示页面。
我不记得我从哪里得到了这个解决方案和 Jquery.rails.js 文件。但是肯定是从一些可信赖的来源获取的。
以下是该文件的代码:
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'));
        });
    });
});

更新

您可以从这里获取最新的Jquery.rails.js副本。

   https://raw.github.com/rails/jquery-ujs/master/src/rails.js

2
如果您正在使用资产管道,这不是最好的方法。如果您使用资产管道,Justin Houk的答案更好。 - Mab879
@Justin houk的回答更好,我不明白为什么这个回答的投票比他高。无论如何,谢谢Mab879,你节省了我的时间,也感谢Justin houk。 - edisonthk
1
@edisonthk 因为我回答这个问题的时候,jquery-rails gem还没有发布。现在我已经更改了接受的答案。 - Mohit Jain
我能理解保持更新并不容易... 无论如何,愉快编码。 - edisonthk

8
我遇到了Mohit遇到的相同问题,也需要在我的JavaScript资产中包含“Unobtrusive JavaScript Library”(或“ujs”)。 在我的当前Rails(v3.2.5)中,UJS库将自动提供。 您可以通过在Gemfile中查看以下行来验证此操作: gem 'jquery-rails' 以及在app / assets / javascripts / application.js文件中查看以下行: //= require jquery_ujs 由于我不知道更好的方法,因此已从我的application.js文件中删除了require jquery_ujs行,这花费了我一些时间才弄清楚为什么我的link_to ...,:method =>:delete 调用不再起作用!
一旦我理解了问题,就很容易将上述两行添加回它们各自的文件中,然后一切都像预期的那样开始工作。

4

确保在你的布局文件中包含默认的Rails JavaScript文件。

<%= javascript_include_tag :defaults %>

3
我正在使用jQuery,为什么还需要这样做测试呢?虽然出于测试目的我已经这样做了,但仍然没有生效。 - Mohit Jain
Rails 3 使用不显眼的 JavaScript 使其运作。因此,您必须包括某些 JavaScript 框架(Prototype 或 JQuery)和适当的 rails.js。有关更多信息,请参见 Ryan Bates 的 screencast - Simon Perepelitsa
如果你使用jquery-rails而不是默认的prototype-rails gem,你应该在这里获取jquery的javascripts。这个答案仅适用于Rails 3.0版本。 - Simon Perepelitsa

2
确保在您的布局中包含默认的Rails JavaScript文件。
<%= javascript_include_tag "application" %>

application.js 是一个空的 js 文件 :P 检查我的答案。 - Mohit Jain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接