ActiveRecord::ReadOnlyRecord: Diff在destroy_all上被标记为只读

3

我有一个如下所示的「耙子任务」:

desc "Cleanup Snippets with Empty Diffs"

task cleanup_snippets_with_empty_diffs: :environment do
  Snippet.includes(:diffs).where(diffs: { body: "<div class=\"diff\"></div>"}).destroy_all
end

然而当我运行它时,我得到了这个:

$ rake cleanup_snippets_with_empty_diffs
rake aborted!
ActiveRecord::ReadOnlyRecord: Diff is marked as readonly

这可能是什么原因引起的?

编辑1

请注意,我的Snippet.rb模型如下:

class Snippet < ApplicationRecord
  has_many :diffs, dependent: :destroy
end

还有像这样的Diff.rb

class Diff < ApplicationRecord
  belongs_to :snippet
end
1个回答

6

通过使用includes,Rails将确定是使用多个查询(使用preload)还是单个左外连接查询(使用eager_load)。在您的情况下,因为您的where子句在关联上,所以Rails将使用eager_load,因此是一个LEFT OUTER JOIN。还要注意,通过join加载的关联被标记为readonly,这是您收到的错误的原因。解决方案是将includes切换为left_joins并在调用destroy_all之前设置readonly(false)

Snippet.left_joins(:diffs).readonly(false).where(diffs: { body: "<div class=\"diff\"></div>"}).destroy_all

注意

我最初认为您可以执行

Snippet.includes(:diffs).readonly(false).where(diffs: { body: "<div class=\"diff\"></div>"}).destroy_all

但出于某些原因,这并不起作用(目前没有足够的时间进行调查)。无论如何,由于使用 includes 会导致 LEFT OUTER JOIN,因此您可以使用上述解决方案来获得所需的结果。


记住我使用的是 includes,而不是 joins - marcamillion
抱歉,我在这里的“joins”指的是连接而不一定是joins方法。请查看我的更新答案以获取进一步解释和可能的解决方案。谢谢。 - Bart Jedrocha
谢谢!救命稻草! - Tiago Farias

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接