Rails 3 UJS - link_to :remote 导致控制器被调用两次

34
我遇到了一个奇怪的问题,即JQuery为link_to方法创建了两个AJAX请求。我正在使用Rails 3应用程序和JQuery进行UJS开发。我有一个切换链接,可以在“关注”和“取消关注”之间切换。
我的链接呈以下渲染形式:
<span id="follow_link">
  <a href="/tfollow_artist?id=8103103" data-method="post" data-remote="true" id="follow_artist" rel="nofollow">Unfollow</a>
</span>

我的控制器设置如下:

def tfollow_artist
  @artist = Artist.find(params[:id])
  if current_user.following?(@artist) 
    current_user.stop_following(@artist)
  else 
    current_user.follow(@artist)
  end
 end

最终将其呈现为以下js:

 $('#follow_link').html('<%= escape_javascript(render :partial => "follow") %>');

这实际上是用不同的文本替换了带有'id="follow_link"'的<span>元素中的HTML内容,但URL保持相同。例如,现在会呈现为:

<span id="follow_link">
  <a href="/tfollow_artist?id=8103103" data-method="post" data-remote="true" id="follow_artist" rel="nofollow">Follow</a>
</span>

然而这些代码会导致 JQuery 发起两次 AJAX 请求。

有人能看出问题在哪里吗?

我正在使用 'jquery-rails' gem,它将最新的 jquery-ujs 文件复制到我的应用程序中。JQuery 版本是 1.4.3。


我也遇到了这个错误,有解决方案吗? - Anand
这里也有同样的问题。仍在寻找解决方案。 - Joost Schuur
这个问题我也遇到了,你最后解决了吗? - noli
也遇到了同样的问题...jquery-rails版本1.0.16。 - Docunext
11个回答

27

感谢这个对话:

https://github.com/rails/jquery-ujs/issues/208

我发现jquery和jquery_ujs被包含了两次。

我猜测jquery-rails gem会自动把它们放进application.js,然后我也在application.js中把它们包含了。

似乎无论我删除所有requires,application.js都会自动捆绑app/assets/javascripts/中的所有内容。

所以,如果您使用了:remote => true表单并且提交两次,请检查一下application.js。

希望这可以帮助您!

更新: 我认为这可能与我未使用摘要预渲染资产有关,因此当我的开发环境从app/assets/application.js动态地向html头添加脚本标签时,它还会为应该为空的动态application.js添加一个标签,但是静态文件public/assets中的文件会被加载。混淆?没错!


17

我遇到了同样的问题,通过注释掉这一行代码来解决了。

\#config.assets.debug = true

在开发模式中


1
这对我起作用了,重复的 AJAX 调用被消除了,但在我的另一台工作站上出于某种原因我不需要这样做。这个设置是什么意思,为什么我们需要打开/关闭它,何时使用它? - Homan
2
这仍然有效。有人能脱口而出地知道为什么吗? - polarblau

5

我遇到了类似的问题。运行以下rake任务解决了我的问题。

rake tmp:clear
rake assets:clean

3
我认为的情况是,你的JavaScript代码没有阻止浏览器执行链接。因此,你会得到AJAX请求和浏览器请求。
在Rails Cast 174中有关于这个问题的说明和解决方案。文字说明请查看这里,页面下方大约3/4处。

感谢提供链接和解释。这很有道理。然而,当调用link_to :remote时,已经使用了“live”方法和“prevents”默认的Javascript(在jquery-ujs' rails.js (https://github.com/rails/jquery-ujs/raw/master/src/rails.js)中:$('a[data-remote],input[data-remote]').live('click.rails', function (e) { $(this).callRemote(); e.preventDefault(); });因此不确定是否还有其他问题。 - chandru
难道不应该取决于返回值吗? - Miguel Ping

2
我遇到了同样的问题:在使用 :remote => true 时出现重复请求。这个问题是由于我使用了Heroku并且预编译了资产。在部署到Heroku之前,我会进行资产预编译(rake assets:precompile)。这实际上在公共文件夹中创建了一个资产管道的副本。因此,和Docunext提到的一样,每个请求都有多个javascript文件处理。
如果我在本地工作时删除公共目录中的资产(git rm -rf public/assets),它就可以解决了。从公共目录中删除资产后,它停止发送多个请求。

1
同样的问题也困扰着我:在link_to...:remote=>"true"上出现了两次XMLHttpRequest。
我解决了,在locals/application.rb中,通过注释// config.assets.paths << Rails.root.join('vendor','assets','stylesheets','javascripts')和取消注释config.action_view.javascript_expansions[:defaults] = %w(jquery jquery-ui application)来实现。
然后我忘记在最后一次git pull之后执行了这个操作。希望能帮助到其他人。

1

尝试使用以下代码...来防止在远程链接上双击。

$('a[data-remote=true]').live('ajax:before', function () {
   if ($(this).attr('ajax-loading')) {
     return false;
   } else {
     $(this).attr('ajax-loading', true);
   }
}).live('ajax:complete', function () {
  $(this).removeAttr('ajax-loading');
});

要点


0

在Eugene的回答基础上,需要注意的是,如果您在本地预编译了用于生产的资产并进行开发,那么...

bundle exec rake assets:precompile RAILS_ENV=production

...然后随着您继续开发,Rails AssetPipeline 将希望提供您未编译和已编译的资产。

解决问题的一种方法是使用 Eugene 的 Rails 标准 rake 任务。另一种方法是通过像这样删除那些讨厌的预编译生产就绪资产:

$ rm -rf #{Rails.root}/public/assets

0
我刚刚遇到了同样的问题。检查了所有代码更改并尝试了其他方法,但都没有成功。最后清除了浏览器缓存。这有所帮助。

0

在 JavaScript 文件中,您希望将哪些文件作为“默认”(application.js 总是包括在内)。

 config.action_view.javascript_expansions[:defaults] = %w(jquery rails)

注释行清楚地说明了application.js始终被包含在内。 在我的应用程序中,我已经将application添加到默认设置中。因此,对于ajax .submit,它在我的应用程序中创建了两个记录。


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