Очень так, все, что вам нужно сделать, это использовать функцию обратного вызова, чтобы установить значение 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
Таким образом, вы сохранить функциональность и получить некоторую гибкость.
Как вы думаете, лучше ли будет ShippingProfile.find (1) .dimensions.width = 4? – macarthy