ActiveModel Serializers:has_many在运行时有条件吗?

pro*_*ils 6 ruby-on-rails active-model-serializers

我使用rails(5.0.1)和active_model_serializers(0.10.2).我想以某种方式有条件地序列化has_many关联:

class Question < ApplicationRecord
    has_many :responses, :inverse_of => :question
end

class Response < ApplicationRecord
    belongs_to :question, :inverse_of => :responses
end

class QuestionSerializer < ActiveModel::Serializer
  attributes :id, :title, :created_at, :updated_at
  has_many :responses
end

class ResponseSerializer < ActiveModel::Serializer
  attributes :id, :title
end
Run Code Online (Sandbox Code Playgroud)

我使用jsonapi并查询http://localhost:3000/api/questions/1我得到这个回复:

回应1:

{
  "data": {
    "id": "1",
    "type": "questions",
    "attributes": {
      "title": "First",
      "created-at": "2017-02-14T09:49:20.148Z",
      "updated-at": "2017-02-14T13:55:37.365Z"
    },
    "relationships": {
      "responses": {
        "data": [
          {
            "id": "1",
            "type": "responses"
          }
        ]
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如果我has_many :responses从我删除QuestionSerializer得到这个:

回应-2:

{
  "data": {
    "id": "1",
    "type": "questions",
    "attributes": {
      "title": "First",
      "created-at": "2017-02-14T09:49:20.148Z",
      "updated-at": "2017-02-14T13:55:37.365Z"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如何在运行时有条件地获得Response-1Response-2?我尝试了所有建议 - 不适用于AMS 0.10.2.目前,条件只有这样:

class QuestionSerializer < ActiveModel::Serializer
  attributes :id, :title, :created_at, :updated_at
  has_many :responses if true
end
Run Code Online (Sandbox Code Playgroud)

要么:

class QuestionSerializer < ActiveModel::Serializer
  attributes :id, :title, :created_at, :updated_at
  has_many :responses if false
end
Run Code Online (Sandbox Code Playgroud)

在这2个案例中,我真的得到了Response-1Response-2.但这是硬编码的,我想将一个参数传递给序列化器或做一些类似的事情.

我该怎么办?

gka*_*ats 6

我想你已经回答了你自己的问题。如果您查看关联的 AMS 文档,它会说支持条件。

据我所知,你只差一个错字

class QuestionSerializer < ActiveModel::Serializer
   has_many :responses, if: false
end
Run Code Online (Sandbox Code Playgroud)

attributes方法还支持该if选项,如此处所述

active_model_serializers你的版本是什么?

编辑:我的答案也有错误。我正在使用active_model_serializers (0.10.3)并且我能够做到

class QuestionSerializer < ActiveModel::Serializer
   has_many :responses, if: -> { false }
end
Run Code Online (Sandbox Code Playgroud)

if选项适用于方法、过程或字符串。我认为您可以通过提供一个方法作为条件来在运行时做出决定。

class QuestionSerializer < ActiveModel::Serializer
  attr_writer :should_render_association
  has_many :responses, if: -> { should_render_association }
end
# Usage: 
serializer = QuestionSerializer.new(question)
serializer.should_render_association = false
serializer.to_json
# => no "responses" key
Run Code Online (Sandbox Code Playgroud)


pro*_*ils 5

感谢@gkats,我找到了答案(AMS 0.10.2):

class QuestionSerializer < ActiveModel::Serializer
  attributes :id, :title, :created_at, :updated_at
  has_many :responses, if: -> { should_render_association }

  def should_render_association
    @instance_options[:show_children]
  end
end

class Api::ResponsesController < Api::ApplicationController
  def show
    render json: @response, show_children: param[:include_children]
  end
end
Run Code Online (Sandbox Code Playgroud)

问题完全在于语法:if:在序列化程序中应该应用于块而不是函数。