Class: Artemis::Client
- Inherits:
-
Object
- Object
- Artemis::Client
- Includes:
- ActiveSupport::Configurable
- Defined in:
- lib/artemis/client.rb
Instance Attribute Summary collapse
-
#client ⇒ Object
readonly
Returns a plain
GraphQL::Client
object.
Class Method Summary collapse
-
.after_execute(&block) ⇒ Object
Defines a callback that will get called right after the client’s execute method has finished.
-
.before_execute(&block) ⇒ Object
Defines a callback that will get called right before the client’s execute method is executed.
- .connection(context = {}) ⇒ Object
-
.default_context ⇒ Hash
Returns the default configured context or an empty hash by default.
-
.endpoint ⇒ Object
Returns the registered meta data (generally present in
config/graphql.yml
) for the client. - .execute(query, context: {}, **arguments) ⇒ Object
- .graphql_file_paths ⇒ Object
-
.instantiate_client(context = {}) ⇒ Object
Instantiates a new instance of
GraphQL::Client
for the service. -
.load_constant(const_name) ⇒ Object
(also: load_query)
Looks up the GraphQL file that matches the given
const_name
and sets it to a constant. - .multiplex(**context, &block) ⇒ Object
- .namespace ⇒ Object
- .preload! ⇒ Object
- .resolve_graphql_file_path(filename, fragment: false) ⇒ Object
Instance Method Summary collapse
-
#execute(query, context: {}, **arguments) ⇒ GraphQL::Client::Response
Executes a given query, raises if we didn’t define the operation.
-
#initialize(context = {}) ⇒ Client
constructor
Creates a new instance of the GraphQL client for the service.
Constructor Details
#initialize(context = {}) ⇒ Client
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"
58 59 60 |
# File 'lib/artemis/client.rb', line 58 def initialize(context = {}) @client = self.class.instantiate_client(context) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, context: {}, **arguments) ⇒ Object (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
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
320 321 322 323 324 |
# File 'lib/artemis/client.rb', line 320 def method_missing(method_name, context: {}, **arguments) execute(method_name, context: context, **arguments) rescue GraphQLFileNotFound super end |
Instance Attribute Details
#client ⇒ Object (readonly)
Returns a plain GraphQL::Client
object. For more details please refer to the official documentation for graphql-client
gem[https://github.com/github/graphql-client].
37 38 39 |
# File 'lib/artemis/client.rb', line 37 def client @client end |
Class Method Details
.after_execute(&block) ⇒ Object
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
158 159 160 |
# File 'lib/artemis/client.rb', line 158 def after_execute(&block) config.after_callbacks = [*config.after_callbacks, block] end |
.before_execute(&block) ⇒ Object
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
140 141 142 |
# File 'lib/artemis/client.rb', line 140 def before_execute(&block) config.before_callbacks = [*config.before_callbacks, block] end |
.connection(context = {}) ⇒ Object
215 216 217 |
# File 'lib/artemis/client.rb', line 215 def connection(context = {}) Executor.new(endpoint.connection, callbacks, default_context.deep_merge(context)) end |
.default_context ⇒ Hash
Returns the default configured context or an empty hash by default
165 166 167 |
# File 'lib/artemis/client.rb', line 165 def default_context config.default_context || {} end |
.endpoint ⇒ Object
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
101 102 103 |
# File 'lib/artemis/client.rb', line 101 def endpoint Artemis::GraphQLEndpoint.lookup(name) end |
.execute(query, context: {}, **arguments) ⇒ Object
219 220 221 |
# File 'lib/artemis/client.rb', line 219 def execute(query, context: {}, **arguments) new(default_context).execute(query, context: context, **arguments) end |
.graphql_file_paths ⇒ Object
177 178 179 |
# File 'lib/artemis/client.rb', line 177 def graphql_file_paths @graphql_file_paths ||= query_paths.flat_map {|path| Dir["#{path}/#{namespace}/*.graphql"] } end |
.instantiate_client(context = {}) ⇒ Object
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
124 125 126 |
# 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) ⇒ Object Also known as: load_query
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
203 204 205 206 207 208 209 210 211 212 |
# File 'lib/artemis/client.rb', line 203 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 |
.multiplex(**context, &block) ⇒ Object
223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/artemis/client.rb', line 223 def multiplex(**context, &block) queue = MultiplexQueue.new wrapped_executor = Executor.new(queue, callbacks, default_context.deep_merge(context)) api_client = ::GraphQL::Client.new(schema: endpoint.schema, execute: wrapped_executor) service_client = new service_client.instance_variable_set(:@client, api_client) block.call(service_client) connection.multiplex(queue.queries, context: context) end |
.namespace ⇒ Object
181 182 183 |
# File 'lib/artemis/client.rb', line 181 def namespace name.underscore end |
.preload! ⇒ Object
185 186 187 188 189 |
# File 'lib/artemis/client.rb', line 185 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) ⇒ Object
169 170 171 172 173 174 175 |
# File 'lib/artemis/client.rb', line 169 def resolve_graphql_file_path(filename, fragment: false) filename = filename.to_s.underscore graphql_file_paths.detect do |path| path.end_with?("#{namespace}/#{filename}.graphql") || (fragment && path.end_with?("#{namespace}/_#{filename}.graphql")) end end |
Instance Method Details
#execute(query, context: {}, **arguments) ⇒ GraphQL::Client::Response
Executes a given query, raises if we didn’t define the operation
293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/artemis/client.rb', line 293 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 |