Today topic what is super simple if we are using any frameworks. Environments.

It’s nice to split our configuration between different situations. If we have some external integrations, probably we are going to use different API keys at every environment. But even when we are thinking on local stuff, every environment should use different database

By having multiple environments, you can isolate different stages of the application’s lifecycle and ensure that changes are thoroughly tested and validated before reaching the live environment. It helps reduce risks, maintain stability, and provide a better user experience

By default we are using 3 of them. Development, Production, Test. Some apps have never finished production. Some developers have never written tests. But don’t talk about weird situation. In some projects we have also stagings, preprods. On heroku is super easy to configure environment per pull request. In some projects is super useful, in some projects is super overkill. In my case everything more than 3 (Development, Production, Test) would be also overkill.

At this moment of my application. Switching to using multiple environments it’s quite easy. Rack allows use to run our application with special flag rackup -E test. We could even use separate config.ru files per environment.

In my main app I created new endpoint /environment to check current environment

It’s not necessary, but it’s nice to have for educational purposes.

when "/environment"
  [200, {"content-type" => "text/plain"}, [ENV["RACK_ENV"]]]
else

When I run rackup this endpoint returns development but, when I run test is test, we can name it whatever we want.

I can write test for it

describe "GET /environment" do
  it "returns environment name" do
    get "/environment"
    expect(last_response).to be_ok
    expect(last_response.header["content-type"]).to eq("text/plain")
    expect(last_response.body).to eq("test")
  end
end

@hich fails, ENV[“RACK_ENV”] is not set. We have to run tests with command RACK_ENV=test rspec . On CI would be easier, I have to just setup RACK_ENV in githubaction configuration.

But this is only one environment variables. I want to use more

Somehow I have to recognise what stage I have. To handle environment variables I’m using dotenv gem this days. I don’t remember any issues with it.

I can create files .env.development and .env.test

COMPONENTS_FILE=components.csv
BIKES_FILE=bikes.csv
COMPONENTS_FILE=components.csv
BIKES_FILE=bikes.csv

Now I can change my controllers, I have to load envs:

Dotenv.load(".env.development") if ENV["RACK_ENV"] == "development"
Dotenv.load(".env.test") if ENV["RACK_ENV"] == "test"

I can user file from envs

module Components
  class Controller
    def initialize
      @database = ENV["COMPONENTS_FILE"]
    end
module Bikes
  class Controller
    def initialize
      @database = ENV["BIKES_FILE"]
    end

Code is on github. In the future, it would be nice to create some helper for that, but right now it should be fine to use it as I wrote it. Before I finish and merge everything I have to set these ENVs on github actions and fly.io.