Plugin for graphql-ruby which helps to select only the required fields from the database.
Switch branches/tags
Nothing to show
Clone or download
Latest commit 3d44273 Nov 10, 2018

README.md

Cult Of Martians Gem Version Build Status

GraphQL::SmartSelect

Plugin for graphql-ruby which helps to select only the required fields from the database.

Requirements

  • Ruby >= 2.3.0
  • graphql-ruby ~> 1.8.7
  • activerecord >= 4.2

Installation

Add this line to your application's Gemfile:

gem 'graphql-smart_select'

The Problem

Consider the following query:

query {
  posts {
    id
    title
  }
}

Ruby interface for serving this query:

module GraphqlAPI
  module Types
    class Query < GraphQL::Schema::Object
      field :posts, Types::Post, null: false

      def posts
        Post.all
      end
    end
  end
end

In the default case, this leads to the query: SELECT * FROM posts, and we only need id and title. For tables with a large number of columns, this could have a negative effect on performance (due to both DB reads and ActiveRecord object instantiation).

Usage

Smart Select works as an extension for field_class:

module GraphqlAPI
  module Types
    class Query < GraphQL::Schema::Object
      # use plugin
      field_class.prepend(GraphQL::SmartSelect)

      # activate plugin
      field :posts, Types::Post, null: false, smart_select: true

      # You can also explicitly specify which fields
      # to include in every query
      field :posts, Types::Post, null: false, smart_select: [:id]

      def posts
        Post.all
      end
    end

    class Post < GraphQL::Schema::Object
      field_class.prepend(GraphQL::SmartSelect)

      field :id, ID
      field :title, String
      field :raw_content, String
      field :another_content, String
  
      # We'll tell the plugin which fields are needed
      # for resolve this field
      field :contents, db_columns: [:raw_content, :another_content]
      
      # For one_to_one AR assosiation we include foreign_key
      field :user, Types::User

      # For has_many AR assosiation we include primary_key
      field :comments, [Types::Comment]

      def contents
        [object.id, object.title].join
      end
    end
  end
end

For this example query:

query {
  posts {
    title
    contents
    user { name }
    comments { id }
  }
}

It performs the following query: SELECT id, title, raw_content, another_content, user_id FROM posts

Notes

Custom Resolvers are not supported.

Tested for activerecord version >= 4.2

Development

For regression testing, run the following

# install Appraisals dependencies
bundle exec appraisal install
# run test suit through all dependencies listed in Appraisals file
bundle exec appraisal rake spec

License

The gem is available as open source under the terms of the MIT License.