Por que chamar super em PostSerializer#raw causa um erro 500 enquanto chamar object.raw funciona?

Olá a todos,

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.

Agradeço antecipadamente por qualquer ajuda!

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.

4 curtidas

Você quer usar add_to_serializer em vez disso.

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

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!

Não :roll_eyes: esse não é o caminho

[quote=“RGJ, post:4, topic:390455”]Você quer usar add_to_serializer em vez disso.
[/quote]

2 curtidas

Ah. Certo. Eu sabia disso. Não sei por que essa não foi minha resposta. :person_shrugging:

2 curtidas

Tecnicamente, sua resposta foi a correta, pois explica o erro 500.

1 curtida

Eu respondo à pergunta que ele fez. Você respondeu à pergunta que ele deveria ter feito!

Mas pelo menos eu acertei.

1 curtida