arql 0.3.31 → 0.4.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.
- checksums.yaml +4 -4
- data/.vscode/launch.json +1 -1
- data/Gemfile.lock +1 -1
- data/README-zh_CN.org +616 -491
- data/README.org +803 -628
- data/auto-set-id-before-save-zh_CN.org +1 -1
- data/auto-set-id-before-save.org +1 -1
- data/custom-configurations-zh_CN.org +40 -3
- data/custom-configurations.org +71 -32
- data/define-associations-zh_CN.org +31 -17
- data/define-associations.org +52 -29
- data/initializer-structure-zh_CN.org +23 -5
- data/initializer-structure.org +46 -18
- data/lib/arql/app.rb +98 -71
- data/lib/arql/cli.rb +37 -15
- data/lib/arql/commands/info.rb +41 -28
- data/lib/arql/commands/models.rb +106 -61
- data/lib/arql/commands/reconnect.rb +8 -4
- data/lib/arql/commands/redefine.rb +3 -1
- data/lib/arql/commands/sandbox.rb +6 -4
- data/lib/arql/commands.rb +0 -2
- data/lib/arql/concerns/global_data_definition.rb +40 -6
- data/lib/arql/concerns/model_extension.rb +168 -0
- data/lib/arql/concerns/table_data_definition.rb +20 -20
- data/lib/arql/concerns.rb +1 -0
- data/lib/arql/definition.rb +169 -317
- data/lib/arql/ext/active_record/relation.rb +29 -0
- data/lib/arql/ext/active_record/result.rb +29 -0
- data/lib/arql/ext/array.rb +40 -1
- data/lib/arql/ext/kernel.rb +70 -61
- data/lib/arql/ext/object.rb +14 -0
- data/lib/arql/ext/ransack/search.rb +29 -0
- data/lib/arql/mysqldump.rb +0 -1
- data/lib/arql/repl.rb +1 -1
- data/lib/arql/ssh_proxy.rb +25 -22
- data/lib/arql/version.rb +1 -1
- data/lib/arql.rb +11 -7
- data/oss-files-zh_CN.org +2 -2
- data/oss-files.org +2 -2
- data/sql-log-zh_CN.org +8 -3
- data/sql-log.org +8 -3
- metadata +6 -5
- data/lib/arql/commands/table.rb +0 -55
- data/lib/arql/commands/vd.rb +0 -46
- data/lib/arql/connection.rb +0 -16
data/lib/arql/app.rb
CHANGED
@@ -1,114 +1,141 @@
|
|
1
1
|
module Arql
|
2
2
|
class App
|
3
|
+
attr_accessor :log_io, :environments, :definitions, :options, :config
|
3
4
|
|
4
5
|
class << self
|
5
|
-
attr_accessor :
|
6
|
+
attr_accessor :instance
|
6
7
|
|
7
|
-
def
|
8
|
-
|
8
|
+
def log_io
|
9
|
+
instance.log_io
|
10
|
+
end
|
11
|
+
|
12
|
+
def log_io=(io)
|
13
|
+
instance.log_io = io
|
14
|
+
end
|
15
|
+
|
16
|
+
# environment names
|
17
|
+
def environments
|
18
|
+
instance.environments
|
9
19
|
end
|
10
20
|
|
11
21
|
def prompt
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
22
|
+
instance.prompt
|
23
|
+
end
|
24
|
+
|
25
|
+
def config
|
26
|
+
instance.config
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def prompt
|
31
|
+
if environments.present?
|
32
|
+
environments.join('+')
|
33
|
+
else
|
34
|
+
File.basename(@options.database)
|
17
35
|
end
|
18
36
|
end
|
19
37
|
|
20
38
|
def initialize(options)
|
21
|
-
require "arql/connection"
|
22
39
|
require "arql/definition"
|
40
|
+
|
41
|
+
App.instance = self
|
42
|
+
|
43
|
+
# command line options
|
23
44
|
@options = options
|
24
|
-
|
25
|
-
|
26
|
-
|
45
|
+
|
46
|
+
# env names
|
47
|
+
@environments = @options.environments
|
48
|
+
@environments ||= ['default']
|
49
|
+
|
27
50
|
print "Defining models..."
|
28
|
-
@
|
51
|
+
@definitions = config[:environments].each_with_object({}) do |(env_name, env_conf), h|
|
52
|
+
h[env_name] = Definition.new(env_conf)
|
53
|
+
end.with_indifferent_access
|
54
|
+
|
29
55
|
print "\u001b[2K"
|
30
56
|
puts "\rModels defined"
|
31
57
|
print "Running initializers..."
|
32
58
|
load_initializer!
|
33
59
|
print "\u001b[2K"
|
34
60
|
puts "\rInitializers loaded"
|
35
|
-
App.instance = self
|
36
|
-
end
|
37
|
-
|
38
|
-
def connect_options
|
39
|
-
connect_conf = effective_config.slice(:adapter, :host, :username,
|
40
|
-
:password, :database, :encoding,
|
41
|
-
:pool, :port, :socket)
|
42
|
-
if effective_config[:ssh].present?
|
43
|
-
connect_conf.merge!(start_ssh_proxy!)
|
44
|
-
end
|
45
|
-
|
46
|
-
connect_conf
|
47
61
|
end
|
48
62
|
|
49
63
|
def load_initializer!
|
50
|
-
return unless
|
51
|
-
|
64
|
+
return unless config[:options][:initializer]
|
65
|
+
|
66
|
+
initializer_file = File.expand_path(config[:options][:initializer])
|
52
67
|
unless File.exist?(initializer_file)
|
53
|
-
|
68
|
+
warn "Specified initializer file not found, #{config[:options][:initializer]}"
|
54
69
|
exit(1)
|
55
70
|
end
|
56
71
|
load(initializer_file)
|
57
72
|
end
|
58
73
|
|
59
|
-
def
|
60
|
-
|
61
|
-
local_ssh_proxy_port = Arql::SSHProxy.connect(ssh_config.slice(:host, :user, :port, :password).merge(
|
62
|
-
forward_host: effective_config[:host],
|
63
|
-
forward_port: effective_config[:port],
|
64
|
-
local_port: ssh_config[:local_port]))
|
65
|
-
{
|
66
|
-
host: '127.0.0.1',
|
67
|
-
port: local_ssh_proxy_port
|
68
|
-
}
|
69
|
-
end
|
70
|
-
|
71
|
-
def config
|
72
|
-
@config ||= YAML.load(IO.read(File.expand_path(@options.config_file)), aliases: true).with_indifferent_access
|
74
|
+
def config_from_file
|
75
|
+
@config_from_file ||= YAML.safe_load(IO.read(File.expand_path(@options.config_file)), aliases: true).with_indifferent_access
|
73
76
|
rescue ArgumentError
|
74
|
-
@
|
77
|
+
@config_from_file ||= YAML.safe_load(IO.read(File.expand_path(@options.config_file))).with_indifferent_access
|
75
78
|
end
|
76
79
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
+
# Returns the configuration for config file.
|
81
|
+
# or default configuration (built from CLI options) if no environment specified
|
82
|
+
def environ_config_from_file
|
83
|
+
if @options.enviroments.present? || @options.environments&.any? { |env_names| !config_from_file.key?(env_names) }
|
84
|
+
warn "Specified ENV `#{@options.env}' not exists in config file"
|
85
|
+
exit(1)
|
80
86
|
end
|
81
|
-
|
82
|
-
|
87
|
+
conf = if @options.environments.present?
|
88
|
+
@config_from_file.slice(*@options.environments)
|
83
89
|
else
|
84
|
-
{}
|
90
|
+
{ default: @options.to_h }.with_indifferent_access
|
85
91
|
end
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
@@effective_config ||= nil
|
90
|
-
unless @@effective_config
|
91
|
-
@@effective_config = selected_config.deep_merge(@options.to_h)
|
92
|
-
if @@effective_config[:adapter].blank?
|
93
|
-
@@effective_config[:adapter] = 'sqlite3'
|
92
|
+
conf.each do |env_name, env_conf|
|
93
|
+
unless env_conf.key?(:namespace)
|
94
|
+
env_conf[:namespace] = env_name.to_s.gsub(/[^a-zA-Z0-9]/, '_').camelize
|
94
95
|
end
|
95
|
-
@@effective_config[:database] = File.expand_path(@@effective_config[:database]) if @@effective_config[:adapter] == 'sqlite3'
|
96
96
|
end
|
97
|
-
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the effective configuration for the application.
|
100
|
+
# structure like:
|
101
|
+
# {
|
102
|
+
# options: {show_sql: true,
|
103
|
+
# write_sql: 'output.sql',
|
104
|
+
# },
|
105
|
+
# environments: {
|
106
|
+
# development: {adapter: 'mysql2',
|
107
|
+
# host: 'localhost',
|
108
|
+
# port: 3306},
|
109
|
+
# test: {adapter: 'mysql2',
|
110
|
+
# host: 'localhost',
|
111
|
+
# port: 3306},
|
112
|
+
# }
|
113
|
+
# }
|
114
|
+
def config
|
115
|
+
@config ||= {
|
116
|
+
options: @options,
|
117
|
+
environments: environ_config_from_file.each_with_object({}) { |(env_name, env_conf), h|
|
118
|
+
conf = env_conf.deep_merge(@options.to_h)
|
119
|
+
conf[:adapter] = 'sqlite3' if conf[:adapter].blank?
|
120
|
+
conf[:database] = File.expand_path(conf[:database]) if conf[:adapter] == 'sqlite3'
|
121
|
+
h[env_name] = conf
|
122
|
+
h
|
123
|
+
}.with_indifferent_access
|
124
|
+
}
|
98
125
|
end
|
99
126
|
|
100
127
|
def run!
|
101
128
|
show_sql if should_show_sql?
|
102
129
|
write_sql if should_write_sql?
|
103
130
|
append_sql if should_append_sql?
|
104
|
-
if
|
105
|
-
eval(
|
106
|
-
elsif
|
107
|
-
|
108
|
-
elsif
|
131
|
+
if @options.code&.present?
|
132
|
+
eval(@options.code)
|
133
|
+
elsif @options.args.present?
|
134
|
+
@options.args.first.tap { |file| load(file) }
|
135
|
+
elsif $stdin.isatty
|
109
136
|
run_repl!
|
110
137
|
else
|
111
|
-
eval(
|
138
|
+
eval($stdin.read)
|
112
139
|
end
|
113
140
|
end
|
114
141
|
|
@@ -117,32 +144,32 @@ module Arql
|
|
117
144
|
end
|
118
145
|
|
119
146
|
def should_show_sql?
|
120
|
-
|
147
|
+
@options.show_sql
|
121
148
|
end
|
122
149
|
|
123
150
|
def should_write_sql?
|
124
|
-
|
151
|
+
@options.write_sql
|
125
152
|
end
|
126
153
|
|
127
154
|
def should_append_sql?
|
128
|
-
|
155
|
+
@options.append_sql
|
129
156
|
end
|
130
157
|
|
131
158
|
def show_sql
|
132
159
|
App.log_io ||= MultiIO.new
|
133
160
|
ActiveRecord::Base.logger = Logger.new(App.log_io)
|
134
|
-
App.log_io <<
|
161
|
+
App.log_io << $stdout
|
135
162
|
end
|
136
163
|
|
137
164
|
def write_sql
|
138
|
-
write_sql_file =
|
165
|
+
write_sql_file = @options.write_sql
|
139
166
|
App.log_io ||= MultiIO.new
|
140
167
|
ActiveRecord::Base.logger = Logger.new(App.log_io)
|
141
168
|
App.log_io << File.new(write_sql_file, 'w')
|
142
169
|
end
|
143
170
|
|
144
171
|
def append_sql
|
145
|
-
write_sql_file =
|
172
|
+
write_sql_file = @options.append_sql
|
146
173
|
App.log_io ||= MultiIO.new
|
147
174
|
ActiveRecord::Base.logger = Logger.new(App.log_io)
|
148
175
|
App.log_io << File.new(write_sql_file, 'a')
|
data/lib/arql/cli.rb
CHANGED
@@ -12,6 +12,7 @@ module Arql
|
|
12
12
|
def parse_options!
|
13
13
|
@options = OpenStruct.new(config_file: default_config_file,
|
14
14
|
initializer: default_initializer,
|
15
|
+
babel_compatable: false,
|
15
16
|
ssh: {})
|
16
17
|
|
17
18
|
|
@@ -19,7 +20,7 @@ module Arql
|
|
19
20
|
opts.banner = <<~EOF
|
20
21
|
Usage: arql [options] [ruby file]
|
21
22
|
|
22
|
-
If neither [ruby file] nor -e option specified, and STDIN is
|
23
|
+
If neither [ruby file] nor -e option specified, and STDIN is a tty, a Pry REPL will be launched,
|
23
24
|
otherwise the specified ruby file or -e option value or ruby code read from STDIN will be run, and no REPL launched
|
24
25
|
|
25
26
|
EOF
|
@@ -32,8 +33,12 @@ module Arql
|
|
32
33
|
@options.initializer = initializer
|
33
34
|
end
|
34
35
|
|
35
|
-
opts.on('-eENVIRON', '--env=ENVIRON', 'Specify config environment
|
36
|
-
@options.
|
36
|
+
opts.on('-eENVIRON', '--env=ENVIRON', 'Specify config environment, multiple environments allowed, separated by comma') do |env_names|
|
37
|
+
@options.environments = env_names.split(/[,\+:]/)
|
38
|
+
if @options.environments.any? { |e| e =~ /^default|arql$/i }
|
39
|
+
warn '[default, arql] are reserved environment names, please use another name'
|
40
|
+
exit(1)
|
41
|
+
end
|
37
42
|
end
|
38
43
|
|
39
44
|
opts.on('-aDB_ADAPTER', '--db-adapter=DB_ADAPTER', 'Specify database Adapter, default is sqlite3') do |db_adapter|
|
@@ -92,6 +97,11 @@ module Arql
|
|
92
97
|
@options.code = code
|
93
98
|
end
|
94
99
|
|
100
|
+
opts.on('-b', '--babel', 'Enable compatibility for Org-Mode Babel') do
|
101
|
+
@options.babel_compatable = true
|
102
|
+
end
|
103
|
+
|
104
|
+
|
95
105
|
opts.on('-S', '--show-sql', 'Show SQL on STDOUT') do
|
96
106
|
@options.show_sql = true
|
97
107
|
end
|
@@ -117,24 +127,36 @@ module Arql
|
|
117
127
|
end.parse!
|
118
128
|
|
119
129
|
@options.args = ARGV
|
130
|
+
|
131
|
+
if @options.environments&.size&.positive? && any_database_options?
|
132
|
+
$stderr.puts "Following options are not allowed when using multiple environments specified: #{database_options.join(', ')}"
|
133
|
+
$stderr.puts " #{database_options.join(', ')}"
|
134
|
+
exit(1)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def any_database_options?
|
139
|
+
%i[adapter host port database username
|
140
|
+
password encoding pool ssh].reduce(false) do |acc, opt|
|
141
|
+
acc || @options.send(opt).present?
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def database_options
|
146
|
+
['--db-adapter', '--db-host', '--db-port', '--db-name', '--db-user', '--db-password',
|
147
|
+
'--db-encoding', '--db-pool', '--ssh-host', '--ssh-port', '--ssh-user', '--ssh-password', '--ssh-local-port']
|
120
148
|
end
|
121
149
|
|
122
150
|
def default_config_file
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
return conf if File.file?(conf)
|
127
|
-
conf = File.expand_path('~/.arql.d/init.yml')
|
128
|
-
return conf if File.file?(conf)
|
129
|
-
conf = File.expand_path('~/.arql.d/init.yaml')
|
130
|
-
return conf if File.file?(conf)
|
151
|
+
['~/.arql.yml', '~/.arql.yaml', '~/.arql.d/init.yml', '~/.arql.d/init.yaml'].find { |f|
|
152
|
+
File.file?(File.expand_path(f))
|
153
|
+
}.try { |f| File.expand_path(f) }
|
131
154
|
end
|
132
155
|
|
133
156
|
def default_initializer
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
return conf if File.file?(conf)
|
157
|
+
['~/.arql.rb', '~/.arql.d/init.rb',].find { |f|
|
158
|
+
File.file?(File.expand_path(f))
|
159
|
+
}.try { |f| File.expand_path(f) }
|
138
160
|
end
|
139
161
|
end
|
140
162
|
end
|
data/lib/arql/commands/info.rb
CHANGED
@@ -3,38 +3,49 @@ require 'rainbow'
|
|
3
3
|
module Arql::Commands
|
4
4
|
module Info
|
5
5
|
class << self
|
6
|
-
def db_info
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
6
|
+
def db_info(env_name_regexp)
|
7
|
+
|
8
|
+
Arql::App.instance.definitions.map do |env_name, definition|
|
9
|
+
next unless env_name =~ env_name_regexp
|
10
|
+
config = Arql::App.config[:environments][env_name]
|
11
|
+
<<~DB_INFO
|
12
|
+
|
13
|
+
#{env_name} Database Connection Information:
|
14
|
+
|
15
|
+
Active: #{color_boolean(definition.connection.active?)}
|
16
|
+
Host: #{config[:host]}
|
17
|
+
Port: #{config[:port]}
|
18
|
+
Username: #{config[:username]}
|
19
|
+
Password: #{(config[:password] || '').gsub(/./, '*')}
|
20
|
+
Database: #{config[:database]}
|
21
|
+
Adapter: #{config[:adapter]}
|
22
|
+
Encoding: #{config[:encoding]}
|
23
|
+
Pool Size: #{config[:pool]}
|
24
|
+
DB_INFO
|
25
|
+
end
|
21
26
|
end
|
22
27
|
|
23
|
-
def ssh_info
|
24
|
-
|
28
|
+
def ssh_info(env_name_regexp)
|
29
|
+
Arql::App.instance.definitions.map do |env_name, definition|
|
30
|
+
next unless env_name =~ env_name_regexp
|
31
|
+
config = Arql::App.config[:environments][env_name]
|
32
|
+
next unless config[:ssh].present?
|
33
|
+
<<~SSH_INFO
|
25
34
|
|
26
|
-
|
35
|
+
#{env_name} SSH Connection Information:
|
27
36
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
37
|
+
Active: #{color_boolean(definition.ssh_proxy.active?)}
|
38
|
+
Host: #{config[:ssh][:host]}
|
39
|
+
Port: #{config[:ssh][:port]}
|
40
|
+
Username: #{config[:ssh][:user]}
|
41
|
+
Password: #{(config[:ssh][:password] || '').gsub(/./, '*')}
|
42
|
+
Local Port: #{definition.ssh_proxy.local_ssh_proxy_port}
|
43
|
+
SSH_INFO
|
44
|
+
end
|
35
45
|
end
|
36
46
|
|
37
47
|
private
|
48
|
+
|
38
49
|
def color_boolean(bool)
|
39
50
|
if bool
|
40
51
|
Rainbow('TRUE').green
|
@@ -44,9 +55,11 @@ module Arql::Commands
|
|
44
55
|
end
|
45
56
|
end
|
46
57
|
|
47
|
-
Pry.commands.block_command 'info' do
|
48
|
-
|
49
|
-
|
58
|
+
Pry.commands.block_command 'info' do |env_name_regexp|
|
59
|
+
env_name_regexp ||= '.*'
|
60
|
+
env_name_regexp = Regexp.new(env_name_regexp, Regexp::IGNORECASE)
|
61
|
+
output.puts Info::db_info(env_name_regexp)
|
62
|
+
output.puts Info::ssh_info(env_name_regexp)
|
50
63
|
end
|
51
64
|
end
|
52
65
|
end
|
data/lib/arql/commands/models.rb
CHANGED
@@ -3,84 +3,129 @@ require 'terminal-table'
|
|
3
3
|
module Arql::Commands
|
4
4
|
module Models
|
5
5
|
class << self
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
if column_regexp.nil?
|
18
|
-
Terminal::Table.new do |t|
|
19
|
-
models.each_with_index { |row, idx| t << (row || :separator) if row.nil? ||
|
20
|
-
table_regexp.nil? ||
|
21
|
-
idx.zero? ||
|
22
|
-
row.any? { |e| e =~ table_regexp }
|
23
|
-
}
|
6
|
+
def filter_tables(env_name, definition, format, table_regexp=nil)
|
7
|
+
result = ''
|
8
|
+
result << '-- ' if format == 'sql'
|
9
|
+
result << "Environment: #{env_name}\n"
|
10
|
+
result << "------------------------------\n\n"
|
11
|
+
if format == 'sql'
|
12
|
+
definition.models.each do |model|
|
13
|
+
if table_regexp? || ( model[:table] =~ table_regexp || model[:comment] =~ table_regexp )
|
14
|
+
result << "-- Table: #{table_name}\n\n"
|
15
|
+
result << definition.connection.exec_query("show create table `#{table_name}`").rows.last.last + ';'
|
16
|
+
end
|
24
17
|
end
|
25
18
|
else
|
26
|
-
|
27
|
-
|
28
|
-
t << ['
|
19
|
+
Terminal::Table.new do |t|
|
20
|
+
t.style = table_style_for_format(format)
|
21
|
+
t << ['Table Name', 'Model Class', 'Abbr', 'Comment']
|
29
22
|
t << :separator
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
next if matched_columns.empty?
|
34
|
-
matched_columns.each do |column|
|
35
|
-
pk = if [connection.primary_key(definition[:table])].flatten.include?(column.name)
|
36
|
-
'Y'
|
37
|
-
else
|
38
|
-
''
|
39
|
-
end
|
40
|
-
t << [pk, definition[:table], model_class.name, column.name, column.sql_type,
|
41
|
-
column.sql_type_metadata.type, column.sql_type_metadata.limit || '',
|
42
|
-
column.sql_type_metadata.precision || '', column.sql_type_metadata.scale || '', column.default || '',
|
43
|
-
column.null, "#{definition[:comment]} - #{column.comment}"]
|
23
|
+
definition.models.each do |model|
|
24
|
+
if table_regexp.nil? || ( model[:table] =~ table_regexp || model[:comment] =~ table_regexp )
|
25
|
+
t << [model[:table], model[:model].name, model[:abbr] || '', model[:comment] || '']
|
44
26
|
end
|
45
27
|
end
|
28
|
+
end.try { |e|
|
29
|
+
case format
|
30
|
+
when 'md'
|
31
|
+
result << e.to_s.lines.map { |l| ' ' + l }.join
|
32
|
+
when 'org'
|
33
|
+
result << e.to_s.lines.map { |l| ' ' + l.gsub(/^\+|\+$/, '|') }.join
|
34
|
+
else
|
35
|
+
result << e.to_s
|
36
|
+
end
|
37
|
+
}
|
38
|
+
end
|
39
|
+
result
|
40
|
+
end
|
41
|
+
|
42
|
+
def filter_columns(env_name, definition, format, column_regexp=nil)
|
43
|
+
result = ''
|
44
|
+
result << '-- ' if format == 'sql'
|
45
|
+
result << "Environment: #{env_name}\n"
|
46
|
+
result << "------------------------------\n\n"
|
47
|
+
Terminal::Table.new do |t|
|
48
|
+
t.style = table_style_for_format(format)
|
49
|
+
t << ['Table', 'Model', 'Name', 'SQL Type', 'Ruby Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']
|
50
|
+
t << :separator
|
51
|
+
definition.models.each do |model_def|
|
52
|
+
model_class = model_def[:model]
|
53
|
+
matched_columns = model_class.columns.select { |column| column.name =~ column_regexp || column.comment =~ column_regexp }
|
54
|
+
next if matched_columns.empty?
|
55
|
+
matched_columns.each do |column|
|
56
|
+
t << [model_def[:table], model_class.name, column.name, column.sql_type,
|
57
|
+
column.sql_type_metadata.type, column.sql_type_metadata.limit || '',
|
58
|
+
column.sql_type_metadata.precision || '', column.sql_type_metadata.scale || '', column.default || '',
|
59
|
+
column.null, "#{model_def[:comment]} - #{column.comment}"]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end.try { |e|
|
63
|
+
case format
|
64
|
+
when 'md'
|
65
|
+
result << e.to_s.lines.map { |l| ' ' + l }.join
|
66
|
+
when 'org'
|
67
|
+
result << e.to_s.lines.map { |l| ' ' + l.gsub(/^\+|\+$/, '|') }.join
|
68
|
+
else
|
69
|
+
result << e.to_s
|
46
70
|
end
|
47
|
-
|
71
|
+
}
|
72
|
+
result
|
73
|
+
end
|
74
|
+
|
75
|
+
def table_style_for_format(format)
|
76
|
+
case format
|
77
|
+
when 'md'
|
78
|
+
{
|
79
|
+
border_top: false,
|
80
|
+
border_bottom: false,
|
81
|
+
border_i: '|'
|
82
|
+
}
|
83
|
+
when 'org'
|
84
|
+
{
|
85
|
+
border_top: false,
|
86
|
+
border_bottom: false,
|
87
|
+
}
|
88
|
+
else
|
89
|
+
{}
|
48
90
|
end
|
49
91
|
end
|
50
92
|
end
|
51
93
|
end
|
52
94
|
|
53
|
-
Pry.commands.
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
95
|
+
Pry.commands.create_command 'm' do
|
96
|
+
description 'List models or columns (specified by `-c`): m [-e env_name_regexp] -c [column_regexp] [table_regexp]'
|
97
|
+
|
98
|
+
def options(opt)
|
99
|
+
opt.on '-e', '--env', 'Environment name regexp', argument: true, as: String, required: false, default: nil
|
100
|
+
opt.on '-f', '--format', 'Table format, available: terminal(default), md, org, sql', argument: true, as: String, required: false, default: 'terminal'
|
101
|
+
opt.on '-c', '--column', 'Column name regexp', argument: true, as: String, required: false, default: nil
|
60
102
|
end
|
61
|
-
end
|
62
103
|
|
63
|
-
|
64
|
-
end
|
104
|
+
def process
|
65
105
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
106
|
+
if opts[:format] == 'sql' && opts[:column]
|
107
|
+
output.puts 'SQL format is not supported for column listing'
|
108
|
+
return
|
109
|
+
end
|
70
110
|
|
71
|
-
|
72
|
-
|
73
|
-
end
|
111
|
+
env_names = opts[:env].try {|e| [e]}.presence || Arql::App.environments
|
112
|
+
env_names = env_names.map { |e| e.start_with?('/') ? eval(e) : Regexp.new(e) }
|
74
113
|
|
75
|
-
|
76
|
-
|
77
|
-
end
|
114
|
+
Arql::App.instance.definitions.each do |env_name, definition|
|
115
|
+
next unless env_names.any? { |e| env_name =~ e }
|
78
116
|
|
79
|
-
|
80
|
-
|
81
|
-
|
117
|
+
output.puts
|
118
|
+
if opts[:column]
|
119
|
+
column_regexp = opts[:column]
|
120
|
+
output.puts Models::filter_columns(env_name, definition, opts[:format], column_regexp.try { |e| e.start_with?('/') ? eval(e) : Regexp.new(e) })
|
121
|
+
else
|
122
|
+
table_regexp = args&.first
|
123
|
+
output.puts Models::filter_tables(env_name, definition, opts[:format], table_regexp.try { |e| e.start_with?('/') ? eval(e) : Regexp.new(e) })
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
82
127
|
|
83
|
-
def model_names
|
84
|
-
models[2..-1].map(&:second)
|
85
128
|
end
|
129
|
+
|
130
|
+
Pry.commands.alias_command 'l', 'm'
|
86
131
|
end
|
@@ -2,13 +2,17 @@ module Arql::Commands
|
|
2
2
|
module Reconnect
|
3
3
|
class << self
|
4
4
|
def reconnect
|
5
|
-
Arql::
|
6
|
-
|
5
|
+
Arql::App.instance.definitions.each do |_, definition|
|
6
|
+
definition.ssh_proxy.reconnect if definition.options[:ssh].present?
|
7
|
+
definition.connection.reconnect! unless definition.connection.active?
|
8
|
+
end
|
7
9
|
end
|
8
10
|
|
9
11
|
def reconnect!
|
10
|
-
Arql::
|
11
|
-
|
12
|
+
Arql::App.instance.definitions.each do |_, definition|
|
13
|
+
definition.ssh_proxy.reconnect if definition.options[:ssh].present?
|
14
|
+
definition.connection.reconnect!
|
15
|
+
end
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|