How to get the current Rack environment in Rake?

17,345

Solution 1

Question is old but never fetched the best practice answer or a satisfying answer at all.

The real question is: How to go sure which environment is used in a Rake task in order to load the correct configuration / hitting into correct if-conditions.

Note: As Rake doesn't give much about Rack (Rake is not using HTTP) to rely on the RACK_ENV is basically wrong but common and handy if a Rake task loads your main Sinatra application (the RACK_ENV is required to let Sinatras development? / test? / production? being set correctly).

The answer: Set the environment with each Rake task call.

Command line call:

/usr/bin/rake namespace:task_name RACK_ENV=production

Cronjob call (in crontab):

cd /into/your/app/root && /usr/bin/rake namespace:task_name RACK_ENV=production --silent

Note: To specify the path of the Rake bin is not necessary if you have it in your global system variables. Your path might differs from mine used in the examples, check on Unix systems with: whereis rake

You can check the RACK_ENV in your tasks via:

puts ENV["RACK_ENV"]

Solution 2

As other environment variable, you can retrieve it using:

ENV['RACK_ENV']

Considering it's a Sinatra application, and that you've set the environment into config/environment.rb, you can add the following to your Rakefile:

task :environment do
  require File.expand_path('config/environment', File.dirname(__FILE__))
end

task :your_task => :environment do
  # task
end

Then, you can retrieve the environment (depending how you set it up in your environment.rb) with ENV['RACK_ENV'] or Sinatra::Application.environment.

Considering there isn't a config/environment.rb config file, only the application file, for instance hello_world.rb, the following works:

hello_world.rb:

require 'sinatra'

set :environment, :production

get '/' do
  'Hello World'
end

Rakefile:

task :environment do
  require File.expand_path('hello_world', File.dirname(__FILE__)) # your Sinatra app
end

task :your_task => :environment do
  puts Sinatra::Application.environment
end

When doing rake your_task you should obtain:

> rake your_task
production

Solution 3

After 2.5 years, I want to share what I've found to be the best solution.


Create a .env file in the root folder of the application, and add a flag specifying the application environment:

ENVIRONMENT=development

Then use Brandon Keepers' dotenv gem to load all environment variables from this file. Now you can use any environment variables specified in .env within Rake tasks.

Rake will rely on the explicit value set in .env, so you must create separate .env files for each environment you plan on using (e.g. dev, test, staging, production, etc).

Sample Rakefile:

require 'dotenv/tasks'

task :default => :help

desc 'Show this help menu'
task :help do
    puts "Available rake tasks:"
    system('rake --tasks')
end

# Will run in any environment
desc 'Demo task'
task :demo_task => :dotenv do
    puts "Running demo task in '#{ENV['ENVIRONMENT']}' mode"
end

# Will only run if ENVIRONMENT value in .env file is set to 'production'
desc 'Production-only task'
task :production_task => :dotenv do
    if ENV['ENVIRONMENT'] == 'production'
        puts "Running 'Production-only' task"
    else
        puts "Won't run, because the environment is not set to PRODUCTION!"
    end
end

# Will only run if ENVIRONMENT value in .env file is set to 'development'
desc 'Development-only task'
task :dev_task => :dotenv do
    if ENV['ENVIRONMENT'] == 'development'
        puts "Running 'Development-only' task"
    else
        puts "Won't run, because the environment is not set to DEVELOPMENT!"
    end
end

If you want to use the environment variables within your Rack or Sinatra app (which you probably do), add the following to the application's config or bootstrap block:

require 'dotenv'
Dotenv.load
Share:
17,345
Arman H
Author by

Arman H

"In theory, theory and practice are the same. In practice, they’re not." - Yoggi Berra “Any code of your own that you haven't looked at for six or more months might as well have been written by someone else. ” - Eagleson's law “The first 90% of the code accounts for the first 90% of the development time. The remaining 10% of the code accounts for the other 90% of the development time. ” - Tom Cargill “To iterate is human, to recurse divine.” - L. Peter Deutsch "To err is human... to really foul up requires the root password." “Software sucks because users demand it to. ” - Nathan Myhrvold “If debugging is the process of removing software bugs, then programming must be the process of putting them in. ” - Edsger Dijkstra "Measuring programming progress by lines of code is like measuring aircraft building progress by weight." - Bill Gates “It's hard enough to find an error in your code when you're looking for it; it's even harder when you've assumed your code is error-free. ” - Steve McConnell “Walking on water and developing software from a specification are easy if both are frozen. ” - Edward V Berard “Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. ” - Brian Kernighan “Computer science education cannot make anybody an expert programmer any more than studying brushes and pigment can make somebody an expert painter.” - Eric S. Raymond “Most of you are familiar with the virtues of a programmer. There are three, of course: laziness, impatience, and hubris.” - Larry Wall "Perl – The only language that looks the same before and after RSA encryption." - Keith Bostic "The last good thing written in C was Franz Schubert's Symphony No. 9." - Werner Trobin "XML is like violence - if it doesn’t solve your problems, you are not using enough of it." - Nokogiri "Brooks's Law: Adding manpower to a late software project makes it later." - Fred Brooks "Some people, when confronted with a problem, think 'I know, I'll use regular expressions." Now they have two problems.'" - Jamie Zawinski "It should be noted that no ethically-trained software engineer would ever consent to write a DestroyBaghdad procedure. Basic professional ethics would instead require him to write a DestroyCity procedure, to which Baghdad could be given as a parameter." - Nathaniel Borenstein "There are two major products that come out of Berkeley: LSD and UNIX. We don't believe this to be a coincidence." - Jeremy S. Anderson "... one of the main causes of the fall of the Roman Empire was that, lacking zero, they had no way to indicate successful termination of their C programs." - Robert Firth "Saying that Java is nice because it works on all OSs is like saying that anal sex is nice because it works on all genders." - Alanna

Updated on June 22, 2022

Comments

  • Arman H
    Arman H almost 2 years

    Is there a way to get information about the current Rack environment in Rake? For example, how can I tell whether Rack is running in development or production mode?

    I understand that Rake is not Rack-aware. I'm trying to avoid replicating code in nearly-identical Rake tasks between production and dev environments.

  • Arman H
    Arman H about 11 years
    Doesn't work. Here's a simple Rakefile to illustrate: task :test_rack_env do puts ENV['RACK_ENV'] end Prints a blank line.
  • toch
    toch about 11 years
    Where do you set the Rack environment to production or development?
  • Arman H
    Arman H about 11 years
    I'm using Sinatra, so it sets the environment.
  • toch
    toch about 11 years
    @ArmanH I've updated my answer. Hope it will help you this time.
  • Arman H
    Arman H about 11 years
    Thanks for the expanded answer; however, there is no config file in a Sinatra app, and the environment is not being set through it. Instead, Sinatra uses set :environment, :production.
  • toch
    toch about 11 years
    @ArmanH I've updated my answer considering you just have one Sinatra app where you have set up the environment.
  • wgp
    wgp over 8 years
    I usually have an :environment task that all other tasks depend on. Within that I always set default values any other task would need. So I'd go further and suggest defining ENV['RACK_ENV'] ||= 'development' either at the top of the Makefile or inside of an :environment task.
  • EricC
    EricC over 8 years
    Thanks! Exactly what I'm looking for! Just to clarify, to use different .env files for different environments, do you use avdi's approach or some other mechanism for rake to pick up env vars in different .env files?
  • Arman H
    Arman H over 8 years
    To test production settings locally, I have a file called .env.production, which I switch out with .env while running tests (renaming the local env file to .env.local while testing).