Правильный способ удаления has_many: через записи объединений?
class Post < ActiveRecord::Base
has_many :posts_tags
has_many :tags, through: :posts_tags
end
class PostsTag < ActiveRecord::Base
belongs_to :post
belongs_to :tag
end
class Tag < ActiveRecord::Base
has_many :posts_tags
has_many :posts, through: :posts_tags
end
Когда сообщение будет уничтожено, я хочу, чтобы все его ассоциации также были удалены. Я НЕ хочу, чтобы проверки на модели PostsTag выполнялись. Я просто хочу удалить.
Я обнаружил, что добавление зависимости от отношения к тегам сообщений из модели Post работает так, как я хочу: has_many :posts_tags, dependent: :delete_all
.
Однако документация по этому вопросу, похоже, предполагает, что я должен сделать это вместо: has_many :tags, through: :posts_tags, dependent: :delete_all
. Когда я это делаю, объект Tag уничтожается и объект объединения остается.
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many
Для has_many, destroy всегда будет вызывать метод уничтожения удаляемой записи (ов), чтобы выполнялись обратные вызовы. Однако удаление будет либо выполнять удаление в соответствии со стратегией, заданной опцией: зависимый, либо если нет: зависимая опция указана, то она будет следовать стратегии по умолчанию. Стратегия по умолчанию: nullify (установить внешние ключи в nil), , за исключением has_many: through, где стратегия по умолчанию - delete_all (удалить записи объединения, не выполняя их обратные вызовы).
- Как я могу использовать стандартную стратегию по умолчанию? Если я уйду: полностью зависеть, записи вообще не удаляются. И я не могу просто указать: зависит от отношения has_many. Rails возвращается и говорит: "Игнорируемый вариант ожидает либо: destroy,: delete_all,: nullify или: restrict ({})".
- Если я не укажу: зависит от любого из отношений, он НЕ сбрасывает значение post_id в объекте PostsTag, поскольку он, кажется, предлагает
Возможно, я читаю это неправильно, и подход, который я нашел, работает правильно?
Ответы
Ответ 1
Ваше первоначальное представление:
has_many :posts_tags, dependent: :delete_all
- это именно то, что вы хотите. Вы не хотите объявлять это в ассоциации has-many-while :tags
, поскольку это уничтожит все связанные теги. То, что вы хотите удалить, это сама ассоциация - это то, что представляет собой модель объединения PostTag.
Итак, почему документы говорят, что они делают? Вы не понимаете сценарий описания документации:
Post.find(1).destroy
Post.find(1).tags.delete
Первый вызов (ваш сценарий) просто уничтожит сообщение. То есть, если вы не укажете стратегию :dependent
, как я вам предлагаю. Второй вызов - это то, что описывает документация. Вызов .tags.delete
не будет (по умолчанию) фактически уничтожать теги (поскольку к ним присоединяется has-many-through), но связанная модель соединения, которая объединяет эти теги.