class GraphQL::Rails::Resolver

Constants

VERSION

Attributes

resolvers[RW]

Public Class Methods

id_field(value=nil) click to toggle source
# File lib/graphql/rails/resolver.rb, line 224
def id_field(value=nil)
  @@id_field = value if value.present?
  @@id_field
end
new(callable=nil) click to toggle source
# File lib/graphql/rails/resolver.rb, line 8
def initialize(callable=nil)
  unless callable.nil?
    raise ArgumentError, "Resolver requires a callable type or nil" unless callable.respond_to? :call
  end

  @callable =
    if callable.present?
      callable
    else
      Proc.new { |obj|
        subfield = model.name.underscore.pluralize
        if obj.respond_to? subfield
          obj.send(subfield)
        else
          model.all
        end
      }
    end

  @obj = nil
  @args = nil
  @ctx = nil
  @resolvers = self.class.resolvers
  @id_field = self.class.id_field
end
resolve(arg, definition=nil, **otherArgs) click to toggle source
# File lib/graphql/rails/resolver.rb, line 234
def resolve(arg, definition=nil, **otherArgs)
  @resolvers ||= {}
  @resolvers[arg] ||= []
  @resolvers[arg].push([definition, otherArgs])
end
resolve_method(arg) click to toggle source
# File lib/graphql/rails/resolver.rb, line 253
def resolve_method(arg)
  warn "[DEPRECATION] `resolve_method` is deprecated.  Please use `resolve` instead."
  resolve(arg)
end
resolve_scope(arg, test=nil, scope_name: nil, with_value: false) click to toggle source
# File lib/graphql/rails/resolver.rb, line 245
def resolve_scope(arg, test=nil, scope_name: nil, with_value: false)
  warn "[DEPRECATION] `resolve_scope` is deprecated.  Please use `resolve` instead."
  test = lambda { |value| value.present? } if test.nil?
  scope_name = arg if scope_name.nil?

  resolve(arg, :scope => -> (value) { test.call(value) ? scope_name : nil }, :with_value => with_value)
end
resolve_where(arg) click to toggle source
# File lib/graphql/rails/resolver.rb, line 240
def resolve_where(arg)
  warn "[DEPRECATION] `resolve_where` is deprecated.  Please use `resolve` instead."
  resolve(arg)
end
resolvers() click to toggle source
# File lib/graphql/rails/resolver.rb, line 229
def resolvers
  @resolvers ||= {}
  @resolvers
end

Public Instance Methods

call(obj, args, ctx) click to toggle source
# File lib/graphql/rails/resolver.rb, line 34
def call(obj, args, ctx)
  @obj = obj
  @args = args
  @ctx = ctx

  @result = @callable.call(obj, args, ctx)

  # If there's an ID type, offer ID resolution_strategy
  if has_id_argument? and args.key? @id_field
    @result = resolve_id(args[@id_field])
  end

  @resolvers.each do |arg, resolvers|
    if args.key? arg
      original_value = args[arg]

      resolvers.each do |method, params|
        next unless condition_met?(params.fetch(:if, nil), true, original_value)
        next unless condition_met?(params.fetch(:unless, nil), false, original_value)
        value = map_value(params.fetch(:map, nil), original_value)

        # Match scopes
        if params.key? :scope
          scope_name = params[:scope]
          scope_name = scope_name.call(value) if scope_name.respond_to? :call

          scope_args = []
          scope_args.push(value) if params.key? :with_value and params[:with_value] == true

          @result = @result.send(scope_name, *scope_args) unless scope_name.nil?
        # Match custom methods
        elsif params.key? :method
          @result = send(params[:method], value)
        elsif method.present?
          # Match first param
          if method.respond_to? :call
            # Match implicit blocks
            @result = method.call(value)
          elsif self.respond_to? method
            # Match method name to current resolver class
            @result = send(method, value)
          elsif @result.respond_to? method
            # Match method name to object
            @result = @result.send(method, value)
          else
            raise ArgumentError, "Unable to resolve parameter of type #{method.class} in #{self}"
          end
        else
          # Resolve ID arguments
          if is_arg_id_type? arg
            value = resolve_id(value)
          end

          if self.respond_to? arg and params[:where].present? == false
            @result = send(arg, value)
          elsif @result.respond_to? arg and params[:where].present? == false
            @result = @result.send(arg, value)
          elsif @result.respond_to? :where
            attribute =
              if params[:where].present?
                params[:where]
              else
                arg
              end

            unless @result.has_attribute?(attribute)
              raise ArgumentError, "Unable to resolve attribute #{attribute} on #{@result}"
            end

            hash = {}
            hash[attribute] = value
            @result = @result.where(hash)
          else
            raise ArgumentError, "Unable to resolve argument #{arg} in #{self}"
          end
        end
      end
    end
  end

  result = payload

  @obj = nil
  @args = nil
  @ctx = nil

  result
end
condition_met?(conditional, expectation, value) click to toggle source
# File lib/graphql/rails/resolver.rb, line 201
def condition_met?(conditional, expectation, value)
  if conditional.respond_to? :call
    conditional.call(value) == expectation
  elsif (conditional.is_a?(Symbol) || conditional.is_a?(String)) && self.respond_to?(conditional)
    self.send(conditional, value) == expectation
  else
    true
  end
end
connection?() click to toggle source
# File lib/graphql/rails/resolver.rb, line 158
def connection?
  @ctx.irep_node.definitions.all? { |field_defn| field_defn.resolve_proc.is_a?(GraphQL::Relay::ConnectionResolve) }
end
field_name() click to toggle source
# File lib/graphql/rails/resolver.rb, line 132
def field_name
  @ctx.ast_node.name
end
get_arg_type(key) click to toggle source
# File lib/graphql/rails/resolver.rb, line 170
def get_arg_type(key)
  args = get_field_args
  args[key].type
end
get_field_args() click to toggle source
# File lib/graphql/rails/resolver.rb, line 166
def get_field_args
  @ctx.irep_node.parent.return_type.get_field(@ctx.irep_node.definition_name).arguments
end
has_id_argument() click to toggle source
# File lib/graphql/rails/resolver.rb, line 148
def has_id_argument
  warn "[DEPRECATION] `has_id_argument` is deprecated.  Please use `has_id_argument?` instead."
  has_id_argument?
end
has_id_argument?() click to toggle source
# File lib/graphql/rails/resolver.rb, line 136
def has_id_argument?
  @ctx.irep_node.definitions.any? do |field_defn|
    if field_defn.name === field_name
      field_defn.arguments.any? do |k,v|
        is_field_id_type?(v.type)
      end
    else
      false
    end
  end
end
has_id_field() click to toggle source
# File lib/graphql/rails/resolver.rb, line 153
def has_id_field
  warn "[DEPRECATION] `has_id_field` is deprecated.  Please use `has_id_argument` instead."
  has_id_argument?
end
is_arg_id_type?(key) click to toggle source
# File lib/graphql/rails/resolver.rb, line 181
def is_arg_id_type?(key)
   is_field_id_type?(get_arg_type(key))
end
is_field_id_type?(field) click to toggle source
# File lib/graphql/rails/resolver.rb, line 175
def is_field_id_type?(field)
   field == ::GraphQL::ID_TYPE ||
        (field.kind == ::GraphQL::TypeKinds::LIST && field.of_type == ::GraphQL::ID_TYPE) ||
        (field.kind == ::GraphQL::TypeKinds::NON_NULL && field.of_type == ::GraphQL::ID_TYPE)
end
list?() click to toggle source
# File lib/graphql/rails/resolver.rb, line 162
def list?
  @ctx.irep_node.definitions.all? { |field_defn| field_defn.type.kind.eql?(GraphQL::TypeKinds::LIST) }
end
map_value(mapper, value) click to toggle source
# File lib/graphql/rails/resolver.rb, line 211
def map_value(mapper, value)
  if mapper.respond_to? :call
    mapper.call(value)
  elsif (mapper.is_a?(Symbol) || mapper.is_a?(String)) && self.respond_to?(mapper)
    self.send(mapper, value)
  else
    value
  end
end
model() click to toggle source
# File lib/graphql/rails/resolver.rb, line 185
def model
  unless self.class < Resolvers::Base
    raise ArgumentError, "Cannot call `model` on BaseResolver"
  end

  "::#{self.class.name.demodulize}".constantize
end
payload() click to toggle source
# File lib/graphql/rails/resolver.rb, line 123
def payload
  # Return all results if it's a list or a connection
  if connection? or list?
    @result
  else
    @result.first
  end
end
resolve_id(value) click to toggle source
# File lib/graphql/rails/resolver.rb, line 193
def resolve_id(value)
  if value.kind_of? Array
    value.compact.map { |v| @ctx.schema.object_from_id(v, @ctx) }.compact
  else
    @ctx.schema.object_from_id(value, @ctx)
  end
end