diff options
-rw-r--r-- | railties/lib/rails/commands/dbconsole.rb | 56 | ||||
-rw-r--r-- | railties/test/commands/dbconsole_test.rb | 128 |
2 files changed, 162 insertions, 22 deletions
diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb index 6fc127efae..25a8caeec3 100644 --- a/railties/lib/rails/commands/dbconsole.rb +++ b/railties/lib/rails/commands/dbconsole.rb @@ -5,12 +5,15 @@ require 'rbconfig' module Rails class DBConsole + attr_reader :arguments + def self.start(app) new(app).start end - def initialize(app) + def initialize(app, arguments = ARGV) @app = app + @arguments = arguments end def start @@ -31,8 +34,8 @@ module Rails options['header'] = h end - opt.parse!(ARGV) - abort opt.to_s unless (0..1).include?(ARGV.size) + opt.parse!(arguments) + abort opt.to_s unless (0..1).include?(arguments.size) end unless config = @app.config.database_configuration[Rails.env] @@ -40,20 +43,6 @@ module Rails end - def find_cmd(*commands) - dirs_on_path = ENV['PATH'].to_s.split(File::PATH_SEPARATOR) - commands += commands.map{|cmd| "#{cmd}.exe"} if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ - - full_path_command = nil - found = commands.detect do |cmd| - dir = dirs_on_path.detect do |path| - full_path_command = File.join(path, cmd) - File.executable? full_path_command - end - end - found ? full_path_command : abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.") - end - case config["adapter"] when /^mysql/ args = { @@ -72,17 +61,17 @@ module Rails args << config['database'] - exec(find_cmd('mysql', 'mysql5'), *args) + find_cmd_and_exec(['mysql', 'mysql5'], *args) when "postgresql", "postgres" ENV['PGUSER'] = config["username"] if config["username"] ENV['PGHOST'] = config["host"] if config["host"] ENV['PGPORT'] = config["port"].to_s if config["port"] ENV['PGPASSWORD'] = config["password"].to_s if config["password"] && include_password - exec(find_cmd('psql'), config["database"]) + find_cmd_and_exec('psql', config["database"]) when "sqlite" - exec(find_cmd('sqlite'), config["database"]) + find_cmd_and_exec('sqlite', config["database"]) when "sqlite3" args = [] @@ -91,7 +80,7 @@ module Rails args << "-header" if options['header'] args << config['database'] - exec(find_cmd('sqlite3'), *args) + find_cmd_and_exec('sqlite3', *args) when "oracle", "oracle_enhanced" logon = "" @@ -102,12 +91,35 @@ module Rails logon << "@#{config['database']}" if config['database'] end - exec(find_cmd('sqlplus'), logon) + find_cmd_and_exec('sqlplus', logon) else abort "Unknown command-line client for #{config['database']}. Submit a Rails patch to add support!" end end + + protected + + def find_cmd_and_exec(commands, *args) + commands = Array(commands) + + dirs_on_path = ENV['PATH'].to_s.split(File::PATH_SEPARATOR) + commands += commands.map{|cmd| "#{cmd}.exe"} if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ + + full_path_command = nil + found = commands.detect do |cmd| + dir = dirs_on_path.detect do |path| + full_path_command = File.join(path, cmd) + File.executable? full_path_command + end + end + + if found + exec full_path_command, *args + else + abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.") + end + end end end diff --git a/railties/test/commands/dbconsole_test.rb b/railties/test/commands/dbconsole_test.rb new file mode 100644 index 0000000000..0bf417c014 --- /dev/null +++ b/railties/test/commands/dbconsole_test.rb @@ -0,0 +1,128 @@ +require 'abstract_unit' +require 'rails/commands/dbconsole' + +class Rails::DBConsoleTest < ActiveSupport::TestCase + def teardown + %w[PGUSER PGHOST PGPORT PGPASSWORD'].each{|key| ENV.delete(key)} + end + + def test_no_database_configured + start [], false + assert aborted + assert_match /No database is configured for the environment '\w+'/, output + end + + def test_mysql + dbconsole.expects(:find_cmd_and_exec).with(%w[mysql mysql5], 'db') + start [], {adapter: 'mysql', database: 'db'} + assert !aborted + end + + def test_mysql_full + dbconsole.expects(:find_cmd_and_exec).with(%w[mysql mysql5], '--host=locahost', '--port=1234', '--socket=socket', '--user=user', '--default-character-set=UTF-8', '-p', 'db') + start [], {adapter: 'mysql', database: 'db', host: 'locahost', port: 1234, socket: 'socket', username: 'user', password: 'qwerty', encoding: 'UTF-8'} + assert !aborted + end + + def test_mysql_include_password + dbconsole.expects(:find_cmd_and_exec).with(%w[mysql mysql5], '--user=user', '--password=qwerty', 'db') + start ['-p'], {adapter: 'mysql', database: 'db', username: 'user', password: 'qwerty'} + assert !aborted + end + + def test_postgresql + dbconsole.expects(:find_cmd_and_exec).with('psql', 'db') + start [], {adapter: 'postgresql', database: 'db'} + assert !aborted + end + + def test_postgresql_full + dbconsole.expects(:find_cmd_and_exec).with('psql', 'db') + start [], {adapter: 'postgresql', database: 'db', username: 'user', password: 'q1w2e3', host: 'host', port: 5432} + assert !aborted + assert_equal 'user', ENV['PGUSER'] + assert_equal 'host', ENV['PGHOST'] + assert_equal '5432', ENV['PGPORT'] + assert_not_equal 'q1w2e3', ENV['PGPASSWORD'] + end + + def test_postgresql_include_password + dbconsole.expects(:find_cmd_and_exec).with('psql', 'db') + start ['-p'], {adapter: 'postgresql', database: 'db', username: 'user', password: 'q1w2e3'} + assert !aborted + assert_equal 'user', ENV['PGUSER'] + assert_equal 'q1w2e3', ENV['PGPASSWORD'] + end + + def test_sqlite + dbconsole.expects(:find_cmd_and_exec).with('sqlite', 'db') + start [], {adapter: 'sqlite', database: 'db'} + assert !aborted + end + + def test_sqlite3 + dbconsole.expects(:find_cmd_and_exec).with('sqlite3', 'db') + start [], {adapter: 'sqlite3', database: 'db'} + assert !aborted + end + + def test_sqlite3_mode + dbconsole.expects(:find_cmd_and_exec).with('sqlite3', '-html', 'db') + start ['--mode', 'html'], {adapter: 'sqlite3', database: 'db'} + assert !aborted + end + + def test_sqlite3_header + dbconsole.expects(:find_cmd_and_exec).with('sqlite3', '-header', 'db') + start ['--header'], {adapter: 'sqlite3', database: 'db'} + assert !aborted + end + + def test_oracle + dbconsole.expects(:find_cmd_and_exec).with('sqlplus', 'user@db') + start [], {adapter: 'oracle', database: 'db', username: 'user', password: 'secret'} + assert !aborted + end + + def test_oracle_include_password + dbconsole.expects(:find_cmd_and_exec).with('sqlplus', 'user/secret@db') + start ['-p'], {adapter: 'oracle', database: 'db', username: 'user', password: 'secret'} + assert !aborted + end + + def test_unknown_command_line_client + start [], {adapter: 'unknown', database: 'db'} + assert aborted + assert_match /Unknown command-line client for db/, output + end + + private + attr_reader :aborted, :output + + def dbconsole + @dbconsole ||= Rails::DBConsole.new(app) + end + + def start(argv = [], database_configuration = {}) + dbconsole.stubs(arguments: argv) + app.config.stubs(database_configuration: { + Rails.env => database_configuration ? database_configuration.stringify_keys : database_configuration + }) + + @aborted = false + @output = capture(:stderr) do + begin + dbconsole.start + rescue SystemExit + @aborted = true + end + end + end + + def app + @app ||= begin + config = mock("config") + stub("app", config: config) + end + end +end |