Очень, все, что вам нужно сделать, это использовать обратный вызов для установки значения self.dimensions:
class ShippingProfile < ActiveRecord::Base
after_initialize :set_default_dimensions
after_validation :set_dimensions
serialize :dimensions, Hash
attr_accessor :width, :height, :depth
attr_accessible :width, :height, :depth, :dimensions
private
def set_default_dimensions
self.dimensions ||= {:width => 0, :height => 0, :depth => 0}
end
def set_dimensions
self.dimensions = {
:width => self.width || self.dimensions[:width],
:height => self.height || self.dimensions[:height],
:depth => self.depth || self.dimensions[:depth],
}
end
end
Вам нужно использовать self.foo || self.dimensions[:foo]
, чтобы гарантировать, что вы уже сохраните любые существующие значенияустановить в хэш.Зачем?Ваши атрибуты измерения (я предполагаю) не сохраняются в базе данных - вы используете attr_accessor, а не настраиваете их в качестве полей в вашей таблице.
В целом, я думаю, что выидти о вашей модели дизайна в неправильном направлении.Сохраняя измерения в виде хэша в базе данных, вы не только теряете возможность делать запросы на основе этих атрибутов, но и добавляете уровень хрупкости, который вам не нужен.
Если вы сохраняя ваши индивидуальные атрибуты измерения в виде отдельных полей, вы вводите избыточность и сложность.Вы бы лучше обслужили, если бы три атрибута были полями в вашей базе данных (если вы еще этого не сделали), а затем генерировали хэш измерений на лету, когда это необходимо:
class ShippingProfile < ActiveRecord::Base
def dimensions
{ :width => self.width, :height => self.height, :depth => self.depth }
end
end
Таким образом, вы сохраняетефункциональность и получить некоторую гибкость.