使用active_model_serializers序列化深层嵌套的关联 [英] Serializing deeply nested associations with active_model_serializers
问题描述
我正在使用Rails 4.2.1
和active_model_serializers 0.10.0.rc2
我是API的新手,所以选择了active_model_serializers
,因为它似乎已成为Rails的标准(尽管我不反对使用RABL
或其他序列化器)
I'm new to API's and chose active_model_serializers
because it seems to be becoming the standard for rails (Although I'm not opposed to using RABL
or another serializer)
我遇到的问题是,我似乎无法在多级关系中包括各种属性.例如,我有:
The problem I'm having is that I can't seem to include various attributes in multi-level relationships. For instance I have:
项目
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
当我按下/projects/1
时,上面的结果会产生:
When I hit the /projects/1
the above produces:
{
"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
}
]
}
但是,我希望它产生的是:
However, what I'd like it to produce is:
{
"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"
}
]
}
]
}
理想情况下,我还希望能够指定每个序列化程序中包含哪些属性,关联以及那些关联的属性.
Ideally, I'd also like to be able to specify which attributes, associations, and attributes of those associations that are included in each serializer.
我一直在研究AMS问题,似乎确实有一些关于如何处理(或者是否实际上支持这种功能)的来回信息,但是我很难弄清楚当前状态是什么.
I've been looking through the AMS issues, and there does seem to be some back and forth on how this should be handled (or if this kind of functionality is even actually supported) but I'm having difficulty figuring out exactly what the current state is.
- https://github.com/rails-api/active_model_serializers/issues/835
- https://github.com/rails-api/active_model_serializers/issues/968
- https://github.com/rails-api/active_model_serializers/issues/414
- https://github.com/rails-api/active_model_serializers/issues/444
- https://github.com/rails-api/active_model_serializers/issues/835
- https://github.com/rails-api/active_model_serializers/issues/968
- https://github.com/rails-api/active_model_serializers/issues/414
- https://github.com/rails-api/active_model_serializers/issues/444
提出的解决方案之一是使用一种调用嵌套属性的方法来覆盖属性,但这似乎被认为是一种hack,因此我想尽可能避免使用它.
One of the proposed solutions was to override the attribute with a method to call the nested attributes, but that seems to be regarded as a hack so I wanted to avoid it if possible.
无论如何,将不胜感激如何使用此建议或常规API建议的示例.
Anyway, an example of what of how to go about this or general API advice would be much appreciated.
推荐答案
所以这不是最好的,甚至不是一个好的答案,但这是我需要的.
So this my not be the best or even a good answer, but this is working how I need it to.
当将json_api
适配器与AMS一起使用时,似乎支持嵌套和侧载属性,但我需要支持平面json.此外,此方法之所以有效,是因为每个序列化程序都专门生成了我需要的内容,从而独立于任何其他序列化程序,而无需在控制器中执行任何操作.
While including nested and side-loaded attributes appears to be supported when using the json_api
adapter with AMS, I needed support for flat json. In addition, this method worked well because each serializer is specifically generating exactly what I need it to independent of any other serializer and without having to do anything in the controller.
始终欢迎评论/其他方法.
Comments / alternate methods are always welcome.
项目模型
class Project < ActiveRecord::Base
has_many :estimates, autosave: true, dependent: :destroy
end
ProjectsController
def index
@projects = Project.all
render json: @projects
end
ProjectSerializer
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
选择特定属性.希望将来会有一个更优雅的解决方案.
I basically disregarded trying to implement any has_many
or belongs_to
associations in the serializers and just customized the behavior. I used slice
to select specific attributes. Hopefully a more elegant solution will be forth coming.
这篇关于使用active_model_serializers序列化深层嵌套的关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!