Каков наилучший способ переопределить поведение уничтожения Rails ActiveRecord? - PullRequest
10 голосов
/ 21 ноября 2010

У меня есть приложение, в котором я хотел бы переопределить поведение уничтожения для многих из моих моделей. Вариант использования заключается в том, что у пользователей может быть законная необходимость удалить конкретную запись, но на самом деле удаление строки из базы данных приведет к разрушению ссылочной целостности, которая влияет на другие связанные модели. Например, пользователь системы может захотеть удалить клиента, с которым он больше не ведет бизнес, но необходимо вести транзакции с этим клиентом.

Кажется, у меня есть как минимум два варианта:

  1. Дублирование данных в необходимые модели эффективно денормализует мою модель данных, чтобы удаленные записи не влияли на связанные данные.
  2. Переопределите поведение «уничтожить» ActiveRecord, чтобы сделать что-то вроде установки флага, указывающего, что пользователь «удалил» запись, и используйте этот флаг, чтобы скрыть запись.

Мне не хватает лучшего способа?

Вариант 1 кажется мне ужасной идеей, хотя я бы хотел услышать аргументы об обратном.

Вариант 2 выглядит как Rails-ish, но мне интересно, как лучше справиться с этим. Должен ли я создать свой собственный родительский класс, который наследуется от ActiveRecord :: Base, переопределить там метод destroy, а затем наследовать от этого класса в моделях, где я хочу это поведение? Должен ли я также переопределить поведение поиска, чтобы записи, помеченные как удаленные, не возвращались по умолчанию?

Если бы я сделал это, как бы я справился с динамическими искателями? А как насчет именованных областей?

Ответы [ 2 ]

8 голосов
/ 21 ноября 2010

Если вы на самом деле не заинтересованы в том, чтобы снова увидеть эти записи, но заботитесь только о том, чтобы потомки все еще существовали, когда родитель уничтожен, задание простое: добавьте :dependent => :nullify к вызову has_many, чтобы установить ссылки на автоматически уничтожить родительский элемент NULL и научить представление справляться с отсутствующей ссылкой. Однако это работает только в том случае, если вы согласны с тем, что больше никогда не увидите строку, т. Е. При просмотре этих транзакций отображается «[NO LONGER EXISTS]» под названием компании.

Если вы действительно хотите снова увидеть эти данные, это звучит так, как будто то, что вы хотите, не имеет никакого отношения к фактическому уничтожению записей, что означает, что вам никогда не понадобится обращаться к их снова. Кажется, прятаться - путь.

Вместо переопределения уничтожения, поскольку вы на самом деле не уничтожаете запись, кажется, что значительно проще поместить ваше поведение в метод hide, который вызывает флаг, как вы предложили.

Оттуда, когда вы хотите перечислить эти записи и включить только видимые записи, одно простое решение состоит в том, чтобы включить область действия visible, которая не включает скрытые записи, и не включать ее, когда вы хотите найти эту конкретную запись, опять скрытая запись. Другой путь - использовать default_scope, чтобы скрыть скрытые записи, и использовать Model.with_exclusive_scope { find(id) }, чтобы найти скрытую запись, но я бы рекомендовал против этого, поскольку это может быть серьезным уловкой для начинающего разработчика и в корне меняет то, что Model.all возврат к совсем не отражает то, что предлагает вызов метода.

Я понимаю желание заставить контроллеры выглядеть так, как будто они делают то, что делает Rails, но когда вы не действительно делаете то, что делает Rails, лучше об этом прямо говорить, особенно когда на самом деле это не такая уж большая боль.

6 голосов
/ 21 ноября 2010

Я написал плагин для этой конкретной цели , называемый паранойей.Я «позаимствовал» идею у acts_as_paranoid и переписал AAP, используя гораздо меньше кода.

Когда вы вызываете destroy для записи, она фактически не удаляется.Вместо этого он установит столбец deleted_at в вашей базе данных на текущее время.

README на странице GitHub должен быть полезен для установки и использования.Если это не так, дайте мне знать, и я посмотрю, смогу ли я это исправить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...