过滤 rails API json 输出中的嵌套属性
Filtering nested attributes in rails API json output
我正在构建一个 API,其中我有一个名为 Studio 的模型。工作室有很多电影和很多系列,电影和系列有很多自己的角色。此外,一个角色可以出现在多部电影 and/or 多个系列中,并且属于一个工作室。
我现在已经弄清楚了所有模型关系表逻辑,但我现在想做的是,我想不出办法。
所以我的路线是这样设计的,所以我可以做类似 localhost:3000/api/v1/studios/1/characters 的事情 -> 这样我就可以显示工作室的所有 (studio_id: 1) 个角色(来自所有属于该工作室的电影和系列)。
只需执行以下操作即可相当容易:
@characters = Character.where(studio_id:@studio.id)
在我的 CharactersController 中,我有
def get_studio
@studio = Studio.find(params[:studio_id])
end
现在我正在尝试设计物流,这样我就可以做到localhost:3000/api/v1/studios/1/seriees/1/characters
并且只从该特定系列中获取角色。 localhost:3000/api/v1/studios/1/movies/1/characters
应该也是有效的。
我试过了
def get_movie
@movie = Movie.find(params[:movie_id])
end`
和
def get_serie
@serie = Seriee.find(params[:seriee_id])
end
在我的 CharactersController 中,在代码的最开头有 before_action :get_serie
和 before_action :get_movie
,但它给了我一个错误,因为我从来没有同时得到 movie_id 和seriee_id,非此即彼,无法同时搜索。
来自角色的 POST 我只会从 localhost:3000/studios/1/characters
做,所以这不是问题,我只想能够从 localhost:3000/studios/1/movies/1/characters
和 localhost:3000/studios/1/seriees/1/characters
我希望我没有啰嗦太多,你能理解我。如果您认为我解决这个问题的方法不对,请告诉我,因为我只是在学习,任何建议都将非常有价值。
我怀疑您是否真的想将这些资源嵌套得超过一层:
Rule of thumb: resources should never be nested more than 1 level deep. A collection may need to be scoped by its parent, but a specific member can always be accessed directly by an id, and shouldn’t need scoping (unless the id is not unique, for some reason).
- Jamis Buck
鉴于此处的域,您必须指定工作室才能获取给定电影的角色是没有意义的。嵌套在 REST 中的目标是通过使两个实体成为 URL 结构的一部分来明确两个实体之间的关系——不要过于明确。
当涉及到 url 生成之类的东西时,过多的嵌套会导致一些非常复杂的代码 - 我的意思是你真的想写吗?
url_for [:ap1, :v1, studio, movie, :characters]
您可以使用 shallow: true
选项解决这些问题:
resources :studios do
resources :movies, shallow: :true do
resources :characters
end
end
或者避免“俄罗斯娃娃”调用 resources
:
resources :studios do
resources :movies, only: [:new, :create]
end
resources :movies, only: [:show, :update, :destroy] do
resources :characters, only: [:create, :index]
end
您也确实应该使用关联来获取嵌套项。
class CharactersController
before_action :set_movie, only: [:index, :create]
# GET /api/v1/movies/1/characters.json
def index
@characters = @movie.characters
end
private
def set_movie
@movie = Movie.find(params[:movie_id])
end
end
一般来说,像 Character.where(studio_id: @studio.id)
这样的代码应该避免,因为它会泄露关系的实现细节。您的控制器不需要知道角色和工作室之间的关系 - 它只知道 movie
有一个名为 characters
.
的方法
而且我真的不想在这里详细介绍您的建模,但是 Character.where(studio_id: @studio.id)
不适用于电影很可能包含工作室角色的子集 - 而不是全部角色的要求电影宇宙。相反,您需要一个连接电影和角色的联接 table。
我正在构建一个 API,其中我有一个名为 Studio 的模型。工作室有很多电影和很多系列,电影和系列有很多自己的角色。此外,一个角色可以出现在多部电影 and/or 多个系列中,并且属于一个工作室。 我现在已经弄清楚了所有模型关系表逻辑,但我现在想做的是,我想不出办法。
所以我的路线是这样设计的,所以我可以做类似 localhost:3000/api/v1/studios/1/characters 的事情 -> 这样我就可以显示工作室的所有 (studio_id: 1) 个角色(来自所有属于该工作室的电影和系列)。 只需执行以下操作即可相当容易:
@characters = Character.where(studio_id:@studio.id)
在我的 CharactersController 中,我有
def get_studio
@studio = Studio.find(params[:studio_id])
end
现在我正在尝试设计物流,这样我就可以做到localhost:3000/api/v1/studios/1/seriees/1/characters
并且只从该特定系列中获取角色。 localhost:3000/api/v1/studios/1/movies/1/characters
应该也是有效的。
我试过了
def get_movie
@movie = Movie.find(params[:movie_id])
end`
和
def get_serie
@serie = Seriee.find(params[:seriee_id])
end
在我的 CharactersController 中,在代码的最开头有 before_action :get_serie
和 before_action :get_movie
,但它给了我一个错误,因为我从来没有同时得到 movie_id 和seriee_id,非此即彼,无法同时搜索。
来自角色的 POST 我只会从 localhost:3000/studios/1/characters
做,所以这不是问题,我只想能够从 localhost:3000/studios/1/movies/1/characters
和 localhost:3000/studios/1/seriees/1/characters
我希望我没有啰嗦太多,你能理解我。如果您认为我解决这个问题的方法不对,请告诉我,因为我只是在学习,任何建议都将非常有价值。
我怀疑您是否真的想将这些资源嵌套得超过一层:
Rule of thumb: resources should never be nested more than 1 level deep. A collection may need to be scoped by its parent, but a specific member can always be accessed directly by an id, and shouldn’t need scoping (unless the id is not unique, for some reason).
- Jamis Buck
鉴于此处的域,您必须指定工作室才能获取给定电影的角色是没有意义的。嵌套在 REST 中的目标是通过使两个实体成为 URL 结构的一部分来明确两个实体之间的关系——不要过于明确。
当涉及到 url 生成之类的东西时,过多的嵌套会导致一些非常复杂的代码 - 我的意思是你真的想写吗?
url_for [:ap1, :v1, studio, movie, :characters]
您可以使用 shallow: true
选项解决这些问题:
resources :studios do
resources :movies, shallow: :true do
resources :characters
end
end
或者避免“俄罗斯娃娃”调用 resources
:
resources :studios do
resources :movies, only: [:new, :create]
end
resources :movies, only: [:show, :update, :destroy] do
resources :characters, only: [:create, :index]
end
您也确实应该使用关联来获取嵌套项。
class CharactersController
before_action :set_movie, only: [:index, :create]
# GET /api/v1/movies/1/characters.json
def index
@characters = @movie.characters
end
private
def set_movie
@movie = Movie.find(params[:movie_id])
end
end
一般来说,像 Character.where(studio_id: @studio.id)
这样的代码应该避免,因为它会泄露关系的实现细节。您的控制器不需要知道角色和工作室之间的关系 - 它只知道 movie
有一个名为 characters
.
而且我真的不想在这里详细介绍您的建模,但是 Character.where(studio_id: @studio.id)
不适用于电影很可能包含工作室角色的子集 - 而不是全部角色的要求电影宇宙。相反,您需要一个连接电影和角色的联接 table。