Rails中的非RESTful操作
好吧,当GitHub关闭时,代码设计问题:
我总是在rails应用程序(通常)中使用非标准RESTful操作进行分析瘫痪。
我有乔布斯,我希望能够取消(并重新激活)它们。 它不像设置复选框那么简单; 还有一些其他的事情需要发生。所以我不能只使用现有的JobsController#update
动作。
我认为这是我的选择:
1.只需添加cancel
并reactivate
现有作业控制器即可。 路线将是这样的:
POST /admin/jobs/cancel/:job_id POST /admin/jobs/reactivate/:job_id
(不是RESTful;假设这是一个坏主意)
2.使用create
和destroy
动作创建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
操作的JobReactivationsController
和JobReactivationsController
具有create
操作的JobReactivationsController
。
这样做的“正确”方法是什么? 或者至少,哪些是我可以迅速消除的“不正确”方式? 我错过了一种完全不同的,更好的方式吗?
在讨论了Ruby Australia冗余渠道后,我将建议整合到下面:
答案
只需添加cancel
并reactivate
现有的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,你真的需要重新启动相同的工作吗? 要求取消后创建新作业可能会更加清晰。 也许提供一些机制来克隆现有的工作。