<?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: OneHQ</title>
    <description>The latest articles on DEV Community by OneHQ (@onehq).</description>
    <link>https://dev.to/onehq</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%2Forganization%2Fprofile_image%2F2256%2Fd260e101-e1c5-4a7e-8b67-2f71d15ffc30.png</url>
      <title>DEV Community: OneHQ</title>
      <link>https://dev.to/onehq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/onehq"/>
    <language>en</language>
    <item>
      <title>Move fast with GraphQL, Rails, and TypeScript</title>
      <dc:creator>Danny Jones</dc:creator>
      <pubDate>Wed, 06 May 2020 22:55:48 +0000</pubDate>
      <link>https://dev.to/onehq/move-fast-38il</link>
      <guid>https://dev.to/onehq/move-fast-38il</guid>
      <description>&lt;p&gt;Here at OneHQ, we've had great success using GraphQL with Rails and TypeScript. I wanted to take the time to show off a couple techniques that we use to enable developers to move fast &lt;del&gt;and break things&lt;/del&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dynamically create GraphQL types in Ruby&lt;/li&gt;
&lt;li&gt;Commit the GraphQL schema to version control&lt;/li&gt;
&lt;li&gt;Auto-generate GraphQL types in TypeScript&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Dynamically create GraphQL types in Ruby
&lt;/h3&gt;

&lt;p&gt;Our database schemas are continuously evolving, and we didn't want the overhead of having to keep our tables, models, and GraphQL types in sync. ActiveRecord gets around this by using meta-programming to dynamically analyze the database to generate methods. Why couldn't we do the same with GraphQL? &lt;/p&gt;




&lt;p&gt;We could and we did! Thus was born &lt;a href="https://github.com/OneHQ/hq-graphql"&gt;hq-graphql&lt;/a&gt;. hq-graphql is a wrapper around &lt;a href="https://graphql-ruby.org/"&gt;graphql-ruby&lt;/a&gt; that does all of the necessary magic to integrate with ActiveRecord. Instead of creating a bajillion types with a bazillion fields...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdvisorType&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;GraphQL&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Object&lt;/span&gt;
  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ISO8601DateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="c1"&gt;# &amp;lt;bazillion fields go here (use your imagination)&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;# &amp;lt;bazillion fields go here (use your imagination)&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;# &amp;lt;bazillion fields go here (use your imagination)&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can now simply reference the model to dynamically create fields.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdvisorType&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HQ&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;GraphQL&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Object&lt;/span&gt;
  &lt;span class="n"&gt;with_model&lt;/span&gt; &lt;span class="s2"&gt;"Advisor"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;h3&gt;
  
  
  Commit the GraphQL schema to version control
&lt;/h3&gt;

&lt;p&gt;Once we began creating types dynamically, I feared that devs would add/remove columns from our schema without realizing that it affected GraphQL. Too much magic can be bad, especially if there isn't feedback for when something changes.&lt;/p&gt;

&lt;p&gt;For this reason, we dump and commit the GraphQL IDL (Interface Definition Language) to a file named schema.graphql whenever the schema changes. Checking in the schema to version control helps both the developer and code reviewer identify breaking changes before they hit production.&lt;/p&gt;

&lt;p&gt;To make things &lt;em&gt;even&lt;/em&gt; easier, we created a test that compares the current schema with what's committed so that they can't forget to check it in! This ensures that our CI process fails whenever a dev forgets to update the schema file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Auto-generate GraphQL types in TypeScript
&lt;/h3&gt;

&lt;p&gt;Another fear of mine was that we would update the schema and forget to update the front-end!&lt;sup&gt;(I'm afraid of a lot)&lt;/sup&gt; Of course you could write tests to circumvent this (and we do), but what if we could auto-generate our GraphQL types in TypeScript instead of creating them by hand? This would give us another layer of protection and allow for us to easily correct any disparities when something does change.&lt;/p&gt;




&lt;p&gt;Good news! This was the easiest of all our problems as there's already a tool out there that does this. &lt;a href="https://github.com/apollographql/apollo-tooling#apollo-clientcodegen-output"&gt;Apollo Codegen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Point codegen to the code that uses GraphQL and run it! It pulls out any GraphQL queries and uses introspection to dynamically generate your types. If the GraphQL queries in your client don't align with your back-end, then it throws an error and lets you know what's wrong&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;apollo client:codegen src/graphql/types/index.ts &lt;span class="nt"&gt;--endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://[::1]:8080/graphql &lt;span class="nt"&gt;--target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;typescript &lt;span class="nt"&gt;--includes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'src/graphql/**/**/*.{ts,tsx}'&lt;/span&gt; &lt;span class="nt"&gt;--tagName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gql &lt;span class="nt"&gt;--addTypename&lt;/span&gt; &lt;span class="nt"&gt;--outputFlat&lt;/span&gt;
  ⠏ Loading Apollo Project
    Generating query files
.../src/graphql/application/useApplications.ts: Cannot query field &lt;span class="s2"&gt;"names"&lt;/span&gt; on &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="s2"&gt;"Application"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; Did you mean &lt;span class="s2"&gt;"name"&lt;/span&gt;?
ToolError: Validation of GraphQL query document failed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Using meta-programming to generate types has saved us countless hours at OneHQ by allowing us to focus on what really matters. &lt;strong&gt;But beware!!!&lt;/strong&gt; Using meta-programming without checks and balances in your code review process could lead to a broken app.&lt;/p&gt;

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