Tip: Accessing Rails environment variables from a StimulusJS Controller
Environment variables are a great way to configure your Rails apps. You can use the Rails.env
variable to conditionally change behavior when you are in development/test or production. And you can add your own application specific variables for things like API tokens or global settings.
While Stimulus has a values
API to read from HTML data attributes, sometimes you need data that you don’t want to pass in every time you create a controller.
One alternative is to use <meta>
tags when rendering your view. Then, inside your Stimulus Javascript code, you can query the <meta>
DOM element to retrieve the value.
Usage
First, add the <meta>
tag to your application template inside the <head>
section. For this example, let’s say we want to know the Rails.env
because we want to change a setting when running the app in test mode (I recently had to do this to change a setting in a 3rd-party library to work with headless system tests).
You can use the Rails tag
helper to avoid a bunch of string interpolation:
# Inside the <head> tag of your application layout
<%= tag :meta, name: :rails_env, content: Rails.env %>
This will render a <meta>
tag like:
<meta name="rails_env" content="development">
Next, in your Stimulus controller, query for the tag and read the content.
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
connect() {
if (this.isTestEnvironment) {
// Do something for testing
} else {
// Do something for dev/prod
}
}
get isTestEnvironment() {
return document.head.querySelector("meta[name=rails_env]").content === "test"
}
}
You can also extract this into a helper if you want – here is a utility function from the Rails request.js
library which uses this same <meta>
tag pattern to access the Rails CSRF token when sending Javascript requests.
function metaContent (name) {
const element = document.head.querySelector(`meta[name="${name}"]`)
return element && element.content
}
Remember that this data is visible in your page source! Unlike environment variables that only exist on the server, putting data into your HTML makes it accessible to end-users. Make sure you are only exposing data that is safe to be public.
References
MDN: metadata element