lib/ardb/cli/commands.rb in ardb-0.28.3 vs lib/ardb/cli/commands.rb in ardb-0.29.0

- old
+ new

@@ -1,17 +1,15 @@ -require 'ardb' -require 'ardb/cli/clirb' -require 'much-plugin' +require "ardb" +require "ardb/cli/clirb" +require "much-plugin" module Ardb; end class Ardb::CLI - InvalidCommandError = Class.new(ArgumentError) CommandExitError = Class.new(RuntimeError) class InvalidCommand - attr_reader :name, :clirb def initialize(name) @name = name @clirb = CLIRB.new @@ -20,31 +18,30 @@ def new; self; end def run(argv) @clirb.parse!([@name, argv].flatten.compact) raise CLIRB::HelpExit if @name.to_s.empty? - raise InvalidCommandError, "'#{self.name}' is not a command." + raise InvalidCommandError, "\"#{self.name}\" is not a command." end - def help + def command_help "Usage: ardb [COMMAND] [options]\n\n" \ "Options: #{@clirb}\n" \ "Commands:\n" \ "#{COMMANDS.to_s.split("\n").map{ |l| " #{l}" }.join("\n")}\n" end - end module ValidCommand include MuchPlugin - plugin_included do - include InstanceMethods + plugin_class_methods do + def command_name; raise NotImplementedError; end + def command_summary; ""; end end - module InstanceMethods - + plugin_instance_methods do def initialize(&clirb_build) @clirb = CLIRB.new(&clirb_build) end def clirb; @clirb; end @@ -53,223 +50,316 @@ @clirb.parse!(argv) @stdout = stdout || $stdout @stderr = stderr || $stderr end - def summary - '' - end + def command_name; self.class.command_name; end + def command_summary; self.class.command_summary; end + def command_help + "Usage: ardb #{self.command_name} [options]\n\n" \ + "Options: #{self.clirb}\n" \ + "Description:\n" \ + " #{self.command_summary}" + end end - end class ConnectCommand include ValidCommand + def self.command_name; "connect"; end + def self.command_summary; "Connect to the configured DB"; end + def run(argv, *args) super - Ardb.init(false) begin + Ardb.init(false) Ardb.adapter.connect_db - @stdout.puts "connected to #{Ardb.config.adapter} db `#{Ardb.config.database}`" + @stdout.puts "connected to #{Ardb.config.adapter} db #{Ardb.config.database.inspect}" + rescue ActiveRecord::NoDatabaseError => e + @stderr.puts "error: database #{Ardb.config.database.inspect} "\ + "does not exist" rescue StandardError => e @stderr.puts e @stderr.puts e.backtrace.join("\n") @stderr.puts "error connecting to #{Ardb.config.database.inspect} database " \ "with #{Ardb.config.activerecord_connect_hash.inspect}" raise CommandExitError end end - - def summary - "Connect to the configured DB" - end - - def help - "Usage: ardb connect [options]\n\n" \ - "Options: #{@clirb}\n" \ - "Description:\n" \ - " #{self.summary}" - end - end class CreateCommand include ValidCommand + def self.command_name; "create"; end + def self.command_summary; "Create the configured DB"; end + def run(argv, *args) super - Ardb.init(false) begin + Ardb.init(false) Ardb.adapter.create_db - @stdout.puts "created #{Ardb.config.adapter} db `#{Ardb.config.database}`" + @stdout.puts "created #{Ardb.config.adapter} db #{Ardb.config.database.inspect}" + rescue ActiveRecord::StatementInvalid => e + @stderr.puts "error: database #{Ardb.config.database.inspect} "\ + "already exists" rescue StandardError => e @stderr.puts e @stderr.puts "error creating #{Ardb.config.database.inspect} database" raise CommandExitError end end - - def summary - "Create the configured DB" - end - - def help - "Usage: ardb create [options]\n\n" \ - "Options: #{@clirb}\n" \ - "Description:\n" \ - " #{self.summary}" - end - end class DropCommand include ValidCommand + def self.command_name; "drop"; end + def self.command_summary; "Drop the configured DB"; end + def run(argv, *args) super - Ardb.init(true) begin + Ardb.init(true) Ardb.adapter.drop_db - @stdout.puts "dropped #{Ardb.config.adapter} db `#{Ardb.config.database}`" + @stdout.puts "dropped #{Ardb.config.adapter} db #{Ardb.config.database.inspect}" + rescue ActiveRecord::NoDatabaseError => e + @stderr.puts "error: database #{Ardb.config.database.inspect} "\ + "does not exist" rescue StandardError => e @stderr.puts e @stderr.puts "error dropping #{Ardb.config.database.inspect} database" raise CommandExitError end end - - def summary - "Drop the configured DB" - end - - def help - "Usage: ardb drop [options]\n\n" \ - "Options: #{@clirb}\n" \ - "Description:\n" \ - " #{self.summary}" - end - end - class MigrateCommand + class GenerateMigrationCommand include ValidCommand + def self.command_name; "generate-migration"; end + def self.command_summary; "Generate a MIGRATION-NAME migration file"; end + def run(argv, *args) super - Ardb.init(true) begin - Ardb.adapter.migrate_db - Ardb.adapter.dump_schema unless ENV['ARDB_MIGRATE_NO_SCHEMA'] + Ardb.init(false) + + require "ardb/migration" + migration = Ardb::Migration.new(Ardb.config, @clirb.args.first) + migration.save! + @stdout.puts "generated #{migration.file_path}" + rescue Ardb::Migration::NoIdentifierError => exception + error = ArgumentError.new("MIGRATION-NAME must be provided") + error.set_backtrace(exception.backtrace) + raise error rescue StandardError => e @stderr.puts e @stderr.puts e.backtrace.join("\n") - @stderr.puts "error migrating #{Ardb.config.database.inspect} database" + @stderr.puts "error generating migration" raise CommandExitError end end - def summary - "Migrate the configured DB" + def command_help + "Usage: ardb #{self.command_name} MIGRATION-NAME [options]\n\n" \ + "Options: #{self.clirb}\n" \ + "Description:\n" \ + " #{self.command_summary}" end + end - def help - "Usage: ardb migrate [options]\n\n" \ - "Options: #{@clirb}\n" \ - "Description:\n" \ - " #{self.summary}" + module MigrateCommandBehaviors + include MuchPlugin + + plugin_included do + include ValidCommand end + plugin_instance_methods do + def migrate; raise NotImplementedError; end + + def run(argv, *args) + super + + begin + Ardb.init(true) + self.migrate + Ardb.adapter.dump_schema unless ENV["ARDB_MIGRATE_NO_SCHEMA"] + rescue ActiveRecord::NoDatabaseError => e + @stderr.puts "error: database #{Ardb.config.database.inspect} "\ + "does not exist" + rescue StandardError => e + @stderr.puts e + @stderr.puts e.backtrace.join("\n") + @stderr.puts "error migrating #{Ardb.config.database.inspect} database" + raise CommandExitError + end + end + end end - class GenerateMigrationCommand - include ValidCommand + class MigrateCommand + include MigrateCommandBehaviors - def run(argv, *args) - super + def self.command_name; "migrate"; end + def self.command_summary; "Migrate the configured DB"; end - Ardb.init(false) - begin - require 'ardb/migration' - migration = Ardb::Migration.new(Ardb.config, @clirb.args.first) - migration.save! - @stdout.puts "generated #{migration.file_path}" - rescue Ardb::Migration::NoIdentifierError => exception - error = ArgumentError.new("MIGRATION-NAME must be provided") - error.set_backtrace(exception.backtrace) - raise error - rescue StandardError => e - @stderr.puts e - @stderr.puts e.backtrace.join("\n") - @stderr.puts "error generating migration" - raise CommandExitError + def migrate + Ardb.adapter.migrate_db + end + end + + module MigrateStyleBehaviors + include MuchPlugin + + plugin_included do + include MigrateCommandBehaviors + end + + plugin_class_methods do + def command_style; raise NotImplementedError; end + + def command_name; "migrate-#{self.command_style}"; end + def command_summary; "Migrate the configured DB #{self.command_style}"; end + end + + plugin_instance_methods do + def migrate + Ardb.adapter.send("migrate_db_#{self.class.command_style}", *migrate_args) end + + private + + def migrate_args; raise NotImplementedError; end end + end - def summary - "Generate a migration file given a MIGRATION-NAME" + module MigrateDirectionBehaviors + include MuchPlugin + + plugin_included do + include MigrateStyleBehaviors end - def help - "Usage: ardb generate-migration [options] MIGRATION-NAME\n\n" \ - "Options: #{@clirb}\n" \ - "Description:\n" \ - " #{self.summary}" + plugin_class_methods do + def command_style; self.command_direction; end + def command_direction; raise NotImplementedError; end end + plugin_instance_methods do + def initialize + super do + option(:target_version, "version to migrate to", value: String) + end + end + + private + + def migrate_args + [@clirb.opts[:target_version]] + end + end end - class CommandSet + module MigrateStepDirectionBehaviors + include MuchPlugin + plugin_included do + include MigrateStyleBehaviors + end + + plugin_class_methods do + def command_style; self.command_direction; end + def command_direction; raise NotImplementedError; end + end + + plugin_instance_methods do + def initialize + super do + option(:steps, "number of migrations to migrate", value: 1) + end + end + + private + + def migrate_args + [@clirb.opts[:steps]] + end + end + end + + class MigrateUpCommand + include MigrateDirectionBehaviors + + def self.command_direction; "up"; end + end + + class MigrateDownCommand + include MigrateDirectionBehaviors + + def self.command_direction; "down"; end + end + + class MigrateForwardCommand + include MigrateStepDirectionBehaviors + + def self.command_direction; "forward"; end + end + + class MigrateBackwardCommand + include MigrateStepDirectionBehaviors + + def self.command_direction; "backward"; end + end + + class CommandSet def initialize(&unknown_cmd_block) @lookup = Hash.new{ |h,k| unknown_cmd_block.call(k) } @names = [] @aliases = {} @summaries = {} end - def add(klass, name, *aliases) + def add(klass) begin cmd = klass.new - rescue StandardError => err - # don't add any commands you can't init + rescue StandardError + # don"t add any commands you can"t initialize else - ([name] + aliases).each{ |n| @lookup[n] = cmd } + @lookup[cmd.command_name] = cmd @to_s = nil - @names << name - @aliases[name] = aliases.empty? ? '' : "(#{aliases.join(', ')})" - @summaries[name] = cmd.summary.to_s.empty? ? '' : "# #{cmd.summary}" + @names << cmd.command_name + @summaries[cmd.command_name] = cmd.command_summary.to_s end end - def remove(name) - @lookup.delete(name) - @names.delete(name) - @aliases.delete(name) + def remove(klass) + @lookup.delete(klass.command_name) + @names.delete(klass.command_name) + @summaries.delete(klass.command_name) @to_s = nil end - def [](name) - @lookup[name] + def [](cmd_name) + @lookup[cmd_name] end def size @names.size end def to_s max_name_size = @names.map{ |n| n.size }.max || 0 - max_alias_size = @aliases.values.map{ |v| v.size }.max || 0 @to_s ||= @names.map do |n| - "#{n.ljust(max_name_size)} #{@aliases[n].ljust(max_alias_size)} #{@summaries[n]}" + "#{n.ljust(max_name_size)} #{@summaries[n]}" end.join("\n") end - end - end