<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hari Gopal</title>
    <description>The latest articles on DEV Community by Hari Gopal (@harigopal).</description>
    <link>https://dev.to/harigopal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F236051%2Ffeec08d9-8c4a-470d-877d-f5795c1feab1.jpeg</url>
      <title>DEV Community: Hari Gopal</title>
      <link>https://dev.to/harigopal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harigopal"/>
    <language>en</language>
    <item>
      <title>A Complete Guide to Setting up a GraphQL Server on Rails</title>
      <dc:creator>Hari Gopal</dc:creator>
      <pubDate>Sat, 14 Dec 2019 08:06:03 +0000</pubDate>
      <link>https://dev.to/harigopal/a-complete-guide-to-setting-up-a-graphql-server-on-rails-cc2</link>
      <guid>https://dev.to/harigopal/a-complete-guide-to-setting-up-a-graphql-server-on-rails-cc2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;"Convention over configuration"&lt;/em&gt; is one of the reasons Rails became as popular as it did. Conventions allow developers to be productive without &lt;a href="https://en.wiktionary.org/wiki/bikeshedding"&gt;&lt;em&gt;bike-shedding&lt;/em&gt;&lt;/a&gt;. However, introducing new concepts to Rails involves a period of experimentation during which there are no answers to troublesome questions.&lt;/p&gt;

&lt;p&gt;Setting up a GraphQL server on Rails is one of those tasks.&lt;/p&gt;

&lt;p&gt;This post presents a method for setting up a GraphQL server, while also tackling two issues that are generally glossed over by existing documentation surrounding the use of the &lt;code&gt;graphql-ruby&lt;/code&gt; gem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How do I handle authorization?&lt;/li&gt;
&lt;li&gt;How do I avoid N+1 queries?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Start with &lt;em&gt;graphql-ruby&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;We'll be using the &lt;a href="https://graphql-ruby.org/getting_started"&gt;well-documented &lt;code&gt;graphql-ruby&lt;/code&gt; gem&lt;/a&gt; to get started with setting up a GraphQL server on Rails. If you're someone who's already familiar with &lt;code&gt;graphql-ruby&lt;/code&gt;, feel free to skip this section.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;gem 'graphql-ruby', '~&amp;gt; 1.9'&lt;/code&gt; to your &lt;code&gt;Gemfile&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;bundle install&lt;/code&gt; on the command line.&lt;/li&gt;
&lt;li&gt;Run the gem's installation generator: &lt;code&gt;rails generate graphql:install&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;If Rails complains that it can't find &lt;code&gt;graphql:install&lt;/code&gt;, try again after stopping &lt;code&gt;spring&lt;/code&gt;, with &lt;code&gt;bin/spring stop&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The previous step will have updated the &lt;code&gt;Gemfile&lt;/code&gt;, so you'll need run &lt;code&gt;bundle install&lt;/code&gt; again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point, &lt;code&gt;graphql-ruby&lt;/code&gt; is all set up. Let's take a quick look at what the gem added to our Rails application, so that the following steps are easier to understand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
├─ config/routes.rb          (updated to include /graphql, and /graphiql)
├─ controllers/
|  └─ graphql_controller.rb  (all requests are handled by the execute action)
└─ graphql/
   ├─ my_rails_app_schema.rb (the web of interconnected types starts here)
   ├─ types/
   |  ├─ query_type.rb       (base type for all queries)
   |  ├─ mutation_type.rb    (base type for all mutations)
   |  └─ base_*.rb           (many other base types - object, enum, etc.)
   └─ mutations/
      └─ .keep               (empty - we haven't made any mutations yet)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If we take a look inside the &lt;code&gt;routes.rb&lt;/code&gt; file, we can see that a new &lt;code&gt;/graphql&lt;/code&gt; path is handled by the &lt;code&gt;GraphqlController#execute&lt;/code&gt; method:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Notice how the incoming query is passed onto the schema (along with &lt;em&gt;context&lt;/em&gt;) for execution. The &lt;em&gt;schema&lt;/em&gt; defines only two things right now:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The schema says that mutations can be found in &lt;code&gt;Types::MutationType&lt;/code&gt; and queries in &lt;code&gt;Types::QueryType&lt;/code&gt;. If we take a look in either, we'll see a dummy field that we can play around with.&lt;/p&gt;

&lt;p&gt;One thing that I glossed over in &lt;code&gt;routes.rb&lt;/code&gt; is that the gem also mounted the awesome &lt;em&gt;GraphiQL&lt;/em&gt; app on the &lt;code&gt;/graphiql&lt;/code&gt; path. Visit the &lt;code&gt;/graphiql&lt;/code&gt; path in your browser, and try running the following query there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query {
  testField
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You should get this response:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "data": {
    "testField": "Hello World!"
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;There you go! Now that we're done with our whirlwind tour of the &lt;code&gt;graphql-ruby&lt;/code&gt; gem, let's start digging a bit deeper.&lt;/p&gt;
&lt;h2&gt;
  
  
  Here Be Dragons
&lt;/h2&gt;

&lt;p&gt;While the &lt;code&gt;graphql-ruby&lt;/code&gt; gem has added a &lt;em&gt;ton&lt;/em&gt; of functionality to our app, it doesn't really go into detail as to what the best practices are for actually &lt;em&gt;using&lt;/em&gt; the gem. Specifically, as mentioned at the beginning of this guide, two issues that are glossed over are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How to handle authorization, and...&lt;/li&gt;
&lt;li&gt;How to efficiently query data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Just like the &lt;a href="https://graphql.org/learn/authorization/"&gt;official documentation about authorization in GraphQL&lt;/a&gt;, the &lt;a href="https://graphql-ruby.org/authorization/overview.html#authorization-in-your-business-logic"&gt;gem's documentation&lt;/a&gt; also suggests pushing the responsibility for authorization into &lt;em&gt;business&lt;/em&gt; logic, specifically into model methods that accept &lt;code&gt;context&lt;/code&gt; and decide what kind of relation or data is accessible for &lt;em&gt;that&lt;/em&gt; user.&lt;/p&gt;

&lt;p&gt;As for the potential for N+1 queries, it's pretty much ignored altogether - I'm guessing that you're expected to handle this on a case-by-case basis.&lt;/p&gt;

&lt;p&gt;I'd like to suggest an alternative: new &lt;em&gt;conventions&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;em&gt;Resolvers&lt;/em&gt; authorize and fetch data
&lt;/h2&gt;

&lt;p&gt;Let's start by adding an &lt;code&gt;ApplicationQuery&lt;/code&gt; class that'll act as the base class for &lt;em&gt;resolvers&lt;/em&gt; and &lt;em&gt;mutators&lt;/em&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;With that in place, we can start writing &lt;em&gt;resolver&lt;/em&gt; objects that will help us retrieve properly authorized data for GraphQL queries. Let's start by creating a query that asks for a list of users:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Notice how the &lt;code&gt;users&lt;/code&gt; method simply hands over the responsibility for loading the data to a &lt;code&gt;UsersResolver&lt;/code&gt; object:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;What you're looking at is the essence of this approach.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All requests are individually authorized.&lt;/li&gt;
&lt;li&gt;There is an assumption that once a query is authorized, all data returned by the resolver (or mutator) can be accessed by the authenticated user.&lt;/li&gt;
&lt;li&gt;Avoid N+1-s by making sure that the resolver method &lt;code&gt;includes&lt;/code&gt; all necessary data for the response.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before we move onto mutators, let's also look at how we deal with queries that have arguments, using a variation of what we've done above:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Only a few things are different here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;args&lt;/code&gt; is passed to the resolver in addition to context.&lt;/li&gt;
&lt;li&gt;There's a &lt;code&gt;property :id&lt;/code&gt; in the resolver class defining what data the query will work with.&lt;/li&gt;
&lt;li&gt;Instead of a relation, the &lt;code&gt;user&lt;/code&gt; method in the resolver returns a &lt;code&gt;User&lt;/code&gt; object, since the &lt;em&gt;type&lt;/em&gt; for the query is a single object.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;Mutators&lt;/em&gt; authorize, modify, and supply a response
&lt;/h2&gt;

&lt;p&gt;GraphQL mutations aren't really all that different from queries. Mutations are queries that are, &lt;em&gt;by convention&lt;/em&gt;, allowed to modify data. And just like queries, they too can return structured data.&lt;/p&gt;

&lt;p&gt;As with queries, let's start with a simple example that shows just how similar &lt;em&gt;mutators&lt;/em&gt; are to &lt;em&gt;resolvers&lt;/em&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Notice how there's a call to &lt;code&gt;.valid?&lt;/code&gt; before the &lt;code&gt;.create_comment&lt;/code&gt; is called. This triggers validations that can be configured in the mutator class:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Again, there's very little that's new here.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Because &lt;code&gt;ApplicationQuery&lt;/code&gt; includes &lt;code&gt;ActiveModel::Model&lt;/code&gt;, we have access to all of the validation methods that we're familiar with.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;property&lt;/code&gt; helper simply combines &lt;code&gt;validates&lt;/code&gt; and &lt;code&gt;attr_accessor&lt;/code&gt; into a single-step, and helps avoid bugs because the former depends on the latter.&lt;/li&gt;
&lt;li&gt;We can either process the request in the mutator directly in the &lt;code&gt;create_comment&lt;/code&gt; method, or pass it onto a service as shown in the example.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As with queries, there is an assumption that the &lt;code&gt;create_comment&lt;/code&gt; method will return an object that responds to the &lt;em&gt;fields&lt;/em&gt; mentioned in the mutation class. In this case, that's &lt;code&gt;id&lt;/code&gt;, and as long as the service returns a &lt;code&gt;Comment&lt;/code&gt; object, everything should work as expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create types for complex returns
&lt;/h3&gt;

&lt;p&gt;While GraphQL unsubtly suggests the use of relations in your response types, there is no need to follow that pattern. Often, it's much more straight-forward to create a custom type that fits exactly the data that you want to return:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here, the custom &lt;code&gt;UpdatePostType&lt;/code&gt; is used to compose exactly what the UI requires in this imaginary app, when a post is updated.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the advantages of this approach?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;On the server-side:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You have a self-documenting API. Testing it is a breeze thanks to GraphiQL.&lt;/li&gt;
&lt;li&gt;The Rails server will crash with a useful error message if your code ever disobeys the type specification.&lt;/li&gt;
&lt;li&gt;Pagination of resources is simple and straight-forward, thanks to &lt;a href="https://graphql-ruby.org/relay/connections.html"&gt;built-in, well-thought-out conventions&lt;/a&gt; that cover a large variety of pagination-use-cases.&lt;/li&gt;
&lt;li&gt;Avoids a lot of bike-shedding. &lt;code&gt;PUT&lt;/code&gt; vs &lt;code&gt;PATCH&lt;/code&gt;? &lt;code&gt;400&lt;/code&gt; vs &lt;code&gt;422&lt;/code&gt;? How to handle deprecation? These questions, and more, are no longer concerns.&lt;/li&gt;
&lt;li&gt;The server's response can be extended to include more standardized behavior.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;On the client-side (assuming that you're using a typed language):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your API is integrated with the editor - it'll suggest names, arguments, and return values - writing correct queries is much simpler.&lt;/li&gt;
&lt;li&gt;Your compiler will prevent the application from generating code with invalid queries.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  About extensibility
&lt;/h3&gt;

&lt;p&gt;Your server always supplies a JSON response. This means that you can add more fields to it if you'd like.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://www.pupilfirst.com"&gt;PupilFirst&lt;/a&gt;, we've expanded the response object to include a &lt;code&gt;notifications&lt;/code&gt; field. If present, the response handler in the client automatically converts them into &lt;em&gt;flash&lt;/em&gt; notifications that are shown to the user. This helps us preserve a &lt;em&gt;Rails-like&lt;/em&gt; experience in our mutators, and keeps notifications &lt;em&gt;DRY&lt;/em&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The query superclass has simple methods that inject notifications into the context...&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;...which then gets placed in the response by the GraphQL controller:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  However, concerns still exist
&lt;/h2&gt;

&lt;h3&gt;
  
  
  This isn't what GraphQL promised
&lt;/h3&gt;

&lt;p&gt;One of the stated advantages of GraphQL is that it solves the problem of over-fetching by allowing the client to specify exactly what data it needs, leading to the server fetching &lt;em&gt;only&lt;/em&gt; the asked-for data.&lt;/p&gt;

&lt;p&gt;This approach definitely &lt;strong&gt;ignores&lt;/strong&gt; that goal. We're taking this approach because of two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Over-fetching is not a problem for &lt;a href="https://www.pupilfirst.com"&gt;us&lt;/a&gt;. It might become a problem &lt;em&gt;at scale&lt;/em&gt;, but we're not at that size yet. It's generally better to tackle problems that exist now (ease of API usage, and avoiding clerical mistakes), instead of one that &lt;em&gt;might&lt;/em&gt; happen in the future.&lt;/li&gt;
&lt;li&gt;GraphQL doesn't actually &lt;em&gt;do&lt;/em&gt; anything to solve over-fetching - it just specifies how to deliver the data once you've retrieved it. However, retrieving data correctly is &lt;a href="https://graphql.org/learn/thinking-in-graphs/#business-logic-layer"&gt;still up to your &lt;em&gt;business logic&lt;/em&gt;&lt;/a&gt;, which is always vaguely defined in all documentation that I've come across.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Arbitrarily loading relational data and incurring huge performance hits is one of the easiest mistakes to make with GraphQL, and it's not a problem whose solution is clear. At this point, I think it's appropriate to mention that Shopify has released a &lt;code&gt;graphql-batch&lt;/code&gt; gem that &lt;em&gt;claims&lt;/em&gt; to tackle this issue. Unfortunately, I think it's poorly documented, and I couldn't really make sense of how it's supposed to work, but it may be worth looking at if you're already &lt;em&gt;at scale&lt;/em&gt;, and dealing with issues like over-fetching.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why not authorize fields?
&lt;/h3&gt;

&lt;p&gt;The simple answer is that it's much easier to think about authorizing requests rather than fields. Requests always have a context which can be used to determine whether &lt;em&gt;this&lt;/em&gt; user is allowed to access some data or make a change.&lt;/p&gt;

&lt;p&gt;However, if the fields that a client can request are unbounded, i.e., the type allows the client to dig deeper into relationships and ask for &lt;em&gt;distant&lt;/em&gt; data, then field-level authorization is your only option. This is why we suggest creating response types specific to queries if the requested data is complicated. Yes, this is restrictive, but requires only one authorization, and ensures that we're limiting the response to a selection of data that we know the client is &lt;em&gt;definitely&lt;/em&gt; allowed to access.&lt;/p&gt;

&lt;h3&gt;
  
  
  How is this any different from REST?
&lt;/h3&gt;

&lt;p&gt;First, I'd like to point you to the list of advantages written above.&lt;/p&gt;

&lt;p&gt;You'll notice that the process I've suggested is very similar to how REST works. And you know what? REST has some &lt;em&gt;really&lt;/em&gt; good ideas about how to manage communication - it's just that &lt;em&gt;some&lt;/em&gt; of its requirements don't make sense anymore when building APIs. REST has an uncomplicated approach to authorization and data-delivery that I think we should adopt even when we're using GraphQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real-world example
&lt;/h2&gt;

&lt;p&gt;If you'd like to take a look at a Rails application that uses this approach, take a look at codebase for &lt;a href="https://github.com/SVdotCO/pupilfirst"&gt;the PupilFirst LMS&lt;/a&gt;. The patterns described here were created as &lt;a href="https://www.sv.co"&gt;our team&lt;/a&gt; gradually switched to using ReasonML and ReasonReact on the front-end, and adopted GraphQL in order to leverage the presence of types and a compiler.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
  </channel>
</rss>
