Проверка, сохраняется ли модель DataMapper (или другая ORM) - PullRequest
2 голосов
/ 17 июля 2010

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

Примером может быть:

class Shipment
  include DataMapper:Resource

  belongs_to :address, :required => false

  def shippable?
    valid? && persisted? && !address.nil? && address.valid? && address.persisted?
  end
end

В этомВ этом случае у меня должен быть метод, сообщающий мне, возможна ли отправка товара.Это верно, когда он действителен, сохранен в БД и имеет сохраненный адрес.

Другой пример - использование его в обратных вызовах для определения необходимости определенных вещей (пересчет цены).

Является ли этот код безопасным и правильным?

1 Ответ

2 голосов
/ 17 июля 2010

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

Но так ли это на самом деле?Как вы попадаете на эту акцию?Я бы подумал о двух рабочих процессах:

  1. Существует заказ, который вы хотите отправить.Вы нажимаете на "отправить это дерьмо!"и доберитесь до ShipmentsController#new, введите ваши данные.При нажатии «сохранить» ваш груз будет подтвержден и сохранен, если он действителен.После успешного сохранения (я полагаю, shipment.save возвращает false, если нет), вы можете сразу перейти к действию доставки (что бы там ни было).Если shipment.save сообщит вам, что оно не сохранилось, представление #new будет обработано в другой раз, а доставка еще не выполнена.Так что это идея wizard -подобного рабочего процесса с « gate », который позволяет выполнять доставку только в случае успешного сохранения.

  2. Создание отправлений и отгрузка отправлений полностью отделены .Допустим, один парень планирует поставки, а другой выполняет их.Первый создает новую, действительную, постоянную отправку.Последний начинается со списка готовых поставок.ShipmentsController#index загружает грузы непосредственно из базы данных, используя Shipment.all.Не нужно проверять persisted?, затем в действии ShipmentsController#perform.

ОК.Давайте усложним: предположим, что мы находимся в сценарии 2, и первый парень может удалить груз, пока второй выполняет его.Без учета этого случая наивное приложение снова сохранит груз после того, как #perform завершит установку, установив дату отправки.Это будет означать, что произошла аномалия базы данных потерянных "delete" .Однако не будете ли вы использовать конечный автомат 1036 * в любом случае?Допустим, есть запланированные переходы -> удалено и запланировано -> отправлено .Если парень № 1 устанавливает статус удалено , пока парень № 2 выполняет отправку, конечный автомат выдаст исключение: «Нет перехода от удаленного к отправленному, моя дорогая!» при попытке обновить статус.

Поэтому я не могу придумать сценарий, в котором проверка персистентности явно не параноидальна.Но если у вас есть тот, где это может действительно произойти из-за «небезопасного» рабочего процесса, вы должны проверить на стойкость.

...