【问题标题】:Best practice for observing RESTful routing in Rails and coupling resource models and controllers?在 Rails 中观察 RESTful 路由并耦合资源模型和控制器的最佳实践?
【发布时间】:2012-05-20 13:10:54
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: ruby-on-rails model-view-controller rest controller


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:

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

      我会为这种状态转换定义单独的类似更新的操作。我认为通过这种方式,您可以以最经济的方式利用 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 的更新操作。见

      Can somebody give an active record example for pluginaweek - statemachine?

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-09
        • 1970-01-01
        • 1970-01-01
        • 2014-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-16
        相关资源
        最近更新 更多