Stimulus Discourse

Organize controllers in Rails app without webpacker


#1

Hi,

I’m wondering. What’s your recommendation on file organization for a Rails application that’s not using a build system?

For example, let’s say a Rails 5.1 app without webpacker. I saw the doc from https://stimulusjs.org/handbook/installing#using-without-a-build-system but it seems to suggest registering every controller in the same file, which I guess won’t be desirable for most developers.

Where would you suggest placing Stimulus controllers? How would you “share” the application object across the different _controller.js files if you are working with an application manifest with a require_tree?

Thanks


Advice Request: Stimulus + Webpack - Best practices bundle-splitting for multi-page, SSR site
#2

Were you ever able to find a good solution for sharing the application instance across the controller files? I’m starting a new project and need to find a good solution. Thanks!


#3

I’m wondering the same things.


#4

I’ve been using Stimulus in a Rails app that still uses Sprockets, where I managed to organize the controllers in separate folders and files without the use of Webpacker. The trick is to attach the running Stimulus application to the window object, which makes it accessible across multiple files.

First, ensure that you’ve installed the sprockets-es6 gem in the project if you want to use Babel and that Stimulus is added before the application manifest inside <head>:

<!-- layouts/application.html.erb -->
<script src="https://unpkg.com/stimulus/dist/stimulus.umd.js"></script>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => 'reload' %>

Then you can create a folder structure similar to the following:

javascripts/
├── application.coffee
├── initializers/
│   └── stimulus.coffee
└── controllers/
    ├── wizard.es6
    └── bootstrap/
        ├── tooltip.es6
        └── modal.es6
    

Where each file looks something like this:

# application.coffee
#= require_tree ./initializers
#= require_tree ./controllers
# initializers/stimulus.coffee
window.stimulus = Stimulus.Application.start() unless 'stimulus' of window
// controllers/wizard.es6
stimulus.register("wizard", class extends Stimulus.Controller {
  // ...
})
// controllers/bootstrap/modal.es6
stimulus.register("bootstrap--modal", class extends Stimulus.Controller {
  // ...
})
// controllers/bootstrap/tooltip.es6
stimulus.register("bootstrap--tooltip", class extends Stimulus.Controller {
  // ...
})

Hope that helps :slight_smile: