Ruby

Rails

Load Envless variables before a Rails app is configured with the envless-env Railtie, so database.yml and every initializer see them, and hand client variables to views.

Rails reads its configuration while it boots, and config/database.yml, config/credentials, initializers and gems all read ENV along the way. The Railtie loads your Envless environment before any of that runs. Require it from your Gemfile:

Gemfile
gem "envless-env", require: "envless/env/rails"

Bundler.require in config/application.rb loads the Railtie, and the Railtie calls Envless::Env.load in before_configuration, the first hook Rails runs when your application class is defined. From then on every value is in Envless.env and in ENV, so database.yml works unchanged:

config/database.yml
production:
  adapter: postgresql
  url: <%= ENV["DATABASE_URL"] %>

Read typed values anywhere else through Envless.env:

config/initializers/stripe.rb
Stripe.api_key = Envless.env[:STRIPE_SECRET_KEY]

bin/rails server, the console, runners, Active Job and Sidekiq workers and the test suite all boot through config/application.rb, so every entry point loads before anything else runs. When the load fails, boot stops with Envless::Env::LoadError and its message, instead of an app that starts with a hole in its configuration.

Client variables in views

The Railtie adds an envless helper to every view. It returns the client variables, the ones marked client in Envless, so a template can never print a server variable through it.

app/views/layouts/application.html.erb
<%= javascript_tag do %>
  window.ENVLESS = <%= raw envless.to_json %>;
<% end %>

Building assets

bin/rails assets:precompile boots the app, so it loads too and needs the same credentials. In a Docker build, run the task under envless run, which injects the values without putting a key in the image:

bash
envless run --env production -- bin/rails assets:precompile

Tests

The test suite boots the app like any other entry point, so tests load from Envless too. Point a CI job at a test environment with its own machine key, or run the suite under envless run --env test -- bin/rails test, which needs no key in the process at all. Layer a value for one test with Envless::Env.override.