Предотвращение ActiveRecord save () в экземпляре - PullRequest
8 голосов
/ 30 мая 2010

У меня есть объект модели ActiveRecord Foo;он представляет стандартную строку базы данных.

Я хочу иметь возможность отображать измененные версии экземпляров этого объекта.Я хотел бы повторно использовать сам класс, так как он уже содержит все необходимые мне аспекты и аспекты.(Например: у меня уже есть представление, которое отображает соответствующие атрибуты).По сути, я хочу клонировать экземпляр модели, изменить некоторые его свойства и передать его вызывающей стороне (просмотр, тестирование и т. Д.).

Я делаю , а не хочу получить эти модификации атрибутовобратно в базу данных.Однако я хочу включить атрибут id в клонированную версию, поскольку это значительно облегчает работу с помощниками маршрута.Таким образом, я планирую вызвать ActiveRecord::Base.clone(), вручную установить идентификатор клонированного экземпляра, а затем внести соответствующие изменения атрибута в новый экземпляр.Это меня беспокоит, хотя;один save() на измененном экземпляре, и мои исходные данные будут засорены.

Итак, я пытаюсь заблокировать новый экземпляр, чтобы он не повредил ничему другому.Я уже планирую вызвать freeze() (при том понимании, что это предотвращает дальнейшую модификацию объекта, хотя документация не очень понятна ).Однако я не вижу очевидного способа предотвратить сохранение ().

Каков наилучший подход для достижения этой цели?

Ответы [ 3 ]

20 голосов
/ 19 марта 2013

Вы можете использовать ActiveRecord :: Base # только для чтения!

model = MyModel.find 1
model.readonly!
model.save!

вызовет ActiveRecord :: ReadOnlyRecord

4 голосов
/ 30 мая 2010

freeze(), кажется, добивается того, чего я хочу, хотя и безобразно.

x = Factory.create(:my_model)
x.save!    # true
x.freeze
x.save!
TypeError: can't modify frozen hash

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

Итак, замораживание предотвратит сохранение ... но я бы оценил более надежный метод с более конкретным сообщением об ошибке.

4 голосов
/ 30 мая 2010

Возможно, существует более идиоматический способ сделать это, но один из способов - установить виртуальный атрибут и проверить его в обратном вызове before_save. Когда вы клонируете объект, установите виртуальный атрибут - возможно, что-то вроде is_clone в true. Затем определите обратный вызов before_save для вашего класса модели, который запрещает сохранение, если этот атрибут установлен.

...