rails 4: Rails.env is different from ENV["RAILS_ENV"] - ruby-on-rails

I set in my config/environment.rb file ENV["RAILS_ENV"] = "production" in order to run my server on my machine (using rails server) and get the production behavior. I have a lot of lines in my code that check if Rails.env.production? to assign a different functionality for some of the app components.
My problem is that when I check the environment in one of my controller I get different results for Rails.env and ENV["RAILS_ENV"]. The first will show "development" while the second will be "production".
Shouldn't both of the methods return the same value?

By the time config/environment.rb is evaluated you're just modifying the ENV hash. If you want to run your app in production set the RAILS_ENV environment variable in the shell you use to run rails.
RAILS_ENV=production bundle exec rails c

To run your rails server in production mode run :
rails s -e production
And to answer your actual question :
Rails.env uses ENV["RAILS_ENV"] internally, see :
https://github.com/rails/rails/blob/d25fe31c40928712b5e08fe0afb567c3bc88eddf/railties/lib/rails.rb#L59-L61
def env
#_env ||= ActiveSupport::StringInquirer.new(ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development")
end
but ENV["RAILS_ENV"] which is actually not set till now, so the option that is passed with -e if passed while the rails server command is triggered comes into picture, see:
https://github.com/rails/rails/blob/3e36db4406beea32772b1db1e9a16cc1e8aea14c/railties/lib/rails/commands/server.rb#L62-64
def set_environment
ENV["RAILS_ENV"] ||= options[:environment]
end
for environment option see:
https://github.com/rails/rails/blob/3e36db4406beea32772b1db1e9a16cc1e8aea14c/railties/lib/rails/commands/server.rb#L31
opts.on("-e", "--environment=name", String,
"Specifies the environment to run this server under (test/development/production).",
"Default: development") { |v| options[:environment] = v }
and all this is happening before your applications environment.rb is executed.
Hope this helps.

Related

Does ENV['RAILS_ENV'] and ENV['RACK_ENV'] need to be set in staging and production?

ENV['RAILS_ENV'] and ENV['RACK_ENV'] in development. returns development. In staging or production, it returns nil. Are we supposed to explicitly set these two environment variables for the staging and production environments?
Does Rails expect this to be set?
I also notice the following. I have this intializer: config/initializers/01_redis.rb:
redis_connection = Redis.new(host: URI.parse(ENV['REDIS_SERVER_URL']).host, port: URI.parse(ENV['REDIS_SERVER_URL']).port)
$redis = Redis::Namespace.new(Rails.env.to_sym, redis: redis_connection)
When this file is inspected in staging. Rails.env.to_sym is interpreted as :development. Moreover, running Rails.env in Rails console, in staging, returns staging. Perhaps Rails needs ENV['RAILS_ENV'] and ENV['RACK_ENV'] prior to initializing the Rails app.
What are your thoughts?
Rails needs to know what environment is it running on. The specific part of code can be found at https://github.com/rails/rails/blob/master/railties/lib/rails.rb#L69
def env
#_env ||= ActiveSupport::StringInquirer.new(ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development")
end
If you want to work in production mode, yes, you should set that environment variable.
However, some servers set the variable for you. For example, Apache Passenger, defaults to production and does exactly that.
https://www.phusionpassenger.com/library/config/apache/reference/#passengerappenv

config.ru file for Rails 2.3.18 app

Does anyone know what the contents of config.ru should be for a Rails 2.3.18 app in production to run on Passenger/Unicorn/Puma?
So far I've got:
# Require your environment file to bootstrap Rails
require ::File.dirname(__FILE__) + '/config/environment'
# Dispatch the request
run ActionController::Dispatcher.new
but it's loading development instead of the correct production environment.
It turns out this is a perfect config.ru.
The real problem is that Unicorn's -E parameter sets RACK_ENV and Rails 2.3.18 needs RAILS_ENV in order to correctly detect the environment.
So, at the top of config/environment.rb, I've set ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] and this is working just great.

Gem stalker on production

I'm using Stalker to interact with beanstalkd on a production server. My jobs file looks like this:
gem 'stalker'
# config/jobs.rb with Rails
RAILS_ENV = ENV["RAILS_ENV"] || "development"
require File.expand_path("../environment", __FILE__)
job "mapeamento_paciente.importar" do |args|
mapeamento = Mapeamento::Paciente.find(args['id'])
importador = ImportadorPaciente.new(mapeamento)
importador.importar!
end
I'm trying to start stalker by issuing the command:
bundle exec stalk config/jobs.rb RAILS_ENV=production
But on loading the environment file, Rails tries to access the development database, instead of production, issuing an error. Does anybody knows how to solve this issue!?
Thanks!
RAILS_ENV=production bundle exec stalk config/jobs.rb

How to detect Rails environment inside whenever

This question will probably only make sense if you know about the whenever gem for creating cron jobs.
For my app, I want to use whenever in all the environments, including testing and development.
My schedule.rb looks like this:
set :output, {
:error => "#{path}/log/error.log",
:standard => "#{path}/log/cron.log"
}
set :environment, Rails.env.to_sym
every 5.minutes do
rake 'db:activity:synchronize'
end
but it fails on Rails.env.to_sym (and the same stands for RAILS_ENV):
/home/marius/.rvm/gems/ruby-1.9.2-p290#uxolo/gems/whenever-0.6.8/lib/whenever/job_list.rb:21:in `eval': uninitialized constant Whenever::JobList::Rails (NameError)
from /home/marius/.rvm/gems/ruby-1.9.2-p290#uxolo/gems/whenever-0.6.8/lib/whenever/job_list.rb:21:in `eval'
from /home/marius/.rvm/gems/ruby-1.9.2-p290#uxolo/gems/whenever-0.6.8/lib/whenever/job_list.rb:21:in `initialize'
from /home/marius/.rvm/gems/ruby-1.9.2-p290#uxolo/gems/whenever-0.6.8/lib/whenever.rb:15:in `new'
from /home/marius/.rvm/gems/ruby-1.9.2-p290#uxolo/gems/whenever-0.6.8/lib/whenever.rb:15:in `cron'
from /home/marius/.rvm/gems/ruby-1.9.2-p290#uxolo/gems/whenever-0.6.8/lib/whenever/command_line.rb:41:in `run'
from /home/marius/.rvm/gems/ruby-1.9.2-p290#uxolo/gems/whenever-0.6.8/lib/whenever/command_line.rb:8:in `execute'
from /home/marius/.rvm/gems/ruby-1.9.2-p290#uxolo/gems/whenever-0.6.8/bin/whenever:38:in `<top (required)>'
from /home/marius/.rvm/gems/ruby-1.9.2-p290#uxolo/bin/whenever:19:in `load'
from /home/marius/.rvm/gems/ruby-1.9.2-p290#uxolo/bin/whenever:19:in `<main>'
So, my question basically boils down to:
How do I access the current environment, or
What should I do to use whenever in all the environments?
At least in newer version of whenever it is possible to access the environment with #environment. For example if you want whenever to only generate cron entries for some jobs in production:
case #environment
when 'production'
every 1.day, :at => '0:00 am' do
rake "some:task"
end
end
The error message suggests that Rails isn't defined. i.e the framework isn't loaded when you're asking the question what environment is rails running with.
In fact from looking at the code for Whenever it looks like rails isn't a requirement for it (i.e. You can install and run Whenever without rails even being installed on your system). Hence there's no way for Whenever to look at your rails environment (as far as i can tell)
As recommended by the gem author, the solution is to pass in the current environment as a variable:
$ whenever --set environment=test
0,5,10,15,20,25,30,35,40,45,50,55 * * * * /bin/bash -l -c 'cd /home/marius/uxolo && RAILS_ENV=test rake db:activity:synchronize --silent >> /home/marius/uxolo/log/cron.log 2>> /home/marius/uxolo/log/error.log'
$ whenever --set environment=development
0,5,10,15,20,25,30,35,40,45,50,55 * * * * /bin/bash -l -c 'cd /home/marius/uxolo && RAILS_ENV=development rake db:activity:synchronize --silent >> /home/marius/uxolo/log/cron.log 2>> /home/marius/uxolo/log/error.log'
And Chris Bailey is right: Whenever itself doesn't load the Rails environment.
A variation of the first answer to a similar question worked for me. Add
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
to the top of schedule.rb and you'll be able to call Rails.env to access the current Rails environment.
Note: the above path would be different if your environment.rb file isn't in /app/config
I took the implementation of Rails.env I found here (by clicking on "source"), and used it to initialize the ::Rails module at the beginning of the config/schedule.rb
eval %Q(module ::Rails
def self.env
'#{#environment}' || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
end
end
)
This creates the Rails module, and makes its environment return what you supplied as --set environment=... in the whenever command line, as the script author suggests.
However, whenever sets the #environment to production by default, so this large "or" may be not quite useful.
Now the Rails.env call in the Whenever script would work. What was more important in my case, it also worked in other scripts I included into schedule.rb, such as the one that loaded application.yml.
P.S. The eval call is used to access #environment available in the scope of the schedule.rb script from inside the definition of a module.

How to set rails_env for a script or batch file

I put my batch file in lib folder
and use rails db configuration, active-record like this.
require "#{File.dirname(__FILE__)}/../config/environment.rb"
class Batch
def hello
Message.new do |t|
t.title = "hello"
t.save
end
end
end
batch = Batch.new
batch.hello
when excute batch
ruby lib/batch.rb
in development environment it's ok
but production environment still save development database...
how do i set rails_env batch.rb like this
ruby lib/batch.rb RAILS_ENV=production
To initialise the Rails environment, instead of putting
require "#{File.dirname(__FILE__)}/../config/environment.rb"
launch your batch file using script/runner and specify the environment with the -e option
e.g.
script/runner -e production lib/batch.rb
I think the above is The Rails Way of writing and executing a script that needs the Rails framework initialised in order to work. The alternative, as neutrino says, is to prefix the command with RAILS_ENV=value e.g.
$ RAILS_ENV=production lib/batch.rb
This is a standard shell feature to set an environment variable prior to executing a command.
Just FYI without script/runner :
RAILS_ENV=production ruby lib/batch.rb

Resources