在 PostSerializer#raw 中调用 super 导致 500 错误,而调用 object.raw 却可以工作的原因是什么?

大家好,

我正在学习如何扩展 Discourse 的序列化器(serializer),遇到了一个我不完全理解的行为。

我添加了以下代码来覆盖 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

这运行得非常完美。

然而,如果我将其更改为使用 super

require_dependency "post_serializer"

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

scope.can_edit?(object)时,调用 super 导致 /posts/:id.json 返回 500 错误

我知道通过使用 object.raw 而不是 super 可以避免这个问题,但我很想了解为什么在这种情况下调用 super 会导致 500 错误,特别是考虑到我也覆盖了其他方法(如 cookedpost_stream 等),并且在那些情况下调用 super 运行正常。

由于我对 Discourse 的内部机制还不太熟悉,我非常希望能得到以下方面的解释:

  • superPostSerializer#raw 内部实际解析为什么;
  • 为什么在这种情况下调用 super 会导致 500 错误;
  • 为什么 raw 的行为与 cooked 等方法不同。

提前感谢任何帮助!

我非常确定这是因为 raw 不在普通帖子的序列化器中。只有在编辑时才会包含 raw。要显示帖子,只需要 cooked;在不需要 raw 的情况下也包含它是一种浪费。

cookedpost_stream 都在序列化器中,所以 super 可以正常工作。

这是 Ruby 的一个特性。当你使用 class ::PostSerializer 时,你是在覆盖原始类中的定义,而不是继承它。因为你没有继承 PostSerializer,所以 super 找不到相应的方法。

你应该使用 prepend 而不是重新打开一个已定义的类。

4 个赞

您想改用 add_to_serializer

例如:How to add user data to the post serializer?

感谢您的解释!
您说得对——重新打开 ::PostSerializer 是问题所在。改用 prepend 后,一切都按预期工作了。

我现在使用的是这个模块:

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

这在我这边完美运行。再次感谢您的指导!

没有 :roll_eyes: 那不是正确的方法

2 个赞

哦。对。我知道的。不确定为什么那不是我的答案。:person_shrugging:

2 个赞

从技术上讲,你的答案是正确的,因为它解释了 500 错误。

1 个赞

我回答了他问的问题。你回答了他本该问的问题!

但至少我答对了。

1 个赞