Skip to content

Instantly share code, notes, and snippets.

@rpanachi
Created April 10, 2016 21:26
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save rpanachi/f16447f8b03fa5edcf935863fcdffb95 to your computer and use it in GitHub Desktop.
Save rpanachi/f16447f8b03fa5edcf935863fcdffb95 to your computer and use it in GitHub Desktop.
Rakefile for Sequel database operations
namespace :db do
require 'sequel'
Sequel.extension(:migration)
MIGRATIONS_PATH = 'db/migrations'
def db_conn_env
ENV["BOOKSHELF_DATABASE_URL"]
end
def db_conn_url
db = split_db_url(db_conn_env)
db_conn = "postgres://#{db[:user]}:#{db[:pass]}@#{db[:host]}"
end
def split_db_url(url)
user, pass, host, database = url.scan(/postgres:\/\/(.+?):(.+?)@(.+?)\/(.+?)$/).first
data = {
user: user,
pass: pass,
host: host,
database: database
}
end
def db_migrate(version = db_migrations.last)
puts "Migrating database to version #{version}"
Sequel::Migrator.run(DB, MIGRATIONS_PATH, target: version.to_i)
end
def db_migrated?(version, schema = :sequel)
db_versions(schema).include?(version.to_s)
end
def db_versions(schema = :sequel)
if schema == :sequel
DB[:schema_migrations].order(:filename).select_map(:filename)
elsif schema == :rails
DB[:schema_migrations].order(:version).select_map(:version)
else
[]
end
end
def db_migrations
Dir[MIGRATIONS_PATH + "/*.rb"]
.map { |f| File.basename(f) }
.sort
end
def db_schema(object)
Hash[DB.schema(object)]
rescue Sequel::DatabaseError
nil
end
desc 'Seed the database with application required data'
task seed: :environment do
load 'db/seeds.rb'
end
desc "Prints current schema version"
task :version => :environment do
puts "Current Schema Version: #{db_versions(:sequel).last}"
end
desc "Perform migration up to latest migration available"
task :migrate, [:version] => :environment do |t, args|
db_migrate(args[:version] || db_migrations.last)
Rake::Task['db:version'].execute
end
desc "Perform rollback to specified target or previous version as default"
task :rollback, [:version] => :environment do |t, args|
version = args[:version] || db_versions(:sequel)[-2]
db_migrate(version)
Rake::Task['db:version'].execute
end
desc "Perform migration reset (full rollback and migration) only on local environment"
task :reset => :environment do
if (ENV["HANAMI_ENV"] || ENV["RACK_ENV"]) == "production"
abort "You can't run this rake on production environment"
end
db_migrate(0)
db_migrate(db_migrations.last)
Rake::Task['db:version'].execute
end
desc "Creates database"
task :create => :"settings:load" do
db = split_db_url(db_conn_env)
exec "psql",
"#{db_conn_url}",
"-c", "CREATE DATABASE #{db[:database]}"
end
desc "Drops database"
task :drop => :"settings:load" do
if (ENV["HANAMI_ENV"] || ENV["RACK_ENV"]) == "production"
abort "You can't run this rake on production environment"
end
db = split_db_url(db_conn_env)
exec "psql",
"#{db_conn_url}",
"-c", "DROP DATABASE IF EXISTS #{db[:database]}"
end
desc "Start a database console on environment"
task :console => :'settings:load' do
exec "psql", db_conn_env
end
namespace :structure do
require 'hanami/model'
require 'hanami/model/migrator'
task :check_schema_migrations do
raise "Schema_migrations not prepared! Run 'rake db:migrate'" unless db_schema(:schema_migrations)
end
task :check_structure_sequel do
raise "Sequel schema_migrations not prepared! Run 'rake db:structure:to_sequel'" unless db_schema(:schema_migrations)[:filename]
end
task :prepare_structure_sequel do
schema_migrations = db_schema(:schema_migrations)
DB.run "alter table schema_migrations alter column version drop not null;" if schema_migrations[:version]
DB.run "alter table schema_migrations add filename varchar;" unless schema_migrations[:filename]
puts "Structure: DONE"
end
task :migrate_structure_sequel do
db_migrations.each do |filename|
version = filename.to_i
if db_migrated?(version, :rails)
DB.run "update schema_migrations set filename = '#{filename}' where version = '#{version}';"
else
DB.run "insert into schema_migrations (version, filename) values ('#{version}', '#{filename}');"
end
puts "> #{filename} DONE"
end
puts "Migration: DONE"
end
task :check_structure_rails do
raise "Rails schema_migrations not prepared! Run 'rake db:structure:to_rails'" unless db_schema(:schema_migrations)[:version]
end
task :prepare_structure_rails do
schema_migrations = db_schema(:schema_migrations)
DB.run "alter table schema_migrations drop constraint schema_migrations_pkey;" if db_schema(:schema_migrations_pkey)
DB.run "alter table schema_migrations alter column filename drop not null;" if schema_migrations[:filename]
DB.run "alter table schema_migrations add version varchar;" unless schema_migrations[:version]
puts "Structure: DONE"
end
task :migrate_structure_rails do
db_migrations.each do |filename|
version = filename.to_i
if db_migrated?(filename, :sequel)
DB.run "update schema_migrations set version = '#{version}' where filename = '#{filename}';"
else
DB.run "insert into schema_migrations (version, filename) values ('#{version}', '#{filename}');"
end
puts "> #{filename} DONE"
end
puts "Migration: DONE"
end
desc "Setup database structure from Sequel to Rails Migrations"
task :to_rails => [
:environment,
:check_schema_migrations,
:check_structure_sequel,
:prepare_structure_rails,
:migrate_structure_rails
]
desc "Setup database structure from Rails to Sequel Migrations"
task :to_sequel => [
:environment,
:check_schema_migrations,
:check_structure_rails,
:prepare_structure_sequel,
:migrate_structure_sequel
]
# Configure Hanami::Model for structure dump/load
task :configure do
Hanami::Model.configure do
adapter type: :sql, uri: db_conn_env
migrations 'db/migrations'
schema 'db/schema.sql'
mapping {}
end.load!
end
desc "Dump database structure to db/schema.sql"
task dump: [:environment, :configure] do
adapter = Hanami::Model::Migrator::Adapter.for(DB)
adapter.dump
end
desc "Load db/schema.sql database structure"
task load: :environment do
adapter = Hanami::Model::Migrator::Adapter.for(DB)
adapter.load
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment