web-dev-qa-db-ja.com

Rails 3 UJS-コントローラーはlink_to:remoteによって2回呼び出されます

JQueryがlink_toメソッドの2つのAJAXリクエストを作成しているという奇妙な問題があります。JQueryforUJSを使用してRails 3アプリを開発しています。 'Follow'と 'Unfollow'を切り替えるトグルリンク

私のリンクは次のようにレンダリングされます:

<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") %>');

これは基本的に、 '<span 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が2つのAJAXリクエストを行う原因になっています。

ここで何が悪いのか誰かがわかりますか?

最新のjquery-ujsファイルをアプリにコピーしている「jquery-Rails」gemを使用しています。 JQueryのバージョンは1.4.3です

33
chandru

このダイアログのおかげで:

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

Jqueryとjquery_ujsが2回含まれていることを発見できました。

Jquery-Rails gemはそれらを自動的にapplication.jsに入れてから、application.jsにも含めたと思います。

何らかの理由で、application.jsはapp/assets/javascripts /にすべてを自動的にバンドルしているようです-必要なものをall削除しても。

したがって、:remote => trueフォームが2回送信される場合は、application.jsを確認してみてください。

お役に立てれば!

更新:これは、ダイジェストを使用せずにアセットを事前レンダリングすることに関係している可能性があると思います。そのため、開発環境がapp/assets/application.jsのrequiresから動的にhtmlヘッドにスクリプトタグを追加すると、また、public/assetsからの静的なものがロードされることを除いて、空の動的なapplication.jsであるべきもののために1つを追加します。紛らわしい?うん!

26
Docunext

私は同じ問題を抱えていましたが、この行にコメントすることで修正されました

\#config.assets.debug = true

開発モードで

17
freeman

私は同様の問題を抱えていました。次のrakeタスクを実行すると、問題が解決しました。

rake tmp:clear
rake assets:clean
5
Eugene

何が起こっているのかというと、JavaScriptがリンクのブラウザによる実行を停止していないということだと思います。したがって、AJAXリクエストを取得してから、ブラウザリクエストを取得します。

これに対する説明と解決策はRails Cast 174です。テキストの説明 ここ 、ページの約3/4下にあります。

3
dteoh

私は同じ問題を抱えていました:: remote => trueを使用するとリクエストが重複します。私の問題は、Herokuの使用とアセットのプリコンパイルが原因でした。 Herokuにデプロイする前にアセットをプリコンパイルしています(rakeassets:precompile)。これにより、基本的に、パブリックフォルダーにアセットパイプラインの複製コピーが作成されます。したがって、Docunextで述べたのと同じことが起こっていました。つまり、各リクエストを処理する複数のjavascriptファイルがありました。

ローカルで作業しているときにパブリックディレクトリ(git rm -rf public/assets)のアセットを削除すると、修正されます。パブリックディレクトリからアセットを削除した後、複数のリクエストの送信を停止しました

2
hoitomt

このコードを試してください....リモートリンクのダブルクリックを防ぐために..

$('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');
});

要点

1
prasannaboga

私にとっても同じ問題:link_toで2回XMLHttpRequest ...:remote => "true"

私は解決しました

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プルの後にするのを忘れました。私は誰かを助けることを願っています。

1
rfellons

Eugeneの回答に基づいて、本番用にアセットをローカルでプリコンパイルした後に開発している場合は、次のように注意してください...

bundle exec rake assets:precompile Rails_ENV=production

...次に、開発を続けると、Rails AssetPipelineは両方コンパイルされていないおよびコンパイルされたアセットを提供したいと思うでしょう。

これを修正する1つの方法は、Eugene'sRailsの標準的なレーキタスクを使用することです。もう1つの方法は、次のような厄介なプリコンパイル済みの本番用アセットを削除することです。

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

私はちょうど今同じ問題に直面しました。すべてのコード変更をチェックアウトし、他のことを試しましたが、役に立ちませんでした。最終的にブラウザのキャッシュをクリアしました。それは助けになりました。

0
prasad.surase

:defaultsとして必要なJavaScriptファイル(application.jsは常に含まれています)。

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

コメント行は、application.jsが常に含まれていることを明確に示しています。私のアプリケーションでは、デフォルトでアプリケーションを追加しました。したがって、ajax .submitの場合、アプリケーションで2つのレコードが作成されていました。

0
chaitanya

Ujsファイルが2回ロードされている場所がわからない場合は、このコードをRails.js/application.jsにコピーするだけです(できればここにはありません)。

var alreadyInitialized = function() {
    var events = $(document).data('events');
    return events.click && $.grep(events.click, function(e) { return e.namespace === 'Rails'; }).length;
    }

if ( alreadyInitialized() ) {
    $.error('jquery-ujs has already been loaded!');
}
0