Pourquoi appeler super dans PostSerializer#raw provoque une erreur 500 alors que appeler object.raw fonctionne ?

Bonjour à tous,

J’apprends à étendre les serializers de Discourse et je suis tombé sur un comportement que je ne comprends pas entièrement.

J’ai ajouté ce code pour surcharger 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

Cela fonctionne parfaitement.

Cependant, si je le modifie pour utiliser super :

require_dependency "post_serializer"

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

Lorsque scope.can_edit?(object) est vrai, l’appel à super provoque une erreur 500 lors de la requête à /posts/:id.json.

Je sais que je peux éviter le problème en utilisant object.raw au lieu de super, mais je veux comprendre pourquoi super provoque une exception dans ce cas, d’autant plus que je surcharge d’autres méthodes (cooked, post_stream, etc.) et que super fonctionne bien dans ces cas.

Comme je suis encore nouveau dans les mécanismes internes de Discourse, j’apprécierais vraiment une explication sur :

  • à quoi super se résout à l’intérieur de PostSerializer#raw,
  • pourquoi appeler super dans ce cas conduit à une erreur 500,
  • et pourquoi raw se comporte différemment par rapport à des méthodes comme cooked.

Merci d’avance pour toute aide !

Je suis presque certain que c’est parce que raw n’est pas dans le sérialiseur pour un message normal. Ce n’est que lorsque vous modifiez que raw est inclus. Pour afficher un message, vous n’avez besoin que de cooked ; ce serait un gaspillage d’inclure également raw quand ce n’est pas nécessaire.

cooked et post_stream sont dans le sérialiseur, donc super fonctionne.

Ceci est une fonctionnalité de Ruby. Lorsque vous utilisez class ::PostSerializer, vous outrepassez la définition dans la classe originale au lieu d’en hériter. Comme vous n’héritez pas de PostSerializer, super ne peut pas trouver la méthode correspondante.

Vous devriez utiliser prepend au lieu de rouvrir une classe déjà définie.

4 « J'aime »

Vous voulez utiliser add_to_serializer à la place.

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

Merci pour l’explication !
Vous avez raison — rouvrir ::PostSerializer était le problème. Après être passé à prepend, tout fonctionne comme prévu.

J’utilise maintenant ce 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

Cela fonctionne parfaitement de mon côté. Merci encore pour les conseils !

Non :roll_eyes: ce n’est pas la bonne façon

[quote=“RGJ, post:4, topic:390455”]Vous voulez utiliser add_to_serializer à la place.
[/quote]

2 « J'aime »

Ah. C’est vrai. Je le savais. Je ne sais pas pourquoi ce n’était pas ma réponse. :person_shrugging:

2 « J'aime »

Techniquement, votre réponse était la bonne, car elle explique l’erreur 500.

1 « J'aime »

Je réponds à la question qu’il a posée. Vous avez répondu à la question qu’il aurait dû poser !

Mais au moins, j’ai eu la bonne réponse.

1 « J'aime »