Forwarding the `scope:` down a tree of serializers: just do it, or not?

Serializers can be provided with a scope: parameter intended to provide the permissions-context for the serializer. In the Discourse code, the provided scope is a Guardian, and it looks like every serializer is intended to receive a Guardian as its scope. ApplicationController (the base class of all the controllers) maintains a Guardian and it has multiple mechanisms to try to ensure that Guardian is injected as the scope: for all serializers.

However, not every scenario is not covered by these mechanisms. Whenever a serializer is explictly constructed, e.g., calls to ActiveModel::ArraySerializer.new(...), then the scope needs to be injected manually. Indeed, most instances of XxxxSerializer.new(...) have a scope: scope or scope: guardian in the argument list. But, not all of them.

So, my question: what is the development philosophy here? Is it:

  1. Scope should simply always be forwarded (unless there is a specific reason not to); if someone forgot to do that, it is a bug-waiting-to-happen and should get fixed with an appropriate scope: ... added; OR
  2. Yeah, that is fine; someone can fix those spots as they come up when they actually break something for someone.

In my case, I added a use of scope to BasicUserSerializer… and then was sorely perplexed when I discovered that it broke things in Chat… which I finally realized (after way too much digging) was a result of some serializer buried in a chain XxxSerializer -> YyySerializer -> ... -> BasicUserSerializer not forwarding the scope!

1 Like