0

严格的 REST 支持者可能会说,如果您发现自己在不是 CRUD 的控制器上定义了一个操作,那么您应该强烈考虑创建一个新资源并将您的操作定义为对新资源的 CRUD 操作。

一个例子可能是改变模型状态的操作——比如购买。在此示例中,您可以创建 CompletePurchasesController 并使用 create 操作将购买状态更新为已完成,而不是在 PurchaseController 上定义“完成”操作。

假设上述情况,您显然不会将 PurchaseState 直接保存到数据库中。

我的问题是你什么时候将控制器耦合到模型?何时定义 PurchaseState 模型(未持久化)以及何时直接使用 Purchase。

这是一个复杂性和您在控制器操作中与之交互的松散关联模型的数量的问题吗?

4

2 回答 2

0

“完成”是(现有)购买的状态转换事件。我发现将此操作概念化为对虚拟资源的创建而不是对耦合到购买模型的控制器(实际上是购买控制器本身)上的更新操作是违反直觉的。

我会为这种状态转换定义单独的类似更新的操作。我认为通过这种方式,您可以以最经济的方式利用 rails 结构,包括模型初始化、视图调度、路由、访问控制。假设您使用了inherited_resources,cancan只需添加

# routes.rb
resource :purchase do 
  put :complete, :on => :member
end

# purchase_controller.rb
def complete
  @purchase.complete!
end

# cancan ability (entry already there for basic crud)
can :manage, Purchase, :user_id => user.id

您已经完成了整个 UI 的实现(视图/模型逻辑除外)。在rails中是多么酷啊。

如果您的典型用例是购买仅由状态转换更新,尤其是所有具有相同访问权限和重定向视图的,那么我什至会使用带有 state_event 属性的 PurchaseController 的更新操作。看

有人可以为 pluginaweek - statemachine 提供一个活动记录示例吗?

严格的 REST 主义者,咬我!:)

于 2012-05-12T02:35:27.523 回答
0

要更新购买状态,您可能只需要一个 PurchasesController 更新操作,您可以在路由文件中将其定义为“put”或“patch”方法。

如果更新时发生的所有事情都是更改购买对象上的状态字段,那么您可能只需在更新操作中执行此操作即可。

如果围绕某些状态转换存在一些业务逻辑,但最终您只是更改了该购买对象,那么您可能希望将其放入您的购买模型中。

如果其他表也更新了,或者你也在做一些事情,比如排队给你的用户发送一封电子邮件,祝贺他们新购买,我认为你可以添加一个单独的 PurchaseComplete 或 PurchaseAbort 模型/服务对象。当动作的逻辑更复杂时,这些似乎最自然地发挥作用,和/或您对多个模型进行了更改,或者正在做其他事情。

于 2014-04-24T21:13:22.217 回答