Organizing javascript & stylesheets

I created a new rails app and I want to attach client side behavior to an action. Where should my javascript go? How do I make sure my javascript only executes for a single action? How can I isolate my CSS classes to a single action or controller? These are common questions from newbies. We already have fantastic ways to organize controllers, actions, and routes, but we need something similar for javascript and CSS.

The easiest solution is to decorate the element with the controller and action, then use a bit of javascript to run the appropriate client side actions. CSS can be scoped to that tag as well. See the decade-old thoughtbot flutie gem for an example of this pattern.

Sample code:

<body id="todo_index" data-action="todo_index">
body#todo_index { color: red }
body#todo_show { color: green }
function todo_index() { alert("hi"); }

const actions = {
  todo_index,
  todo_show,
};

function onReady() {
  const actionName = document.querySelector('body').dataset.action;
  const action = actions[actionName];
  if (action) {
    action();
  }
}
3 Likes

I think you will love StimulusJS https://stimulusjs.org

2 Likes

sounds a lot like GitHub - ViewComponent/view_component: A framework for building reusable, testable & encapsulated view components in Ruby on Rails.

in my experience view components really help with view-related stuff, which Rails isn’t … particularly great at.

Executing some JS code for a single page has been a WTF for me too since the early days.

Not that it’s hard to do with a bit of hacking, but there is no official guidance on how to do that in Rails, although this is a pretty common use case.

What is the best Rails-sanctioned way to do this?

I don’t know that I would call this “rails-sanctioned” but I would look at why it’s single-page JS code. In general, I find that “single-page” JS is actually “single-component” JS, so I name the component and put the JS in with the rest of my JS.

1 Like

I really think something like Stimulus is the answer here. Assuming you aren’t looking to add a full-blown frontend framework like Vue or React or whatever, using Stimulus is a great way to go because you can build controllers for each little piece of functionality… Or you can literally throw a giant layout div on your page and have the Stimulus controller take it away from there. It’s up to you how you want to structure it, but thankfully Stimulus handles all the hard parts like figuring out which bits of code to run at which times for what things on each page.

2 Likes