我遇到了为模型实现状态的问题。这可能是由于错误的设计造成的。
有一个具有状态的模型。可以有多个模型实例,只有少数预定义状态(如:创建,更新,检索等)。对于每个单独的状态,模型都有一些计算逻辑。例如。 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 :(得分:2)
您所描述的内容似乎是状态机的完美案例。
有许多Ruby状态机实现。您可以在ruby-toolbox
看到具有相当代表性的列表定义状态机时,您可以定义多个状态和转换。每个转换将您的模型从一个状态转移到另一个状态,同时执行一些代码。 DSL 通常非常好。
您的示例看起来像
model.retrieve!
如果当前状态未转换为已检索,这会将模式状态从“检索更改为”或抛出异常。
答案 1 :(得分: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
...
答案 2 :(得分:1)
另请尝试查看acts_as_state_machine
插件。我最近在一个项目中使用它并且运行良好。