2011-02-10 2 views
3

У меня есть атрибут dimensions, который я хочу установить на основе моих width, height и depth атрибутов.установка атрибута activerecord на основе виртуальных атрибутов

, например, я хочу сделать ShippingProfile.find(1).width = 4, и это сохранить размеры как {: ширина => 4: высота => 0: глубина => 0} `

это возможно?

class ShippingProfile < ActiveRecord::Base 
    after_initialize :set_default_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 
end 
+0

Как вы думаете, лучше ли будет ShippingProfile.find (1) .dimensions.width = 4? – macarthy

ответ

7

Очень так, все, что вам нужно сделать, это использовать функцию обратного вызова, чтобы установить значение 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 

Таким образом, вы сохранить функциональность и получить некоторую гибкость.

+0

, поэтому я пошел с сохранением индивидуальных размеров. это было гораздо менее проблематично и, как вы сказали, гораздо более гибким в вопросе. иногда я доволен сохранением красивой БД, но реальность этого, я никогда не должен действительно смотреть на нее :) – brewster

0

Вы можете использовать класс в сериализации, так

class ShippingProfile < ActiveRecord::Base 
    serialize :dimensions, Dimensions 
end 

class Dimensions 
    attr_accessor :width, :height,:depth 

    def initialize 
    @width = 0 
    @height = 0 
    @depth = 0 
    end 

    def volume 
    width * height * depth 
    end 
end 

Теперь вы можете сделать ShippingProfile.dimensions.width = 1 и позже ShippingProfile.dimension.volume и т.д ..

модель будет более богатое представление, чем хеш

Смежные вопросы