Access doorkeeper_token (or current_user) in Active_model_serializers

2.7k Views Asked by At

I'm working on Rails API made with RocketPants. For JSON serializing I use active_model_serializers, and for OAuth - Doorkeeper.

The problem is with accessing current_user helper method in class UserSerializer < ActiveModel::Serializer. Error:

NameError (undefined local variable or method `request' for #<UserSerializer:0xb5892118>)

current_user helper uses this snippet:

User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token

and doorkeeper_token is:

def doorkeeper_token
    methods = Doorkeeper.configuration.access_token_methods
    @token ||= OAuth::Token.authenticate request, *methods
end

So as I find out, there is no request object accessible in Serializer. How can I make it accessible? Or should there be other way to implement current_user?

Thanks in advance

2

There are 2 best solutions below

1
On

I've honestly never really used this stuff, but from looking at the code and documentation, it appears that ActiveModel::Serializer makes the current_user available from the controller but it does so via the scope attribute of the serializer. So within the serializer, if you need to check whether the current_user is an admin, for example, you'd do that like:

if scope.is_admin?
  #your code here
end
4
On

Ok, so the correct answer is to use scope object, included in active-model-serializers. But there were some problems: If I just try to access scope in Serializer - it's nil. I've tried to define it directly through serialization_scope :current_user and got no method error, as such method wasn't included... Then I've included needed module:

class Api::V1::BaseController < RocketPants::Base
    include ActionController::Serialization
    ............

And got strange behaviour: it now was complaining about can't use 'merge' on Nil. Digging into gem's code I've found function

def default_serializer_options
  {
    :url_options => url_options,
    :root        => false
  }
end

, which was overriden in ActionController::Serialization and was empty function there, so that was the point where I got nil.

I've had to change that function to return super - now it wasn't complaining about errors, but then there was still nil instead of scope. This I managed to repair by including :scope => serialization_scope in default_serializer_options. Now I'm able to access scope object as intended.

Still don't know, why it is such a long path with strange patching required, while I can't google any of such cases.

Please, if someone can clear this for me, do it =)