[英]ActiveModel Serializers: has_many with condition at run-time?
I use rails (5.0.1) and active_model_serializers (0.10.2).我使用 rails (5.0.1) 和 active_model_serializers (0.10.2)。 I would like to somehow conditionally serialize the
has_many
associations:我想以某种方式有条件地序列化
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
I use jsonapi and querying http://localhost:3000/api/questions/1
I get this response:我使用 jsonapi 并查询
http://localhost:3000/api/questions/1
我得到这个响应:
Response-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"
}
]
}
}
}
}
If I remove has_many :responses
from QuestionSerializer
I get this:如果我从
QuestionSerializer
删除has_many :responses
我得到这个:
Response-2 :响应 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"
}
}
}
How do I conditionally get either Response-1 or Response-2 at run time?如何在运行时有条件地获得Response-1或Response-2 ? I tried all the recommendations found - neither works with AMS 0.10.2.
我尝试了找到的所有建议 - 都不适用于 AMS 0.10.2。 Currently, the condition works only this way:
目前,条件只能这样工作:
class QuestionSerializer < ActiveModel::Serializer
attributes :id, :title, :created_at, :updated_at
has_many :responses if true
end
OR:或者:
class QuestionSerializer < ActiveModel::Serializer
attributes :id, :title, :created_at, :updated_at
has_many :responses if false
end
In these 2 cases I really get either Response-1 or Response-2 .在这两种情况下,我真的得到了Response-1或Response-2 。 But this is hard-coded and I would like to maybe pass a param into the serializer or do some similar thing.
但这是硬编码的,我想将参数传递给序列化程序或做一些类似的事情。
What should I do?我该怎么办?
Thanks to @gkats, I found an answer (AMS 0.10.2):感谢@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
The problem was all about the syntax: if:
in the serializer should be applied to a block rather than to a function.问题全在于语法:
if:
在序列化器中应该应用于块而不是函数。
I think you've kind of answered your own question.我想你已经回答了你自己的问题。 If you look into the AMS documentation for associations it says that conditionals are supported.
如果您查看关联的 AMS 文档,它会说支持条件。
From what I can tell you're just a typo away从我可以告诉你的只是一个错字
class QuestionSerializer < ActiveModel::Serializer
has_many :responses, if: false
end
The attributes
method also supports the if
option, as described here .该
attributes
方法也支持if
选项,描述在这里。
What's your active_model_serializers
version?你的
active_model_serializers
版本是什么?
EDIT : I have an error in my answer too.编辑:我的答案也有错误。 I'm using
active_model_serializers (0.10.3)
and I'm able to do我正在使用
active_model_serializers (0.10.3)
并且我能够做到
class QuestionSerializer < ActiveModel::Serializer
has_many :responses, if: -> { false }
end
The if
option works with either methods, procs or strings. if
选项适用于方法、过程或字符串。 I think you can decide at runtime by providing a method as the conditional.我认为您可以在运行时通过提供一个方法作为条件来决定。
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
I struggled a lot with the same issue.我在同样的问题上挣扎了很多。 Here is working solution I figured.
这是我想出的工作解决方案。
Initialise with except: [:key_one, :key_two]
as arguments.使用
except: [:key_one, :key_two]
作为参数初始化。
class QuestionsController
def index
@questions = Question.all
render(json: ActiveModel::ArraySerializer.new(@questions,
each_serializer: QuestionSerializer,
root: 'questions',
except: [:responses])
)
end
def show
# you can also pass the :except arguments here
# render(json: QuestionSerializer.new(@question, except: [:responses]).to_json)
render(json: QuestionSerializer.new(@question).to_json)
end
end
https://www.rubydoc.info/gems/active_model_serializers/0.9.3/ActiveModel%2FArraySerializer:initialize https://www.rubydoc.info/gems/active_model_serializers/0.9.3/ActiveModel%2FArraySerializer:initialize
https://www.rubydoc.info/gems/active_model_serializers/0.9.1/ActiveModel%2FSerializer:initialize https://www.rubydoc.info/gems/active_model_serializers/0.9.1/ActiveModel%2FSerializer:initialize
Here is how you can pass parameters from the parent serializer and show or hide attributes based on these parameters in the child serializer.以下是如何从父序列化程序传递参数并根据这些参数在子序列化程序中显示或隐藏属性的方法。
Parent serializer:父序列化器:
class LocationSharesSerializer < ActiveModel::Serializer
attributes :id, :locations, :show_title, :show_address
def locations
ActiveModelSerializers::SerializableResource.new(object.locations, {
each_serializer: PublicLocationSerializer,
params: {
show_title: object.show_title
},
})
end
end
Child serializer子序列化器
class PublicLocationSerializer < ActiveModel::Serializer
attributes :id, :latitude, :longitude, :title, :directions, :description, :address, :tags, :created_at, :updated_at, :photos
def title
object.title if @instance_options[:params][:show_title]
end
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.