stable-cli-rails 0.7.12 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/stable/bootstrap.rb +1 -0
  3. data/lib/stable/cli.rb +2 -6
  4. data/lib/stable/commands/doctor.rb +1 -0
  5. data/lib/stable/commands/list.rb +37 -32
  6. data/lib/stable/commands/new.rb +1 -0
  7. data/lib/stable/commands/remove.rb +1 -0
  8. data/lib/stable/commands/restart.rb +1 -0
  9. data/lib/stable/commands/setup.rb +1 -0
  10. data/lib/stable/commands/start.rb +1 -0
  11. data/lib/stable/commands/stop.rb +1 -0
  12. data/lib/stable/db_manager.rb +22 -7
  13. data/lib/stable/paths.rb +10 -1
  14. data/lib/stable/registry.rb +57 -7
  15. data/lib/stable/scanner.rb +1 -0
  16. data/lib/stable/services/app_creator.rb +12 -10
  17. data/lib/stable/services/app_registry.rb +31 -19
  18. data/lib/stable/services/app_remover.rb +1 -0
  19. data/lib/stable/services/app_restarter.rb +1 -0
  20. data/lib/stable/services/app_starter.rb +28 -4
  21. data/lib/stable/services/app_stopper.rb +1 -0
  22. data/lib/stable/services/caddy_manager.rb +1 -0
  23. data/lib/stable/services/database/base.rb +1 -0
  24. data/lib/stable/services/database/mysql.rb +1 -0
  25. data/lib/stable/services/database/postgres.rb +1 -0
  26. data/lib/stable/services/dependency_checker.rb +58 -9
  27. data/lib/stable/services/hosts_manager.rb +18 -7
  28. data/lib/stable/services/process_manager.rb +50 -7
  29. data/lib/stable/services/ruby.rb +1 -0
  30. data/lib/stable/services/setup_runner.rb +110 -16
  31. data/lib/stable/system/shell.rb +1 -0
  32. data/lib/stable/utils/package_manager.rb +68 -0
  33. data/lib/stable/utils/platform.rb +105 -0
  34. data/lib/stable/utils/prompts.rb +1 -0
  35. data/lib/stable/validators/app_name.rb +1 -0
  36. data/lib/stable.rb +1 -0
  37. metadata +6 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f092ba86af858aef49a2de7704a7039e3f25accafaf9028254469e9621c754ea
4
- data.tar.gz: 4ab71b60ae850c74508c790cf0fce5b14c2d12e0c8f2ec793a6b5e5234a95529
3
+ metadata.gz: 55fbeca00cb3d5ac0cf360dd86a8022081e3bf8b00af321c8ac8dec7482e7e5b
4
+ data.tar.gz: a1d3fa2c7d8ffb2ae339e75d4ebdd1aa67e4b1e7b88ef0377ce8d06dc170c94d
5
5
  SHA512:
6
- metadata.gz: 830108d826c9a63cdbaabf2c539b083795d7cf2772e1d8cea0c91d39dcefcaf06e792e1865793d7c7ab1da428b810228a36bbba34038555bcf20aefe03d2c295
7
- data.tar.gz: acdf43e4787cf9115eb29b4900f670cb9e2ce0a0fed29ba3f251cf40f00948897a3ed1c1edff3109053031c3ed6d238e4632d28f681fc591548635f9f03951ac
6
+ metadata.gz: 3e90d7e10d507ea30367e375dc99576f0b9902d77f9d7d2facf45e16fe116fff5eaac586eacec099b664b31f05f25dc33ec83db2d5b89926b0bb1fcf196588c8
7
+ data.tar.gz: 81a7739540c1b55e429867f7c7efd22af8a96559b239710fb290179c67d8ca67e1c6e5fc4448d3f6380cedf61b62fae4c1b737c5f98d532848c63652f2c05dcf
@@ -3,6 +3,7 @@
3
3
  require 'fileutils'
4
4
 
5
5
  module Stable
6
+ # Bootstrap utilities for setting up Stable environment
6
7
  module Bootstrap
7
8
  def self.run!
8
9
  FileUtils.mkdir_p(Paths.root)
data/lib/stable/cli.rb CHANGED
@@ -9,12 +9,12 @@ require_relative 'scanner'
9
9
  require_relative 'registry'
10
10
 
11
11
  module Stable
12
+ # Main CLI class for the Stable command-line interface
12
13
  class CLI < Thor
13
14
  def initialize(*)
14
15
  super
15
16
  Stable::Bootstrap.run!
16
17
  Services::SetupRunner.ensure_dependencies!
17
- dedupe_registry!
18
18
  end
19
19
 
20
20
  def self.exit_on_failure?
@@ -156,11 +156,7 @@ module Stable
156
156
  end
157
157
 
158
158
  def port_in_use?(port)
159
- system("lsof -i tcp:#{port} > /dev/null 2>&1")
160
- end
161
-
162
- def dedupe_registry!
163
- Services::AppRegistry.dedupe
159
+ Stable::Utils::Platform.port_in_use?(port)
164
160
  end
165
161
  end
166
162
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Commands
5
+ # Doctor command - checks system health and dependencies
5
6
  class Doctor
6
7
  def call
7
8
  puts 'Running Stable health checks...'
@@ -1,47 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../utils/platform'
4
+
3
5
  module Stable
4
6
  module Commands
7
+ # List command - displays all registered applications
5
8
  class List
6
- def call
7
- apps = Services::AppRegistry.all
9
+ def call
10
+ apps = Services::AppRegistry.all
8
11
 
9
- if apps.empty?
10
- puts 'No apps registered.'
11
- return
12
- end
12
+ if apps.empty?
13
+ puts 'No apps registered.'
14
+ return
15
+ end
13
16
 
14
- print_header
17
+ print_header
15
18
 
16
- apps.each do |app|
17
- puts format_row(app)
18
- end
19
+ apps.each do |app|
20
+ # Determine status based on whether the app is actually running (port check)
21
+ status = app_running?(app) ? 'running' : 'stopped'
22
+ puts format_row(app, status)
19
23
  end
24
+ end
20
25
 
21
- private
26
+ private
22
27
 
23
- def print_header
24
- puts 'APP DOMAIN PORT RUBY STATUS '
25
- puts '-' * 78
26
- end
28
+ def app_running?(app)
29
+ return false unless app && app[:port]
27
30
 
28
- def format_row(app)
29
- status =
30
- if app[:started_at]
31
- 'running'
32
- else
33
- 'stopped'
34
- end
35
-
36
- format(
37
- '%-18s %-26s %-8s %-10s %-10s',
38
- app[:name],
39
- app[:domain],
40
- app[:port],
41
- app[:ruby],
42
- status
43
- )
44
- end
31
+ # Check if something is listening on the app's port (cross-platform)
32
+ Stable::Utils::Platform.port_in_use?(app[:port])
33
+ end
34
+
35
+ def format_row(app, status)
36
+ format(
37
+ '%<name>-18s %<domain>-26s %<port>-8s %<ruby>-10s %<status>-10s',
38
+ name: app[:name],
39
+ domain: app[:domain],
40
+ port: app[:port],
41
+ ruby: app[:ruby],
42
+ status: status
43
+ )
44
+ end
45
+
46
+ def print_header
47
+ puts 'APP DOMAIN PORT RUBY STATUS '
48
+ puts '-' * 78
49
+ end
45
50
  end
46
51
  end
47
52
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Commands
5
+ # New command - creates a new Rails application
5
6
  class New
6
7
  def initialize(name, options)
7
8
  @name = name
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Commands
5
+ # Remove command - removes a Rails application
5
6
  class Remove
6
7
  def initialize(name)
7
8
  @name = name
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Commands
5
+ # Restart command - restarts a Rails application
5
6
  class Restart
6
7
  def initialize(name)
7
8
  @name = name
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Commands
5
+ # Setup command - initializes Stable environment
5
6
  class Setup
6
7
  def call
7
8
  Services::SetupRunner.new.call
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Commands
5
+ # Start command - starts a Rails application
5
6
  class Start
6
7
  def initialize(name)
7
8
  @name = name
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Commands
5
+ # Stop command - stops a Rails application
5
6
  class Stop
6
7
  def initialize(name)
7
8
  @name = name
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Stable
4
+ # Database management utilities for Rails applications
4
5
  class DBManager
5
6
  attr_reader :name, :adapter
6
7
 
@@ -101,16 +102,30 @@ module Stable
101
102
  )) or abort('Failed to repair MySQL root authentication')
102
103
  end
103
104
 
104
- # Detect MySQL socket on macOS / Linux
105
+ # Detect MySQL socket on macOS / Linux / Windows
105
106
  def mysql_socket
106
- paths = [
107
- '/opt/homebrew/var/mysql/mysql.sock', # Homebrew macOS
108
- '/tmp/mysql.sock', # Default
109
- '/var/run/mysqld/mysqld.sock' # Linux default
110
- ]
107
+ platform = RUBY_PLATFORM
108
+
109
+ paths = case platform
110
+ when /darwin/ # macOS
111
+ [
112
+ '/opt/homebrew/var/mysql/mysql.sock', # Homebrew macOS
113
+ '/tmp/mysql.sock' # Fallback
114
+ ]
115
+ when /linux/
116
+ [
117
+ '/var/run/mysqld/mysqld.sock', # Linux default
118
+ '/tmp/mysql.sock' # Fallback
119
+ ]
120
+ when /mingw|mswin|win32/ # Windows
121
+ # Windows typically uses TCP connections, not sockets
122
+ return nil
123
+ else
124
+ ['/tmp/mysql.sock'] # Generic fallback
125
+ end
111
126
 
112
127
  paths.each { |p| return p if File.exist?(p) }
113
- abort 'MySQL socket not found. Is MySQL running?'
128
+ abort 'MySQL socket not found. Is MySQL running? (On Windows, ensure MySQL is configured for TCP connections)'
114
129
  end
115
130
 
116
131
  # Default Rails DB user
data/lib/stable/paths.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Stable
4
+ # Path utilities for Stable configuration and data directories
4
5
  module Paths
5
6
  def self.root
6
- File.expand_path('~/StableCaddy')
7
+ ENV['STABLE_TEST_ROOT'] || File.expand_path('~/StableCaddy')
7
8
  end
8
9
 
9
10
  def self.caddy_dir
@@ -21,5 +22,13 @@ module Stable
21
22
  def self.apps_file
22
23
  File.join(root, 'apps.yml')
23
24
  end
25
+
26
+ def self.projects_dir
27
+ File.join(root, 'projects')
28
+ end
29
+
30
+ def self.app_config_file(app_name)
31
+ File.join(projects_dir, app_name, "#{app_name}.yml")
32
+ end
24
33
  end
25
34
  end
@@ -4,17 +4,39 @@ require 'yaml'
4
4
  require 'fileutils'
5
5
 
6
6
  module Stable
7
+ # Application registry for managing Rails app configurations
7
8
  class Registry
8
- def self.file_path
9
- Stable::Paths.apps_file
10
- end
9
+ def self.apps
10
+ apps = []
11
+
12
+ # Read legacy apps.yml file for backward compatibility
13
+ legacy_file = Stable::Paths.apps_file
14
+ if File.exist?(legacy_file)
15
+ legacy_apps = load_legacy_apps(legacy_file)
16
+ apps.concat(legacy_apps)
17
+ end
18
+
19
+ # Read individual app config files from projects directory
20
+ projects_dir = Stable::Paths.projects_dir
21
+ if Dir.exist?(projects_dir)
22
+ Dir.glob(File.join(projects_dir, '*/')).each do |app_dir|
23
+ app_name = File.basename(app_dir)
24
+ config_file = Stable::Paths.app_config_file(app_name)
25
+
26
+ next unless File.exist?(config_file)
11
27
 
12
- def self.save(apps)
13
- FileUtils.mkdir_p(Stable.root)
14
- File.write(file_path, apps.to_yaml)
28
+ # Skip if we already have this app from legacy file
29
+ next if apps.any? { |app| app[:name] == app_name }
30
+
31
+ app_config = load_app_config(app_name)
32
+ apps << app_config if app_config
33
+ end
34
+ end
35
+
36
+ apps
15
37
  end
16
38
 
17
- def self.apps
39
+ def self.load_legacy_apps(file_path)
18
40
  return [] unless File.exist?(file_path)
19
41
 
20
42
  data = YAML.load_file(file_path) || []
@@ -27,5 +49,33 @@ module Stable
27
49
  end
28
50
  end
29
51
  end
52
+
53
+ def self.save_app_config(app_name, config)
54
+ config_file = Stable::Paths.app_config_file(app_name)
55
+ FileUtils.mkdir_p(File.dirname(config_file))
56
+ File.write(config_file, config.to_yaml)
57
+ end
58
+
59
+ def self.load_app_config(app_name)
60
+ config_file = Stable::Paths.app_config_file(app_name)
61
+ return nil unless File.exist?(config_file)
62
+
63
+ parse_config_file(config_file)
64
+ end
65
+
66
+ def self.remove_app_config(app_name)
67
+ config_file = Stable::Paths.app_config_file(app_name)
68
+ FileUtils.rm_f(config_file)
69
+ end
70
+
71
+ def self.parse_config_file(config_file)
72
+ data = YAML.load_file(config_file)
73
+ return nil unless data.is_a?(Hash)
74
+
75
+ data.each_with_object({}) do |(k, v), memo|
76
+ key = k.is_a?(String) ? k.to_sym : k
77
+ memo[key] = v
78
+ end
79
+ end
30
80
  end
31
81
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Stable
4
+ # Scanner utility for application discovery and management
4
5
  class Scanner
5
6
  def self.run
6
7
  Registry.save([])
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Services
5
+ # Service for creating new Rails applications
5
6
  class AppCreator
6
7
  def initialize(name, options)
7
8
  @name = name
@@ -11,17 +12,19 @@ module Stable
11
12
  def call
12
13
  ruby = @options[:ruby] || RUBY_VERSION
13
14
  port = @options[:port] || next_free_port
14
- app_path = File.expand_path(@name)
15
+ app_path = File.join(Stable::Paths.projects_dir, @name)
15
16
  domain = "#{@name}.test"
16
17
 
18
+ # --- Check if app already exists ---
19
+ config_file = Stable::Paths.app_config_file(@name)
20
+ abort "App '#{@name}' already exists" if File.exist?(config_file)
21
+
17
22
  # --- Register app in registry ---
18
23
  Services::AppRegistry.add(
19
24
  name: @name, path: app_path, domain: domain, port: port,
20
25
  ruby: ruby, started_at: nil, pid: nil
21
26
  )
22
27
 
23
- abort "Folder already exists: #{app_path}" if File.exist?(app_path)
24
-
25
28
  # --- Ensure Ruby version & RVM ---
26
29
  Ruby.ensure_version(ruby)
27
30
  Ruby.ensure_rvm!
@@ -45,11 +48,9 @@ module Stable
45
48
 
46
49
  # --- Create Rails app ---
47
50
  puts "Creating Rails app #{@name} (Ruby #{ruby})..."
48
- System::Shell.run("bash -lc '#{rvm_cmd} rails new #{app_path} \
49
- --skip-importmap \
50
- --skip-hotwire \
51
- --skip-javascript \
52
- --skip-solid'")
51
+ rails_cmd = "#{rvm_cmd} rails new #{app_path} " \
52
+ '--skip-importmap --skip-hotwire --skip-javascript --skip-solid'
53
+ System::Shell.run("bash -lc '#{rails_cmd}'")
53
54
 
54
55
  # --- Write ruby version/gemset ---
55
56
  Dir.chdir(app_path) do
@@ -82,7 +83,8 @@ module Stable
82
83
  System::Shell.run(rvm_run('bundle install --jobs=4 --retry=3', chdir: app_path))
83
84
  System::Shell.run(rvm_run('bundle exec rails db:prepare', chdir: app_path))
84
85
 
85
- rails_version = `bash -lc 'cd #{app_path} && #{rvm_cmd} bundle exec rails runner "puts Rails.version"'`.strip.to_f
86
+ rails_check = "cd #{app_path} && #{rvm_cmd} bundle exec rails runner \"puts Rails.version\""
87
+ rails_version = `bash -lc '#{rails_check}'`.strip.to_f
86
88
 
87
89
  begin
88
90
  rails_ver = Gem::Version.new(rails_version)
@@ -190,7 +192,7 @@ module Stable
190
192
  end
191
193
 
192
194
  def port_in_use?(port)
193
- system("lsof -i tcp:#{port} > /dev/null 2>&1")
195
+ Stable::Utils::Platform.port_in_use?(port)
194
196
  end
195
197
 
196
198
  def wait_for_port(port, timeout: 20)
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Services
5
+ # Application registry management service
5
6
  class AppRegistry
6
7
  class << self
7
8
  def all
@@ -42,32 +43,43 @@ module Stable
42
43
  end
43
44
 
44
45
  def add(app)
45
- apps = Stable::Registry.apps
46
- apps.reject! { |a| a[:name] == app[:name] }
47
- apps << app
48
- Stable::Registry.save(apps)
49
- end
50
-
51
- # Remove duplicate app entries (by name) and persist the canonical list
52
- def dedupe
53
- apps = Stable::Registry.apps
54
- apps.uniq! { |a| a[:name] }
55
- Stable::Registry.save(apps)
56
- apps
46
+ Stable::Registry.save_app_config(app[:name], app)
57
47
  end
58
48
 
59
49
  def remove(name)
60
- apps = Stable::Registry.apps.reject { |a| a[:name] == name }
61
- Stable::Registry.save(apps)
50
+ Stable::Registry.remove_app_config(name)
62
51
  end
63
52
 
64
53
  def update(name, attrs)
65
- apps = Stable::Registry.apps
66
- idx = apps.index { |a| a[:name] == name }
67
- return unless idx
54
+ app = find(name)
55
+ return unless app
56
+
57
+ updated_app = app.merge(attrs)
58
+
59
+ # Check if this is a legacy app (from apps.yml) or new format app
60
+ config_file = Stable::Paths.app_config_file(name)
61
+ if File.exist?(config_file)
62
+ # New format: update individual config file
63
+ Stable::Registry.save_app_config(name, updated_app)
64
+ else
65
+ # Legacy format: update apps.yml file
66
+ update_legacy_app(name, updated_app)
67
+ end
68
+ end
69
+
70
+ def update_legacy_app(name, updated_app)
71
+ legacy_file = Stable::Paths.apps_file
72
+ return unless File.exist?(legacy_file)
73
+
74
+ data = YAML.load_file(legacy_file) || []
75
+ idx = data.find_index { |app| app['name'] == name || app[:name] == name }
68
76
 
69
- apps[idx] = apps[idx].merge(attrs)
70
- Stable::Registry.save(apps)
77
+ if idx
78
+ # Convert symbols to strings for YAML compatibility
79
+ legacy_format = updated_app.transform_keys(&:to_s)
80
+ data[idx] = legacy_format
81
+ File.write(legacy_file, data.to_yaml)
82
+ end
71
83
  end
72
84
 
73
85
  def mark_stopped(name)
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Services
5
+ # Service for removing Rails applications
5
6
  class AppRemover
6
7
  def initialize(name)
7
8
  @name = name
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Services
5
+ # Service for restarting Rails applications
5
6
  class AppRestarter
6
7
  def initialize(name)
7
8
  @name = name
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Services
5
+ # Service for starting Rails applications
5
6
  class AppStarter
6
7
  def initialize(name)
7
8
  @name = name
@@ -20,6 +21,14 @@ module Stable
20
21
 
21
22
  if app_running?(app)
22
23
  puts "#{@name} is already running on https://#{app[:domain]} (port #{port})"
24
+ # Update the registry with the correct PID if it's missing
25
+ if !app[:pid] || !app[:started_at]
26
+ rails_pid = find_rails_pid(port)
27
+ if rails_pid
28
+ AppRegistry.update(app[:name], started_at: Time.now.to_i, pid: rails_pid)
29
+ puts "Updated registry with correct PID (#{rails_pid})"
30
+ end
31
+ end
23
32
  return
24
33
  end
25
34
 
@@ -50,7 +59,9 @@ module Stable
50
59
 
51
60
  wait_for_port(port, timeout: 30)
52
61
 
53
- AppRegistry.update(app[:name], started_at: Time.now.to_i, pid: pid)
62
+ # Find the actual Rails process PID by checking what's listening on the port
63
+ rails_pid = find_rails_pid(port)
64
+ AppRegistry.update(app[:name], started_at: Time.now.to_i, pid: rails_pid)
54
65
 
55
66
  Stable::Services::CaddyManager.add_app(app[:name], skip_ssl: false)
56
67
  Stable::Services::CaddyManager.reload
@@ -68,7 +79,7 @@ module Stable
68
79
  end
69
80
 
70
81
  def port_in_use?(port)
71
- system("lsof -i tcp:#{port} > /dev/null 2>&1")
82
+ Stable::Utils::Platform.port_in_use?(port)
72
83
  end
73
84
 
74
85
  def wait_for_port(port, timeout: 20)
@@ -86,9 +97,22 @@ module Stable
86
97
  end
87
98
 
88
99
  def app_running?(app)
89
- return false unless app && app[:port]
100
+ return false unless app
101
+
102
+ # First check if we have PID info and if the process is alive
103
+ if app[:pid] && app[:started_at]
104
+ return ProcessManager.pid_alive?(app[:pid])
105
+ end
106
+
107
+ # Fallback to port checking if no PID info available
108
+ return false unless app[:port]
109
+
110
+ Stable::Utils::Platform.port_in_use?(app[:port])
111
+ end
90
112
 
91
- system("lsof -i tcp:#{app[:port]} -sTCP:LISTEN > /dev/null 2>&1")
113
+ def find_rails_pid(port)
114
+ pids = Stable::Utils::Platform.find_pids_by_port(port)
115
+ pids.first
92
116
  end
93
117
  end
94
118
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Services
5
+ # Service for stopping Rails applications
5
6
  class AppStopper
6
7
  def initialize(name)
7
8
  @app = AppRegistry.fetch(name)
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Stable
4
4
  module Services
5
+ # Service for managing Caddy web server configuration
5
6
  class CaddyManager
6
7
  class << self
7
8
  def caddyfile
@@ -3,6 +3,7 @@
3
3
  module Stable
4
4
  module Services
5
5
  module Database
6
+ # Base class for database management services
6
7
  class Base
7
8
  def initialize(app_name:, app_path:, ruby:)
8
9
  @app_name = app_name
@@ -3,6 +3,7 @@
3
3
  module Stable
4
4
  module Services
5
5
  module Database
6
+ # MySQL database management service
6
7
  class MySQL < Base
7
8
  def setup
8
9
  creds = Stable::Utils::Prompts.mysql_root_credentials
@@ -3,6 +3,7 @@
3
3
  module Stable
4
4
  module Services
5
5
  module Database
6
+ # PostgreSQL database management service
6
7
  class Postgres < Base
7
8
  def setup
8
9
  System::Shell.run("createdb #{@database_name}")