How to use GraphiQL in Rails
Tags: rails, graphql, graphiql
Published: 2020-08-13 07:52:35

I recently wanted to use `graphiql-rails` gem to play around with a GraphQL endpoint that I was running in a Rails project.

For some reasons, I was not able to set it up properly since the gem doesn't seem to be working without Rails Asset Pipeline... or may be I was just too lazy to look it up how to make it work.

So I came up with a workaround:

---

If exists, remove `graphiql-rails` from `Gemfile`, then run `bundle`.

If exist, remove these lines from `./config/routes.rb`.

```ruby
if Rails.env.development?
  mount GraphiQL::Rails::Engine, at: "/graphiql", graphql_path: "/your/endpoint"
end
```

These things may have been auto-generated if you followed the installation instructions from the `graphql` gem.

---

Add to `./config/routes.rb`

```ruby
get '/graphiql', to: 'graphiql#index' if Rails.env.development?
```

This adds a new route `/graphiql` and maps it to the `index` action of controller `GraphiqlController`, which we are going to define next...

---

Create `./app/controllers/graphiql_controller.rb` with this content:

```ruby
class GraphiqlController < ApplicationController
  layout false

  def index; end
end
```

We can leave the `index` method empty, and continue with the view...

---

Create `./app/views/graphiql/index.html.erb` with this content:

```html
<html>
  <head>
    <title>Simple GraphiQL</title>
    <link href="https://unpkg.com/graphiql/graphiql.min.css" rel="stylesheet" />
    <%= csrf_meta_tags %>
  </head>
  <body style="margin: 0;">
    <div id="graphiql" style="height: 100vh;"></div>

    <script crossorigin src="https://unpkg.com/react/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom/umd/react-dom.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/graphiql/graphiql.min.js"></script>

    <script>
      const graphqlEndpointUrl = "<%= graphql_url %>";
      const graphQLFetcher = graphQLParams =>
        fetch(graphqlEndpointUrl, {
          method: 'post',
          headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': document.querySelector(`meta[name="csrf-token"]`).content
          },
          body: JSON.stringify(graphQLParams),
        })
          .then(response => response.json())
          .catch(() => response.text());
      ReactDOM.render(
        React.createElement(GraphiQL, { fetcher: graphQLFetcher }),
        document.getElementById('graphiql'),
      );
    </script>
  </body>
</html>
```

That content originally comes from the official [GraphiQL README Page](https://github.com/graphql/graphiql/tree/main/packages/graphiql#cdn-bundle).

It loads the GraphiQL source from a CDN, so you need to be connected to the internet in order to use it.

However, the file has been enriched in 3 locations in order to work with Rails:

1. `<%= csrf_meta_tags %>` : This writes the CSRF token as a `<meta>`-tag, which we are going to use in the AJAX request below.
2. `const graphqlEndpointUrl = "<%= graphql_url %>";` : If your Rails application runs the GraphQL endpoint, its URL will automatically be defined here.
3. ``'X-CSRF-Token': document.querySelector(`meta[name="csrf-token"]`).content`` : This reads the CSRF token from the `<meta>`-tag and sends it together with the GraphQL query to the Rails server. If this is missing, Rails will refuse the request with the error `ActionController::InvalidAuthenticityToken`.

---

Finally, start the rails server `bin/rails s` and go to `http://localhost:3000/graphiql`:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ujyswbupw2r4d9x65o7z.png)