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=123
或schools?user_id=123
)。
@melcher 从 RESTful 设计的角度来看,查询参数实际上并不意味着这两个资源之间存在关系,如果您需要一个包含一堆资源的单个端点,我只会真正考虑它过滤选项,或者如果参数不是真正的关系,例如/schools?name="Zoolander"
。
完全同意您的观点,这取决于用例和关系类型。我的假设是用户与学校“关联”(例如 HABTM),但它不是主要关系,因此嵌套不一定有意义,特别是如果您可能需要通过其他关系进行过滤。以上是关于Rails 最佳 API 设计,用于获取与某个用户关联的所有记录的主要内容,如果未能解决你的问题,请参考以下文章