Ancient City Ruby 2019

Seamless GraphQL in Rails and React Native

Ancient City Ruby 2019

00:00:12.610 Thank you very much! I'm Jamon Holmgren, and with me is Morgan Laco.
00:00:19.220 Morgan is going to be doing live coding while I narrate. This is a little bit of an analogy for our day jobs.
00:00:25.640 Morgan is a mobile software engineer at Infinite Red, and I am the CTO, which means I talk a lot.
00:00:33.140 So, Morgan, if you don't mind pulling up the slides that we created, I will go through those really quickly.
00:00:41.180 Fun fact: We practiced for a 30-minute talk and could never get it below 45 minutes. Then I realized it is actually a 45-minute talk, so that's perfect!
00:00:48.170 Okay, so our talk is about seamless GraphQL in Rails and React Native. Like I said, I'm Jamon Holmgren, and I live in the Pacific Northwest. It's really nice to be here right now and not there, where it's cold and wet.
00:01:00.409 I co-founded Infinite Red and work on the React Native open source community core. You can find me on Twitter at @JamonHolmgren.
00:01:07.070 Morgan?
00:01:12.110 I am Morgan Laco. I work at Infinite Red. I actually started with Rails at Code School, then went to Infinite Red and worked with Elixir at the beginning.
00:01:17.540 Then they switched me into mobile development with React Native. By the way, Morgan lives in Orlando.
00:01:23.180 A little bit about Infinite Red: we are a consultancy focused on mobile and web design. React is what we are most known for.
00:01:29.079 We are also starting to do some AI and machine learning projects as of January this year.
00:01:35.210 Alright Morgan, do you have the latest? I'm seeing a little problem here.
00:01:41.180 Thank you. Chain React is our conference focused on React Native. If you're attending React Native, please come and visit Portland in the summer, specifically in July.
00:01:48.170 I hear it gets a little warm here, so that's a good time to get out of the heat. The next one will be in July 2020.
00:01:56.080 You can find more about that at infinite.red/chainreactcomp.
00:02:01.540 Cool, so we're going to be talking about a lot of different tools during our live coding exercise.
00:02:07.990 We're not going to touch any of them too deeply, but there is a lot more depth.
00:02:14.200 Let's go through these tools very quickly. First up is Rails. Who here has heard of Rails?
00:02:19.650 Okay, a few of you! I won't talk about that too much because I know there are a lot of Rails developers here.
00:02:28.180 Now, GraphQL Ruby: has anybody used GraphQL Ruby?
00:02:33.790 Okay, actually a fair number. GraphQL Ruby is a gem that will provide our Rails generators and the GraphQL endpoint we're going to use.
00:02:40.690 We are going to generate a GraphQL schema. That's one of the main points of this talk.
00:02:45.760 We want to show how you can have one schema between your backend and your mobile app.
00:02:51.280 You can also translate this to the web as well. I'm doing a mobile app to illustrate this.
00:02:56.709 We'll also show how to implement this on a web frontend.
00:03:04.030 We will be using a tool called MST GQL to generate our MobX state tree models from the GraphQL schema.
00:03:10.209 Think of MobX state tree as being Redux-like state management but with some better features.
00:03:16.170 We've used Redux for several years at Infinite Red, but we got tired of the boilerplate.
00:03:21.519 MobX state tree is probably the most popular alternative to Redux you will find.
00:03:27.370 We'll also be using React Native with our starter kit called Ignite Bowser.
00:03:32.710 This is a boilerplate for React Native that will save you about two weeks of initial setup.
00:03:39.400 We'll be starting off with a fresh Ignite Bowser setup. We haven't modified it much, just ensured all of our dependencies are installed.
00:03:45.460 Go ahead and proceed to the next step.
00:03:52.150 This is what we'll be building. Morgan, could you confirm?
00:03:57.640 Yes, we're building a simple demo to demonstrate how to consume an API using GraphQL on a React Native client.
00:04:01.990 We're keeping it simple here because we only have 45 minutes.
00:04:08.210 We'll be doing live coding. Head to the next screen quickly.
00:04:18.289 Since we're introducing multiple tools, I want you to take your mobile phone or laptop and go to get.io/JAECR or scan the QR code.
00:04:29.990 This will redirect you to a README we're following today. Morgan and I wrote it, and you can follow along too.
00:04:36.520 Everything is open source, and we will do our best to explain the code as we go.
00:04:43.130 But just in case you want to spend a little more time on something, feel free to.
00:04:49.570 So get.io/JAECR or scan the QR code to access the GitHub repo.
00:04:56.370 Alright, let's do the demo.
00:05:01.130 On our left, we have our Rails app—a brand new Rails 6.0 project. It's completely fresh.
00:05:09.270 On the right, there's a fresh Ignite Bowser React Native app. The first thing we’ll do is add the GraphQL Ruby gem.
00:05:16.990 Let's open up VS Code here to ensure we have the GraphQL gem installed.
00:05:23.680 We actually already have it installed to avoid using hotel Wi-Fi.
00:05:28.740 Now, let’s open up the terminal and run the generator that comes with the GraphQL Ruby gem.
00:05:35.130 Rails G GraphQL: install will bring in all the necessary files for working with the GraphQL endpoint and schema.
00:05:41.610 Next, we will create a scaffold. A lot of Rails developers don't really use scaffolds, but they are good for demo purposes.
00:05:50.190 So, let's run Rails G scaffold to create a Post model with attributes of title and body, both as strings.
00:05:56.100 Then, we can run Rails DB:migrate to apply our new model.
00:06:04.650 This creates the Post model along with basic views for creating, editing, and deleting posts.
00:06:10.740 Next, we are going to create the corresponding GraphQL object. This will help us leverage GraphQL for our Rails app.
00:06:19.920 Let's run Rails G GraphQL:Object Post and define its fields.
00:06:27.900 The fields will include an ID, title, and body. All fields need to match the attributes we defined earlier.
00:06:35.120 Alright, let’s quickly check that we have the PostType.rb file.
00:06:40.000 You will see it under the GraphQL folder that was created, featuring the three fields we defined.
00:06:48.570 Next, we’ll move to our QueryType.rb file. Here is where we define the types of queries that can be run against our GraphQL endpoint.
00:06:56.000 We will also hook it up to the Post object we created earlier.
00:07:02.040 Morgan, let's copy and paste that in. I’ll walk you through what’s happening.
00:07:08.100 To save time, we’re copying and pasting, but I’ll explain everything to avoid any errors.
00:07:15.530 The posts field defines what we’re returning back - an array of posts of the Post type.
00:07:23.589 We implement it using a method that performs a regular active record request to return all the posts.
00:07:30.309 We could sort or filter them based on arguments, but we'll keep it basic and stick to fetching all the posts.
00:07:40.399 To see this in action, let’s run Rails server and navigate to localhost:3000/posts.
00:07:50.469 Given that the server is running, we should be able to create a new post.
00:07:58.489 We can add some content to it; Morgan, go ahead and create another post.
00:08:06.469 Great! Now that we have some content, let's jump to GraphiQL.
00:08:15.090 GraphiQL is a UI that comes with the GraphQL Ruby gem, allowing you to run queries and see responses.
00:08:21.790 It's incredibly helpful during development. One cool thing is that GraphQL allows you to shape data as you need it.
00:08:29.589 Let's run an example query. The field name we defined earlier was 'posts', so type that in.
00:08:36.449 When we run it, we’ll see a data property that has posts, which is an array.
00:08:43.930 Currently, we’re only getting IDs back, which isn't very useful, so let's add some fields.
00:08:49.990 GraphiQL features autocomplete, making this a very efficient tool for developers.
00:08:56.129 After adding more fields, run the query again, and this time we will see expanded data returned.
00:09:03.890 This is one of the best aspects about GraphQL: you can request only the fields you need.
00:09:10.820 This leads to better experiences for front-end developers because they have control over what data they receive.
00:09:17.540 At Infinite Red, most of our work involves collaborating with backend teams.
00:09:24.750 With traditional REST APIs, we’re often limited by what backend teams can implement.
00:09:31.180 But with GraphQL, we can request exactly what we need, significantly improving our workflow.
00:09:38.227 Morgan particularly likes that GraphQL is composable. If we add authors, we can easily fetch their details without altering the API.
00:09:45.080 That’s right! If we had an authors field, we could simply query for it.
00:09:51.530 With correct setup, GraphQL efficiently manages related data without causing N+1 query issues.
00:09:58.170 Alright, now that our backend is pretty much done for this initial version, let's move to the frontend.
00:10:05.720 We need to implement the React Native Ignite Bowser app to query this schema.
00:10:12.650 Let's create a rake task for easier schema management in our Rails app.
00:10:19.780 We can use rails G task GraphQL dump to generate a task that outputs our current schema.
00:10:27.000 Let’s navigate to that file in the 'lib/tasks' directory.
00:10:35.280 The command we ran earlier generates a new object in our Rails schema.
00:10:42.490 This command will return the definition of our GraphQL schema, which we will write to a file.
00:10:50.709 Next, let's run the rake task we created by using rake GraphQL: dump.
00:10:58.020 This step is crucial because as our backend evolves, we need to synchronize changes with the frontend.
00:11:04.380 We want to keep a single source of truth for our schema to avoid inconsistencies.
00:11:11.330 Let’s open the GraphQL file we just generated, located at the root of our project.
00:11:17.600 Here, we see the types we defined, including post with its fields ID, body, and title.
00:11:25.530 Next, we need to update the GraphQL controller that was generated during the install process.
00:11:33.129 This controller sets up the endpoint we will be using for the mobile app.
00:11:39.620 Because we’re working with a mobile app, we need to adjust our cross-site scripting settings.
00:11:47.500 We need to add a line at the top to protect from forgery with nil session.
00:11:54.010 This essentially disables the default protection, but remember to implement your own safety measures.
00:12:01.860 Alright, we've finalized the Rails app. Now we need to display the posts in our React Native app.
00:12:07.700 Let's open the React Native simulator; this is how an Ignite Bowser app looks out of the box.
00:12:15.320 If you've installed Ignite and created a new app, this is the initial setup you can expect.
00:12:22.480 React Native is cross-platform, running on both iOS and Android.
00:12:28.709 Let me explain more about Ignite: we began working with React Native in 2015.
00:12:34.320 Initially, we recognized a lack of best practices in setting up a React Native app.
00:12:40.610 After searching for boilerplates, we decided to create our own, which led to Ignite.
00:12:48.090 We've since refined Ignite and released a second version called Bowser.
00:12:54.270 We will regularly update Ignite with new features and best practices.
00:13:02.250 If you continue through Ignite, you can explore various demo features.
00:13:07.450 Rich Evans is here and is the primary maintainer of Reactotron, a desktop app to inspect React Native apps.
00:13:13.300 Reactotron can also be used with standard React apps, providing logging and debugging capabilities.
00:13:21.019 However, for now, we will focus on editing the welcome screen to display posts.
00:13:26.950 The first step is to add MSTGQL to our project.
00:13:33.630 We can run yarn add MST GQL GraphQL request to do this.
00:13:41.290 MSTGQL provides functionality to request data from the Rails server.
00:13:46.920 On the right side, we see our React Native app with the necessary dependencies.
00:13:53.200 MSTGQL also comes with a runtime component for making requests.
00:14:01.090 We will create a custom hook after Jake discussed hooks, which will help us manage queries.
00:14:07.750 Let's proceed and run the command yarn MST GQL to generate necessary files.
00:14:14.700 We're using Typescript with this demo, similar to Flow, to maintain type safety.
00:14:23.340 MST GQL will utilize the GraphQL schema to generate Typescript types.
00:14:30.130 We will indicate where the schema lives, which will produce corresponding files.
00:14:36.950 An important aspect to note is that the script can be executed multiple times.
00:14:43.790 It's crucial not to edit the generated files directly; instead, we will inherit from them.
00:14:50.540 Now, we need to import the generated model into our app.
00:14:56.150 We want to utilize the root store base that we’ll be implementing for the application.
00:15:02.220 We can keep route stores organized as children for ease of access across the app.
00:15:10.550 Revamping the root store model will help us manage properties seamlessly.
00:15:19.050 We can get back to the root store base and ensure we have correct typings in place.
00:15:28.470 The environment file will handle setup for our GraphQL requests.
00:15:38.290 To initialize our context, we'll use createStoreContext to achieve this.
00:15:45.570 Our custom hooks will assist in managing queries to fetch data effortlessly.
00:15:54.000 Now, let’s return to the welcome screen and inject the GraphQL capabilities.
00:16:05.450 The welcome screen contains JSX that will build the UI.
00:16:12.890 We’ll add the necessary hooks there to manage the queries for the posts.
00:16:20.360 The useStore hook will allow us to access the stores defined in the application.
00:16:27.610 This allows us to map through the posts and render their titles.
00:16:35.820 To show these changes, let’s incorporate a stylized button for deleting posts.
00:16:40.570 When the user clicks this button, it will trigger the delete action.
00:16:47.940 Now, let's ensure that we properly update the UI with this information.
00:16:60.800 The action will handle the state and re-render the component to reflect the deletion.
00:17:07.050 So let's implement the changes and refresh to see the results.
00:17:14.400 By running the app in the simulator, we will see how posts are displayed.
00:17:22.860 We should also add the touchable button that will execute the delete query.
00:17:29.610 The delete operation will require an ID to specify which post to remove.
00:17:37.080 During refresh, the user will see updated posts reflecting the deleted ones.
00:17:43.900 After hitting delete, verify signatures are not visible in the inventory.
00:17:51.470 Now that we have implemented the mutation, everything should work as planned.
00:17:58.370 Replacing text in components when refreshed will show the new state.
00:18:05.200 Our goal was to set up a seamless experience fetching data and managing states.
00:18:13.020 Despite facing some technical glitches, we managed to cover everything.
00:18:20.830 You can access the README markdown, which contains additional insights.
00:18:28.000 We’ll share the presentation with more resources and links to Infinite Red.
00:18:35.390 Thank you for participating, and I look forward to your questions!
00:18:41.870 Thank you!