Search code examples
ruby-on-railsrubyactive-model-serializersrails-api

How to access @current_user variable defined in ApplicationController inside of Serializer


I'm using Active Model Serializers.

I am trying to access @current_user which is defined inside ApplicationController like this:

class ApplicationController < ActionController::API
  before_action :authenticate_request

  private
  def authenticate_request
    auth_header = request.headers['Authorization']
    regex = /^Bearer /
    auth_header = auth_header.gsub(regex, '') if auth_header
    begin
      @current_user = AccessToken.get_user_from_token(auth_header)
    rescue JWT::ExpiredSignature
      return render json: {error: "Token expired"}, status: 401
    end
    render json: { error: 'Not Authorized' }, status: 401 unless @current_user
  end
end

I can use @current_user anywhere I want except inside my ProjectSerializer, which looks like this:

class V1::ProjectSerializer < ActiveModel::Serializer
  attributes(:id, :name, :key, :type, :category, :created_at)
  attribute :is_favorited
  belongs_to :user, key: :lead

  def is_favorited
    if object.favorited_by.where(user_id: @current_user.id).present?
      return true
    else
      return false
    end
  end

end

ProjectSerializer is located in my app/ project tree structure:

app/
  serializers/
    v1/
      project_serializer.rb

I get an error trying to access @current_user:

NoMethodError in V1::UsersController#get_current_user
undefined method `id' for nil:NilClass 

This happens when I'm calling the function from UserController, which then goes to UserSerializer and then that serializer has has_many :projects field which calls ProjectSerializer.


Solution

  • You can access the variables using instance_options. I believe you can access @current_user in projects controller. For example :

    def projects
      @projects = Project.all
      render_json: @projects, serializer: ProjectSerializer, current_user: @current_user
    end
    

    Inside the serializer you can access the current_user like wise:

     def is_favorited
        if object.favorited_by.where(user_id: @instance_options[:current_user].id).present?
          return true
        else
          return false
        end
      end