ActiveRecord::ReadOnlyRecord:Diff 在 destroy_all 上标记为只读
ActiveRecord::ReadOnlyRecord: Diff is marked as readonly on destroy_all
我有一个看起来像这样的佣金任务:
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
和includes
,Rails会判断是否使用多查询(using preload
) or a single left outer join query (using eager_load
)。在您的情况下,因为您的 where 子句在关联中,所以 Rails 将使用 eager_load
并因此使用 LEFT OUTER 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
但由于某些原因这不起作用(并且没有足够的时间来调查 atm)。在任何情况下,由于使用 includes
无论如何都会导致 LEFT OUTER JOIN,因此您可以使用上述解决方案来获得所需的结果。
我有一个看起来像这样的佣金任务:
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
和includes
,Rails会判断是否使用多查询(using preload
) or a single left outer join query (using eager_load
)。在您的情况下,因为您的 where 子句在关联中,所以 Rails 将使用 eager_load
并因此使用 LEFT OUTER 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
但由于某些原因这不起作用(并且没有足够的时间来调查 atm)。在任何情况下,由于使用 includes
无论如何都会导致 LEFT OUTER JOIN,因此您可以使用上述解决方案来获得所需的结果。