ENV['false'] is true

Here is a small Ruby ENV variable gotcha I encountered and how I fixed it.

I had an environment variable controlling a feature flag:

if ENV['DISABLE_THING']
  # skip the thing
end

Set DISABLE_THING=false, reloaded the app, and… the thing was still disabled. Which made no sense. I checked the value, I double-checked the spelling, I restarted the server. Same behavior.

The problem is obvious in retrospect. Environment variables are strings. ENV['DISABLE_THING'] returns "false". And in Ruby, "false" is truthy. It’s a non-empty string, so if ENV['DISABLE_THING'] always passes. The actual value doesn’t matter as long as it’s not empty or nil.

I fixed it with three lines at the top of config/application.rb:

def ENV.truthy?(key)
  self[key].to_s.match?(/\A(true|t|1|yes|y|on)\z/i)
end

This method extends ENV to check for truthy boolean values from environment variables.

Usage:

if ENV.truthy?('DISABLE_THING')
  # skip the thing
end

The regex handles the common variants — true, t, 1, yes, y, on — and the i flag makes it case-insensitive, so TRUE, True, T all work. Everything else returns false: false, f, 0, no, n, off, and nil all land in the same bucket.

Nil is the one to watch. ENV['MISSING_KEY'] returns nil, and the .to_s in the method converts it to "", which doesn’t match the regex. So missing keys are treated as false by default. That’s usually what you want for feature flags — opt-in by setting the variable, not opt-out.

For non-boolean ENV variables I reach for ENV.fetch with a default, or .presence when I need to distinguish empty from missing:

config.asset_host = ENV["ASSET_HOST"].presence
workers_count = ENV.fetch("WEB_CONCURRENCY", 5).to_i
generator = Rails.application.key_generator

Rails.application.config.active_record.encryption.deterministic_key =
  ENV.fetch("ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY") {
    generator.generate_key("active_record_encryption_deterministic_key", 32).unpack1("H*")
  }

It’s a small thing, but I keep seeing this pattern come up in codebases. Some projects add a gem for it. Most just hand-roll it and move on. Either way, it’s one of those Ruby-isms that catches everyone at least once.

Saroj Maharjan

Senior Software Engineer building reliable Rails systems and practical AI products.

Berlin, Germany https://sarojmaharjan.com