active_model_serializers
active_model_serializers copied to clipboard
Integration with awesome_nested_set
So I'm running into an issue currently with serializing nested sets, using the Awesome_nested_set gem. I want to get a Category, and serialize it, all of its children, and their children, down to the bottom, and all of its parents, and their parents, all the way to the top.
Currently I can include some children/parents but can only ascend a designated distance. I can use include: 'children'
or include: 'children.children'
but it only goes so far. If I use include: 'children.**'
to try and include everything I hit an infinite loop because that children will call its parent, and that parent will call its children, etc.
class Category < ApplicationRecord
acts_as_nested_set
has_many :products
has_one :image, as: :parent
end
class CategorySerializer < ActiveModel::Serializer
attributes :id, :name, :image
belongs_to :parent
has_many :children
end
def index
@categories = Category.roots
render json: @categories, include: 'children.children, parent.parent, image'
end
Awesome_nested_set has a method that I can use to get all of the categories in a tree, but instead of nesting them, it places them all into a single array. I need them nested into the JSON so that it can easily be used by our front-end applications.
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]
Rails 5.0.0.1
active_model_serializers (0.10.2)
I hit an infinite loop
yeah, that's why deep nesting isn't recommended :)
Yeah, I've seen that mentioned, was hoping that I was just missing something. So are my best chances to just include a a limited number of children, and hope that it's enough? It can be somwhat regulated and i expect the result to be around 5 or 6 levels deep, but still seems like a rather weird/poor work-around.
in the case of Awesome Nested Set or other tree structures you can also instead just flatten the tree into an array in either of these forms to let the code on the other end reconstruct it into a tree
- parent_id, lft,rgt, ...
- parent_id, position(as the position under the parent, which would be parent.lft-self.lft), ...
I've had some success serializing JSON to reflect a children > children > children ... structure using the following. In my example a Job
has_many :steps, but you may be able to use the same attributes :children
override for your Categories.
class JobSerializer < ActiveModel::Serializer
class StepSerializer < ActiveModel::Serializer
attributes :description, :position
# children attribute provided by awesome_nested_set gem
attributes :children
def children
object.children.map { |child| StepSerializer.new(child) }
end
end
has_many :steps, serializer: StepSerializer
end
There's probably a cleverer & faster way to do this than with .map
, but I've yet to hit an infinite loop and end up with JSON that works well with my front-end.
