I'd like to be able to surface custom variables via JSON that I can access in a view. More specifically, I'd like to add methods to currentUser
. The way this is done currently is by adding new attributes
to the CurrentUserSerializer
. These attributes
are then preloaded as JSON within ApplicationController
. I was hoping I could simply do the following in a plugin to add new attributes:
class CurrentUserSerializer < BasicUserSerializer
attributes :my_custom_attribute
def my_custom_attribute
true
end
end
But what this actually did was override the entire CurrentUserSerializer
and break the app. Sad times. I then tried this, knowing that you can use this method with models to reopen and extend them:
class ::CurrentUserSerializer
attributes :my_custom_attribute
def my_custom_attribute
true
end
end
This ended up with the same result, i.e. overrode entire CurrentUserSerializer
and broke the app. Then I thought maybe what I really needed to do was extend the attributes
method. So, I retried both scenarios above (i.e. class CurrentUserSerializer < BasicUserSerializer
and class ::CurrentUserSerializer
) with the following code in a plugin:
def attributes
hash = super
hash['my_custom_attribute'] = true
hash
end
App broke once again...
So that really left me with two options:
- Completely monkey-patch
CurrentUserSerializer
. This works, but the downside here is that if Discourse's CurrentUserSerializer
changes, then my app breaks. Not a good option, IMO.
- Create a new serializer called
MyCurrentUserSerializer
that inherits from CurrentUserSerializer
so that I can override MyCurrentUserSerializer
in a plugin and still keep all the goodness of CurrentUserSerializer
intact. Here's what that would look like:
app/serializers/my_current_user_serializer.rb
class MyCurrentUserSerializer < CurrentUserSerializer; end
app/controllers/application_controller.rb
def preload_current_user_data
store_preloaded("currentUser", MultiJson.dump(MyCurrentUserSerializer.new(current_user, scope: guardian, root: false)))
serializer = ActiveModel::ArraySerializer.new(TopicTrackingState.report([current_user.id]), each_serializer: TopicTrackingStateSerializer)
store_preloaded("topicTrackingStates", MultiJson.dump(serializer))
end
app/controllers/session_controller.rb
def current
if current_user.present?
render_serialized(current_user, MyCurrentUserSerializer)
else
render nothing: true, status: 404
end
end
Then, in my plugin, I can simply do the following and everything works!
class MyCurrentUserSerializer < CurrentUserSerializer
def attributes
hash = super
hash['my_custom_attribute'] = true
hash
end
end
So the question for you, Discourse team, is would you accept this PR if I submitted it? If not, what would you suggest I do instead? Thanks!