Skip to content

Instantly share code, notes, and snippets.

@wikimatze
Last active July 28, 2017 05:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wikimatze/e6edd48ccce0ded45ed44d03ca6da04e to your computer and use it in GitHub Desktop.
Save wikimatze/e6edd48ccce0ded45ed44d03ca6da04e to your computer and use it in GitHub Desktop.
require 'minitest'
require "minitest/autorun"
require "minitest/focus"
require 'rake'
require 'mocha/mini_test'
require 'minitest/pride'
module Padrino
module Generators
# Wrap the sequel rake task
class SequelRakeWrapper
# A basic initialize method.
#
# @param sequel [Sequel]
# @param sequel_migrator [Sequel::Migrator]
# @param sequel_model [Sequel::Model]
# @param sql_helpers [Padrino::Generators::SqlHelpers|nil]
def initialize(sequel, sequel_migrator, sequel_model, sql_helpers = nil)
@sequel = sequel
@sequel_migrator = sequel_migrator
@sequel_model = sequel_model
@sql_helpers = sql_helpers
end
# Perform automigration (reset your db data)
# @return [nil]
def auto
@sequel.extension :migration
@sequel_migrator.run @sequel_model.db, 'db/migrate', :target => 0
@sequel_migrator.run @sequel_model.db, 'db/migrate'
puts '<= sq:migrate:auto executed'
end
# Perform migration up/down to MIGRATION_VERSION
#
# @param version [String|nil]
def to(version = nil)
@sequel.extension :migration
fail "No MIGRATION_VERSION was provided" if version.nil?
@sequel_migrator.apply @sequel_model.db, 'db/migrate', version.to_i
puts "<= sq:migrate:to[#{version}] executed"
end
# Perform migration up to latest migration available
def up
@sequel.extension :migration
@sequel_migrator.run @sequel_model.db, 'db/migrate'
puts '<= sq:migrate:up executed'
end
# Perform migration down (erase all data)
def down
@sequel.extension :migration
@sequel_migrator.run @sequel_model.db, 'db/migrate', :target => 0
puts '<= sq:migrate:down executed'
end
# Create the database
def create
config = @sequel_model.db.opts
user, password, host = config[:user], config[:password], config[:host]
database = config[:database]
charset = config[:charset] || ENV['CHARSET'] || 'utf8'
collation = config[:collation] || ENV['COLLATION'] || 'utf8_unicode_ci'
puts "=> Creating database '#{database}'"
if config[:adapter] == 'sqlite3'
@sequel.sqlite(database)
else
require 'padrino-gen/padrino-tasks/sql-helpers'
@sql_helpers.create_db config[:adapter], config[:user], config[:password], config[:host], config[:database], charset, collation
end
puts "<= sq:create executed"
end
# Drop the database (postgres and mysql only)
def drop
config = @sequel_model.db.opts
user, password, host, database = config[:user], config[:password], config[:host], config[:database]
@sequel_model.db.disconnect
puts "=> Dropping database '#{database}'"
if config[:adapter] == 'sqlite3'
File.delete(database) if File.exist?(database)
else
@sql_helpers.drop_db config[:adapter], user, password, host, database
end
puts "<= sq:drop executed"
end
# Performs the seed command to fill the database
def seed
missing_model_features = Padrino.send(:default_dependency_paths) - Padrino.send(:dependency_paths)
Padrino.require_dependencies(missing_model_features)
Rake::Task['db:seed'].invoke
end
# Grab the migration version from ENV
def env_mig_version
version = ENV["MIGRATION_VERSION"]
if version.nil? && ENV["VERSION"]
deprecated = true
warn "Environment variable VERSION is deprecated, use MIGRATION_VERSION"
version = ENV["VERSION"]
end
version ? Integer(version) : nil
rescue ArgumentError
warn "Environment variable #{deprecated ? '' : 'MIGRATION_'}VERSION=#{version} should be non-existant or Integer"
nil
end
end
end
end
namespace :db do
task :seed
end
describe Padrino::Generators::SequelRakeWrapper do
let(:sequel_mock) { mock }
let(:sequel_migrator_mock) { mock }
let(:sequel_model_mock) { mock }
let(:sql_helpers_mock) { mock }
let(:sequel_db_opts_mock) { mock }
let(:db_mock) { mock }
let(:disconnect_mock) {mock }
it "#auto" do
sequel_mock.stubs(:extension).with(:migration).once
sequel_model_mock.stubs(:db).at_most(2).returns(db_mock)
sequel_migrator_mock.stubs(:run).with(db_mock, 'db/migrate', :target => 0).once
sequel_migrator_mock.stubs(:run).with(db_mock, 'db/migrate').once
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock)
assert_output(/<= sq:migrate:auto executed/) { sequel_wrapper.auto }
end
describe "#to" do
it "throws error if 'version' is not given" do
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock)
sequel_mock.stubs(:extension).with(:migration).once
exception = assert_raises RuntimeError do
sequel_wrapper.to
end
assert_equal 'No MIGRATION_VERSION was provided', exception.message
end
it "migrates to the given 'version'" do
sequel_mock.stubs(:extension).with(:migration).once
sequel_model_mock.stubs(:db).once.returns(db_mock)
sequel_migrator_mock.stubs(:apply).with(db_mock, 'db/migrate', 1).once
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock)
assert_output(/<= sq:migrate:to\[1\] executed/) { sequel_wrapper.to(1) }
end
end
describe "#up" do
it "it migrates to the latest version" do
sequel_mock.stubs(:extension).with(:migration).once
sequel_model_mock.stubs(:db).once.returns(db_mock)
sequel_migrator_mock.stubs(:run).with(db_mock, 'db/migrate').once
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock)
assert_output(/<= sq:migrate:up executed/) { sequel_wrapper.up }
end
end
describe "#down" do
it "erases all data" do
sequel_mock.stubs(:extension).with(:migration).once
sequel_model_mock.stubs(:db).once.returns(db_mock)
sequel_migrator_mock.stubs(:run).with(db_mock, 'db/migrate', :target => 0).once
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock)
assert_output(/<= sq:migrate:down executed/) { sequel_wrapper.down }
end
end
describe "#create" do
it "creates locale database with 'sqlite' adapter" do
expected_credentials = {
database: 'mochadatabase',
adapter: 'sqlite3'
}
sequel_db_opts_mock.stubs(:opts).once.returns(expected_credentials)
sequel_model_mock.stubs(:db).once.returns(sequel_db_opts_mock)
sequel_mock.stubs(:sqlite).with('mochadatabase').once
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock)
expected_output = "=> Creating database 'mochadatabase'\n<= sq:create executed\n"
assert_output (expected_output) { sequel_wrapper.create }
end
it "creates sql database with for given credentials and charset and collation" do
expected_credentials = {
database: 'mochadatabase',
adapter: 'mochiadapter',
user: 'mochamocha',
password: 'mochikochi',
host: 'padrinoovertheworld',
charset: 'mochi_utf8',
collation: 'mochi_utf8_unicode_ci'
}
sequel_model_mock.stubs(:db).once.returns(sequel_db_opts_mock)
sequel_db_opts_mock.stubs(:opts).once.returns(expected_credentials)
sequel_mock.stubs(:sqlite).with('mochadatabase').never
sql_helpers_mock.stubs(:create_db).with('mochiadapter', 'mochamocha', 'mochikochi', 'padrinoovertheworld', 'mochadatabase', 'mochi_utf8', 'mochi_utf8_unicode_ci').once
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock, sql_helpers_mock)
expected_output = "=> Creating database 'mochadatabase'\n<= sq:create executed\n"
clear_sql_helpers_from_loaded_features
assert_equal false, $LOADED_FEATURES.grep(%r{padrino-gen/padrino-tasks/sql-helpers}).any?
assert_output (expected_output) { sequel_wrapper.create }
assert_equal true, $LOADED_FEATURES.grep(%r{padrino-gen/padrino-tasks/sql-helpers}).any?
end
describe "collation and charset" do
it "taking values from ENV" do
expected_credentials = {
database: 'mochadatabase',
adapter: 'mochiadapter',
user: 'mochamocha',
password: 'mochikochi',
host: 'padrinoovertheworld'
}
ENV['CHARSET'] = 'mochi_utf8'
ENV['COLLATION'] = 'mochi_utf8_unicode_ci'
sequel_model_mock.stubs(:db).once.returns(sequel_db_opts_mock)
sequel_db_opts_mock.stubs(:opts).once.returns(expected_credentials)
sequel_mock.stubs(:sqlite).with('mochadatabase').never
sql_helpers_mock.stubs(:create_db).with('mochiadapter', 'mochamocha', 'mochikochi', 'padrinoovertheworld', 'mochadatabase', 'mochi_utf8', 'mochi_utf8_unicode_ci').once
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock, sql_helpers_mock)
expected_output = "=> Creating database 'mochadatabase'\n<= sq:create executed\n"
clear_sql_helpers_from_loaded_features
assert_equal false, $LOADED_FEATURES.grep(%r{padrino-gen/padrino-tasks/sql-helpers}).any?
assert_output (expected_output) { sequel_wrapper.create }
assert_equal true, $LOADED_FEATURES.grep(%r{padrino-gen/padrino-tasks/sql-helpers}).any?
end
it "taking default values" do
expected_credentials = {
database: 'mochadatabase',
adapter: 'mochiadapter',
user: 'mochamocha',
password: 'mochikochi',
host: 'padrinoovertheworld'
}
ENV['CHARSET'] = nil
ENV['COLLATION'] = nil
sequel_model_mock.stubs(:db).once.returns(sequel_db_opts_mock)
sequel_db_opts_mock.stubs(:opts).once.returns(expected_credentials)
sequel_mock.stubs(:sqlite).with('mochadatabase').never
sql_helpers_mock.stubs(:create_db).with('mochiadapter', 'mochamocha', 'mochikochi', 'padrinoovertheworld', 'mochadatabase', 'utf8', 'utf8_unicode_ci').once
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock, sql_helpers_mock)
clear_sql_helpers_from_loaded_features
assert_equal false, $LOADED_FEATURES.grep(%r{padrino-gen/padrino-tasks/sql-helpers}).any?
expected_output = "=> Creating database 'mochadatabase'\n<= sq:create executed\n"
assert_output (expected_output) { sequel_wrapper.create }
assert_equal true, $LOADED_FEATURES.grep(%r{padrino-gen/padrino-tasks/sql-helpers}).any?
end
end
end
describe "#drop" do
describe "sqlite adapter" do
it "deletes the database if it's there" do
expected_credentials = {
database: 'mochadatabase',
adapter: 'sqlite3',
}
sequel_db_opts_mock.stubs(:opts).once.returns(expected_credentials)
disconnect_mock.stubs(:disconnect).once
sequel_model_mock.stubs(:db).at_most(2).returns(sequel_db_opts_mock, disconnect_mock)
File.stubs(:exist?).once.with('mochadatabase').returns(true)
File.stubs(:delete).once.with('mochadatabase')
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock)
expected_output = "=> Dropping database 'mochadatabase'\n<= sq:drop executed\n"
assert_output (expected_output) { sequel_wrapper.drop }
end
it "does not deletes the database if it's not there" do
expected_credentials = {
database: 'mochadatabase',
adapter: 'sqlite3'
}
sequel_db_opts_mock.stubs(:opts).once.returns(expected_credentials)
disconnect_mock.stubs(:disconnect).once
sequel_model_mock.stubs(:db).at_most(2).returns(sequel_db_opts_mock, disconnect_mock)
File.stubs(:exist?).once.with('mochadatabase').returns(false)
File.stubs(:delete).never.with('mochadatabase')
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock)
expected_output = "=> Dropping database 'mochadatabase'\n<= sq:drop executed\n"
assert_output (expected_output) { sequel_wrapper.drop }
end
end
describe "with no 'sqlite' adapter" do
it "drops the database" do
expected_credentials = {
database: 'mochadatabase',
adapter: 'mochiadapter',
user: 'mochamocha',
password: 'mochikochi',
host: 'padrinoovertheworld',
charset: 'mochi_utf8',
collation: 'mochi_utf8_unicode_ci'
}
sequel_db_opts_mock.stubs(:opts).once.returns(expected_credentials)
disconnect_mock.stubs(:disconnect).once
sequel_model_mock.stubs(:db).at_most(2).returns(sequel_db_opts_mock, disconnect_mock)
sql_helpers_mock.stubs(:drop_db).with('mochiadapter', 'mochamocha', 'mochikochi', 'padrinoovertheworld', 'mochadatabase').once
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock, sql_helpers_mock)
expected_output = "=> Dropping database 'mochadatabase'\n<= sq:drop executed\n"
assert_output (expected_output) { sequel_wrapper.drop }
end
end
end
describe "#seed" do
it "performs the seed to command to fill the database" do
Padrino.stubs(:send).once.with(:default_dependency_paths).returns(2)
Padrino.stubs(:send).once.with(:dependency_paths).returns(1)
Padrino.stubs(:require_dependencies).once.with(1)
Rake::Task['db:seed'].stubs(:invoke).once
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock)
sequel_wrapper.seed
end
end
describe "#env_mig_version" do
it "Deprecation message if only VERSION is given and MIGRATION_VERSION is not given" do
ENV['MIGRATION_VERSION'] = nil
ENV['VERSION'] = '1'
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock)
assert_output(nil, /Environment variable VERSION is deprecated, use MIGRATION_VERSION/) { assert_equal 1, sequel_wrapper.env_mig_version }
end
it "MIGRATION_VERSION is a valid number" do
ENV['MIGRATION_VERSION'] = '1'
ENV['VERSION'] = nil
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock)
assert_equal 1, sequel_wrapper.env_mig_version
end
it "MIGRATION_VERSION is not a number" do
ENV['MIGRATION_VERSION'] = 'a'
sequel_wrapper = Padrino::Generators::SequelRakeWrapper.new(sequel_mock, sequel_migrator_mock, sequel_model_mock)
assert_output(nil, /Environment variable MIGRATION_VERSION=a should be non-existant or Integer/) { assert_nil sequel_wrapper.env_mig_version }
end
end
end
private
def clear_sql_helpers_from_loaded_features
sql_helpers_index = $LOADED_FEATURES.index { |s| s.include?('padrino-gen/padrino-tasks/sql-helpers.rb')}
$LOADED_FEATURES.delete_at sql_helpers_index if sql_helpers_index
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment