2016-07-29 7 views
2

У меня есть задача грабли, что выглядит следующим образом:ActiveRecord :: ReadOnlyRecord: Diff отмечен как неизменяемые на 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 

Что может быть причиной этого?

Edit 1

Обратите внимание, что моя Snippet.rb модель выглядит следующим образом:

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

И Diff.rb вроде этого:

class Diff < ApplicationRecord 
    belongs_to :snippet 
end 

ответ

5

С includes, Rails будет определять, следует ли использовать несколько запросов (с использованием preload) или одного левого t внешний запрос соединения (используя 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 

ПРИМЕЧАНИЕ

Первоначально я думал, что вы могли бы сделать

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

, но это не работает по какой-то причине (и не имеют достаточно времени, чтобы исследовать атм). В любом случае, поскольку использование includes приведет к ЛЕВЫМ ВЗАИМОДЕЙШИМ СОЕДИНЕНИЕМ в любом случае, вы можете использовать вышеуказанное решение для получения желаемого результата.

+0

Мне нравится эта идея. Но это не работает :( – marcamillion

+0

Помните, что я использую 'includes', а не' joins'. – marcamillion

+0

Извините «joins» Я имел в виду * соединение * и не обязательно метод 'joins'. См. Мой обновленный ответ для дальнейшего объяснение и возможное решение Спасибо. –

 Смежные вопросы

  • Нет связанных вопросов^_^