React on Rails
Ever try writing Angular on Rails? I have and it’s nothing short of belly flopping into a pool of rusty nails and sadness.
Don’t get me wrong. We love Angular here at Cloudspace and it’s our front end framework of choice for most split stack applications. However, as a light front end layer for a Rails app….no. Just no. For all the fun directives, controllers, filters, and animation helpers give you, the battle for ownership over business logic, routing, and other kinds logic becomes a fierce neverending struggle driving you closer and closer to the bar for happy hour.
All I can say is that React on Rails has made full stack development fun for me again.
Ruby on Rails is a full encompassing web application framework. It’s goal is to be the one platform for you application and glue together any extra components you need through the use of gems and engines. Ruby on Rails on it’s own however, is terrible at complex and highly interactive user interfaces.
Like everything in Ruby, react-rails is just a gem. The install instructions can be found on their github page here, but they fundamentally come down to just installing a gem and running a generator. https://github.com/reactjs/react-rails
When generated, the gem adds a components directory to your assets directory and allows you to write in Facebook’s flavor of JSX. You also have access to view helpers that will render those components inline with your HAML or ERB.
A Bit on Web Components
This would build a navbar contained to the custom root element that we specify. This is highly reusable, and should ideally carry very few dependencies.
The react-rails gem fully embraces the web component philosophy while at the same time, embraces web component like structures as a part of the Rails framework. They are treated as just another layer on top of models, views, and controllers. This pattern might better be thought of as Model, View, Controller, Web Component. Just promise to not abbreviate that as MVCWC. We really don’t need more acronyms.
You can generate a new component by just running a generator like you would a model, controller, or a migration.
This will add a new base React component in your assets directory and exposes an associated view helper.
This allows your React class to act on a new level below your view, like a directive might in Angular. This, my friends, acts like a component.
Example Project: From Database to Graph
The following files show how we might implement a d3 bar graph detailing the number of blog posts per topic in an application. You can see how we just allow data to move in a linear fashion from the database, to the model, to the controller, to the view, and eventually to the bar graph.
The full project can be viewed here. https://github.com/cloudspace/react-rails-blogpost
Step 1: Setup
Add to your gemfile
Step 2: Scaffold your Model
We don’t need anything really complex for our data layer. Really we just want the supporting elements to make a graph possible. So, we’re going to run the default scaffold for a model.
rails g scaffold Post topic:string content:string title:string
This will build our model
Step 3: Create some Seed Data
In your seeds file, you’re going to want to create a few posts to work with when we migrate the database. So, just add the following.
Step 4: Build a Method to Pull Down Data
Our graph is going to need our data in a certain format to work with. Make the Post model look like this. Since this method makes use of all of the Posts, we put it on the class level.
In our PostsController we’re also going to want to grab hold of this data from the model and pass it to the view like so.
Step 5: Generate a Component
Step 6: Building the Graph
We’re going to make the graph component look like this. Since, this isn’t a D3.JS post, I won’t go too much into how the graphing logic works, but I will point out what is custom, and what React is expecting.
React is expecting two properties in this particular object to exist, ‘propTypes’, and ‘render’. All React components are duck typed to expect a variety of different methods that hook into different steps of compilation and validation. In this case, we only care that the types that we pass in are correct and translated from Rails to JSX, as well as that we actually render the graph.
Everything else is custom to how we want our component to actually work. For example, the xScale and yScale functions just help us abstract out some of the D3 code to be a bit more readable.
Step 7: Including our component
It’s not going to look very pretty, but all we care about right now is that we can see the graph. Head over to
app/posts/index.html.erb and add the following right under the h1 tag.
React-rails will handle the translation of data as it moves between languages for us. Stats is a Ruby hash, yet will be an object literal when we jump to our JSX code.
Step 8: Styling our Graph
We don’t need much style, but we do want to make sure that graph works and looks semi decent, especially since our graphing logic in the component has no styling whatsoever. Create a new sass file named chart.scss and add the following.
Componentizing your front end can do wonders for your web apps, especially in a world where spaghetti jQuery runs amuck. React is just one solution, but there are several options out there that can help you achieve a similar result. I hope that next time you start a Rails app though, that you will give React, or a similar component like framework a try.