Ruby on rails 延迟作业-销毁对象后无法为非持久记录创建作业
轨道4和延迟_作业4.1.2。我试图在销毁审查后延迟重新计算总体评级,但显然是因为销毁审查对象后,审查对象没有ID。因此,每次尝试销毁对象后,它都会尝试创建延迟作业,但会抛出以下错误:Ruby on rails 延迟作业-销毁对象后无法为非持久记录创建作业,ruby-on-rails,delayed-job,Ruby On Rails,Delayed Job,轨道4和延迟_作业4.1.2。我试图在销毁审查后延迟重新计算总体评级,但显然是因为销毁审查对象后,审查对象没有ID。因此,每次尝试销毁对象后,它都会尝试创建延迟作业,但会抛出以下错误: ArgumentError (job cannot be created for non-persisted record: #<Review id: 44, review: "Bad", rating: 1, reviewable_id: 2, reviewable_type: "Spot", use
ArgumentError (job cannot be created for non-persisted record:
#<Review id: 44, review: "Bad", rating: 1, reviewable_id: 2,
reviewable_type: "Spot", user_id: 1, created_at: "2016-05-30 17:13:29",
updated_at: "2016-05-30 17:13:29">):
app/controllers/reviews_controller.rb:40:in `destroy'
ArgumentError(无法为非持久记录创建作业:
#):
app/controllers/reviews\u controller.rb:40:in'destroy'
我有以下代码:
# reviews_controller.rb
class ReviewsController < ApplicationController
def destroy
review.destroy
flash[:success] = t("reviews.destroy.success")
end
end
# review.rb
class Review < ActiveRecord::Base
after_destroy :calculate_overall_rating
def calculate_overall_rating
if number_of_reviews > 0
reviewable.update_attribute(:overall_rating, overall_rating)
else
reviewable.update_attribute(:overall_rating, 0)
end
end
handle_asynchronously :calculate_overall_rating
end
#查看_controller.rb
类ReviewController0
可查看。更新_属性(:总体_评级,总体_评级)
其他的
可查看。更新_属性(:总体_评级,0)
结束
结束
异步处理\u:计算\u总体\u评级
结束
值得注意的是,calculate\u totall\u rating
不需要Review
对象
如果我删除handle\u异步:计算\u总体\u评级
它将工作,然后重新计算。但我正在尝试延迟此作业。当您尝试延迟已删除(或尚未创建)记录上的方法时,此错误确实是由延迟的作业造成的。此错误的直接原因是,在异步调用handle\u
方法时,延迟了作为目标对象的作业(即刚刚删除的审阅对象)。我不知道它为什么会这样,我刚从gem的一位作者那里找到一个例子,说它与ActiveJob的工作方式相同
无论如何,在我看来,您可能在错误的位置定义了重新计算方法。如果我理解正确,在销毁评论后,将根据给定的可评论的
(例如一个点)的所有评论重新计算平均评级。我觉得奇怪的是,这样的代码被定义为单个审阅实例的方法。一篇评论(更重要的是一篇被删除的评论)不应该了解同一地点的其他评论,也不应该处理它们
我想方法应该被定义为类方法,而不是可查看的作为参数。当然,这意味着你还必须使用其他的计算方法,如综合评分法和复习次数法。但我认为这也是一件好事,因为这些方法的领域不在单一的审查范围之内。如下所示:
# review.rb
class Review < ActiveRecord::Base
after_destroy :recalculate_overall_rating
def recalculate_overall_rating
self.class.calculate_overall_rating(reviewable)
end
def self.calculate_overall_rating(reviewable)
if number_of_reviews(reviewable) > 0
reviewable.update_attribute(:overall_rating, overall_rating(reviewable))
else
reviewable.update_attribute(:overall_rating, 0)
end
end
handle_asynchronously :calculate_overall_rating
end
# reviewable.rb
module Reviewable
def calculate_overall_rating
if number_of_reviews > 0
update_attribute(:overall_rating, overall_rating)
else
update_attribute(:overall_rating, 0)
end
end
handle_asynchronously :calculate_overall_rating
# overall_rating and number_of_reviews are also defined in this module
end
# review.rb
class Review < ActiveRecord::Base
after_destroy :recalculate_overall_rating
def recalculate_overall_rating
reviewable.calculate_overall_rating
end
end
# post.rb
class Post < ActiveRecord::Base
include Reviewable
end