Estou aprendendo a estender os serializadores do Discourse e encontrei um comportamento que não entendo completamente.
Adicionei este código para sobrescrever 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
Isso funciona perfeitamente.
No entanto, se eu mudar 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
Quando scope.can_edit?(object) é verdadeiro, a chamada para super faz com que /posts/:id.json retorne um erro 500.
Eu sei que posso evitar o problema usando object.raw em vez de super, mas quero entender por que super causa uma exceção aqui, especialmente porque eu também sobrescrevo outros métodos (cooked, post_stream, etc.) e super funciona bem nesses casos.
Como ainda sou novo nos internos do Discourse, agradeceria muito uma explicação sobre:
a que super se resolve dentro de PostSerializer#raw,
por que chamar super neste caso leva a um erro 500,
e por que raw se comporta de maneira diferente em comparação com métodos como cooked.
Tenho quase certeza de que é porque raw não está no serializador para uma postagem normal. É apenas quando você edita que o raw é incluído. Para exibir uma postagem, você precisa apenas do cooked; seria um desperdício incluir também o raw quando não é necessário.
cooked e post_stream estão no serializador, então super funciona.
Este é um recurso do Ruby. Quando você usa class ::PostSerializer, você está sobrescrevendo a definição na classe original em vez de herdar dela. Como você não está herdando de PostSerializer, super não consegue encontrar o método correspondente.
Você deve usar prepend em vez de reabrir uma classe já definida.
Obrigado pela explicação!
Você está certo — reabrir ::PostSerializer era o problema. Depois de mudar para prepend, tudo funciona como esperado.
Estou usando este módulo agora:
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
Isso funciona perfeitamente do meu lado. Obrigado novamente pela orientação!