ich lerne gerade, wie man Discourse Serializer erweitert, und bin auf ein Verhalten gestoßen, das ich nicht ganz verstehe.
Ich habe diesen Code hinzugefügt, um PostSerializer#raw zu überschreiben:
require_dependency "post_serializer"
class ::PostSerializer
def raw
if scope.can_edit?(object)
object.raw
else
object.raw&.truncate(300)
end
end
end
Das funktioniert einwandfrei.
Wenn ich es jedoch ändere, um super zu verwenden:
require_dependency "post_serializer"
class ::PostSerializer
def raw
if scope.can_edit?(object)
super
else
object.raw&.truncate(300)
end
end
end
Wenn scope.can_edit?(object)wahr ist, führt der Aufruf von super dazu, dass /posts/id.json einen 500er Fehler zurückgibt.
Ich weiß, dass ich das Problem vermeiden kann, indem ich object.raw anstelle von super verwende, aber ich möchte verstehen, warum super in diesem Fall eine Ausnahme auslöst, insbesondere weil ich auch andere Methoden überschreibe (cooked, post_stream usw.) und super in diesen Fällen einwandfrei funktioniert.
Da ich noch neu in den internen Abläufen von Discourse bin, würde ich mich über eine Erklärung freuen, was:
super innerhalb von PostSerializer#raw tatsächlich auflöst,
warum der Aufruf von super in diesem Fall zu einem 500er Fehler führt,
und warum sich raw anders verhält als Methoden wie cooked.
Ich bin mir ziemlich sicher, dass es daran liegt, dass raw nicht im Serializer für einen normalen Beitrag enthalten ist. Es wird nur dann einbezogen, wenn Sie bearbeiten. Um einen Beitrag anzuzeigen, benötigen Sie nur cooked; es wäre eine Verschwendung, auch raw einzubeziehen, wenn es nicht benötigt wird.
cooked und post_stream sind im Serializer enthalten, daher funktioniert super.
Dies ist ein Feature von Ruby. Wenn Sie class ::PostSerializer verwenden, überschreiben Sie die Definition in der ursprünglichen Klasse, anstatt von ihr zu erben. Da Sie nicht von PostSerializer erben, kann super die entsprechende Methode nicht finden.
Sie sollten prepend verwenden, anstatt eine bereits definierte Klasse erneut zu öffnen.
Danke für die Erklärung!
Sie hatten Recht – das erneute Öffnen von ::PostSerializer war das Problem. Nach dem Wechsel zu prepend funktioniert alles wie erwartet.
Ich verwende jetzt dieses Modul:
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
Das funktioniert auf meiner Seite perfekt. Nochmals vielen Dank für die Anleitung!