class Artemis::Client

Attributes

client[R]

Returns a plain GraphQL::Client object. For more details please refer to the official documentation for {the graphql-client gem}[https://github.com/github/graphql-client].

Public Class Methods

after_execute(&block) click to toggle source

Defines a callback that will get called right after the client's execute method has finished.

class Github < Artemis::Client

  after_execute do |data, errors, extensions|
    if errors.present?
      Rails.logger.error(errors.to_json)
    end
  end

  ...
end
# File lib/artemis/client.rb, line 158
def after_execute(&block)
  config.after_callbacks = [*config.after_callbacks, block]
end
before_execute(&block) click to toggle source

Defines a callback that will get called right before the client's execute method is executed.

class Github < Artemis::Client

  before_execute do |document, operation_name, variables, context|
    Analytics.log(operation_name, variables, context[:user_id])
  end

  ...
end
# File lib/artemis/client.rb, line 140
def before_execute(&block)
  config.before_callbacks = [*config.before_callbacks, block]
end
connection(context = {}) click to toggle source
# File lib/artemis/client.rb, line 213
def connection(context = {})
  Executor.new(endpoint.connection, callbacks, default_context.deep_merge(context))
end
default_context() click to toggle source

Returns the default configured context or an empty hash by default

@return [Hash]

# File lib/artemis/client.rb, line 165
def default_context
  config.default_context || {}
end
endpoint() click to toggle source

Returns the registered meta data (generally present in config/graphql.yml) for the client.

# config/graphql.yml
development:
  github:
    url:     https://api.github.com/graphql
    adapter: :net_http

# app/operations/github.rb
class Github < Artemis::Client
end

Github.endpoint.url     # => "https://api.github.com/graphql"
Github.endpoint.adapter # => :net_http
# File lib/artemis/client.rb, line 101
def endpoint
  Artemis::GraphQLEndpoint.lookup(name)
end
execute(query, context: {}, **arguments) click to toggle source
# File lib/artemis/client.rb, line 217
def execute(query, context: {}, **arguments)
  new(default_context).execute(query, context: context, **arguments)
end
graphql_file_paths() click to toggle source
# File lib/artemis/client.rb, line 179
def graphql_file_paths
  @graphql_file_paths ||= query_paths.flat_map {|path| Dir["#{path}/#{name.underscore}/*.graphql"] }
end
instantiate_client(context = {}) click to toggle source

Instantiates a new instance of GraphQL::Client for the service.

# app/operations/github/user.graphql
query($id: String!) {
  user(login: $id) {
    name
  }
}

# app/operations/github.rb
class Github < Artemis::Client
end

client = Github.instantiate_client
client.query(Github::User, arguments: { id: 'yuki24' }) # makes a Graphql request

client = Github.instantiate_client(context: { headers: { Authorization: "bearer ..." } })
client.query(Github::User, arguments: { id: 'yuki24' }) # makes a Graphql request with Authorization header
# File lib/artemis/client.rb, line 124
def instantiate_client(context = {})
  ::GraphQL::Client.new(schema: endpoint.schema, execute: connection(context))
end
load_constant(const_name) click to toggle source

Looks up the GraphQL file that matches the given const_name and sets it to a constant.

# app/operations/github.rb
class Github < Artemis::Client
end

defined?(Github::User)      # => nil
Github.load_constant(:User) # => loads an operation definition from app/operations/github/user.graphql
defined?(Github::User)      # => 'constant'

Github.load_constant(:None) # => nil
# File lib/artemis/client.rb, line 201
def load_constant(const_name)
  graphql_file = resolve_graphql_file_path(const_name.to_s.underscore, fragment: true)

  if graphql_file
    graphql = File.open(graphql_file).read
    ast     = instantiate_client.parse(graphql)

    const_set(const_name, ast)
  end
end
Also aliased as: load_query
load_query(const_name)
Alias for: load_constant
new(context = {}) click to toggle source

Creates a new instance of the GraphQL client for the service.

# app/operations/github/user.graphql
query($id: String!) {
  user(login: $id) {
    name
  }
}

# app/operations/github.rb
class Github < Artemis::Client
end

github = Github.new
github.user(id: 'yuki24').data.user.name # => "Yuki Nishijima"

github = Github.new(context: { headers: { Authorization: "bearer ..." } })
github.user(id: 'yuki24').data.user.name # => "Yuki Nishijima"
# File lib/artemis/client.rb, line 58
def initialize(context = {})
  @client = self.class.instantiate_client(context)
end
Also aliased as: with_context
preload!() click to toggle source
# File lib/artemis/client.rb, line 183
def preload!
  graphql_file_paths.each do |path|
    load_constant(File.basename(path, File.extname(path)).camelize)
  end
end
resolve_graphql_file_path(filename, fragment: false) click to toggle source
# File lib/artemis/client.rb, line 169
def resolve_graphql_file_path(filename, fragment: false)
  namespace = name.underscore
  filename  = filename.to_s.underscore

  graphql_file_paths.detect do |path|
    path.end_with?("#{namespace}/#{filename}.graphql") ||
      (fragment && filename.end_with?('fragment') && path.end_with?("#{namespace}/_#{filename}.graphql"))
  end
end
with_context(context = {})

Creates a new instance of the GraphQL client for the service.

# app/operations/github/user.graphql
query($id: String!) {
  user(login: $id) {
    name
  }
}

# app/operations/github.rb
class Github < Artemis::Client
end

github = Github.new
github.user(id: 'yuki24').data.user.name # => "Yuki Nishijima"

github = Github.new(context: { headers: { Authorization: "bearer ..." } })
github.user(id: 'yuki24').data.user.name # => "Yuki Nishijima"
Alias for: new

Private Class Methods

callbacks() click to toggle source

Returns a Callbacks collection object that implements the interface for the Executor object.

@api private

# File lib/artemis/client.rb, line 266
def callbacks
  Callbacks.new(config.before_callbacks, config.after_callbacks)
end
const_missing(const_name) click to toggle source

Looks up the GraphQL file that matches the given const_name and sets it to a constant. If the files it not found it will raise an NameError.

# app/operations/github.rb
class Github < Artemis::Client
end

defined?(Github::User) # => nil
Github::User           # => loads an operation definition from app/operations/github/user.graphql
defined?(Github::User) # => 'constant'

Github::DoesNotExist   # => raises an NameError

@api private

Calls superclass method
# File lib/artemis/client.rb, line 237
def const_missing(const_name)
  load_constant(const_name) || super
end
method_missing(method_name, **arguments, &block) click to toggle source

Delegates a class method call to an instance method call, which in turn looks up the GraphQL file that matches the given method_name and delegates the call to it.

# app/operations/github.rb
class Github < Artemis::Client
end

Github.user # => delegates to Github.new(default_context).user

@api private

Calls superclass method
# File lib/artemis/client.rb, line 251
def method_missing(method_name, **arguments, &block)
  if resolve_graphql_file_path(method_name)
    new(default_context).public_send(method_name, **arguments, &block)
  else
    super
  end
end

Public Instance Methods

execute(query, context: {}, **arguments) click to toggle source

Executes a given query, raises if we didn't define the operation

@param [String] operation @param [Hash] context @param [Hash] arguments

@return [GraphQL::Client::Response]

# File lib/artemis/client.rb, line 278
def execute(query, context: {}, **arguments)
  if self.class.resolve_graphql_file_path(query)
    const_name = query.to_s.camelize

    # This check will be unnecessary once we drop support for Ruby 2.4 and earlier
    if !self.class.const_get(const_name).is_a?(GraphQL::Client::OperationDefinition)
      self.class.load_constant(const_name)
    end

    client.query(self.class.const_get(const_name), variables: arguments, context: context)
  else
    raise GraphQLFileNotFound.new("Query #{query}.graphql not found in: #{query_paths.join(", ")}")
  end
end

Private Instance Methods

method_missing(method_name, context: {}, **arguments) click to toggle source

Delegates a method call to a GraphQL call.

# app/operations/github.rb
class Github < Artemis::Client
end

github = Github.new
github.user # => delegates to app/operations/github/user.graphql

@api private

Calls superclass method
# File lib/artemis/client.rb, line 305
def method_missing(method_name, context: {}, **arguments)
  execute(method_name, context: context, **arguments)
rescue GraphQLFileNotFound
  super
end