ruby-on-rails - ActiveRecord::ReadOnlyRecord:Diff 在 destroy_all 上被标记为只读

标签 ruby-on-rails activerecord rake ruby-on-rails-5

我有一个看起来像这样的 rake 任务:

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 将确定是使用多个查询(使用 preload )还是单个左外连接查询(使用 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,因此您可以使用上述解决方案来获得所需的结果。

关于ruby-on-rails - ActiveRecord::ReadOnlyRecord:Diff 在 destroy_all 上被标记为只读,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38649151/

相关文章:

ruby-on-rails - 动态根路径路由

ruby-on-rails - 如何通过 ActiveRecord 将 Rails 3.1.x 数据库合并到标准的 ruby​​ 应用程序中?

ruby-on-rails - Rails 验证以确保用户不会将自己加为好友

php - CodeIgniter 事件记录查询仅返回表中的第一个条目

ruby - Rake cp 权限在 Windows 上被拒绝

ruby - Rake 的目的是什么?

ruby-on-rails - 如何让 memprof(在 rails 内)跟踪所有之前的过滤器,然后在转储输出之前进行操作?

javascript - 在哪里放置 javascript 文件以将其与 Rails 中的特定 View 文件夹相关联?

ruby-on-rails - 如何从类方法返回未更改的 AR 关系

ruby-on-rails - 如何将数据库结构从 db 导出到迁移文件中?