【问题标题】:Creating Nested Relationships for a Rails JSON API with ActiveModelSerializers使用 ActiveModelSerializers 为 Rails JSON API 创建嵌套关系
【发布时间】:2018-03-15 01:09:18
【问题描述】:

我正在尝试使用以下 JSON 结构构建 Rails API:

{ team: "team_name",
  players: players: [
    {
      name: "player_one",
      contracts: [
        {
          start_date: '7/1/2017',
          seasons: [
            {
              year: 2017,
              salary: 1000000
            }
          ]
        }
      ]
    },
    {
      name: "player_two"
    }
  ]
}

我的模型设置如下:

class Team < ApplicationRecord
  has_many :players
end

class Player < ApplicationRecord
  belongs_to :team
  has_many :contracts
end

class Contract < ApplicationRecord
  belongs_to :player
  has_many :seasons
end

class Season < ApplicationRecord
  belongs_to :contract
end

我目前正在使用以下代码,但我想使用 ActiveModel 序列化器(或其他干净的解决方案)清理它

def show
  @team = Team.find(params[:id])
  render json: @team.as_json(
    except: [:id, :created_at, :updated_at],
    include: {
      players: {
        except: [:created_at, :updated_at, :team_id],
        include: {
          contracts: {
            except: [:id, :created_at, :updated_at, :player_id],
            include: {
              seasons: {
              except: [:id, :contract_id, :created_at, :updated_at]
              }
            }
          }
        }
      }
    }
  )
end

此外,数组项按 ID 降序显示,我希望将其反转。我也希望通过第一份合同、第一个赛季、薪水来订购球员。

【问题讨论】:

    标签: ruby-on-rails active-model-serializers


    【解决方案1】:

    Active Model Serializers 是一个很好的宝石,可以满足您的需求。假设你会使用0-10-stable 分支(最新:0.10.7),你可以这样走:

    序列化程序 (Doc)

    # app/serializers/team_serializer.rb or app/serializers/api/v1/team_serializer.rb (if your controllers are in app/controllers/api/v1/ subdirectory)
    class TeamSerializer < ActiveModel::Serializer
      attributes :name # list all desired attributes here
      has_many :players
    end
    
    # app/serializers/player_serializer.rb
    class PlayerSerializer < ActiveModel::Serializer
      attributes :name # list all desired attributes here
      has_many :contracts
    end
    
    # app/serializers/contract_serializer.rb
    class ContractSerializer < ActiveModel::Serializer
      attributes :start_date # list all desired attributes here
      has_many :seasons
    end
    
    # app/serializers/season_serializer.rb
    class SeasonSerializer < ActiveModel::Serializer
      attributes :year, :salary # list all desired attributes here
    end
    

    团队控制器

    def show
      @team = Team
        .preload(players: [contracts: :seasons])
        .find(params[:id])
    
      render json: @team, 
        include: ['players.contracts.seasons'], 
        adapter: :attributes
    end
    

    注意1:使用preload(或includes)将帮助您eager-load multiple associations,从而使您免于N + 1问题

    注意2:您可能希望从Doc阅读render方法中include选项的详细信息

    【讨论】:

      【解决方案2】:

      我认为你的方法是正确的。看起来很干净。 你也可以在你的模型上使用named_scopes

      在此处查看docs

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-23
        • 2019-04-19
        • 2010-10-25
        • 1970-01-01
        • 2020-08-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多