如何在group_by中使用ActiveModelSerializer?

我在rails中使用active_model_serializer 。 我有两个序列化程序: TodoSerializerProjectSerializer

 class TodoSerializer < ActiveModel::Serializer attributes :id, :project, :note has_one :project end 

 class ProjectSerializer < ActiveModel::Serializer attributes :id, :name has_many :todos end 

我打电话的时候

 render json: @todos 

一切都很好,我得到了我期望的输出。 但是当我打电话时:

 render json: @todos.group_by(&:project_id) 

它恢复到另一个JSON调用,但它不起作用。

我也尝试过:

 render json: @todos.group_by(&:project_id), serializer: TodoSerializer 

如果我这样做,我会收到错误

 > undefined method `id' for # 

我刚遇到类似的问题,并找到了一个我觉得可以接受的解决方案:

 class GroupedTodoSerializer < ActiveModel::Serializer def attributes { project_id => serialized_todos } end private def serialized_todos todos.map{ |todo| serialize_todo(todo) } end def serialize_todo todo TodoSerializer.new(todo, root:false) # you can opt out on the root option end def todos object.last end def project_id object.first end end 

然后在控制器中你做

 render json: @todos.group_by(&:project_id).to_a, each_serializer: GroupedTodoSerializer 

这个技巧很有效,因为你将从group_by返回的Hash更改为一个数组,然后为该数组编写一个自定义的each_serializer。

我在这里发布了一个更通用的解决方案版本: https : //makandracards.com/bitcrowd/38771-group_by-with-activemodel-serializers

更新:

我刚刚发现它产生一个略微关闭的JSON字符串,因为它有一个数组括号太多了to_a。

我更新了makandracard,但是这个解决方案可能会在下一个gem版本中破解。 但0.10.0仍处于RC状态且没有向后兼容性。

 class GroupedSomeModelSerializer < ActiveModel::Serializer # method override def serializable_hash @object.map do |some_group_key, some_models| [ some_group_key , serialized_some_models(some_models) ] end.to_h end private def serialized_some_models some_models some_models.map{ |some_model| SomeModelSerializer.new(some_model, root: false) } end end 

然后在控制器中:

 @some_models = SomeModel.all.group_by(&:some_group_key) render json: @some_models, serializer: GroupedSomeModelSerializer