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.
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.
¡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!