在 ActiveModelSerializers 的子序列化器中访问父对象
Accessing Parent object in Child serializer in ActiveModelSerializers
提出我的问题的一个假设的简化版本。假设我有一个网站,用户可以在其中创建带有自己品牌的商店,并从产品目录中选择要在他们的商店中展示的产品。 Shops & Products 具有拥有和属于许多 (HABTM) 的关系。每个产品都有自己的商店特定路线。
Rails.application.routes.draw do
resources :shops do
resources :products
end
end
class ShopSerializer < ActiveModel::Serializer
has_many :products
end
class ProductSerializer < ActiveModel::Serializer
include Rails.application.routes.url_helpers
attribute :url do
shop_product_url(NEED SHOP ID, product_id: object.id)
end
end
当商店被序列化时,其产品的集合也被序列化,我希望产品序列化器知道正在对其进行序列化的商店,并使用它在序列化输出中包含路由.这怎么可能?我已经尝试了从 ShopSerializer
传递 instance_options
的所有方式,但它没有按预期工作。
# this works except is apparently not threadsafe as multiple
# concurrent requests lead to the wrong shop_id being used
# in some of the serialized data
has_many :products do
ActiveModelSerializers::SerializableResource.new(shop_id: object.id).serializable_hash
end
# shop_id isn't actually available in instance_options
has_many :products do
ProductSerializer.new(shop_id: object.id)
end
不幸的是,序列化器关联似乎没有提供将自定义属性传递给子序列化器的简洁方法。虽然有一些不太漂亮的解决方案。
1.手动调用ProductSerializer
,在ShopSerializer
中添加URL
class ProductSerializer < ActiveModel::Serializer
end
class ShopSerializer < ActiveModel::Serializer
include Rails.application.routes.url_helpers
attribute :products do
object.products.map do |product|
ProductSerializer.new(product).serializable_hash.merge(
url: shop_product_url(object.id, product_id: product.id)
)
end
end
end
2。在将 Product
个实例提供给 ProductSerializer
之前,将商店 ID 添加到 Product
个实例
class ProductSerializer < ActiveModel::Serializer
include Rails.application.routes.url_helpers
attribute :url do
shop_product_url(object.shop_id, product_id: object.id)
end
end
class ShopSerializer < ActiveModel::Serializer
has_many :products, serializer: ProductSerializer do
shop = object
shop.products.map do |product|
product.dup.tap do |instance|
instance.singleton_class.send :define_method, :shop_id do
shop.id
end
end
end
end
end
两种解决方案都应该是线程安全的,但第一个解决方案对我来说似乎是一个更好的主意,因为第二个解决方案使 ProductSerializer
无法单独使用——即当只有一个 Product
是在不知道它应该属于哪个特定商店的情况下进行了序列化。
提出我的问题的一个假设的简化版本。假设我有一个网站,用户可以在其中创建带有自己品牌的商店,并从产品目录中选择要在他们的商店中展示的产品。 Shops & Products 具有拥有和属于许多 (HABTM) 的关系。每个产品都有自己的商店特定路线。
Rails.application.routes.draw do
resources :shops do
resources :products
end
end
class ShopSerializer < ActiveModel::Serializer
has_many :products
end
class ProductSerializer < ActiveModel::Serializer
include Rails.application.routes.url_helpers
attribute :url do
shop_product_url(NEED SHOP ID, product_id: object.id)
end
end
当商店被序列化时,其产品的集合也被序列化,我希望产品序列化器知道正在对其进行序列化的商店,并使用它在序列化输出中包含路由.这怎么可能?我已经尝试了从 ShopSerializer
传递 instance_options
的所有方式,但它没有按预期工作。
# this works except is apparently not threadsafe as multiple
# concurrent requests lead to the wrong shop_id being used
# in some of the serialized data
has_many :products do
ActiveModelSerializers::SerializableResource.new(shop_id: object.id).serializable_hash
end
# shop_id isn't actually available in instance_options
has_many :products do
ProductSerializer.new(shop_id: object.id)
end
不幸的是,序列化器关联似乎没有提供将自定义属性传递给子序列化器的简洁方法。虽然有一些不太漂亮的解决方案。
1.手动调用ProductSerializer
,在ShopSerializer
class ProductSerializer < ActiveModel::Serializer
end
class ShopSerializer < ActiveModel::Serializer
include Rails.application.routes.url_helpers
attribute :products do
object.products.map do |product|
ProductSerializer.new(product).serializable_hash.merge(
url: shop_product_url(object.id, product_id: product.id)
)
end
end
end
2。在将 Product
个实例提供给 ProductSerializer
Product
个实例
class ProductSerializer < ActiveModel::Serializer
include Rails.application.routes.url_helpers
attribute :url do
shop_product_url(object.shop_id, product_id: object.id)
end
end
class ShopSerializer < ActiveModel::Serializer
has_many :products, serializer: ProductSerializer do
shop = object
shop.products.map do |product|
product.dup.tap do |instance|
instance.singleton_class.send :define_method, :shop_id do
shop.id
end
end
end
end
end
两种解决方案都应该是线程安全的,但第一个解决方案对我来说似乎是一个更好的主意,因为第二个解决方案使 ProductSerializer
无法单独使用——即当只有一个 Product
是在不知道它应该属于哪个特定商店的情况下进行了序列化。