我刚遇到了类似的问题,并找到了一个解决方案,我觉得还不错:
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)
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
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
它会回到另一个JSON调用,但它不起作用。
- MilesStanfieldrender json: @todos.map { |todo| TodoSerializer.new(todo).as_json }.group_by { |todo| todo['project_id'] }
。 - Kuldeep