I have a rake task that looks like this:
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
Yet when I run it, I get this:
$ rake cleanup_snippets_with_empty_diffs
rake aborted!
ActiveRecord::ReadOnlyRecord: Diff is marked as readonly
What could be the cause of this?
Edit 1
Note that my Snippet.rb model looks like this:
class Snippet < ApplicationRecord
has_many :diffs, dependent: :destroy
end
And Diff.rb like this:
class Diff < ApplicationRecord
belongs_to :snippet
end
With includes, Rails will determine whether to use multiple queries (using preload) or a single left outer join query (using eager_load). In your case, because your where clause is on the association, Rails will use eager_load and therefore a LEFT OUTER JOIN. Also note that associations loaded via a join are marked as readonly and is the cause of the error you're receiving. The solution is to switch includes to left_joins and set readonly(false) prior to calling destroy_all.
Snippet.left_joins(:diffs).readonly(false).where(diffs: { body: "<div class=\"diff\"></div>"}).destroy_all
NOTE
I originally thought you could do
Snippet.includes(:diffs).readonly(false).where(diffs: { body: "<div class=\"diff\"></div>"}).destroy_all
but this doesn't work for some reason (and don't have enough time to investigate atm). In any case, since using includes would result in a LEFT OUTER JOIN anyways, you can use the above solution to get the desired outcome.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With