Why does calling super in PostSerializer#raw cause a 500 error while calling object.raw works?

Hi everyone,

I’m learning how to extend Discourse serializers, and I ran into a behavior that I don’t fully understand.

I added this code to override PostSerializer#raw:

require_dependency "post_serializer"

class ::PostSerializer
  def raw
    if scope.can_edit?(object)
      object.raw
    else
      object.raw&.truncate(300)
    end
  end
end

This works perfectly.

However, if I change it to use super:

require_dependency "post_serializer"

class ::PostSerializer
  def raw
    if scope.can_edit?(object)
      super
    else
      object.raw&.truncate(300)
    end
  end
end

When scope.can_edit?(object) is true, the call to super causes /posts/<id>.json to return a 500 error.

I know I can avoid the problem by using object.raw instead of super, but I want to understand why super causes an exception here, especially because I also override other methods (cooked, post_stream, etc.) and super works fine in those cases.

Since I’m still new to Discourse internals, I would really appreciate an explanation of:

  • what super actually resolves to inside PostSerializer#raw,
  • why calling super in this case leads to a 500 error,
  • and why raw behaves differently compared to methods like cooked.

Thanks in advance for any help!

I’m pretty sure it’s because raw isn’t in the serializer for a normal post. It’s only when you edit that raw is included. To display a post you need only cooked; it would be a waste to also include raw when it’s not needed.

cooked and post stream are in the serializer, so super works.

This is a feature of Ruby. When you use class ::PostSerializer, you are overriding the definition in the original class instead of inheriting from it. Because you are not inheriting from PostSerializer, super cannot find the corresponding method.

You should use prepend instead of reopening an already defined class.

4 likes

You want to use add_to_serializer instead.

E.g. How to add user data to the post serializer?

Thanks for the explanation!
You’re right — reopening ::PostSerializer was the issue. After switching to prepend, everything works as expected.

I’m now using this module:

module PostSerializerExtension
  def raw
    if scope.can_edit?(object)
      super
    else
      object.raw&.truncate(300)
    end
  end
end

reloadable_patch do
  require_dependency "post_serializer"
  ::PostSerializer.prepend(::PostSerializerExtension)
end

This works perfectly on my side. Thanks again for the guidance!

No :roll_eyes: that is not the way

2 likes

Oh. Right. I knew that. Not sure why that wasn’t my answer. :person_shrugging:

2 likes

Technically, your answer was the correct one, since it explains the 500 error.

1 like

I answer the question he asked. You answered the question he should have asked!

But at least I got it right.

1 like