Rake: How do I forward params to child Rake calls? - ruby-on-rails

So, in my rake command, when I do --trace, it only does it on the command I manually execute, and none of the rake commands that the custom rake executes.
My Rake command:
namespace :db do
task :regenesis do
#because of how devestating this command could be, it's going
# to be forced to use the Test Environment
puts "Re-Generating the Database"
Rake::Task["db:drop RAILS_ENV=test --trace"].invoke
Rake::Task["db:create RAILS_ENV=test"].invoke
Rake::Task["db:create RAILS_ENV=test"].invoke
Rake::Task["db:bootstrap RAILS_ENV=test"].invoke
end
end
Twould be ideal to not have to hard code the --trace in there =D
So, I should be able to do rake db:regenesis --trace, and it should append trace onto all of those rake commands.
How do I do that?

Please check this question. If you cannot modify your tasks to add the parameters ( for some reason ), then you can use environment variables, like:
namespace :db do
task :regenesis do
#because of how devestating this command could be, it's going
# to be forced to use the Test Environment
puts "Re-Generating the Database"
ENV["extra_option"] = "--trace"
Rake::Task["db:drop RAILS_ENV=test"].invoke
Rake::Task["db:create RAILS_ENV=test"].invoke
Rake::Task["db:create RAILS_ENV=test"].invoke
Rake::Task["db:bootstrap RAILS_ENV=test"].invoke
end
end
And in your tasks you'd have to look for ENV["extra_option"]

Related

Running db:test:prepare in Rake task throws off environment

I have the following 2 rake tasks:
task :clone => :environment do |t, args|
Rake::Task["db:drop"].invoke
Rake::Task["db:create"].invoke
system "pg_restore -O -d database_name last_dump"
Rake::Task["db:migrate"].invoke
Rake::Task["db:test:prepare"].invoke
# Try to force the rails env to reload, but this doesn't solve the problem
Rake::Task["environment"].execute
Rake::Task["db:company_count"].invoke
end
task :company_count => :environment do
puts Company.count
end
When I run rake db:clone the output the Company.count is 0 indicating there are no Companies in the database, but when I run rake db:clone && rake db:company_count the output is 2.
How do I get the correct Company.count after loading the database in the first task?
The Company.count is correct if I remove Rake::Task["db:test:prepare"].invoke from the clone task, but I'm not sure why
My guess is first task is not using the console environment because it creates its own terminal session for the rake, and the second one is.
Try printenv and compare the variables
Also try prefixing the commands with RAILS_ENV=development or whatever environment you want.
guides.rubyonrails.org indicates that the task db:test:prepare is used to do the following to your test database:
drop the database
create the database
run the migrations
After this task completes, you will not have any data in there. Here are stack overflow answers that explains this:
PG undefinedtable error relation users does not exist
What does rake db:test:prepare actually do
I believe the behavior you are seeing has nothing to do with the environment, but a misunderstanding in the intention of this rake task.

Rake task dependent if database already exists

Just to preface that I've read through this question and others but no answer really mentions a way to do it in a rake task.
I want to do a setup script that somewhat looks like this:
if database_exists?
sh 'rake db:migrate'
else
sh 'rake db:setup'
end
I haven't written database_exists? but how can I tell if the users system has this database already created?
I don't want to run rake db:setup every time which will drop the users database.
I suppose I could run rake db:create && rake db:migrate each time but then the user would need to run rake db:seed in addition to the rake task which right now is part of the db:setup process.
My advice is to write a ruby script to run with rails runner or a rake task, where you can define your database_exists? method like this:
def database_exists?
ActiveRecord::Base.connection
rescue ActiveRecord::NoDatabaseError
false
else
true
end
Documentation
ActiveRecord::Base.connection
ActiveRecord::NoDatabaseError

How do I execute a "rake task" after every db:reset

I'm working on a personal project and I have a strange doubt. At the localhost, I do rake db:reset almost every time and I always need to run another task named newsworker:create (in other words, I run rake newsworker:create).
My questions are:
How can I execute a specific rake task after every rake db:reset?
How can I generalize the above question to work with rake db:create and other tasks?
Thanks!
In my opinion, the best way is to create your own rake task calling all the tasks needed (to avoid changing Rails/Rake basic tasks):
# lib/tasks/reset_and_create
namespace :database do
desc 'Reset the database to a fresh and clean DB ready for use'
task :reset_and_create do
Rake::Task['db:reset'].invoke
Rake::Task['newsworker:create'].invoke
# if you need to pass arguments to your tasks, use:
# Rake::Task['your_task'].invoke(your_arg, another_arg)
end
end
And use it like this:
rake database:reset_and_create

how to run this rake task with 2 args and environment in rails 4?

Here are the first few lines of my rake task:
desc "Import National Data into DB\n Usage:
rake import_regional[/Users/am/0925/xyz.csv, some_market]"
task :import_regional, [:file_path, :market] => [:environment] do |t, args|
.......
Here is how Im trying to run this task on the command line:
rake import_regional ["/Users/xyz.csv", "northeast"]
when I try this, I get this error
rake aborted!
Don't know how to build task
'import_regional[/Users/xyz.csv,'
I suspect it's the way in which you're running the task on the command-line; the [] doesn't have its Ruby meaning, there. Instead, maybe see if this works for you:
rake "import_regional[/Users/xyz.csv, northeast]"
This should still allow for spaces, etc. in :file_path, if required.
Peace,
tiredpixel
Command line isn't a Ruby interpreter, it's mangling things before it gets to Rake.
Try this:
rake "import_regional['/Users/xyz.csv', 'northeast']"

Disabling Rails' db:reset task

To avoid an accidental 'rake db:reset' on our production environments, I was thinking about disabling 'rake db:reset' and related tasks that drop the database in the production environment. Is there an easy way to do this, or do I have to redefine the rake task?
Is there a better alternative?
In your Rake file you can add
Rake.application.instance_variable_get('#tasks').delete('db:reset')
and the command is not available any more. If you want to disable multiple commands, put it in a remove_task method for readability.
But a better alternative seem to just not type the rake db:reset command, which is not something you'd accidentally type.
Having a nice backup of your (production) database is also a better solution I suppose.
Put this in lib/tasks/db.rake:
if Rails.env == 'production'
tasks = Rake.application.instance_variable_get '#tasks'
tasks.delete 'db:reset'
tasks.delete 'db:drop'
namespace :db do
desc 'db:reset not available in this environment'
task :reset do
puts 'db:reset has been disabled'
end
desc 'db:drop not available in this environment'
task :drop do
puts 'db:drop has been disabled'
end
end
end
Found here.
Append this on your Rakefile.
namespace :db do
task :drop => :abort_on_production
end
task :abort_on_production do
abort "Don't drop production database. aborted. " if Rails.env.production?
end
It also blocks rake db:reset and rake db:migrate:reset because they call db:drop
You could always overwrite the db:reset task with something like this in lib/db.rake:
namespace :db do
desc 'Resets your database using your migrations for the current environment'
task :reset do
if RAILS_ENV == 'production'
Rake::Task["db:drop"].invoke
Rake::Task["db:create"].invoke
Rake::Task["db:migrate"].invoke
end
end
end
For the record, We have an application linking into our live production database, we use test login details and from there shard's to out test DB.
The last thing we wanted was for rails to wipe out or database schema when running rspec/unit tests.
use the information is this question and here: Is it possible to get a list of all available rake tasks in a namespace?
I was able to come up with the following solution:
Rake.application.in_namespace(:db){|x|
x.tasks.map{|t|
Rake.application.instance_variable_get('#tasks').delete(t.name)
}
}
This placed into the end of our Rakefile enabled us to remove all db: rake tasks as can be seen here:
[davidc#david-macbookp app1{master}]$ rake -T db
[davidc#david-macbookp app1{master}]$
With a little tweaking this could be done to disable on a per environment basis
Update:
Word of warning doing this for db namespace broke testunit and was required to add the addison:
namespace :db do
task 'test:prepare' do
end
end
You could also use the rails_db_protect gem.
You just add the gem and it automatically prevents you from running the following dangerous tasks in production:
db:setup db:reset db:drop db:create db:schema:load
If you have a production environment, like a staging environment, where you want to be able to run these tasks, you can configure the environment to allow it:
ENV['ALLOW_DANGEROUS_TASKS'] = 'true'
There is also the gem rails-safe-tasks which allows more configuration but does not appear to have any tests supporting it.

Resources