【问题标题】:Changing from Prototype to JQuery leads to double POST从 Prototype 更改为 JQuery 会导致双重 POST
【发布时间】:2011-12-01 07:31:45
【问题描述】:

在 Michael Hartl 的 Ruby on Rails Tutorial 第 12 章中,用户的个人资料页面上有一个按钮,您可以翻转以关注或取消关注他/她。 (见图12.12和12.13)

我正在使用 rvm 1.8.6 和 Rails 3.1.1。

当我使用 Prototype 时,单击按钮的行为可以正常工作。 在 /sample_app/app/views/layouts/application.html.erb 中,

<%= javascript_include_tag :defaults %>

点击“关注”时,它会先 POST 然后 GET 以重新呈现页面。日志如下。

Started POST "/relationships" for 127.0.0.1 at 2011-11-30 22:07:04 -0800
  Processing by RelationshipsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"sVoNM/yyDmn0czvbza+dxzLsPW4mPNlGxAI1vKN7Ez4=", "relationship"=>{"followed_id"=>"13"}, "commit"=>"Follow"}
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", "13"]]
  SQL (0.6ms)  INSERT INTO "relationships" ("created_at", "followed_id", "follower_id", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Thu, 01 Dec 2011 06:07:04 UTC +00:00], ["followed_id", 13], ["follower_id", 1], ["updated_at", Thu, 01 Dec 2011 06:07:04 UTC +00:00]]
  Redirected to ht.p://localhost:3000/users/13
  Completed 302 Found in 52ms

Started GET "/users/13" for 127.0.0.1 at 2011-11-30 22:07:04 -0800
  Processing by UsersController#show as HTML
  Parameters: {"id"=>"13"}
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", "13"]]
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
  Relationship Load (0.2ms)  SELECT "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = 1 AND "relationships"."followed_id" = 13 LIMIT 1
  CACHE (0.0ms)  SELECT "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = 1 AND "relationships"."followed_id" = 13 LIMIT 1
Rendered users/_unfollow.html.erb (6.9ms)
Rendered users/_follow_form.html.erb (54.5ms)
(0.2ms)  SELECT COUNT(*) FROM "microposts" WHERE "microposts"."user_id" = 13
  CACHE (0.0ms)  SELECT COUNT(*) FROM "microposts" WHERE "microposts"."user_id" = 13
(0.2ms)  SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = 13
(0.1ms)  SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = 13
Rendered shared/_stats.html.erb (4.2ms)
Rendered users/show.html.erb within layouts/application (67.5ms)
Rendered layouts/_stylesheets.html.erb (1.4ms)
Rendered layouts/_header.html.erb (2.5ms)
Rendered layouts/_footer.html.erb (0.7ms)
Completed 200 OK in 100ms (Views: 83.1ms | ActiveRecord: 1.9ms)

但是,在我按照第 13 章切换到 JQuery 后,单击关注按钮的行为导致异常并导致 Web 服务器崩溃。 在我将 /sample_app/app/views/layouts/application.html.erb 修改为之后,

<%= javascript_include_tag "application" %>

它会 POST 两次。而且我猜 db 唯一违规使 Ruby 崩溃了。日志如下。

Started POST "/relationships" for 127.0.0.1 at 2011-11-30 21:08:51 -0800
  Processing by RelationshipsController#create as JS
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"sVoNM/yyDmn0czvbza+dxzLsPW4mPNlGxAI1vKN7Ez4=", "relationship"=>{"followed_id"=>"19"}, "commit"=>"Follow"}
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", "19"]]
  SQL (4.6ms)  INSERT INTO "relationships" ("created_at", "followed_id", "follower_id", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Thu, 01 Dec 2011 05:08:51 UTC +00:00], ["followed_id", 19], ["follower_id", 1], ["updated_at", Thu, 01 Dec 2011 05:08:51 UTC +00:00]]
  Relationship Load (0.2ms)  SELECT "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = 1 AND "relationships"."followed_id" = 19 LIMIT 1
Rendered users/_unfollow.html.erb (3.7ms)
   (0.2ms)  SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = 19
Rendered relationships/create.js.erb (7.7ms)
Completed 200 OK in 103ms (Views: 13.7ms | ActiveRecord: 6.0ms)


Started POST "/relationships" for 127.0.0.1 at 2011-11-30 21:08:51 -0800
  Processing by RelationshipsController#create as JS
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"sVoNM/yyDmn0czvbza+dxzLsPW4mPNlGxAI1vKN7Ez4=", "relationship"=>{"followed_id"=>"19"}, "commit"=>"Follow"}
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", "19"]]
  SQL (0.5ms)  INSERT INTO "relationships" ("created_at", "followed_id", "follower_id", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Thu, 01 Dec 2011 05:08:51 UTC +00:00], ["followed_id", 19], ["follower_id", 1], ["updated_at", Thu, 01 Dec 2011 05:08:51 UTC +00:00]]
SQLite3::ConstraintException: constraint failed: INSERT INTO "relationships" ("created_at", "followed_id", "follower_id", "updated_at") VALUES (?, ?, ?, ?)
Completed 500 Internal Server Error in 86ms

SQLite3::ConstraintException (columns follower_id, followed_id are not unique):

Rendered /home/anson/.rvm/gems/ruby-1.9.2-p290/gems/actionpack-3.1.1/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.2ms)
Rendered /home/anson/.rvm/gems/ruby-1.9.2-p290/gems/actionpack-3.1.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.0ms)
Rendered /home/anson/.rvm/gems/ruby-1.9.2-p290/gems/actionpack-3.1.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (4.2ms)
/home/anson/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.1/lib/active_record/connection_adapters/sqlite_adapter.rb:84: [BUG] Segmentation fault
ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]

-- control frame ----------
c:0044 p:---- s:0205 b:0205 l:000204 d:000204 CFUNC  :close
...
[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
Aborted

有人可以帮忙吗?

代码如下。 app/views/users/_follow_form.html.erb

<% unless current_user?(@user) %>
  <div id="follow_form">
  <% if current_user.following?(@user) %>
    <%= render 'unfollow' %>
 <% else %>
    <%= render 'follow' %>
  <% end %>
  </div>
<% end %>

app/views/users/_follow.html.erb

<%= form_for current_user.relationships.build(:followed_id => @user.id),
             :remote => true do |f| %>
  <div><%= f.hidden_field :followed_id %></div>
  <div class="actions"><%= f.submit "Follow" %></div>
<% end %>

app/views/users/_unfollow.html.erb

<%= form_for current_user.relationships.find_by_followed_id(@user),
             :html => { :method => :delete },
             :remote => true do |f| %>
  <div class="actions"><%= f.submit "Unfollow" %></div>
<% end %>

app/controllers/relationships_controller.rb

class RelationshipsController < ApplicationController
  before_filter :authenticate

  def create
    @user = User.find(params[:relationship][:followed_id])
    current_user.follow!(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end

  def destroy
    @user = Relationship.find(params[:id]).followed
    current_user.unfollow!(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end
end

app/views/relationships/create.js.erb

$("follow_form").update("<%= escape_javascript(render('users/unfollow')) %>")
$("followers").update('<%= "#{@user.followers.count} followers" %>')

app/views/relationships/destroy.js.erb

$("follow_form").update("<%= escape_javascript(render('users/follow')) %>")
$("followers").update('<%= "#{@user.followers.count} followers" %>')

【问题讨论】:

  • 虽然我需要查看代码,但可能是默认表单行为(提交)正在采取行动以及您的 js 代码。尝试在处理表单提交的 js 代码开头添加一个 e.preventDefault。
  • 我已经添加了代码。你能告诉我在哪里可以添加 e.preventDefault 吗?
  • 在js事件处理函数中,function(e) { e.preventDefault(); ... }
  • 如果您使用的是 Rails 3.1,那么您并没有完全遵循使用 Rails 3.0 的教程。使用与教程中不同的 Rails 版本可能会产生不同的结果。我建议使用教程中使用的确切 gem 版本。如果你渴望使用 Rails 3.1,请参阅第 13 章。目前正在准备一个新版本,整个使用 Rails 3.1。

标签: ruby-on-rails railstutorial.org


【解决方案1】:

我遇到了同样的问题,包括服务器崩溃,并设法像这样修复它: (请求确实被发送了两次,可能是因为旧脚本) - 基本上删除除 application.js 之外的所有 js 文件(应该由 rails new for rails 3.1 生成)

    #   deleted:    app/assets/javascripts/controls.js
    #   deleted:    app/assets/javascripts/dragdrop.js
    #   deleted:    app/assets/javascripts/effects.js
    #   deleted:    app/assets/javascripts/prototype.js
    #   deleted:    app/assets/javascripts/rails.js

另外,create.js.erb 需要从原型适配到查询:

$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= "#{@user.followers.count} followers" %>')

destroy.js.erb 也是如此:

$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= "#{@user.followers.count} followers" %>')

之后,一切都像以前一样。

【讨论】:

    【解决方案2】:

    检查您的公用文件夹中的 Assets 文件夹,其中包含 application.js。不知道我是如何结束的,但这导致 ajax 查询被处理两次。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-17
      • 2011-01-15
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多