0.01
No commit activity in last 3 years
No release in over 3 years
Ruby client for GraphQL services
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.11
~> 10.0
~> 3.0

Runtime

~> 3.4
~> 0.13
~> 2.0
 Project Readme

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