Skip to content

GraphQL comes to Solidus!

License

BSD-3-Clause, BSD-3-Clause licenses found

Licenses found

BSD-3-Clause
LICENSE
BSD-3-Clause
LICENSE.md
Notifications You must be signed in to change notification settings

solidusio/solidus_graphql_api

SolidusGraphqlApi

Maintainability Test Coverage CircleCI Gem Version

Provides a graphql api for the Solidus ecommerce framework.

Supported Versions

  • Solidus 2.11.x
  • Solidus 3.x

Installation

Add solidus_graphql_api to your Gemfile:

gem 'solidus_graphql_api'

Bundle your dependencies and run the installation generator:

bin/rails generate solidus_graphql_api:install

Unlike the REST API which has a variety of endpoints, the GraphQL API has a single endpoint accessible under /graphql. It will be automatically inserted into your routes.rb file after running the generator.

For example in development you can use:

POST http://localhost:3000/graphql

Documentation

The Solidus GraphQL API documentation can be found here.

Customizations

You can extend the gem functionality through decorators, just like Solidus.

For example, assuming we are placing our grapqhl decorators in app/graphql/types:

Adding a new field

module Graphql
  module Types
    module ProductDecorator
      def self.prepended(base)
        base.field :test, GraphQL::Types::String, null: true
      end

      def test
        'test'
      end

      SolidusGraphqlApi::Types::Product.prepend self
    end
  end
end

or also, if we want to add the taxon relation to the type product:

module Graphql
  module Types
    module ProductDecorator
      def self.prepended(base)
        base.field :taxons, SolidusGraphqlApi::Types::Taxon.connection_type, null: true
      end

      def taxons
        SolidusGraphqlApi::BatchLoader.for(object, :taxons)
      end

      SolidusGraphqlApi::Types::Product.prepend self
    end
  end
end

Modifying an existing field

Like for adding a new field, we modify the name field in the same way:

module Graphql
  module Types
    module ProductDecorator
      def self.prepended(base)
        base.field :name, GraphQL::Types::String, null: true
      end

      def name
        object.concat(' ', 'Graphql')
      end

      SolidusGraphqlApi::Types::Product.prepend self
    end
  end
end

Removing a field

module Graphql
  module Types
    module ProductDecorator
      def self.prepended(base)
        base.remove_field :name
      end

      SolidusGraphqlApi::Types::Product.prepend self
    end
  end
end

Adding a new Type

Let's say we want the Product type to return its stock_items:

First we create a StockItem type:

module Graphql
  module Types
    class StockItem < SolidusGraphqlApi::Types::Base::RelayNode
      description 'StockItem.'

      field :count_on_hand, Integer, null: false
    end
  end
end

And in the product decorator type:

require_relative 'stock_item'

module Graphql
  module Types
    module ProductDecorator
      def self.prepended(base)
        base.field :stock_items, Graphql::Types::StockItem.connection_type, null: false
      end

      def stock_items
        object.stock_items
      end

      SolidusGraphqlApi::Types::Product.prepend self
    end
  end
end

The query may look something like:

query productBySlug ($slug: String!) {
  productBySlug (slug: $slug) {
    stockItems {
      nodes {
        countOnHand
      }
    }
  }
}

Adding a new Query

module Graphql
  module Types
    module QueryDecorator
      def self.prepended(base)
        base.field :taxons, SolidusGraphqlApi::Types::Taxon.connection_type, null: false
      end

      def taxons
        Spree::Taxon.all
      end

      SolidusGraphqlApi::Types::Query.prepend self
    end
  end
end

In your application you probably want to create a query object to retrieves the taxons. Check SolidusGraphqlApi::Types::Query for examples.

Development

Testing the extension

First bundle your dependencies, then run bin/rake. bin/rake will default to building the dummy app if it does not exist, then it will run specs. The dummy app can be regenerated by using bin/rake extension:test_app.

bundle
bin/rake

To run Rubocop static code analysis run

bundle exec rubocop

When testing your application's integration with this extension you may use its factories. Simply add this require statement to your spec_helper:

require 'solidus_graphql_api/factories'

Running the sandbox

To run this extension in a sandboxed Solidus application, you can run bin/sandbox. The path for the sandbox app is ./sandbox and bin/rails will forward any Rails commands to sandbox/bin/rails.

Here's an example:

$ bin/rails server
=> Booting Puma
=> Rails 6.0.2.1 application starting in development
* Listening on tcp://127.0.0.1:3000
Use Ctrl-C to stop

Updating the changelog

Before and after releases the changelog should be updated to reflect the up-to-date status of the project:

bin/rake changelog
git add CHANGELOG.md
git commit -m "Update the changelog"

Releasing new versions

Please refer to the dedicated page on Solidus wiki.

License

Copyright (c) 2020-2021 Nebulab, released under the New BSD License.