programing

레일: active_model_serializer와의 깊이 중첩된 연관성을 직렬화하는 중

bestprogram 2023. 3. 23. 23:13

레일: active_model_serializer와의 깊이 중첩된 연관성을 직렬화하는 중

하고 Rails 4.2.1 ★★★★★★★★★★★★★★★★★」active_model_serializers 0.10.0.rc2

를 선택했습니다.active_model_serializers이 되고 것 것은 ).RABL another serializer ( 시리얼라이저)

제가 안고 있는 문제는 다단계 관계에서 다양한 속성을 포함할 수 없다는 것입니다.예를 들어 다음과 같습니다.

프로젝트

class ProjectSerializer < ActiveModel::Serializer
  attributes                      :id, 
                                  :name,
                                  :updated_at

  has_many                        :estimates, include_nested_associations: true

end

견적

class EstimateSerializer < ActiveModel::Serializer
  attributes                      :id, 
                                  :name, 
                                  :release_version, 
                                  :exchange_rate, 
                                  :updated_at,

                                  :project_id, 
                                  :project_code_id, 
                                  :tax_type_id 

  belongs_to                      :project
  belongs_to                      :project_code
  belongs_to                      :tax_type

  has_many                        :proposals

end

제안.

class ProposalSerializer < ActiveModel::Serializer
  attributes                      :id, 
                                  :name, 
                                  :updated_at,

                                  :estimate_id

  belongs_to                      :estimate
end

가 내 the를 때/projects/1다음 중 하나:

{
  "id": 1,
  "name": "123 Park Ave.",
  "updated_at": "2015-08-09T02:36:23.950Z",
  "estimates": [
    {
      "id": 1,
      "name": "E1",
      "release_version": "v1.0",
      "exchange_rate": "0.0",
      "updated_at": "2015-08-12T04:23:38.183Z",
      "project_id": 1,
      "project_code_id": 8,
      "tax_type_id": 1
    }
  ]
}

다만, 제작하고 싶은 것은 다음과 같습니다.

{
  "id": 1,
  "name": "123 Park Ave.",
  "updated_at": "2015-08-09T02:36:23.950Z",
  "estimates": [
    {
      "id": 1,
      "name": "E1",
      "release_version": "v1.0",
      "exchange_rate": "0.0",
      "updated_at": "2015-08-12T04:23:38.183Z",
      "project": { 
        "id": 1,
        "name": "123 Park Ave."
      },
      "project_code": {
        "id": 8,
        "valuation": 30
      },
      "tax_type": {
        "id": 1,
        "name": "no-tax"
      },
      "proposals": [
        {
          "id": 1,
          "name": "P1",
          "updated_at": "2015-08-12T04:23:38.183Z"
        },
        {
          "id": 2,
          "name": "P2",
          "updated_at": "2015-10-12T04:23:38.183Z"
        }
      ]
    }
  ]
}

또, 이러한 어소시에이션의 어트리뷰트, 어소시에이션, 어소시에이션을 지정하는 것도 이상적입니다.

AMS의 문제를 조사해 본 결과, 이 문제에 대한 대응 방법(또는 이러한 기능이 실제로 지원되고 있는지 여부)에 대해서는 몇 가지 의견이 엇갈리고 있는 것 같습니다만, 현재 상태를 정확하게 파악하는데 어려움을 겪고 있습니다.

제안된 솔루션 중 하나는 네스트된 속성을 호출하는 메서드로 속성을 덮어쓰는 것이었는데, 해킹으로 간주되는 것 같아서 가능하면 피하고 싶었습니다.

어쨌든 이 방법이나 일반적인 API 조언의 예를 들어 주시면 감사하겠습니다.

Commit 1426: https://github.com/rails-api/active_model_serializers/pull/1426 및 관련 설명에 따라 기본 네스팅이 설정되어 있는 것을 확인할 수 있습니다.json ★★★★★★★★★★★★★★★★★」attributes시리얼라이제이션

디폴트로 딥네스트 할 경우 active_model_serializer initializer로 설정 속성을 설정할 수 있습니다.

ActiveModelSerializers.config.default_includes = '**'

v0.10.6의 상세한 것에 대하여는, https://github.com/rails-api/active_model_serializers/blob/v0.10.6/docs/general/adapters.md#include-option 를 참조해 주세요.

JSONAPI 어댑터를 사용하는 경우 다음을 수행하여 중첩된 관계를 렌더링할 수 있습니다.

render json: @project, include: ['estimates', 'estimates.project_code', 'estimates.tax_type', 'estimates.proposals']

자세한 내용은 jsonapi 문서를 참조하십시오.http://jsonapi.org/format/ #fetching-buffer

그래서 이게 최선도 아니고 좋은 대답도 아니지만, 이게 내가 필요한 방식이야.

네스트된 Atribute와 사이드 로드된 Atribute를 포함하는 것은 를 사용하는 경우는 서포트되고 있는 것처럼 보입니다.json_apiAMS 탑재 어댑터, 플랫 json 지원이 필요했습니다.또한 이 방법은 각 시리얼라이저가 컨트롤러에서 아무것도 할 필요 없이 다른 시리얼라이저에 의존하지 않고 필요한 것을 정확하게 생성하기 때문에 잘 작동했습니다.

코멘트 / 대체 방법은 언제든지 환영입니다.

프로젝트 모델

class Project < ActiveRecord::Base      
  has_many  :estimates, autosave: true, dependent: :destroy
end

프로젝트 컨트롤러

def index
  @projects = Project.all
  render json: @projects
end

프로젝트 시리얼라이저

class ProjectSerializer < ActiveModel::Serializer
  attributes  :id, 
              :name,
              :updated_at,

              # has_many
              :estimates



  def estimates
    customized_estimates = []

    object.estimates.each do |estimate|
      # Assign object attributes (returns a hash)
      # ===========================================================
      custom_estimate = estimate.attributes


      # Custom nested and side-loaded attributes
      # ===========================================================
      # belongs_to
      custom_estimate[:project] = estimate.project.slice(:id, :name) # get only :id and :name for the project
      custom_estimate[:project_code] = estimate.project_code
      custom_estimate[:tax_type] = estimate.tax_type

      # has_many w/only specified attributes
      custom_estimate[:proposals] = estimate.proposals.collect{|proposal| proposal.slice(:id, :name, :updated_at)}

      # ===========================================================
      customized_estimates.push(custom_estimate)
    end

    return customized_estimates
  end
end

결과

[
  {
    "id": 1,
    "name": "123 Park Ave.",
    "updated_at": "2015-08-09T02:36:23.950Z",
    "estimates": [
      {
        "id": 1,
        "name": "E1",
        "release_version": "v1.0",
        "exchange_rate": "0.0",
        "created_at": "2015-08-12T04:23:38.183Z",
        "updated_at": "2015-08-12T04:23:38.183Z",
        "project": {
          "id": 1,
          "name": "123 Park Ave."
        },
        "project_code": {
          "id": 8,
          "valuation": 30,
          "created_at": "2015-08-09T18:02:42.079Z",
          "updated_at": "2015-08-09T18:02:42.079Z"
        },
        "tax_type": {
          "id": 1,
          "name": "No Tax",
          "created_at": "2015-08-09T18:02:42.079Z",
          "updated_at": "2015-08-09T18:02:42.079Z"
        },
        "proposals": [
          {
            "id": 1,
            "name": "P1",
            "updated_at": "2015-08-12T04:23:38.183Z"
          },
          {
            "id": 2,
            "name": "P2",
            "updated_at": "2015-10-12T04:23:38.183Z"
          }
        ]
      }
    ]
  }
]

저는 기본적으로 모든 것을 구현하려는 시도를 무시했습니다.has_many또는belongs_to시리얼라이저에 관련지어 동작을 커스터마이즈 했을 뿐입니다.나는 사용했다slice특정 애트리뷰트를 선택합니다.좀 더 우아한 해결책이 나오길 바란다.

변경할 수 있습니다.default_includes를 위해ActiveModel::Serializer:

# config/initializers/active_model_serializer.rb
ActiveModel::Serializer.config.default_includes = '**' # (default '*')

또한 무한 재귀를 방지하기 위해 네스트된 시리얼화를 다음과 같이 제어할 수 있습니다.

class UserSerializer < ActiveModel::Serializer
  include Rails.application.routes.url_helpers

  attributes :id, :phone_number, :links, :current_team_id

  # Using serializer from app/serializers/profile_serializer.rb
  has_one :profile
  # Using serializer described below:
  # UserSerializer::TeamSerializer
  has_many :teams

  def links
    {
      self: user_path(object.id),
      api: api_v1_user_path(id: object.id, format: :json)
    }
  end

  def current_team_id
    object.teams&.first&.id
  end

  class TeamSerializer < ActiveModel::Serializer
    attributes :id, :name, :image_url, :user_id

    # Using serializer described below:
    # UserSerializer::TeamSerializer::GameSerializer
    has_many :games

    class GameSerializer < ActiveModel::Serializer
      attributes :id, :kind, :address, :date_at

      # Using serializer from app/serializers/gamers_serializer.rb
      has_many :gamers
    end
  end
end

결과:

{
   "user":{
      "id":1,
      "phone_number":"79202700000",
      "links":{
         "self":"/users/1",
         "api":"/api/v1/users/1.json"
      },
      "current_team_id":1,
      "profile":{
         "id":1,
         "name":"Alexander Kalinichev",
         "username":"Blackchestnut",
         "birthday_on":"1982-11-19",
         "avatar_url":null
      },
      "teams":[
         {
            "id":1,
            "name":"Agile Season",
            "image_url":null,
            "user_id":1,
            "games":[
               {
                  "id":13,
                  "kind":"training",
                  "address":"",
                  "date_at":"2016-12-21T10:05:00.000Z",
                  "gamers":[
                     {
                        "id":17,
                        "user_id":1,
                        "game_id":13,
                        "line":1,
                        "created_at":"2016-11-21T10:05:54.653Z",
                        "updated_at":"2016-11-21T10:05:54.653Z"
                     }
                  ]
               }
            ]
         }
      ]
   }
}

내 경우 'MyApp/config/initializers'에 있는 'active_model_serializer.rb'라는 파일을 만들었습니다.이 파일은 다음과 같습니다.

ActiveModelSerializers.config.default_includes = '**'

여기에 이미지 설명 입력

서버를 재기동하는 것을 잊지 말아 주세요.

$ rails s

이게 네가 원하는 걸 할 수 있을 거야.

@project.to_json( include: { estimates: { include: {:project, :project_code, :tax_type, :proposals } } } )

최상위 네스팅은 자동으로 포함되지만 그 이상의 깊이는 show 액션 또는 호출 위치에 포함되어야 합니다.

에릭 노크로스의 답변을 뒷받침하기 위해 다음과 같은 답변을 덧붙였습니다.

레일 어플리케이션의 serilization에 jsonapi-serializer gem을 사용하고 있었습니다.컨트롤러에 네스트되어 있는 것과 사이드 로딩된 Atribute를 사용하는 것이 편리하지 않았습니다.나는 단지 더 나은 관심사 분리를 원했을 뿐이다.따라서 시리얼라이제이션과 관련된 것은 시리얼라이제이션파일 내부에만 있어야 하며 컨트롤러 파일과는 관계가 없습니다.

제 경우엔 다음과 같은 연관성이 있었습니다.

학교 모델

module Baserecord
  class School < ApplicationRecord
    has_many :programs, class_name: Baserecord.program_class, dependent: :destroy
    has_many :faculties, class_name: Baserecord.faculty_class, through: :programs, dependent: :destroy
end

프로그램 모델

module Baserecord
  class Faculty < ApplicationRecord
    belongs_to :program, class_name: Baserecord.program_class
    has_many :departments, class_name: Baserecord.department_class, dependent: :destroy
    has_many :program_of_studies, class_name: Baserecord.program_of_study_class, through: :departments,
                                  dependent: :destroy
  end
end

시리얼라이저 파일의 구성은 다음과 같습니다.

학교 시리얼라이저

module Baserecord
  class SchoolSerializer
    include JSONAPI::Serializer
    attributes :id, :name, :code, :description, :school_logo, :motto, :address

    attribute :programs do |object|

      # Create an empty array
      customized_programs = []

      object.programs.each do |program|

        # Assign object attributes (returns a hash)
        custom_program = program.attributes

        # Create custom nested and side-loaded attributes
        custom_program[:faculties] = program.faculties

        # Push the created custom nested and side-loaded attributes into the empty array
        customized_programs.push(custom_program)
      end

      # Return the new array
      customized_programs
    end

    cache_options store: Rails.cache, namespace: 'jsonapi-serializer', expires_in: 1.hour
  end
end

그게 다예요.

이게 도움이 됐으면 좋겠다

언급URL : https://stackoverflow.com/questions/32079897/rails-serializing-deeply-nested-associations-with-active-model-serializers