¿Por qué llamar a super en PostSerializer#raw causa un error 500 mientras que llamar a object.raw funciona?

Hola a todos,

Estoy aprendiendo a extender los serializadores de Discourse y me encontré con un comportamiento que no entiendo del todo.

Agregué este código para sobrescribir 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

Esto funciona perfectamente.

Sin embargo, si lo cambio para usar super:

require_dependency "post_serializer"

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

Cuando scope.can_edit?(object) es true, la llamada a super provoca un error 500 en /posts/:id.json.

Sé que puedo evitar el problema usando object.raw en lugar de super, pero quiero entender por qué super causa una excepción en este caso, especialmente porque también sobrescribo otros métodos (cooked, post_stream, etc.) y super funciona bien en esos casos.

Como todavía soy nuevo en el funcionamiento interno de Discourse, agradecería mucho una explicación de:

  • a qué resuelve super dentro de PostSerializer#raw,
  • por qué llamar a super en este caso conduce a un error 500,
  • y por qué raw se comporta de manera diferente en comparación con métodos como cooked.

¡Gracias de antemano por cualquier ayuda!

Estoy bastante seguro de que se debe a que raw no está en el serializador para una publicación normal. Solo cuando editas se incluye raw. Para mostrar una publicación solo necesitas cooked; sería un desperdicio incluir también raw cuando no es necesario.

cooked y post_stream están en el serializador, por lo que super funciona.

Esta es una característica de Ruby. Cuando usas class ::PostSerializer, estás sobrescribiendo la definición en la clase original en lugar de heredar de ella. Como no estás heredando de PostSerializer, super no puede encontrar el método correspondiente.

Deberías usar prepend en lugar de reabrir una clase ya definida.

4 Me gusta

Quieres usar add_to_serializer en su lugar.

Ejemplo: How to add user data to the post serializer?

¡Gracias por la explicación!
Tienes razón: reabrir ::PostSerializer era el problema. Después de cambiar a prepend, todo funciona como se espera.

Ahora estoy usando este módulo:

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

Esto funciona perfectamente de mi lado. ¡Gracias de nuevo por la guía!

No :roll_eyes: esa no es la manera

2 Me gusta

Oh. Cierto. Sabía eso. No estoy seguro de por qué esa no fue mi respuesta. :person_shrugging:

2 Me gusta

Técnicamente, tu respuesta fue la correcta, ya que explica el error 500.

1 me gusta

Respondo a la pregunta que él hizo. ¡Tú respondiste a la pregunta que él debería haber hecho!

Pero al menos lo hice bien.

1 me gusta