I’m having tremendous difficulty doing something that I thought should be pretty straightforward in RoR: integrating some vanilla JS.
I have a website design that was previously static: just an HTML file, a CSS file, and a JS file inside of a folder. I want to graft these 3 files into an RoR project and serve it on the web.
The HTML part was easy. Just create a route, a controller action, and a view. I then copy/pasted my HTML code into this view and it worked.
The CSS was fairly easy. After a couple of tries, I discovered I could just copy/paste the CSS file itself into the app/assets/stylesheets folder and the require_tree inside of application.css did the rest.
Then I got to JS. This has been very frustrating so far. All I want is to have a properly integrated JS file in the Rails asset pipeline so that I don’t have to do something messy like including all the JS code in a script tag at the bottom of the view.
The documentation isn’t very clear, and all the “solutions” I’ve run into seem incredibly kludgy and improper. There also seems to be multiple competing solutions with various levels of complexity. I don’t even know which one to pursue.
Am I the only one discovering that integrating some simple JS is way harder than it should be? Ideally I would just like to be able to take this JS file, drop it into my Rails app, and have the HTML find the JS to do some simple interactivity.
If you’re accustomed to using a script tag to reference your simple external JS file, you can simply plop that file into your public folder somewhere, add a script tag with a root-anchored path to that file, and “Robert is your mother’s brother”. Let’s say you put my-cool.js in [project folder]/public/js/. Either the page template (if you only want to use this on one or a few pages) or your application layout will add a script tag like so:
<%= javascript_include_tag '/js/my-cool.js' %>
Now, that is not going to get you the automated gzip compression, any “uglifying” or other modern conveniences, but if your experience so far has been a manually-coded static site, then you’re not missing anything, either.
If your app has Sprockets enabled (and it should, as it’s still in the defaults), then you can also get the same effect by putting the JS file in [project folder]/app/assets/javascripts and adding a reference to it in the assets.rb initializer. That would look like this (ripped from a current project):
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
Rails.application.config.assets.precompile += %w[owl-carousel.js]
Now, that file can be referenced in a single template or the global layout like this:
And that will get the whole gzip treatment, a fingerprint (MD5 of the file source in the filename) and all the automatic discovery convenience of any other asset in a modern Rails app.
You, my friend, are amazing. Both methods worked perfectly. THANK YOU.
I’m glad that the solution is simple, but I’m really miffed that these easy instructions aren’t in the docs or in every guide. I can’t be the only one that just wants to include some vanilla CSS and JS.
Thanks man, it was really difficult to understand how to add custom javascript to my rails app, but I have a question, which is the difference between this two options? , and it has some difference at the moment of deploy my app to some server?, thanks in advance.
The first option is just using raw, unmodified JavaScript in HTML, like it’s 1998 or so. No compression, none of the other niceties of modern day code. The second option gives you the full power of the classic Rails asset pipeline, which preceded all the modern Node tooling by quite a few years, and still provides a good mix of developer-centered ergonomics and great browser performance improvements. It handles cache busting automatically, and also allows you to set years-long expiration dates without fear.
It’s no replacement for ESBuild or other build tools, mainly because all kinds of plugins and extensions are currently available for those, while Sprockets has stayed pretty much the same for decades. But it was science fiction when it came out, and it feels like the JS world had to rebuild it a couple dozen times before they settled on something equivalent. If they would just pick something and stick with it…