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