Set RAILS_ENV for test rake tasks - ruby-on-rails

I've done this patch to my test_helper.rb
ENV["RAILS_ENV"] = ENV["RAILS_ENV_TEST"] || "test"
This works in that I can run
RAILS_ENV_TEST=test_dan ruby -Itest test/unit/post_test.rb
but I want to be able to run all kinds of test things, including rake db:test:clone but not using the environment test. How can I do this?

Most rake tasks that are namespaced with "test" will only run on your test environment and not in other environments. It's hardcoded into the task as to mitigate potentially devastating affects they might have in an environment such as production.
You can see that these tasks don't take into account the environment in which they are called in the source.
If you want to run these tasks in whatever environment you want, your best bet is to recreate these tasks and pass in the environment.
namespace :any_environment_test do
task :load => :environment do
...
task :clone => :environment do
...
In this specific case, it's a little trickier, as it sounds like you want to clone from any environment to any environment. If this is the case, you should probably have two vars that are passed, such as FROM_ENV= and TO_ENV=.
Long story longer, you're going to write custom tasks, but can inspire yourself from the link I posted above. :)

Related

Rake task failing to load :environment properly

I'm running a custom rake task...
namespace :import do
desc "Import terms of service as HTML from stdin"
task :terms => :environment do
html = STDIN.read
settings = ApplicationWideSetting.first
settings.terms_and_conditions = html
if settings.save
puts "Updated terms of service"
else
puts "There was an error updating terms of service"
end
end
end
The model ApplicationWideSetting is reported as undefined when running the task in the production environment. However, when running the task on other environments (ie. development, staging, test.) the task runs fine.
Running the process in rails console, in all environments, completes ok.
Does anyone know what's going on, things I could check?
note: I ran the task with
puts Rails.env
To check the shell environment var RAILS_ENV was getting set/read correctly. I've also tried both with and without the square brackets around the :environment dependency declaration.
additional info: Rails v3.2.14
further info: I've setup a completely fresh rails app, and the script works fine in any environment. Since the install in question is a real production environment, I'll have to setup another deploy and check it thoroughly. More info as I find it.
In a nutshell, Rails doesn't eager load models (or anything else) when running rake tasks on Production.
The simplest way to work with a model is to require it when you begin the rake task, and it should work as expected, in this case:
# explicitly require model
require 'application_wide_setting'
It's possible to eager load the entire rails app with:
Rails.application.eager_load!
However, you may have issues with some initializers (ie. devise)

environment change in rake task

I am developing Rails v2.3 app with MySQL database and mysql2 gem. I faced a weird situation which is about changing the environment in rake task.
(all my setting and configurations for environment and database are correct, no problem for that.)
Here is my simple story :
I have a rake task like following:
namespace :db do
task :do_something => :environment do
#1. run under 'development' environment
my_helper.run_under_development_env
#2. change to 'custom' environment
RAILS_ENV='custom'
Rake::Task['db:create']
Rake::Task['db:migrate']
#3. change back to 'development' environment
RAILS_ENV='development'
#4. But it still run in 'customer' environment, why?
my_helper.run_under_development_env
end
end
The rake task is quite simple, what it does is:
1. Firstly, run a method from my_helper under "development" environment
2. Then, change to "custom" environment and run db:create and db:migrate
until now, everything is fine, the environment did change to "custom"
3. Then, change it back again to "development" environment
4. run helper method again under "development" environment
But, though I have changed the environment back to "development" in step 3, the last method still run in "custom" environment, why? and how to get rid of it?
--- P.S. ---
I have also checked a post related with environment change here, and tried to use the solution there (in step 2):
#2. change to 'custom' database
ActiveRecord::Base.establish_connection('custom')
Rake::Task['db:create']
Rake::Task['db:migrate']
to change the database connection instead of changing environment but, the db:create and db:migrate will still run under "development" database, though the linked post said it should run for "custom" database... weird
--------------- important update ---------------------
I just realize that the code in step 2:
#2. change to 'custom' environment
RAILS_ENV='custom'
Rake::Task['db:create']
Rake::Task['db:migrate']
it changes environment to "custom" only if the Rake::Task['db:create'] get called, if I comment out Rake::Task['db:create'] line, code will still run under 'development':
#2. change to 'custom' environment
RAILS_ENV='custom'
#Rake::Task['db:create']
#CODE WILL RUN STILL UNDER 'development' environment.
Why Rake::Task['db:create'] affects environment change in my case...?
I realize this question is from over a month ago, but what they heck - it's Christmas
it seems like running each rake task in its own process will simplify things when switching environments?
namespace :db do
task :do_something => :environment do
unless Rails.env.development? then
raise "Can only run under development environment, but specified env was #{Rails.env}"
end
#1. run under 'development' environment
my_helper.run_under_development_env
#2. do the giggity with custom environment
command = "bundle exec rake db:create RAILS_ENV=custom"
result = %x[#{command}]
raise "rake task failed..........\n#{result}" if result.include?('rake aborted!')
command = "bundle exec rake db:migrate RAILS_ENV=custom"
result = %x[#{command}]
raise "rake task failed..........\n#{result}" if result.include?('rake aborted!')
#3. back to development
my_helper.run_under_development_env
end
end
just type after the rake task RAILS_ENV='production'
in your case
rake db:do_something RAILS_ENV='custom'

Vlad the Deployer - Usage Patterns?

I'm starting to use vlad for new deployments and am wondering what's the best way to set it up so I can use the same tasks for my local development and remote production servers?
I thought about defining everything as remote tasks then having dev/prod methods which set the domain variable, then I can just call rake dev/prod vlad:do_something, but this just feels totally wrong.
Many of my tasks are useful to run on my local server and on my production server and I want to avoid repeating myself by having one 'task' for local and one 'remote_task' for remote. e.g.
def do_something
run "echo something"
end
task :do_something_dev
do_something
end
remote_task do_something_prod
do_something
end
Am I missing something or are these really the only options for using the same rake tasks on both the local and remote machine?
How about this:
[:development, :test, :production].each do |environment|
namespace environment do
task :do_something do
echo "do something on #{environment}"
end
end
end
This will give you:
rake vlad:development:do_something
rake vlad:test:do_something
rake vlad:production:do_something
With just one method it is probably less verbose to do it your way. But as soon as you have 2 or three methods, the overhead can be neglected.

How can I set the Rails environment for my somewhat stand alone Ruby script?

I have a Ruby script in my Rails app that I use to load some data from Twitter.
In the future I will make it an automatic background process, but for now I run it manually like:
ruby /lib/twitter/twitterLoad.rb
In order to use the Rails model classes and such, I have the following as the top line of the script:
require "#{File.dirname(__FILE__)}/../../config/environment.rb"
By default, the development environment is used. But, I'd like to be able to choose the production environment at some point.
Update #1: The RAILS_ENV constant is getting set in the environment.rb file. So, I was able to put ENV['RAILS_ENV'] = 'production' at the very top (before the environment.rb) line and solve my problem somewhat. So, my new question is, can do pass in env vars through the command line?
If you're going to be using the rails environment, your best bet would be to make this a rake script. To do this, put a twitter.rake file into lib/tasks and begin and end it like this:
task(:twitter_load => :environment) do
# your code goes here
end
That way, you're doing it by "following conventions" and it doesn't have that 'orrible smell associated with it.
I currently use the following method, and I know the environment doesn't have the rb extension, it's not needed. You can also set it before running it to overwrite the ENV["RAILS_ENV"].
#!/usr/bin/env ruby
# Set your environment here.
ENV["RAILS_ENV"] ||= "production"
require File.dirname(__FILE__) + "/../../config/environment"
puts "Rails was loaded!"
Then to change the environment, just run it with:
rb /lib/tasks/file.rb RAILS_ENV=development
Don't forget script/runner.
Set your environment variable from the command line and
ruby script/runner your_script_here.rb
The accepted answer to use rake is well-taken, but you may still want to manually set the environment for testing utility classes.
Here's what I use to set up the test environment for utility classes in /lib. For these I tend to use the Ruby convention of making my class file execute its tests when it gets run from the command line. This way I can do TDD outside of Rails' web-centric test harnesses, but still use the class within rake without affecting the environment that it sets.
This goes at the top:
if (__FILE__ == $0)
ENV['RAILS_ENV'] ||= 'test'
require File.join(File.dirname(__FILE__),'../config/environment.rb')
end
and this goes at the bottom:
if (__FILE__ == $0)
require 'test/unit/ui/console/testrunner'
Test::Unit::UI::Console::TestRunner.run(MyClassTest)
end
You can also do
script/console development < path/to/your/script.rb
Admiteddly cumbersome -and will spit out lots of irb garbage after evaluating each and every line of your script- but works for quickies and you dont have to remember that damned require line.
And don't forget that maybe the most elegant way to extend your app with scripts that do useful things is writing Rake tasks!
add the line:
RAILS_ENV = '<your environment of choice>'
http://wiki.rubyonrails.org/rails/pages/Environments#script
pantulis: It's cool that that works, but for quickies I just use RAILS_ENV = '<your environment of choice>' ruby path/to/script.rb. This is how you set environment variables in the console.
require 'bundler'
require 'bundler/setup'
ENV['RAILS_ENV'] ||= 'development'
RAILS_ROOT = Pathname.new(File.expand_path('~/path/to/root'))
puts "Loading Rails Environment from #{RAILS_ROOT}..."
require RAILS_ROOT.join('config/environment').to_s
This works but only if the Gemfile of your script contains all the dependencies of your rails app. You might be able to load one Gemfile from another, e.g just eval it, to overcome this copy/paste.

RoR environment in Ruby standalone script

I want to run a standalone ruby script in which I need my RoR environment to be used. Specifically, I need my models extending ActionMailer and ActiveRecord. I also need to read the database configuration from my database.yml.
How do I go about it?
The easiest way is to change the shebang of your script from :
#!/usr/bin/ruby
to
#!/path/to/your/rails/script/runner
Et voilĂ , your script will be run with the full rails environment loaded. You can also run your script as ./my_script -e production to have it run with the production database.
Check out this thread:
How do I run Ruby tasks that use my Rails models?
Essentially it boils down to:
require "#{ENV['RAILS_ROOT']}/config/environment.rb"
Have fun!
I think the best way to do this is to make it a rake task.
# lib/tasks/mystuff.rake
desc 'do my stuff'
task :my_stuff => [:environment] do
# do my stuff
end
The [:environment] stanza loads the rails environment.

Resources