过滤 rails API json 输出中的嵌套属性

问题描述

我正在构建一个 API,其中有一个名为 Studio 的模型。工作室有很多电影和很多系列,电影和系列有很多自己的角色。此外,一个角色可以出现在许多电影和/或许多系列中,并且属于一个工作室。 我现在已经弄清楚了所有模型关系表物流,但是我现在正在尝试做的事情,我想不出办法。

所以我的路线是这样设计的,所以我可以做一些类似 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_seriebefore_action :get_movie,但它给了我一个错误,因为我从来没有同时获得 movie_id 和 serie_id,它是一个或另一个,所以它不能同时搜索

来自角色的 POST 我只会从 localhost:3000/studios/1/characters 执行所以这不是问题,我只想能够从 localhost:3000/studios/1/movies/1/characterslocalhost:3000/studios/1/seriees/1/characters 获取

我希望我没有说太多,你能理解我。如果您认为我解决这个问题的方式不对,请告诉我,因为我正在学习中,任何建议都非常有价值。

解决方法

我怀疑您是否真的想将这些资源嵌套更深一层:

经验法则:资源的嵌套深度不应超过 1 级。集合可能需要由其父级限定范围,但特定成员始终可以通过 id 直接访问,并且不需要限定范围(除非 id 由于某种原因不是唯一的)。
- 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) 无法满足电影很可能包含工作室角色的子集而不是整个电影世界的要求.相反,您需要一个连接电影和角色的连接表。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...