Run rake db:drop without failure if database doesn't exist - ruby-on-rails

This comment says:
db:drop can run without failure when db does not exist
This is exactly what I need: I need to run db:drop but without throwing an exception or halt my whole process if the database doesn't exist, just delete the database if it exists or do nothing.
How can I do that? how can I tell db:drop not to destroy my life if the database doesn't exist?
This is the code I'm experiencing the problem with (it it help):
namespace :db do
task import: :environment do
Rake::Task["db:drop"].invoke # If the database doesn't already exist, the whole import process terminates!
Rake::Task["db:create"].invoke
Rake::Task["db:migrate"].invoke
database_config = Rails.configuration.database_configuration[Rails.env]
system "psql --username=#{database_config['username']} #{database_config['database']} < PostgreSQL.sql"
end
end

Why can't you go for simple exception handling
namespace :db do
task import: :environment do
begin
Rake::Task["db:drop"].invoke # If the database doesn't already exist, the whole import process terminates!
Rake::Task["db:create"].invoke
Rake::Task["db:migrate"].invoke
database_config = Rails.configuration.database_configuration[Rails.env]
system "psql --username=#{database_config['username']} #{database_config['database']} < PostgreSQL.sql"
rescue Exception => e
p "The Exception is #{e.message}"
end
end
end

Related

The case of the disappearing ActiveRecord attribute

Following the instructions in https://stackoverflow.com/a/24496452/102675 I wound up with the following:
namespace :db do
desc 'Drop, create, migrate, seed and populate sample data'
task seed_sample_data: [:drop, :create, :migrate, :seed, :populate_sample_data] do
puts 'Sample Data Populated. Ready to go!'
end
desc 'Populate the database with sample data'
task populate_sample_data: :environment do
puts Inspector.column_names.include?('how_to_fix')
# create my sample data
end
end
As you would expect, I get true if I run bundle exec rake db:populate_sample_data
BUT if I run bundle exec rake db:seed_sample_data I get all the migration output and then false. In other words I can't see the Inspector attribute how_to_fix even though it definitely exists as proved by the other rake run. Where did my attribute go?
My guess is that this is a "caching" problem. Can you try the following?
task populate_sample_data: :environment do
Inspector.reset_column_information
# ...
end
P.S. We used to have a similar problem working with different databases having the exact same schema (only except some columns here and there)

Rake task to backup in-memory sqlite database

I was wondering how to write a rake task for backing up the default rails database. I tried the following. However, nothing seems to be getting written in the file.
namespace :mockdb do
desc "Back up the database"
task :backup => :environment do
puts "Backing up the database.."
system "sqlite3 .dump > #{dump_path}"
puts "Phew! All data has been backed up!"
end
def dump_path
Rails.root.join('db/mock.sql').to_path
end
end
Apparently the system was not able to find sqlite3. I had to give the installation path. Following is the final snippet
namespace :mockdb do
sqlite_path = "/usr/bin/sqlite3"
sql_file = "db/#{Rails.env}.sqlite3"
desc "Back up the database"
task :backup => :environment do
puts "Backing up the database.."
system "#{sqlite_path} #{sql_file} .dump > #{dump_path}"
puts "All data has been backed up!"
end
def dump_path
Rails.root.join('db/mock.sql').to_path
end
end

How to load multiple schemas into a Rails engine or app?

Seeking to move all my shared models to an engine which can be included in each of my micro apps.
This engine should provide a model layer to all our legacy data, including:
Model files
Schema files
Migrations (we're following Pivotal Labs' pattern, this isn't the issue)
Model files are being patched in automatically, that's fine.
Schema files are being monkey-patched in using Nikolay Strum's db.rake:
namespace :db do
namespace :schema do
# desc 'Dump additional database schema'
task :dump => [:environment, :load_config] do
filename = "#{Rails.root}/db/foo_schema.rb"
File.open(filename, 'w:utf-8') do |file|
ActiveRecord::Base.establish_connection("foo_#{Rails.env}")
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
end
end
end
namespace :test do
# desc 'Purge and load foo_test schema'
task :load_schema do
# like db:test:purge
abcs = ActiveRecord::Base.configurations
ActiveRecord::Base.connection.recreate_database(abcs['foo_test']['database'], mysql_creation_options(abcs['foo_test']))
# like db:test:load_schema
ActiveRecord::Base.establish_connection('foo_test')
ActiveRecord::Schema.verbose = false
load("#{Rails.root}/db/foo_schema.rb")
end
end
end
We need rake db:create and rake db:schema:load to work,
The db.rake patches only affect db:schema:dump and db:test:load_schema (part of tests_prepare, I assume). I've attempted to patch them into db:schema:load using:
namespace :db do
# Helpers
def mysql_creation_options(config)
#charset = ENV['CHARSET'] || 'utf8'
#collation = ENV['COLLATION'] || 'utf8_unicode_ci'
{:charset => (config['charset'] || #charset), :collation => (config['collation'] || #collation)}
end
def load_schema(schema_name)
abcs = ActiveRecord::Base.configurations
ActiveRecord::Base.connection.recreate_database(abcs[schema_name+'_test']['database'], mysql_creation_options(abcs[schema_name+'_test']))
# like db:test:load_schema
ActiveRecord::Base.establish_connection(schema_name+'_test')
ActiveRecord::Schema.verbose = false
load("#{Rails.root}/db/#{schema_name}_schema.rb")
end
namespace :schema do
# desc 'Dump additional database schema'
task :dump => [:environment, :load_config] do
dump_schema = -> (schema_name) {
filename = "#{Rails.root}/db/#{schema_name}_schema.rb"
File.open(filename, 'w:utf-8') do |file|
ActiveRecord::Base.establish_connection("#{schema_name}_#{Rails.env}")
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
end
}
dump_schema.call('kiddom')
dump_schema.call('kiddom_warehouse')
end
# When loading from schema, load these files, too
task :load => [:environment, :load_config] do
load_schema('kiddom')
load_schema('kiddom_warehouse')
end
end
namespace :test do
# desc 'Purge and load foo_test schema'
task :load_schema do
load_schema('kiddom')
load_schema('kiddom_warehouse')
end
end
end
But this gives me the error NoMethodError: undefined method 'recreate_database' for #<ActiveRecord::ConnectionAdapters::SQLite3Adapter:0x007feb6bb43558>. Apparently, this only works on Oracle-type databases?
What are the Rails commands for the underlying DROP and CREATE DATABASE sql I'm trying to affect for the extra schema.rb's?
You are using SQLite as your database engine. Hope that is what you want to do.
Since you are creating SQLite Database , things differ a bit from other database adapters like MySQLAdpter or Postgress.
In case of MySQL, database has to be created prior to establish a connection by spending "CREATE DATABASE ... " SQL commands. So you must create the database before establishing connection.
But in case of SQLite, since the database reside in a file and one file can contain only one database, there is no separate step to create database. An attempt to establishing a connection to the database itself will cause the database file to be created.
Hence create_database method won't work when using SQLiteAdapter. You can simply remove that line from your code.
You may have a look at the source code for the Rake task db:create
https://github.com/rails/rails/blob/f47b4236e089b07cb683ee9b7ff8b06111a0ec10/activerecord/lib/active_record/railties/databases.rake
Also, the source code for 'create' method in SQLiteDatabaseTasks. As you can see, it simply calls the establish_connection method
https://github.com/rails/rails/blob/f47b4236e089b07cb683ee9b7ff8b06111a0ec10/activerecord/lib/active_record/railties/databases.rake

How do I verify if a series of rake tasks ran correctly? Or, what alternatives are there to rake

Somebody has asked a similar question here:
https://github.com/jimweirich/rake/issues/257
The answer from the maintainer was:
I am going to reject this since it allows you to use tasks in non-rake-like ways.
So what are the correct way of using rake if a task depends of other tasks.
task 'succeed' => ['db:drop','stats'] do something end
displays results of stats even if Postgres threw an error and db:drop failded because of active connections.
If rake is not suitable for system maintenace, what tools should I use?
I need to be able to run a backup of a database, then do some tests, then drop the database and finally restore from backup.
to hel you understand my problem look at folowing fragment
namespace :experiment do
desc "TODO"
task 'succeed' => ['stopme', 'stats'] do
puts 'this and stats task should not run'
end
desc "TODO"
task stopme: :environment do
Rake::Task['db:drop'].invoke
end
end
You can invoke tasks manually like that:
task :stats => :environment do
Rake::Task['db:drop'].invoke rescue nil
# do something
end

Active Record error to create database

In my spec/rails_helper.rb, i have the code bellow to create the test database if it doesn`t exits.
def database_exists?
ActiveRecord::Base.connection rescue ActiveRecord::NoDatabaseError ? false : true
end
unless database_exists?
ActiveRecord::Base.establish_connection(:"#{ENV['RAILS_ENV']}")
db_config = ActiveRecord::Base.configurations[ENV['RAILS_ENV']]
ActiveRecord::Base.connection.create_database db_config
end
but i got this error when rspec is called:
.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/connection_adapters/mysql2_adapter.rb:23:in `rescue in mysql2_connection': Unknown database 'my-db-test' (ActiveRecord::NoDatabaseError)
Where is the problem?
If i use system('rake db:create'), it works, but is a good pratice?
The database doesn't exist so to avoid the error you can run:
rake db:create
or you can run:
rake db:setup
This will create the database AND run the migration files.

Resources