Rails中的非RESTful操作

好吧,当GitHub关闭时,代码设计问题:
我总是在rails应用程序(通常)中使用非标准RESTful操作进行分析瘫痪。

我有乔布斯,我希望能够取消(并重新激活)它们。 它不像设置复选框那么简单; 还有一些其他的事情需要发生。所以我不能只使用现有的JobsController#update动作。

我认为这是我的选择:

1.只需添加cancelreactivate现有作业控制器即可。 路线将是这样的:

 POST /admin/jobs/cancel/:job_id POST /admin/jobs/reactivate/:job_id 

(不是RESTful;假设这是一个坏主意)

2.使用createdestroy动作创建JobCancellationsController 。 重新激活作业会destroy JobCancellation资源。

我将使用嵌套路由,如下所示:

 resources :jobs, except: :show do resource :job_cancellation, only: [:create, :destroy] end 

默认情况下会给我一些类似的东西

一个)

 POST /admin/jobs/:job_id/job_cancellation DELETE /admin/jobs/:job_id/job_cancellation 

我可以在不改变控制器的情况下整理路线,就像:

b)

 POST /admin/jobs/:job_id/cancellation DELETE /admin/jobs/:job_id/cancellation 

虽然这看起来不太直观 – “取消”会更好cancel 。 所以我可以在保持控制器相同的同时改变路线:

C)

 POST /admin/jobs/:job_id/cancel DELETE /admin/jobs/:job_id/cancel 

第一条路线现在有意义(虽然严格来说不是RESTful ?),但第二条路线不是……“删除工作取消”? 所以你要改成它:

d)

 POST /admin/jobs/:job_id/cancel POST /admin/jobs/:job_id/reactivate 

现在路由很有意义,但看起来很可疑接近上面的选项1),即使路由确实映射到JobCancellationsController的RESTful操作而不是JobCancellationsController非RESTful操作。 将POST /admin/jobs/:job_id/reactivate路由映射到JobCancellationsController#destroy动作JobCancellationsController#destroy

为了避免使用JobCancellationsController#destroy最后一次性,我可以改为:

3.与选项2类似,但创建两个控制器: JobCancellationsController具有create操作的JobReactivationsControllerJobReactivationsController具有create操作的JobReactivationsController

这样做的“正确”方法是什么? 或者至少,哪些是我可以迅速消除的“不正确”方式? 我错过了一种完全不同的,更好的方式吗?

在讨论了Ruby Australia冗余渠道后,我将建议整合到下面:

答案

只需添加cancelreactivate现有的JobsController

使用此代码:

 resources :jobs do post :cancel, on: :member post :reactivate, on: :member end 

创建如下路线:

 POST /admin/jobs/:job_id/cancel POST /admin/jobs/:job_id/reactivate 

这很简单直观,即使它不是严格的RESTful。

(另一种建议的方法是PATCH到现有的update方法,状态为已取消;虽然我想在更新方法中需要条件cancels与常规updates

讨论中提出的其他有用的观点

  • 当您被出售时,资源非资源的东西是一个常见的陷阱“REST是最好的!” (即, Jobs是一种资源,但JobCancellations并不是真的,所以不要试图让它们成为一种资源)。

  • 如果您不需要删除作业的function,则可以使用destroy操作取消作业而不是cancel操作。

  • IMO完整的REST仅在您不可能遇到的某些情况下有用,除非您在大公司。

  • 制作一个有意义的API。 Rails只是提供了轻松完成CRUD的方法。 这与宁静有关,但不是全部。

  • REST(或HATEOS)方法是让/jobs/1234.json包含cancelLink: {url: "url", method: "POST", rel: "link to the docs"}属性

  • 当我们构建我们的API时,我们有一个非官方的规则,如果我们不确定该怎么做,我们只是复制github所做的,因为我们喜欢他们的API。

  • fwiw,我使用了一堆根据rest设计得很好的“rest”API,但作为开发人员使用起来很糟糕。 更重要的是你A)覆盖原语和B)使它比你遵守REST(或HATEOS,或者你今天关注的任何东西)一样友好。

以上所有内容基本上都指向了我总是试图告诉自己的建议:“最重要的是代码简单易懂。设计模式只有在它们帮助您实现目标的范围内才有用。如果设计模式没有要实现这个目标,你可能会错误地使用它,或者将它应用于不正确的情况,或者过于严格地使用它“。

在这个特定的情况下,为什么不只是

 # Cancel a job (handled by your cancellations controller) DELETE /admin/jobs/:job_id # Likewise, reactivate a job if so instructed by the request body PATCH /admin/jobs/:job_id 

有很多可能会遇到一般的“你没有做正确的REST”辩论,我认为我并不真正关心这个问题。 这个特殊情况看起来像是一个不错的解决方案。

FWIW,你真的需要重新启动相同的工作吗? 要求取消后创建新作业可能会更加清晰。 也许提供一些机制来克隆现有的工作。