Setup

How to prepare your app to use StimulusReflex

Command-Line Install

StimulusReflex relies on Stimulus, an excellent library from the creators of Rails. You can easily install StimulusReflex to new and existing Rails 6 projects. For Rails 5.2, see here.

The terminal commands below will ensure that both Stimulus and StimulusReflex are installed. It creates common files and an example to get you started. It also handles some of the configuration outlined below, including enabling caching in your development environment.

New projects
Existing projects
New projects
rails new myproject --webpack=stimulus
cd myproject
bundle add stimulus_reflex
bundle exec rails stimulus_reflex:install
Existing projects
bundle exec rails webpacker:install:stimulus
bundle add stimulus_reflex
bundle exec rails stimulus_reflex:install

StimulusReflex requires Redis be installed and running. If you don't have Redis, you can learn more on the Redis site.

And that's it! You can start using StimulusReflex in your application.

Manual Configuration

Some developers will need more control than a one-size-fits-all install task, so we're going to step through what's actually required to get up and running with StimulusReflex in your Rails 6+ project. For Rails 5.2, see here.

StimulusReflex requires Redis be installed and running. If you don't have Redis, you can learn more on the Redis site.

First, the easy stuff: let's make sure we have Stimulus installed as part of our project's Webpack configuration. We'll also install the StimulusReflex gem and client library before enabling caching in your development environment. An initializer called stimulus_reflex.rb will be created with default values.

bundle exec rails webpacker:install:stimulus
bundle add stimulus_reflex
yarn add stimulus_reflex
rails dev:cache
bundle exec rails generate stimulus_reflex:config

We need to modify our Stimulus configuration to import and initialize StimulusReflex, which will attempt to locate the existing ActionCable consumer. A new websocket connection is created if the consumer isn't found.

app/javascript/controllers/index.js
app/javascript/controllers/index.js
import { Application } from 'stimulus'
import { definitionsFromContext } from 'stimulus/webpack-helpers'
import StimulusReflex from 'stimulus_reflex'
import consumer from '../channels/consumer'
const application = Application.start()
const context = require.context('controllers', true, /_controller\.js$/)
application.load(definitionsFromContext(context))
StimulusReflex.initialize(application, { consumer })

Cookie-based session management is not currently supported by StimulusReflex. We will set our session management to be managed by the cache store, which in Rails defaults to the memory store.

config/environments/development.rb
Rails.application.configure do
config.session_store :cache_store
# ....
end

Configure ActionCable to use the Redis adapter in development mode:

config/cable.yml
development:
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: your_application_development

You should also add the action_cable_meta_taghelper to your application template so that ActionCable can access important configuration settings:

app/views/layouts/application.html.erb
<head>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= action_cable_meta_tag %>
</head>

Upgrading, package versions and sanity

In the future, should you ever upgrade your version of StimulusReflex, it's very important that you always make sure your gem version and npm package versions match.

Since mismatched versions are the first step on the path to hell, by default StimulusReflex won't allow the server to start if your versions are mismatched.

If you have special needs, you can override this setting in your initializer. :warn will emit the same text-based warning but not prevent the server process from starting. :ignore will silence all mismatched version warnings, if you really just DGAF. ¯\_(ツ)_/¯

config/initializers/stimulus_reflex.rb
StimulusReflex.configure do |config|
config.on_failed_sanity_checks = :warn
end

Authentication

If you're just experimenting with StimulusReflex or trying to bootstrap a proof-of-concept application on your local workstation, you can actually skip this section until you're planning to deploy.

Out of the box, ActionCable doesn't give StimulusReflex the ability to distinguish between multiple concurrent users looking at the same page.

If you deploy to a host with more than one person accessing your app, you'll find that you're sharing a session and seeing other people's updates. That isn't what most developers have in mind!

When the time comes, it's easy to configure your application to support authenticating users by their Rails session or current_user scope. Just check out the Authentication page and choose your own adventure.

Session Storage

We are strong believers in the Rails Doctrine and work very hard to prioritize convention over configuration. Unfortunately, there are some inherent limitations to the way cookies are communicated via websockets that make it difficult to use cookies for session storage in production.

We default to using the :cache_store for config.session_store (and enabling caching) in the development environment if no other option has been declared. Many developers switch to using the redis-session-store gem, especially in production.

You can learn more about session storage on the Deployment page.

Logging

StimulusReflex supports both client and server logging of Reflexes.

ViewComponent Integration

There is no special process required for using view_component with StimulusReflex. If ViewComponent is setup and running properly, you're already able to use them in your Reflex-enabled views.

Many StimulusReflex + ViewComponent developers are enjoying using the view_component_reflex gem, which automatically persists component state to your session between Reflexes.

Rails 5.2+ Support

To use Rails 5.2 with StimulusReflex, you'll need the latest Action Cable package from npm: @rails/actioncable

  1. Replace actioncable with @rails/actioncable in package.json

    • yarn remove actioncable

    • yarn add @rails/actioncable

  2. Replace any instance of import Actioncable from "actioncable" with import { createConsumer } from "@rails/actioncable"

    • This imports the createConsumer function directly

    • Previously, you might call createConsumer() on the Actioncable import: Actioncable.createConsumer()

    • Now, you can reference createConsumer() directly

There's nothing about StimulusReflex 3+ that shouldn't work fine in a Rails 5.2 app if you're willing to do a bit of manual package dependency management.

If you're having trouble with converting your Rails 5.2 app to work correctly with webpacker, you should check out "Rails 5.2, revisited" on the Troubleshooting page.

Polyfills for IE11

If you need to provide support for older browsers, you can yarn add @stimulus_reflex/polyfills and include them before your Stimulus controllers:

app/javascript/packs/application.js
// other stuff
import '@stimulus_reflex/polyfills'
import 'controllers'

Running "Edge"

If you are interested in running the latest version of StimulusReflex, you can point to the master branch on Github:

package.json
"dependencies": {
"stimulus_reflex": "hopsoft/stimulus_reflex#master"
}
Gemfile
gem "stimulus_reflex", github: "hopsoft/stimulus_reflex"

Restart your server(s) and refresh your page to see the latest.

It is really important to always make sure that your Ruby and JavaScript package versions are the same!

Running a branch to test a Github Pull Request

Sometimes you want to test a new feature or bugfix before it is officially merged with the master branch. You can adapt the "Edge" instructions and run code from anywhere.

Using #335 - tab isolation mode v2 as an example, we first need the Github username of the author and the name of their local branch associated with the PR. In this case, the answers are leastbad and isolation_optional. This is a branch on the forked copy of the main project; a pull request is just a proposal to merge the changes in this branch into the master branch of the main project repository.

package.json
"dependencies": {
"stimulus_reflex": "leastbad/stimulus_reflex#isolation_optional"
}
Gemfile
gem "stimulus_reflex", github: "leastbad/stimulus_reflex", branch: "isolation_optional"

Restart your server(s) and refresh your page to see the latest.