Back To Front: Rails To Facebook’s Flux/React

Soon Hin Khor, Ph.D.
Code Oil
Published in
6 min readSep 14, 2015

This is for you if:

  1. You have a Rails back-end, and you want to develop a rich web UI
  2. You want to use Facebook’s Flux framework with React for the UI
  3. You prefer to use Facebook’s plain vanilla Flux implementation

There is a dearth of documentation on getting Facebook’s plain vanilla Flux implementation to work with Rails, which this article hopes to fill.

Bonuses:

  • If you are already using ‘react-rails’ gem, how to integrate with Flux
  • Deploy Rails with Flux onto Heroku
  • Deploy Rails with Flux onto non-Heroku Platforms

You can forego all the explanation about the components involved, and skip to installation in the Get Cracking section.

Why do we need to choose a Flux implementation?

Flux is more pattern than framework, and there has been no lack of implementations. Some are better documented, have shinier features, or are more opinionated than others. For those who are worried about the conformance to specifications or future support of those implementations, going with Facebook’s plain vanilla Flux may help you sleep better.

Overview

Assumptions:

  • You have Rails installed (tested on Rails 4 only)

Goal:

  • Setup Flux on Rails so that we can create our own Rails/Flux/React application based on Facebook’s Flux Todo example tutorial

Why this is difficult:

The Facebook tutorial:

What we will cover:

  • How to get all the Javascripts required by Facebook’s Flux on to Rails
  • Where to put your own Flux/React code within Rails
  • How to use the official dispatcher within your Flux/React application
  • Deployment

Embrace Javascript in Rails

Getting Facebook’s Flux to work in Rails is no different from getting a bunch of related Javascripts into Rails. There are many ways; the main idea behind all is:

  1. Get the required Javascripts into a location that we can inform Rails
  2. Get Rails to bundle them into its asset pipeline

In our case, for 1., we use npm (nodejs package manager), and for 2. we use Rails browserify-rails gem. Arkency’s article advocates the same approach.

I will not go into details of other ways but will link you to resources. You could have used:

npm: Manage and Install Javascripts

npm is very useful to:

  • Manage Javascript dependencies and version compatibility between your Javascripts (think bundler for Javascripts)
  • Install required packages from the web into a single location

To install any package, do:

# Command-line 
npm install --save <package name>

npm downloads the package into ‘./node_modules/’, and the ‘ — save’ option saves information about the package into package.json, which serves the same purpose as Rails Gemfile.

Rails is totally unaware of npm’s presence. Rails only needs to know that it needs to bundle Javascripts in ‘./node_modules/’ into its assets pipeline.

browserify: Bundle Javascripts into a Single File

browserify bundles multiple Javascript files into a single file, which makes adding to web pages simple, i.e., only a single <script> tag is required on web pages.

# HTML file
<script src=‘bundle.js’></script>

browserify-rails does something similar; by default, it looks for Javascript files in ‘./node_modules/’ and ‘app/’, and bundle them into the Rails assets pipeline.

Get Cracking

  • Install npm (this is OS dependent so please refer to the npm website)
# For MacOS, use homebrew
brew install node
  • Create a package.json for npm use (Thanks to cantbecool)
npm init
  • Install browserify-rails
# Gemfile
gem ‘browserify-rails’
# Command-line
bundle install
  • Install Facebook’s Flux
# Command-line# Facebook's Flux implementation
npm install --save flux
  • Optionally, install other Javascript modules required by the tutorial
# Command-line# We create Flux Stores based on Events EventEmitter
npm install --save events
# Use for object property assign
npm install --save object-assign
# Use for simplify writing asynchronous event handling
npm install --save es6-promise
  • Mimic the recommended directory structure in ‘app/assets/javascripts/flux/’, and create your Stores, Actions, etc., under the respective directories
+ app
|
+ assets
|
+ javascripts
|
+ flux
|
+ actions
+ components
+ constants
+ dispatcher
+ stores
  • Create a dispatcher based on Facebook’s plain vanilla Dispatcher
    in ‘app/assets/javascripts/flux/dispatcher/AppDispatcher.js
// app/assets/javascripts/flux/dispatcher/AppDispatcher.jsvar Dispatcher = require(‘flux’).Dispatcher;
module.exports = new Dispatcher();

Wait, what about React?

If you started out with React using ‘react-rails’ gem, prior to this, skip to the Integrating Flux with ‘react-rails’ Gem section.

Otherwise to get React working, we need additional Javascript modules:

# Command-line# With this, we can do "require(‘react’)", which is required
# before we can do React.createClass( … ) in JSX files
npm install --save react
# Enables browserify to compile JSXfiles
npm install --save reactify

And some configuration, to tell browserify-rails, how to recognize JSX files, i.e., by file extension ‘.react.js’, and to use reactify module to convert them into Javascript for bundling into Rails assets pipeline.

# config/application.rb# Declare the file extensions of your jsx files
config.browserify_rails.commandline_options = “-t reactify — extension=\”.react.js\””

We can now create React components in ‘app/assets/javascripts/flux/components’.

For debugging purposes, add:

# config/application.rb# Produce source maps when using Browserify to enable debugging
config.browserify_rails.source_map_environments << ‘development’

Bonus #1: Integrating Flux with ‘react-rails’ Gem

If you are currently using ‘react-rails’, React will just work as it is:

  • Your React components can remain in ‘app/assets/javascripts/components/’ or wherever they are
  • Your React components can use the Store, Actions, etc. that you have created in Flux. Just declare your Flux components in ‘app/assets/javascripts/application.js’, and you can access them elsewhere in your code.
// app/assets/javascripts/application.jsTodoStore = require(‘flux/stores/TodoStore’);
TodoActions = require(‘flux/actions/TodoActions’);
TodoConstants = require(‘flux/constants/TodoConstants’);
// You can now use call TodoStore, TodoActions, TodoConstants
// from your React components, e.g., in TodoApp, you can call
// TodoStore.getAll().
  • Addendum: In the last part of the tutorial, the TodoApp is mounted from ‘app.js’. For Rails, use the 2 Javascript snippets below instead. ‘app/assets/javascripts/application.js’ makes the TodoApp available to other parts of the code and ‘app/views/home/index.html’ mounts the TodoApp.
// app/assets/javascripts/application.js// Make React available to other parts of your code as ReactJS
// We will use ReactJS from index.html where we mount TodoApp
ReactJS = require(‘react’);
// Make TodoApp available to index.html that will mount it
// NOTE: We use createFactory because
// we are going to use TodoApp from index.html which
// is not compiled as jsx
// See: http://facebook.github.io/react/blog/2014/10/14/introducing-react-elements.html#react-without-jsx
TodoApp = ReactJS.createFactory(require(‘flux/components/TodoApp.react’));
// app/views/home/index.html
<script>
ReactJS.render(
React.createElement(AlertApp),
document.getElementById(‘haha’)
);
</script>

Bonus #2: Deploying Rails with Flux onto Heroku

We do not check-in Javascript modules installed by npm in ‘./node_modules/’ into our code repository, much like we do not check-in Ruby gems installed by bundler.

Instead we check-in ‘./package.json’, just like we would check in Gemfile, and Gemfile.lock.

By calling ‘npm install’, we can install the required Javascript modules specified by ‘./package.json’ in any new environment where we clone our code repository, such as Heroku, much like calling ‘bundle install’.

Thus to deploy Rails with Flux onto Heroku we need to instruct Heroku to:

  • Build using both bundler and npm by creating ‘.buildpacks’ file in your application’s root directory
https://github.com/heroku/heroku-buildpack-nodejs
https://github.com/heroku/heroku-buildpack-ruby
  • Use a buildpack that supports different tooling
# Command-line
heroku buildpacks:set https://github.com/heroku/heroku-buildpack-multi.git

Bonus #3: Deploying Rails with Flux (non-Heroku)

For reference, please read this Arkency blog.

If you pre-compile assets, then its business as usual:

# Command-line
rake assets:precompile

Else, install nodejs/npm on your production server and use the rake tasks provided by browerify-rails:

# Command-line
rake npm:install:clean

That’s it! Please help me improve this article by pointing me to errors, etc.

--

--

Soon Hin Khor, Ph.D.
Code Oil

Use tech to make the world more caring, and responsible. Nat. Univ. Singapore, Carnegie Mellon Univ, Univ. of Tokyo. IBM, 500Startups & Y-Combinator companies