我有这样设置的资源:
resources :scoreboards do
resources :teams
end
在我的scoreboard#show
视图页面上,我有一个team
模型的集合,它为每个团队生成一个div。每个团队div旁边都有一个Delete
按钮,该按钮路由到teams_controller
中的一个方法以删除该团队。
以下是与之相关的所有代码的列表:
团队旁边的删除按钮
<div>team example</div> <%= link_to "Del", scoreboard_team_path(@scoreboard, team), remote: true, method: :delete, class: "btn btn-primary" %>
按钮的Teams_controller方法
def destroy
@scoreboard = Scoreboard.find(params[:scoreboard_id])
@team = @scoreboard.teams.find(params[:id])
@team.destroy
respond_to do |format|
format.html {redirect_to scoreboard_url(@scoreboard)}
format.js
end
end
destroy.js.erb文件
$( "#team_<%=@team.id%>" ).hide();
现在的问题是,每当我快速连续地点击删除按钮(一个按钮上两次或多次)时,所有Ajax删除按钮都会停止工作。这很可能是因为团队关联的记分牌资源已被删除,因为我在Scoreboards_Controller
:中收到以下错误
NoMethodError in ScoreboardsController#show
undefined method `teams' for nil:NilClass
def show
@scoreboard = Scoreboard.find_by_id(params[:id])
@team = @scoreboard.teams.build # new team form on the page
@comment = @scoreboard.comments.new
@schedule = @scoreboard.schedules.build
end
然后,当我查看记分牌列表时,与@团队关联的@记分牌资源已不存在。为什么会发生这种情况?
编辑:检查开发日志已经澄清了发生了什么。
所以我很快点击删除,它会破坏与该删除按钮相关的团队。由于在destroy.js.erb文件处理(隐藏已删除的div)之前,我成功地单击了两次删除按钮,Teams_Controller#destroy方法将在已删除的团队上再次运行,但没有任何内容可删除,因此Teams_Controller#destroy继续重定向到@scoreboard。现在,由于某种原因,Scoreboards_Controller#destroy执行并删除@scoreboard,之后它再次尝试重定向,并遇到路由错误,因为记分板已不存在。
以下是一些需要澄清的日志:
Started DELETE "/scoreboards/45/teams/478" for 99.000.000.000 at 2015-12-12 03:54:09 +0000
Processing by TeamsController#destroy as JS
Parameters: {"scoreboard_id"=>"45", "id"=>"478"}
[1m[36mScoreboard Load (0.3ms)[0m [1mSELECT "scoreboards".* FROM "scoreboards" WHERE "scoreboards"."id" = ? ORDER BY "scoreboards"."created_at" DESC LIMIT 1[0m [["id", 45]]
[1m[35mTeam Load (0.2ms)[0m SELECT "teams".* FROM "teams" WHERE "teams"."scoreboard_id" = ? AND "teams"."id" = ? LIMIT 1 [["scoreboard_id", 45], ["id", 478]]
[1m[36m (0.3ms)[0m [1mbegin transaction[0m
[1m[35mSQL (0.4ms)[0m DELETE FROM "teams" WHERE "teams"."id" = ? [["id", 478]]
[1m[36m (10.6ms)[0m [1mcommit transaction[0m
Rendered teams/destroy.js.erb (0.2ms)
Completed 200 OK in 48ms (Views: 28.1ms | ActiveRecord: 11.8ms)
Started DELETE "/scoreboards/45/teams/478" for 99.000.000.000 at 2015-12-12 03:54:09 +0000
Processing by TeamsController#destroy as JS
Parameters: {"scoreboard_id"=>"45", "id"=>"478"}
[1m[35mScoreboard Load (0.3ms)[0m SELECT "scoreboards".* FROM "scoreboards" WHERE "scoreboards"."id" = ? ORDER BY "scoreboards"."created_at" DESC LIMIT 1 [["id", 45]]
[1m[36mTeam Load (0.2ms)[0m [1mSELECT "teams".* FROM "teams" WHERE "teams"."scoreboard_id" = ? AND "teams"."id" = ? LIMIT 1[0m [["scoreboard_id", 45], ["id", 478]]
Redirected to https://score-app-kpauls.c9.io/scoreboards/45
Completed 302 Found in 19ms (ActiveRecord: 0.5ms)
Started DELETE "/scoreboards/45" for 99.000.000.000 at 2015-12-12 03:54:09 +0000
Processing by ScoreboardsController#destroy as JS
Parameters: {"id"=>"45"}
[1m[35mScoreboard Load (0.2ms)[0m SELECT "scoreboards".* FROM "scoreboards" WHERE "scoreboards"."id" = ? ORDER BY "scoreboards"."created_at" DESC LIMIT 1 [["id", 45]]
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1[0m [["id", 105]]
[1m[35mCACHE (0.0ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 105]]
[1m[36mCACHE (0.0ms)[0m [1mSELECT "scoreboards".* FROM "scoreboards" WHERE "scoreboards"."id" = ? ORDER BY "scoreboards"."created_at" DESC LIMIT 1[0m [["id", "45"]]
[1m[35m (0.2ms)[0m begin transaction
[1m[36mTeam Load (0.1ms)[0m [1mSELECT "teams".* FROM "teams" WHERE "teams"."scoreboard_id" = ?[0m [["scoreboard_id", 45]]
[1m[35mSQL (0.3ms)[0m DELETE FROM "teams" WHERE "teams"."id" = ? [["id", 479]]
[1m[36mSQL (0.0ms)[0m [1mDELETE FROM "teams" WHERE "teams"."id" = ?[0m [["id", 480]]
[1m[35mSQL (0.1ms)[0m DELETE FROM "teams" WHERE "teams"."id" = ? [["id", 481]]
[1m[36mSQL (0.1ms)[0m [1mDELETE FROM "teams" WHERE "teams"."id" = ?[0m [["id", 482]]
[1m[35mComment Load (0.1ms)[0m SELECT "comments".* FROM "comments" WHERE "comments"."scoreboard_id" = ? [["scoreboard_id", 45]]
[1m[36mSQL (0.1ms)[0m [1mDELETE FROM "scoreboards" WHERE "scoreboards"."id" = ?[0m [["id", 45]]
[1m[35m (14.1ms)[0m commit transaction
Redirected to https://score-app-kpauls.c9.io/scoreboards
Completed 302 Found in 39ms (ActiveRecord: 15.6ms)
在此之后,程序遇到路由错误。我会继续调查,但如果有人能帮助找到调用scorboards_controller#destroy的原因,我将不胜感激。
问题更新:
所以我已经解决了问题。我在application_controller
文件中有这两种方法。
rescue_from ActiveRecord::RecordNotFound do
flash[:warning] = 'Resource not found.'
redirect_back_or root_path
end
def redirect_back_or(path)
redirect_to request.referer || path
end
每当我连续两次快速点击删除按钮时,销毁操作就会被重新路由到记分牌#show页面,并在第二次点击时继续调用该资源的销毁方法。这是因为调用destroy方法的@team在第一次单击时已经被破坏,因此请求重定向。在我刷新页面进入主页后,我确实收到了这些快闪消息,但一开始我认为它们是相关的,但它们是得出结论的关键。
代码基础结构看起来不错,我建议查看关联并确保team belongs_to :scoreboard
上没有dependent: :destroy
--
关于多个"删除"按钮单击的问题,问题看起来像是重定向到父资源。我没有任何理由会出现这种情况,只是Rails可能有一套内置的功能,可以在子路由失败时加载"父"路由。
我解决这个问题的方法是使用条件:
def destroy
@scoreboard = Scoreboard.find(params[:scoreboard_id])
@team = @scoreboard.teams.find params[:id]
if @team.destroy
respond_to do |format|
format.html {redirect_to scoreboard_url(@scoreboard)} #-> could this be the reason for the redirect?????
format.js
end
else
redirect_to scoreboard_teams_path(@scoreboard), notice: "Team Already Deleted"
end
end
我还想看看@team
-if @team && @team.destroy
-如果你想要更多信息,我可以重构。
这样做将为您提供一个可以处理异常的明确流程。我认为问题在于,当您单击删除按钮(记录不再存在)时,Rails无法处理异常。
Rails返回错误的内置方式是重定向到object_path(@object)
,并显示错误(就像您在format.html
中看到的那样)。
因此,我猜Rails正试图将您带回@scoreboard
(scoreboard_path(@scoreboard)
),并且由于您有method: :delete
,它正在为该控制器运行destroy
方法。
要修复它,您需要使用上面的条件让Rails知道在出现问题时该怎么做。
在你的teams_controller销毁操作中,我建议你更改这一行:
@team = @scoreboard.teams.find(params[:id])
对于
@team = Team.find(params[:id])