首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >状态模型设计模式

状态模型设计模式
EN

Stack Overflow用户
提问于 2009-08-25 09:33:41
回答 3查看 1.3K关注 0票数 3

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

有一个具有状态的模型。模型可以有多个实例,但只有几个预定义的状态(如:已创建、已续订、已检索等)。对于每个单独的状态,模型都有一些计算逻辑。例如,对于每种状态,model.cost()的计算方式不同。

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

代码语言:javascript
复制
model.status = StatusModel.retrieved

代码语言:javascript
复制
case status
  when renewed
    # ...
  when retrieved
    # ..
end

考虑到我需要将状态保存在数据库的模型行中,我现在得到的是:

代码语言:javascript
复制
ModelStatus < ActiveRecord::Base
  has_many :models
Model < ActiveRecord::Base
  belongs_to :model_status

然而,这给我的代码带来了很多问题。有没有人对此有好的想法或模式?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-08-25 10:07:23

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

代码语言:javascript
复制
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语句:

代码语言:javascript
复制
case @model.status
when Model::STAT_CREATED
...
when Model::STAT_RENEWED
...
票数 1
EN

Stack Overflow用户

发布于 2009-08-25 16:53:55

您所描述的似乎是状态机的完美案例。

有许多Ruby状态机实现。你可以在ruby-toolbox上看到一个相当有代表性的列表

在定义状态机时,您可以定义多个状态转换。每个转换,将模型从一种状态转换到另一种状态,并在此过程中执行一些代码。它的DSL通常是相当不错的。

您的示例将如下所示

代码语言:javascript
复制
model.retrieve!

这会将模式状态从原来的状态更改为retrieved,或者如果当前状态未转换为retrieved,则会抛出异常。

票数 2
EN

Stack Overflow用户

发布于 2009-08-25 16:44:43

也可以试着看看acts_as_state_machine插件。我最近在一个项目中使用了它,它工作得很好。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1327138

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档