Rails中的非RESTful操作

时间:2016-01-28 01:21:45

标签: ruby-on-rails rest

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

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

我认为这是我的选择:

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

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

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

2。使用JobCancellationsControllercreate操作创建destroy。 重新激活作业的是destroy - JobCancellation资源。

我将按照以下方式使用嵌套路由:

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

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

的内容

A)

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操作而不是JobsController中的非RESTful操作。将POST /admin/jobs/:job_id/reactivate路由映射到JobCancellationsController#destroy操作似乎非常棒。

为了避免JobCancellationsController#destroy的最后一次尝试,我可以改为:

3。与选项2类似,但创建了两个控制器:JobCancellationsController只有create操作,JobReactivationsController带有create只有行动。

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

2 个答案:

答案 0 :(得分:10)

在讨论了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

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

(另一种建议的方法是修补现有的update方法,其状态为已取消;但我想在cancels与常规{{updates的更新方法中需要条件。 1}})

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

  • 在您被出售时,资源不是资源是一个常见的陷阱" REST是最好的!" (即,Jobs是一种资源,但JobCancellations并非如此,所以不要试图将它们作为资源。

  • 如果您不需要删除作业,则可以使用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,我已经使用了一堆"休息" API根据休息设计得很好,但作为开发人员使用起来很糟糕。更重要的是你A)覆盖原语和B)使它比你遵守REST(或HATEOS,或者你今天所关注的任何东西)一样友好。

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

答案 1 :(得分:2)

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

# 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,你真的需要重新启动相同的工作吗?要求取消后创建新作业可能会更加清晰。也许提供一些克隆现有工作的机制。