Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rendering recursive relations #144

Open
daniel-koudouna opened this issue Oct 8, 2023 · 2 comments
Open

Rendering recursive relations #144

daniel-koudouna opened this issue Oct 8, 2023 · 2 comments
Labels

Comments

@daniel-koudouna
Copy link

daniel-koudouna commented Oct 8, 2023

Hi,

I'm trying to serialize this object, which may contain instances of itself as children, e.g:

class Comment < ApplicationRecord
  belongs_to :parent, class_name: 'Comment', optional: true, inverse_of: :children
  belongs_to :user
  has_many :children, class_name: 'Comment', inverse_of: :parent, foreign_key: 'parent_id'

  ...
end

class CommentSerializer < Panko::Serializer
  attributes :id, :body, :tag, :created_at

  has_one :user, serializer: UserBasicSerializer
  has_many :children, serializer: 'CommentSerializer'

  delegate :tag, to: :object
end

This works on the root object, which has an array of children, but the children comments do not themselves have any children render. The "children" field is completely absent from the json response.

I was reading issue #73 which is related, has there been any progress on this?

EDIT: Using a string for the class name does not resolve the issue.

@daniel-koudouna
Copy link
Author

As an update, I was able to recursively render children of the same model by defining them as an attribute and using a method as below:

# frozen_string_literal: true

class CommentSerializer < Panko::Serializer
  attributes :id, :children

  def children
    Panko::ArraySerializer.new(object.children, each_serializer: CommentSerializer).to_a
  end
end

I am not sure what the impact to performance this would have, but it seems to be working with no issues for now. Let me know if there is a better way of doing this, I would think this is quite a common use case.

@yosiat
Copy link
Owner

yosiat commented Oct 23, 2023

Hey @daniel-koudouna !

First I am sorry for long reply time, I have looked at the bug here and looks like this happen because I am building a "serialization descriptor" (contains attributes, associations and their serializer info) ahead of time and not lazily, from first look it looks like a big one to fix.

I'll try to experiment with multiple options to solve this, but don't have promise of solution for the near-time.

Regarding your suggested solution, it works, but it's not efficient as it could be, since has_many builds the json-string incrementally (using Oj::StringWriter) and with your approach it will serialize the children to array of hashes and then to JSON. I might be able to have quick release to address by doing something like:

class CommentSerializer < Panko::Serializer
  attributes :id, :children

  def children
     serialized_json = Panko::ArraySerializer.new(object.children, each_serializer: CommentSerializer).to_json
     Panko::JsonValue.from(serialized_json)
  end
end

which will be more efficient, if this something that interests you, let me know and I'll work on it.

@yosiat yosiat added the bug label Oct 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants