Предотвращение ActiveRecord save() для экземпляра

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

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

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

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

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


person Craig Walker    schedule 30.05.2010    source источник
comment
Если вам нужно значительно повозиться со стандартным объектом ActiveRecord, вероятно, есть лучший способ решить эту проблему.   -  person Matchu    schedule 30.05.2010
comment
Я, конечно, открыт для альтернатив   -  person Craig Walker    schedule 30.05.2010


Ответы (3)



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

person Jimmy    schedule 30.05.2010

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

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

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

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

person Craig Walker    schedule 30.05.2010
comment
Просто чтобы уточнить, заморозка вообще предотвратит изменение экземпляра, пока только для чтения! позволит вносить изменения, но предотвратит сохранение измененного экземпляра в базе данных. - person David Aldridge; 09.09.2015
comment
Спасибо за обновление @DavidAldridge; Я изменил свой принятый ответ. - person Craig Walker; 10.09.2015