2009-08-25 95 views
3

我遇到了实现模型状态的问题。这可能是由于错误的设计。状态模型设计模式

有一个模型有一个状态。可以有多个模型实例,只有几个预定义的状态(如:创建,更新,检索等)。对于每个人的状态,都有一些模型的计算逻辑。例如。 model.cost()针对每个状态进行不同的计算。

我想在保存模型时让ActiveRecord自动设置正确model_status_id。我认为,在理想情况下,我会做这样的事情:

model.status = StatusModel.retrieved 

case status 
    when renewed 
    # ... 
    when retrieved 
    # .. 
end 

想我需要保存在这个数据库中的模型行中的状态是什么,我现在得到:

ModelStatus < ActiveRecord::Base 
    has_many :models 
Model < ActiveRecord::Base 
    belongs_to :model_status 

但是,这给了我很多代码中的问题。任何人有一些好的想法或模式呢?

+0

如果这些状态是预定义的,那么将它们作为常量存储在代码中而不是在DB中是否足够? – Olly 2009-08-25 10:05:28

回答

1

为什么不保留实际模型的状态部分?如果它们是预定义的,这不是太多的工作:

class Model < ActiveRecord::Base 

    STAT_CREATED = 1 
    STAT_RENEWED = 2 
    STAT_RETRIEVED = 4 

    validates_inclusion_of :status, 
         :in => [1, 2, 4] 


    def created? 
    status & STAT_CREATED 
    end 

    def renewed? 
    status & STAT_RENEWED 
    end 

    def retrieved? 
    status & STAT_RETRIEVED 
    end 

end 

通过这种方式,你可以直接测试模型实例(例如,如果@ model.created?)或写你的case语句那样:

case @model.status 
when Model::STAT_CREATED 
... 
when Model::STAT_RENEWED 
... 
+0

非常感谢!看起来很合乎逻辑。我有时只是觉得方式太复杂。 – benvds 2009-08-25 10:16:47

2

你描述的似乎是状态机的完美情况。

有许多Ruby状态机实现。您可以在ruby-toolbox

看到一个颇具代表性的名单当定义一个状态机,你可以定义多个美国过渡。每个转换将您的模型从一个状态转移到另一个状态,执行一些代码。 DSL通常是相当不错的。

你的榜样看起来像

model.retrieve! 

这将改变模式状态从不管它是检索或抛出一个异常,如果目前的状况不过渡到检索