Ruby on rails 延迟作业-销毁对象后无法为非持久记录创建作业

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

轨道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", 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