Ruby on Rails - 在 REST API 中区分复数和单数资源

10

在开始编写任何代码之前,我正在构建我的REST API的URL。Rails REST魔法非常棒,但是我对于这样的URL格式感到有点困扰:

http://myproject/projects/5

其中Project是我的资源,5是project_id。如果用户想要检索他们所有的projects,那么相应的HTTP GET http://myproject/projects 是有意义的。然而,如果他们想要检索有关特定资源(例如一个project)的信息,那么使用 http://myproject/project/5 而不是 http://myproject/projects/5 是有意义的。最好避免这个麻烦,还是有些人分享同样的担忧,甚至还有更好的解决方案呢?


2
我认为跟随潮流是正确的选择。记住,约定优于配置。 - JRL
3个回答

17

Rails(3)在单数和复数方面有很多惯例。例如,模型类总是单数(Person),而相应的表总是复数(people)。 (例如,Person.all 映射到 select * from people。)

对于路由,还有单数资源和复数资源的概念。因此,如果您执行了resource :account,则会获得路径,例如默认路径/account或用于编辑帐户的表单的路径/account/edit。(请注意,Rails使用具有PUT方法的/account实际上更新帐户。 /account/edit是用于编辑帐户的表单,它是与帐户本身不同的资源。)然而,如果您执行resources :people,则会获得路径如/people/people/1/people/1/edit。路径本身指示是否只能有一种给定类型的资源实例,还是可以通过某种标识符区分多个实例。


3

我同意,跟随流程。考虑URL如何形成层次结构。

你的网站根目录是访问任何内容的起点。

/projects/将内容缩小到仅限于项目,而不包括其他任何内容。从项目中,你可以进行很多事情,例如/list,/index/,/export等... /id进一步限制了内容范围。

在每个/处,所做的事情范围都变得更加狭窄,我认为这是有道理的。

进一步的编程都是关于任意规则的。例如,索引从1开始还是从0开始等等。任何使用你的URL的人都能很快地解决问题。


1

有些情况下,对于资源而言仅有一条路径是非常有帮助的。如果你的资源id是非数字的用户自定义名称,则可能会出现路由冲突。例如:

/applications/new --> 创建一个新应用程序还是显示名为new的用户应用程序?

在这种情况下,您可以选择限制用户输入以避免冲突,或者通过覆盖默认的Rails 3行为来解决此问题:

class ActionDispatch::Routing::Mapper
  module Resources
    RESOURCE_OPTIONS  << :singular_resource
    class Resource
      def member_scope
        @options[:singular_resource] ? "#{singular}/:id" : "#{path}/:id"
      end

      def nested_scope
        @options[:singular_resource] ? "#{singular}/:#{singular}_id" : "#{path}/:#{singular}_id"
      end
    end
  end
end

然后,在指定新的资源路由时:
resources :applications, :singular_resource => true

这将生成路由:
    GET     /applications
    GET     /applications/new
    POST    /applications
    GET     /application/:id
    GET     /application/:id/edit
    PUT     /application/:id
    DELETE  /application/:id

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接