discourse/discourse — pull request #1995 by shivpkumar (2014-02-21 19:34:08+00:00)
Title: Extending CurrentUserSerializer functionality

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:

```ruby
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:

```ruby
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:

```ruby
def attributes
hash = super
hash['my_custom_attribute'] = true
hash
end
```

App broke once again... :frowning:

So that really left me with two options:

1. 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.
2. 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

```ruby
class MyCurrentUserSerializer < CurrentUserSerializer; end
```

###app/controllers/application_controller.rb

```ruby
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

```ruby
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!

```ruby
class MyCurrentUserSerializer < CurrentUserSerializer

def attributes
hash = super
hash['my_custom_attribute'] = true
hash
end
end
```