我在rails中使用active_model_serializer
。我有两个序列化程序:TodoSerializer
和ProjectSerializer
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 #<Hash:0x007fbec2241660>
答案 0 :(得分:3)
我遇到了类似的问题并制定了一个我觉得可以接受的解决方案:
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