我正在使用Rails 5.0.1,我对以下问题感到困惑。我有几个具有多态关联的模型。
class Container < ApplicationRecord
has_many :steps, as: 'parent', dependent: :destroy
end
class Step < ApplicationRecord
belongs_to :parent, polymorphic: true
belongs_to :implementation, polymorphic: true
end
class FirstStep < ApplicationRecord
has_one :step, as: 'implementation'
has_many :params, dependent: :destroy
end
class SecondStep < ApplicationRecord
has_one :step, as: 'implementation'
has_many :headers, dependent: :destroy
end
class Param < ApplicationRecord
belongs_to :first_step
end
class Header < ApplicationRecord
belongs_to :second_step
end
与实施相关联的步骤(FirstStep
,SecondStep
)。除此之外,container
也可以是step
的实现。我正在使用See here将模型信息序列化为JSON。以下是序列化程序的相关代码。
class StepSerializer < ActiveModel::Serializer
attributes :id, :implementation_type, :implementation_id, :active, :position
belongs_to :implementation
end
class FirstStepSerializer < ActiveModel::Serializer
attributes :name, :params_attributes
def params_attributes
object.params.map { |p| ParamSerializer.new(p).attributes }
end
end
class SecondStepSerializer < ActiveModel::Serializer
attributes :id, :title, :headers_attributes
def headers_attributes
object.headers.map { |p| HeaderSerializer.new(p).attributes }
end
end
class ParamSerializer < ActiveModel::Serializer
attributes :id
end
class HeaderSerializer < ActiveModel::Serializer
attributes :id
end
step
模型的实现可以具有不同的属性,如模型中指定的那样。问题是,当我写
render json: container.steps
它触发N + 1个查询以获得结果。我该如何优化它?
修改1
受到Active Model Serializers的启发,我试图通过implementation_type
分隔对象,并且它有效。我做的是:
# my controller action
def index
steps = []
steps += container.steps.where(implementation_type: 'FirstStep').includes(implementation: [:params])
steps += container.steps.where(implementation_type: 'SecondStep').includes(implementation: [:headers])
render json: steps
end
这阻止了N + 1查询提取params
和headers
,但如果step
是container
则无效。
答案 0 :(得分:0)
更改您的FirstStepSerializer
和SecondStepSerializer
序列化程序,如下所示
class FirstStepSerializer < ActiveModel::Serializer
attributes :name
has_many :params, :serializer => ParamSerializer
end
class SecondStepSerializer < ActiveModel::Serializer
attributes :id, :title
has_many :headers, :serializer => HeaderSerializer
end
这可能会有所帮助