This tutorial will cover the steps in adding reactrb and react components (written in Ruby of course) to a simple rails Todo app.
The tutorial is organized as a series of branches in this repo. You are currently on the master
branch, which is the introduction (i.e. chapter 1).
The remaining branches are named chapter-2
, chapter-3
, etc.
In each branch the README
file will be the next chapter of the tutorial.
If you want to skip straight to the end then checkout chapter-8-conclusion
.
As you complete each chapter there is a test spec, which will pass if you have completed the instructions in the chapter.
At the end of each chapter you can move to the next tagged branch, where the changes described in the previous chapter will be stored
For example in this chapter we are going to add the reactrb-ruby-generator
gem to the app, and use it to install react.rb, reactive-record and reactive-router.
To see the results of these changes you can view the 02-adding-a-react-component
chapter.
Of course for best results follow along yourself:
- make sure you have rails v4 installed,
- clone this repo to your computer,
- follow the instructions for each chapter,
- Then run the test specs for the chapter:
bundle exec rspec spec/chapter-xx.rb -f d
Some chapters (like this one) have extra notes at the end of the page with details you may be interested in.
In this chapter we are going to:
- create a new rails app
- add the
reactrb-rails-generator
gem, as well as set of gems used in testing - use the
reactrb-rails-generator
gem to add everything we need to use Reactrb - add a simple Todo model to our app
- test our work
cd
into the directory that you have just cloned from github. If you do an ls
You should see something like the following:
COPY-THESE-TO-YOUR-GEM-FILE LICENSE README.md app spec
Now create a new rails in the directory with this command:
rails new -T --skip-spring .
rails is going to complain because the repo already has created the .gitignore file, so just say n
when rails asks you if it wants you to overwrite
The -T
option will skip creating the unit-test directory, and the --skip-spring
skips installing spring which does not seem to work well
with some of the test harnesses.
Now we want to edit the Gemfile and add the reactrb-rails-generator gem plus a bunch of gems used for driving the testing in this tutorial. Make the end of the Gemfile look like this:
group :development do
gem 'reactrb-rails-generator'
end
group :test do
gem "rspec"
gem "rspec-rails"
gem "rspec-mocks"
gem "rspec-expectations"
gem "pry"
gem 'pry-rescue'#, git: "https://github.com/joallard/pry-rescue.git"
gem 'pry-stack_explorer'
gem "factory_girl_rails"
gem 'shoulda'
gem 'shoulda-matchers'
gem 'rspec-its'
gem 'rspec-collection_matchers'
gem 'database_cleaner', git: "https://github.com/DatabaseCleaner/database_cleaner.git"
gem 'capybara'
gem 'selenium-webdriver'
gem "poltergeist"
gem 'spring-commands-rspec'
gem 'chromedriver-helper'
gem 'rspec-steps'
gem 'parser'
gem 'unparser'
end
Okay lets update our gems, and use the reactrb-rails-generator to add everything you need to begin Reactrb development:
- make sure you added
gem 'reactrb-rails-generator'
to the development section of your app Gemfile (per above instructions) - run
bundle install
- run
bundle exec rails g reactrb:install --all
- run
bundle update
You will now find that you have
-
a
components
directory inside ofapp/views
where your react components (which are simply react views written in ruby) will live, and -
a
public
directory inside ofapp/models
where any models that you want accessible to your components (which will run on the browser) will live. Don't worry! Access to model data is protected by a Hobo style permissions system.
Great! Now seeing as we are going to make a Todo app, we need a Todo model to hold our data: Run the following command:
- run
rails generate model Todo title:string completed:boolean
- run
rake db:migrate
- run
rake db:test:prepare
Now that we have the Todo model, lets add a couple of scopes to the model: Edit app/models/todo.rb
so it looks like this:
class Todo < ActiveRecord::Base
scope :completed, -> () { where(completed: true) }
scope :active, -> () { where(completed: false) }
end
Finally we will be accessing our Todo data on client, so we want to move the todo.rb
file into the app/models/public
directory
Any models in the public directory will be compiled for use on both the client and the server.
If all has gone well you should be able to run:
bundle exec rspec spec/chapter-1.rb -f d
which will check that everything was installed, and that the Todo model is accessible on the client!
For the next instructions : Chapter 2 - Our first React.rb Component
--reactive-router
to install reactive-router
--reactive-record
to install reactive-record
--opal-jquery
to install opal-jquery in the js application manifest
--all
to do all the above
Its recommend to install --all
. You can easily remove things later!
In case you are interested, or perhaps want to customize the install here is what happens:
-
It requires
'components'
and'react_ujs'
at the start of yourapplication.js
file.components
is your manifest of react.rb components, andreact_ujs
is part of the react-rails prerendering system. -
It adds the js code
Opal.load('components')
to the end of theapplication.js
file. This code will initialize all the ruby (opal) code referenced in thecomponents
manifest. -
If you are using reactive-record it adds
route "mount ReactiveRecord::Engine => "/rr"
to your routes file. This is how reactive record will send and receive active record model updates from the client. Note - you can change the mount path fromrr
to whatever you want if necessary. -
It adds the
components
directory toapp/views
. This is the directory that all your components will be stored in. -
If you are using reactive-record, then it also adds the
public
directory toapp/models
. Any models in this directory will have reactive-record proxies loaded on the client. -
It creates the
app/views/components.rb
manifest file. This file is a set of requires for all your ruby component code. The manifest ends with arequire_tree './components'
which in most cases should be sufficient to load all your component code from theviews/components
directory. If you have specific component load ordering needs (which is rare) you can simply require specific files before the require_tree. Note - this manifest is loaded both on the client and in the prerendering engine. Code that depends on browser specific data and functions can be conditionally loaded in the manifest so it will not load during prerendering. -
If you are using reactive-record the
components.rb
file will also requireapp/models/_react_public_models.rb
which is the manifest file for the public models, and simply contains arequire_tree './public'
directive. If you need to order how the models are loaded you can add explicit requires to this file before the require_tree. -
It adds these lines to
application.rb
config.assets.paths << ::Rails.root.join('app', 'views').to_s
If you are using reactive-record it will also addconfig.assets.paths << ::Rails.root.join('app', 'models').to_s
config.eager_load_paths += %W(#{config.root}/app/models/public)
config.autoload_paths += %W(#{config.root}/app/models/public)
The effect of these lines is that the asset pipeline can load components from the views folder, and isomorphic models can be found by both the server and asset pipeline in the models/public folder. -
Finally it adds the following gems to your
Gemfile
:gem 'reactive-ruby'
gem 'react-rails', '~> 1.3.0'
gem 'opal-rails', '>= 0.8.1'
gem 'therubyracer', platforms: :ruby
gem 'react-router-rails', '~>0.13.3'
(if using reactive-router)gem 'reactive-router'
(if using reactive router)gem 'reactive-record'
(if using reactive-record)