我有一个模型Prediction
,其实例通过属性Participant
Match
引用其他模型:participant_id
和:match_id
。
这个想法是@participant每个@match只能有一个@prediction(每个@participant允许每个@match最多一个预测)。
所以我在预测模型中包含了以下验证
validates :match_id, uniqueness: { scope: [:participant_id] }
当相同的@match和@participant已经是@prediciton时,验证可以禁止创建@prediction对象。问题在于,即使我没有改变原始对象的那些指定ID,它也会阻止更新对象。另外,它让我只更新一个预测实例,所有其他实例都是错误的。
令人费解的是,它工作正常,但由于某种原因,我一直无法跟踪,它停止工作,我已经没有关于如何调试的想法。你能提供任何想法吗?低于我检查/尝试的内容:
请求失败的相关参数:
"prediction"=><ActionController::Parameters {"participant_id"=>"1", "match_id"=>"2", "local_score"=>"2", "visitant_score"=>"0"}
我得到的错误:
@details={:match_id=>[{:error=>:taken, :value=>2}]},
@messages={:match_id=>["has already been taken"]}>
数据库中有match_id: 2
的大量预测。但是,尽管数据库中没有match_id: 2
和participant_id: 1
的其他@prediction,但这种情况正在发生,当然,除了在更新时抛出此错误的实例。
有趣的是,如果我在控制台中尝试相同的操作(如下所示),它会成功更新。
@prediction = Prediction.find_by(participant_id: 1, match_id: 2)
@prediction.update_attributes(local_score: 8, visitant_score: 8)
建议问题出在控制器操作中:
应用程序/控制器/ predicitons_controller.rb
def update
respond_to do |format|
if @prediction.update(prediction_params)
format.json { render :show, status: :ok, location: @prediction }
format.js
else
@errorMessages = []
@prediction.errors.full_messages.each do |message|
@errorMessages << message
end
format.js {render template: 'predictions/update_error'}
end
end
end
我认为那里没有问题。此外,似乎发送到成功更新的控制器的唯一请求是:
"prediction"=><ActionController::Parameters {"participant_id"=>"1", "match_id"=>"1", "local_score"=>"1", "visitant_score"=>"1"}
如果我做其他人,例如,它没有:
"prediction"=><ActionController::Parameters {"participant_id"=>"2", "match_id"=>"1", "local_score"=>"0", "visitant_score"=>"0"}
"prediction"=><ActionController::Parameters {"participant_id"=>"2", "match_id"=>"2", "local_score"=>"9", "visitant_score"=>"9"}
"prediction"=><ActionController::Parameters {"participant_id"=>"4", "match_id"=>"1", "local_score"=>"1", "visitant_score"=>"1"
所有这些失败的请求都会抛出&#34; match_id已经采取&#34;错误并在控制台中更新。
控制器请求正在使用以下方法触摸正确的操作:put。我试图改变pool_id的验证切换match_id的语法(这当然不应该有所作为),但没有成功。
任何,帮助将不胜感激。
应用程序/模型/ prediction.rb
class MatchPrediction < ApplicationRecord
belongs_to :participant
belongs_to :match
validates :match_id, uniqueness: { scope: [:pool_participant_id] }
def correct_score?
if match.official_outcome
local_score == match.local_score && visitant_score == match.visitant_score ? true : false
end
end
def correct_outcome?
if match.official_outcome
predicted_outcome == match.official_outcome ? true : false
end
end
end
和服务器输出预回滚:
Started PUT "/pools/1/predictions/19" for 127.0.0.1 at 2018-03-29 18:17:11 +1100
Processing by PredictionsController#update as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"SagJX+a7m0eCAdH7AdA0eYz6BVL1cesXYXOUkoe2FRynta6wyiWdskrC1007V1vyrIApPtdEQnVHWlzhSeJs5Q==", "prediction"=>{"participant_id"=>"4", "match_id"=>"2", "local_score"=>"7", "visitant_score"=>"0"}, "pool_id"=>"1", "id"=>"19"}
User Load (1.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 4], ["LIMIT", 1]]
↳ /Users/andres/.rvm/gems/ruby-2.5.0@global/gems/rack-2.0.4/lib/rack/tempfile_reaper.rb:15
Prediction Load (0.4ms) SELECT "predictions".* FROM "predictions" WHERE "predictions"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/predictions_controller.rb:86
(0.2ms) BEGIN
↳ app/controllers/predictions_controller.rb:55
Participant Load (0.2ms) SELECT "participants".* FROM "participants" WHERE "participants"."id" = $1 LIMIT $2 [["id", 4], ["LIMIT", 1]]
↳ app/controllers/predictions_controller.rb:55
Match Load (0.3ms) SELECT "matches".* FROM "matches" WHERE "matches"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
↳ app/controllers/predictions_controller.rb:55
Prediction Exists (1.8ms) SELECT 1 AS one FROM "predictions" WHERE "predictions"."match_id" = $1 AND "predictions"."id" != $2 AND "predictions"."participant_id" = $3 LIMIT $4 [["match_id", 2], ["id", 1], ["participant_id", 4], ["LIMIT", 1]]
↳ app/controllers/predictions_controller.rb:55
Pool Load (0.5ms) SELECT "pools".* FROM "pools" WHERE "pools"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/models/prediction.rb:35
Round Load (0.6ms) SELECT "rounds".* FROM "rounds" INNER JOIN "groups" ON "rounds"."id" = "groups"."round_id" WHERE "groups"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/models/prediction.rb:21
(0.2ms) ROLLBACK
↳ app/controllers/predictions_controller.rb:55
答案 0 :(得分:0)
真的令人尴尬的错误。我错过了检查Predictions Controller如何设置@prediction。由于@GorillaApe的建议,我抓住了params找不到对象:
def set_match_prediction
@prediction = Prediction.find(params[:pool_id])
end
而不是:
def set_match_prediction
@prediction = Prediction.find(params[:id])
end
这反过来总是设置相同的对象,从而在除了一个实例之外的所有实例中引发验证错误,偶然地,它的:id与:pool_id一致。