mar*_*ion 3 rake activerecord ruby-on-rails 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
Run Code Online (Sandbox Code Playgroud)
然而,当我运行它时,我得到了这个:
$ rake cleanup_snippets_with_empty_diffs
rake aborted!
ActiveRecord::ReadOnlyRecord: Diff is marked as readonly
Run Code Online (Sandbox Code Playgroud)
可能是什么原因造成的?
编辑1
请注意,我的Snippet.rb模型如下所示:
class Snippet < ApplicationRecord
has_many :diffs, dependent: :destroy
end
Run Code Online (Sandbox Code Playgroud)
而Diff.rb像这样:
class Diff < ApplicationRecord
belongs_to :snippet
end
Run Code Online (Sandbox Code Playgroud)
使用includes,Rails将确定是使用多个查询(使用preload)还是使用单个左外连接查询(使用eager_load).在您的情况下,因为您的where子句在关联上,Rails将使用eager_load并因此使用LEFT OUTER JOIN.另请注意,通过连接加载的关联被标记为,readonly并且是您收到错误的原因.解决方案是在呼叫之前切换includes到left_joins并设置.readonly(false)destroy_all
Snippet.left_joins(:diffs).readonly(false).where(diffs: { body: "<div class=\"diff\"></div>"}).destroy_all
Run Code Online (Sandbox Code Playgroud)
注意
我原以为你能做到
Snippet.includes(:diffs).readonly(false).where(diffs: { body: "<div class=\"diff\"></div>"}).destroy_all
Run Code Online (Sandbox Code Playgroud)
但由于某些原因(并且没有足够的时间来调查atm)这不起作用.在任何情况下,由于使用includes将导致LEFT OUTER JOIN无论如何,您可以使用上述解决方案来获得所需的结果.
| 归档时间: |
|
| 查看次数: |
1138 次 |
| 最近记录: |