Rails 最佳 API 设计,用于获取与某个用户关联的所有记录

Posted

技术标签:

【中文标题】Rails 最佳 API 设计,用于获取与某个用户关联的所有记录【英文标题】:Rails Best API design to get all of a record associated with a certain user 【发布时间】:2021-10-31 05:53:04 【问题描述】:

这主要是一个 api 设计问题。我有一个 Rails api,其中包含用户路线和学校路线。我想使用 UserId 参数从我的前端应用程序对 api 进行一次调用,该参数返回与该用户关联的所有学校。

最好的方法是什么?我应该在 UsersController 中创建一个名为 user-schools 的新路由吗?还是 SchoolsController 中的一条新路由,称为学校用户?或者创建一个名为 user-schools 的全新控制器?感谢您的指导!

PS:从控制器中的 ActiveRecord 获取记录不是问题。问题是如何最好地设计这个 api。

【问题讨论】:

【参考方案1】:

定义它的 RESTful 方式是通过 nested route:

GET /users/:user_id/schools

同样的基本设计原则在这里适用于 API 和“经典”应用程序。

您可以通过嵌套对资源宏的调用来定义它:

resources :users do
  resources :schools, only: [:index]
end

这会将/users/:user_id/schools 路由到SchoolsController#index。虽然您可以“嗅探”user_id 参数:

class SchoolsController
  # GET /schools
  # GET /users/1/schools
  def index
    schools = if params[:user_id].present?
      user = User.find(params[:user_id])
      user.schools 
    else
      School.all
    end
    render json: schools
  end
end

更简洁的设计是为嵌套上下文使用单独的控制器:

resources :users do
  resources :schools, only: [:index], module: :users
end
module Users
  class SchoolsController < ApplicationController
    # GET /users/1/schools
    def index
      user = User.find(params[:user_id])
      render json: user.schools
    end
  end
end

这个控制器只做一个工作。您也可以将其命名为 UserSchoolsController,但将控制器拆分为文件夹(和命名空间)可以更轻松地组织它们。

【讨论】:

很好的答案。我认为值得一提的替代方法(并且对嵌套有优点/缺点)是在主控制器中支持过滤结果的查询参数(例如schools?user=123schools?user_id=123)。 @melcher 从 RESTful 设计的角度来看,查询参数实际上并不意味着这两个资源之间存在关系,如果您需要一个包含一堆资源的单个端点,我只会真正考虑它过滤选项,或者如果参数不是真正的关系,例如/schools?name="Zoolander" 完全同意您的观点,这取决于用例和关系类型。我的假设是用户与学校“关联”(例如 HABTM),但它不是主要关系,因此嵌套不一定有意义,特别是如果您可能需要通过其他关系进行过滤。

以上是关于Rails 最佳 API 设计,用于获取与某个用户关联的所有记录的主要内容,如果未能解决你的问题,请参考以下文章

使用明文密码访问 REST API 的最佳实践

DRF完整版

DRF完整版

如何在我的 Rails 应用程序中与亚马逊产品广告 API 交互?

API设计与开发之最佳实践

Rails RESTful API + 设计 - 如何检查用户的凭据