我的资源设置如下:
resources :scoreboards do
resources :teams
end
在我的scoreboard#show
视图页面上,我有一个team
模型的集合,为每个团队生成一个div。除了每个team-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
然后当我查看记分板列表时,@ team所关联的@Scoreboard资源不再存在。为什么会这样?
编辑:检查开发日志已经阐明了正在发生的事情。
所以我非常快地点击删除它会破坏与该删除按钮相关联的团队。由于我设法在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)
此后程序遇到路由错误。我将继续研究它,但如果有人能帮助找到为什么要调用scoreboards_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,因此请求重定向。我刷新页面进入主页后确实收到了flash消息,但最初认为它们是相关的,但它们是结论的关键。
答案 0 :(得分:1)
代码基础架构看起来不错,我建议查看关联并确保dependent: :destroy
上没有team belongs_to :scoreboard
-
关于多个“删除”按钮单击的问题,问题看起来就像您正在重定向到父资源。我没有任何理由为什么会这样,除非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知道在遇到问题时该怎么做。
答案 1 :(得分:1)
在destroy action中的teams_controller中,我建议你更改这一行:
@team = @scoreboard.teams.find(params[:id])
的
@team = Team.find(params[:id])