У меня есть объект модели ActiveRecord Foo
; это представляет стандартную строку базы данных.
Я хочу смочь отобразить измененные версии экземпляров этого объекта. Я хотел бы снова использовать сам класс, поскольку он уже имеет все рычаги и аспекты, мне будет нужно. (Например: у Меня уже есть представление, которое отображает соответствующие атрибуты). В основном я хочу клонировать образцовый экземпляр, изменить некоторые его свойства и подать его назад вызывающей стороне (представление, тест, и т.д.).
Я не хочу эти модификации атрибута, возвращающиеся в базу данных. Однако я действительно хочу включать id
атрибут в клонированной версии, поскольку это делает контакт с помощниками маршрута намного легче. Таким образом я планирую вызов ActiveRecord::Base.clone()
, вручную устанавливая идентификатор клонированного экземпляра и затем внося соответствующие изменения атрибута в новый экземпляр. Это имеет меня, волновался хотя; один save()
на измененном экземпляре и моих исходных данных будет ударен.
Так, я надеюсь блокировать вниз новый экземпляр так, чтобы он не повреждал ничто больше. Я уже - планирование вызова freeze()
(на понимании, что это предотвращает дальнейшую модификацию к объекту, хотя документация не является ужасно четкой). Однако я не вижу очевидного способа предотвратить сохранение ().
Каков был бы лучший подход к достижению этого?
freeze()
, похоже, достигает того, чего я хочу, хотя и некрасивым способом.
x = Factory.create(:my_model)
x.save! # true
x.freeze
x.save!
TypeError: can't modify frozen hash
Я предполагаю, что save() пытается обновить созданные/измененные атрибуты, что не удается, потому что хэш атрибутов заморожен.
Таким образом, замораживание предотвращает сохранение... но я был бы признателен за более надежный метод с более конкретным сообщением об ошибке.
Может быть более идиоматический способ сделать это, но один из способов - установить виртуальный атрибут и проверить его в обратном вызове before_save
. Когда вы клонируете объект, установите виртуальный атрибут - например, is_clone
на true
. Затем определите обратный вызов before_save
для вашего класса модели, который предотвращает сохранение, если этот атрибут установлен.