Skip to content

wakoopa/activegraphql

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ActiveGraphQL

Build Status

ActiveGraphQL connects classes to GraphQL services.

Installation

Add this line to your application's Gemfile:

gem 'activegraphql'

And then execute:

$ bundle

How it works?

The library provides an ActiveGraphQL::Model class that, when subclassed and configured, encapsulates the communication with the service.

class MyModel < ActiveGraphQL::Model
  configure url: 'http://some-graphql-service/endpoint'
end

Any subclass of ActiveGraphQL::Model provides the following methods:

  • all: Retrive all objects for the entity.
  • where(conditions): Retrieve all objects for the entity finding by conditions.
  • find_by(conditions): Retrieve first object for the entity finding by conditions.

Any one of these methods returns an ActiveGraphQL::Fetcher who provides the method fetch(*graph) that is responsible of calling the service. The *graph arguments allow to specify how the response format will be.

For convention, any method is performing a call to the service with a query, that is resolved based on: model class name, conditions and graph.

Retrieving all MyModel objects (just ask for retrieving id)

>> MyModel.all.fetch(:id).first.id
=> "1"

Resolved query:

{ myModels { id } }

Retrieving all MyModel objects with value == "a" (ask for id and name)

>> m = MyModel.where(value: 'a').fetch(:id, :name).first

>> m.id
=> "3"

>> m.name
=> "Whatever"

Resolved query:

{ myModels("value": "a") { id, name } }

Retrieving MyModel object with id == "5" (ask for id, name and nestedObject { id })

>> m = MyModel.find_by(id: '5').fetch(:id, :name, nested_object: [:description])

>> m.id
=> "5"

>> m.name
=> "Whatever"

>> m.nested_object.description
=> "Some description here"

Resolved query:

{ myModel("id": "5") { id, name, nestedObject { description } } }

Localisation support

Any fetcher provides the in_locale(locale) method that makes the call to include the HTTP_ACCEPT_LANGUAGE header to get the content localized in case of the service supporting it.

>> MyModel.all.in_locale(:en).fetch(:some_attribute).first.some_attribute
=> "This is my text"

>> MyModel.all.in_locale(:es).fetch(:some_attribute).first.some_attribute
=> "Este es mi texto"

# Also accepts strings as locale
>> MyModel.all.in_locale('es_ES').fetch(:some_attribute).first.some_attribute
=> "Este es mi texto"

Configuration

Http

ActiveGraphQL::Query uses HttParty as codebase for http calls. The http options used to perform requests can be configured.

class MyModel < ActiveGraphQL::Model
  configure http: { timeout: 0.1 }
end

Retriable

This gem supports retriable strategy with randomized exponential backoff, based on Retriable. Retriable is disabled by default, so ActiveGraphQL::Model.configure accepts the available options for Retriable#retriable.

NOTE: Configuring retriable: true will activate Retriable with its defaults.

class MyModel < ActiveGraphQL::Model
  configure retriable: { on: [Timeout::Error, Errno::ECONNRESET],
                         tries: 10,
                         base_interval: 0.5,
                         max_interval: 1 }
end

Authorization

It's currently supporting simple bearer authorization using auth option.

It basically offers two configuration params:

  • strategy: Currently, bearer strategy is the only one available.
  • class: The existing strategy uses your own custom class to encode a token (the class must provide at least an .encode class method).

Your encoder class may look like that:

class YourEncoderClass
  def self.secret 
    'your-safely-secured-secret'
  end

  def self.encode
    # You could have custom stuff here like adding expiration to the payload.
    payload = { exp: (Time.current.to_i + 100) }
    JWT.encode(payload, secret)
  end
  
  def self.decode(token)
    JWT.decode(token, secret)
  end
end

Then your configuration would look like the next:

class MyModel < ActiveGraphQL::Model
  configure auth: { strategy: :bearer, class: YourEncoderClass }
end