ruby-on-railsruby-on-rails-5graphqlgraphql-ruby

How to pass :current_user in Graphql resolver


I have QueryType

Types::QueryType = GraphQL::ObjectType.define do
  name 'Query'

  field :allProjects, function: Resolvers::Projects
end

And Resolver like this

require 'search_object/plugin/graphql'

module Resolvers
  class Projects
    include SearchObject.module(:graphql)

    type !types[Types::ProjectType]

    scope { Project.all }

    ProjectFilter = GraphQL::InputObjectType.define do
      name 'ProjectFilter'

      argument :OR, -> { types[ProjectFilter] }
      argument :description_contains, types.String
      argument :title_contains, types.String
    end

    option :filter, type: ProjectFilter, with: :apply_filter
    option :first, type: types.Int, with: :apply_first
    option :skip, type: types.Int, with: :apply_skip

    def apply_first(scope, value)
      scope.limit(value)
    end

    def apply_skip(scope, value)
      scope.offset(value)
    end

    def apply_filter(scope, value)
      branches = normalize_filters(value).reduce { |a, b| a.or(b) }
      scope.merge branches
    end

    def normalize_filters(value, branches = [])
      scope = Project.all
      scope = scope.where('description ILIKE ?', "%#{value['description_contains']}%") if value['description_contains']
      scope = scope.where('title ILIKE ?', "%#{value['title_contains']}%") if value['title_contains']
      branches << scope

      value['OR'].reduce(branches) { |s, v| normalize_filters(v, s) } if value['OR'].present?
      branches
    end
  end
end

I want to access current_user in the resolver so i can access current_user.projects not Project.all. I am very new to graphql and learning.

Everything works but i just need to understand the whole flow on how i can get old of the ctx in the resolver.


Solution

  • First you need to set the current_user in the context. This happens in your GraphqlController.

    class GraphqlController < ApplicationController
      before_action :authenticate_user!
    
      def execute
        variables = ensure_hash(params[:variables])
        query = params[:query]
        operation_name = params[:operationName]
        context = {
          current_user: current_user,
        }
        result = HabitTrackerSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
        render json: result
      rescue => e
        raise e unless Rails.env.development?
        handle_error_in_development e
      end
    
      # ...
    end
    

    Once it's done, you can access the current_user from a query (or a mutation) simply by writing:

    context[:current_user]
    

    To make things even simpler, you can add a current_user method toTypes::BaseObject (app/graphql/types/base_object.rb) and you'll be able to call current_user from the #resolve methods.

    module Types
      class BaseObject < GraphQL::Schema::Object
        field_class Types::BaseField
    
        def current_user
          context[:current_user]
        end
      end
    end