class Miguel::Command

Miguel command line interface.

Attributes

env[R]
force[R]
format[R]
loggers[R]
quiet[R]
trace[R]

Public Instance Methods

init() click to toggle source

Initialize the command options.

# File lib/miguel/command.rb, line 14
def init
  @env = nil
  @format = nil
  @loggers = []
  @force = nil
  @quiet = nil
  @trace = nil
end
run( args ) click to toggle source

Run the command.

# File lib/miguel/command.rb, line 24
def run( args )
  args = args.dup
  init
  OptionParser.new( &method( :set_opts ) ).parse!( args )
  execute( args )
  exit 0
rescue Exception => e
  raise if trace or e.is_a?( SystemExit )
  $stderr.print "#{e.class}: " unless e.is_a?( RuntimeError )
  $stderr.puts e.message
  exit 1
end

Private Instance Methods

apply_schema( db, schema ) click to toggle source

Apply given schema to given database.

# File lib/miguel/command.rb, line 213
def apply_schema( db, schema )
  from = import_schema( db )
  changes = Migrator.new.changes( from, schema ).to_s

  if changes.empty?
    puts "No changes are necessary." unless quiet
    return
  end

  unless quiet
    puts "These changes will be applied to the database:"
    print changes
  end

  unless force
    fail "OK, aborting." unless confirm?
  end

  db.instance_eval( changes )

  puts "OK, those changes were applied." unless quiet
end
check_args( args, count ) click to toggle source

Make sure the argument count is as expected.

# File lib/miguel/command.rb, line 150
def check_args( args, count )
  fail "Not enough arguments present, use -h to see usage." if args.count < count
  fail "Extra arguments present, use -h to see usage." if args.count > count
end
confirm?() click to toggle source

Ask the user for a confirmation.

# File lib/miguel/command.rb, line 237
def confirm?
  loop do
    print "Confirm (yes or no)? "

    unless line = $stdin.gets
      puts
      puts "I take EOF as 'no'. Use --force if you want to skip the confirmation instead."
      return
    end

    case line.chomp.downcase
    when 'yes'
      return true
    when 'no'
      return false
    else
      puts "Please answer 'yes' or 'no'."
    end
  end
end
execute( args ) click to toggle source

Execute the command itself.

# File lib/miguel/command.rb, line 103
def execute( args )
  command = args.shift or fail "Missing command, use -h to see usage."
  method = "execute_#{command}"
  fail "Invalid command, use -h to see usage." unless respond_to?( method, true )
  check_args( args, method( method ).arity )
  send( method, *args )
end
execute_apply( db_name, name ) click to toggle source

Execute the apply command.

# File lib/miguel/command.rb, line 137
def execute_apply( db_name, name )
  db = get_db( db_name )
  schema = get_schema( name )
  apply_schema( db, schema )
end
execute_clear( db_name ) click to toggle source

Execute the clear command.

# File lib/miguel/command.rb, line 144
def execute_clear( db_name )
  db = get_db( db_name )
  apply_schema( db, Schema.new )
end
execute_diff( old_name, new_name ) click to toggle source

Execute the diff command.

# File lib/miguel/command.rb, line 130
def execute_diff( old_name, new_name )
  old_schema = get_schema( old_name )
  new_schema = get_schema( new_name )
  show_changes( old_schema, new_schema )
end
execute_down( name ) click to toggle source

Execute the down command.

# File lib/miguel/command.rb, line 124
def execute_down( name )
  schema = get_schema( name )
  show_changes( schema, Schema.new )
end
execute_dump( name ) click to toggle source

Execute the dump command.

# File lib/miguel/command.rb, line 118
def execute_dump( name )
  schema = get_schema( name )
  show_changes( Schema.new, schema )
end
execute_show( name ) click to toggle source

Execute the show command.

# File lib/miguel/command.rb, line 112
def execute_show( name )
  schema = get_schema( name )
  print schema.dump
end
get_db( name ) click to toggle source

Connect to given database.

# File lib/miguel/command.rb, line 174
def get_db( name )
  db = if name.nil? or name.empty?
    fail "Missing database name."
  elsif File.exist?( name )
    config = load_db_config( name )
    Sequel.connect( config )
  elsif name =~ /:/
    Sequel.connect( name )
  else
    fail "Database config #{name} not found."
  end
  db.loggers = loggers
  db
end
get_schema( name ) click to toggle source

Get schema from given schema file or database.

# File lib/miguel/command.rb, line 161
def get_schema( name )
  schema = if name.nil? or name.empty?
    fail "Missing database or schema name."
  elsif File.exist?( name ) and name =~ /\.rb\b/
    Schema.load( name ) or fail "No schema loaded from file '#{name}'."
  else
    db = get_db( name )
    import_schema( db )
  end
  schema
end
import_schema( db ) click to toggle source

Import schema from given database.

# File lib/miguel/command.rb, line 156
def import_schema( db )
  Importer.new( db ).schema
end
load_db_config( name ) click to toggle source

Load database config from given file.

# File lib/miguel/command.rb, line 190
def load_db_config( name )
  require 'yaml'
  config = YAML.load_file( name )
  env = self.env || "development"
  config = config[ env ] || config[ env.to_sym ] || config
  config.keys.each{ |k| config[ k.to_sym ] = config.delete( k ) }
  config
end
set_opts( opts ) click to toggle source

Set the command options.

# File lib/miguel/command.rb, line 40
def set_opts( opts )
  opts.banner = "Miguel: The Database Migrator and Migration Generator for Sequel"
  opts.define_head "Usage: miguel [options] <command> <db|schema> [db|schema]"
  opts.separator ""
  opts.separator "Examples:"
  opts.separator "  miguel show mysql://localhost/main"
  opts.separator "  miguel dump schema.rb"
  opts.separator "  miguel diff db.yml test.yml"
  opts.separator "  miguel apply db.yml schema.rb"
  opts.separator ""
  opts.separator "Commands:"
  opts.separator "  show <db|schema>                   Show schema of given database or schema file"
  opts.separator "  dump <db|schema>                   Dump migration which creates given schema"
  opts.separator "  down <db|schema>                   Dump migration which reverses given schema"
  opts.separator "  diff <db|schema> <db|schema>       Dump migration needed to migrate to the second schema"
  opts.separator "  apply <db> <db|schema>             Apply given schema to the database"
  opts.separator "  clear <db>                         Drop all tables in given database"
  opts.separator ""
  opts.separator "Options:"

  opts.on_tail( '-h', '-?', '--help', 'Show this message' ) do
    puts opts
    exit
  end

  opts.on( '-e', '--env <env>', 'Use given environment config for database(s)' ) do |v|
    @env = v
  end

  opts.on( '-E', '--echo', 'Echo SQL statements' ) do
    require 'logger'
    @loggers << Logger.new( $stdout )
  end

  opts.on( '-f', '--force', 'Force changes to be applied without confirmation' ) do
    @force = true
  end

  opts.on( '-l', '--log <file>', 'Log SQL statements to given file' ) do |v|
    require 'logger'
    @loggers << Logger.new( v )
  end

  formats = [ :bare, :change, :full ]
  opts.on( '-m', '--migration <format>', formats, "Select format for dumped migrations (#{formats.join(', ')})" ) do |v|
    @format = v
  end

  opts.on( '-q', '--quiet', "Don't display the changes to be applied" ) do
    @quiet = true
  end

  opts.on( '-t', '--trace', 'Show full backtrace if an exception is raised' ) do
    @trace = true
  end

  opts.on_tail( '-v', '--version', 'Print version' ) do
    puts "miguel #{Miguel::VERSION}"
    exit
  end
end
show_changes( from, to ) click to toggle source

Show changes between the two schemas.

# File lib/miguel/command.rb, line 200
def show_changes( from, to )
  m = Migrator.new
  case format
  when nil, :bare
    print m.changes( from, to )
  when :change
    print m.change_migration( from, to )
  when :full
    print m.full_migration( from, to )
  end
end