Created
October 26, 2012 18:40
-
-
Save letmein/3960610 to your computer and use it in GitHub Desktop.
Port db:structure:load and db:structure:dump rake tasks from Rails 3.2 to Padrino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ActiveRecord | |
module Tasks # :nodoc: | |
module DatabaseTasks # :nodoc: | |
extend self | |
attr_writer :current_config | |
LOCAL_HOSTS = ['127.0.0.1', 'localhost'] | |
def register_task(pattern, task) | |
@tasks ||= {} | |
@tasks[pattern] = task | |
end | |
register_task(/postgresql/, ActiveRecord::Tasks::PostgreSQLDatabaseTasks) | |
def current_config(options = {}) | |
options.reverse_merge! :env => Padrino.env | |
if options.has_key?(:config) | |
@current_config = options[:config] | |
else | |
@current_config ||= if ENV['DATABASE_URL'] | |
database_url_config | |
else | |
ActiveRecord::Base.configurations[options[:env]] | |
end | |
end | |
end | |
def create(*arguments) | |
configuration = arguments.first | |
class_for_adapter(configuration['adapter']).new(*arguments).create | |
rescue Exception => error | |
$stderr.puts error, *(error.backtrace) | |
$stderr.puts "Couldn't create database for #{configuration.inspect}" | |
end | |
def create_all | |
each_local_configuration { |configuration| create configuration } | |
end | |
def create_current(environment = Padrino.env) | |
each_current_configuration(environment) { |configuration| | |
create configuration | |
} | |
ActiveRecord::Base.establish_connection environment | |
end | |
def create_database_url | |
create database_url_config | |
end | |
def drop(*arguments) | |
configuration = arguments.first | |
class_for_adapter(configuration['adapter']).new(*arguments).drop | |
rescue Exception => error | |
$stderr.puts error, *(error.backtrace) | |
$stderr.puts "Couldn't drop #{configuration['database']}" | |
end | |
def drop_all | |
each_local_configuration { |configuration| drop configuration } | |
end | |
def drop_current(environment = Padrino.env) | |
each_current_configuration(environment) { |configuration| | |
drop configuration | |
} | |
end | |
def drop_database_url | |
drop database_url_config | |
end | |
def charset_current(environment = Padrino.env) | |
charset ActiveRecord::Base.configurations[environment] | |
end | |
def charset(*arguments) | |
configuration = arguments.first | |
class_for_adapter(configuration['adapter']).new(*arguments).charset | |
end | |
def collation_current(environment = Padrino.env) | |
collation ActiveRecord::Base.configurations[environment] | |
end | |
def collation(*arguments) | |
configuration = arguments.first | |
class_for_adapter(configuration['adapter']).new(*arguments).collation | |
end | |
def purge(configuration) | |
class_for_adapter(configuration['adapter']).new(configuration).purge | |
end | |
def structure_dump(*arguments) | |
configuration = arguments.first | |
filename = arguments.delete_at 1 | |
class_for_adapter(configuration['adapter']).new(*arguments).structure_dump(filename) | |
end | |
def structure_load(*arguments) | |
configuration = arguments.first | |
filename = arguments.delete_at 1 | |
class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename) | |
end | |
private | |
def database_url_config | |
@database_url_config ||= | |
ConnectionAdapters::ConnectionSpecification::Resolver.new(ENV["DATABASE_URL"], {}).spec.config.stringify_keys | |
end | |
def class_for_adapter(adapter) | |
key = @tasks.keys.detect { |pattern| adapter[pattern] } | |
@tasks[key] | |
end | |
def each_current_configuration(environment) | |
environments = [environment] | |
environments << 'test' if environment.development? | |
configurations = ActiveRecord::Base.configurations.values_at(*environments) | |
configurations.compact.each do |configuration| | |
yield configuration unless configuration['database'].blank? | |
end | |
end | |
def each_local_configuration | |
ActiveRecord::Base.configurations.each_value do |configuration| | |
next unless configuration['database'] | |
if local_database?(configuration) | |
yield configuration | |
else | |
$stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host." | |
end | |
end | |
end | |
def local_database?(configuration) | |
configuration['host'].blank? || LOCAL_HOSTS.include?(configuration['host']) | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'active_record' | |
namespace :db do | |
def filename | |
@filename ||= ENV['DB_STRUCTURE'] || Padrino.root("db", "structure.sql") | |
end | |
def current_config | |
@current_config ||= ActiveRecord::Tasks::DatabaseTasks.current_config.stringify_keys | |
end | |
task :compatibility do | |
case current_config['adapter'] | |
when /postgresql/ | |
puts "Found a compatible #{current_config['adapter']} adapter." | |
else | |
raise "Task not supported by '#{current_config["adapter"]}'" | |
end | |
end | |
namespace :structure do | |
desc 'Dump the database structure to db/structure.sql. Specify another file with DB_STRUCTURE=db/my_structure.sql' | |
task :dump => :compatibility do | |
ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename) | |
if ActiveRecord::Base.connection.supports_migrations? | |
File.open(filename, "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information } | |
end | |
end | |
# desc "Recreate the databases from the structure.sql file" | |
task :load => :compatibility do | |
ActiveRecord::Tasks::DatabaseTasks.purge(current_config) | |
ActiveRecord::Tasks::DatabaseTasks.structure_load(current_config, filename) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'shellwords' | |
module ActiveRecord | |
module Tasks # :nodoc: | |
class PostgreSQLDatabaseTasks # :nodoc: | |
DEFAULT_ENCODING = ENV['CHARSET'] || 'utf8' | |
delegate :connection, :establish_connection, :clear_active_connections!, | |
to: ActiveRecord::Base | |
def initialize(configuration) | |
@configuration = configuration | |
end | |
def create(master_established = false) | |
establish_master_connection unless master_established | |
connection.create_database configuration['database'], | |
configuration.merge('encoding' => encoding) | |
establish_connection configuration | |
end | |
def drop | |
establish_master_connection | |
connection.drop_database configuration['database'] | |
end | |
def charset | |
connection.encoding | |
end | |
def collation | |
connection.collation | |
end | |
def purge | |
clear_active_connections! | |
drop | |
create true | |
end | |
def structure_dump(filename) | |
set_psql_env | |
search_path = configuration['schema_search_path'] | |
unless search_path.blank? | |
search_path = search_path.split(",").map{|search_path_part| "--schema=#{Shellwords.escape(search_path_part.strip)}" }.join(" ") | |
end | |
command = "pg_dump -i -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(configuration['database'])}" | |
raise 'Error dumping database' unless Kernel.system(command) | |
File.open(filename, "a") { |f| f << "SET search_path TO #{ActiveRecord::Base.connection.schema_search_path};\n\n" } | |
end | |
def structure_load(filename) | |
set_psql_env | |
Kernel.system("psql -f #{filename} #{configuration['database']}") | |
end | |
private | |
def configuration | |
@configuration | |
end | |
def encoding | |
configuration['encoding'] || DEFAULT_ENCODING | |
end | |
def establish_master_connection | |
establish_connection configuration.merge( | |
'database' => 'postgres', | |
'schema_search_path' => 'public' | |
) | |
end | |
def set_psql_env | |
ENV['PGHOST'] = configuration['host'] if configuration['host'] | |
ENV['PGPORT'] = configuration['port'].to_s if configuration['port'] | |
ENV['PGPASSWORD'] = configuration['password'].to_s if configuration['password'] | |
ENV['PGUSER'] = configuration['username'].to_s if configuration['username'] | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment