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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.vscode/launch.json +1 -1
  3. data/Gemfile.lock +1 -1
  4. data/README-zh_CN.org +616 -491
  5. data/README.org +803 -628
  6. data/auto-set-id-before-save-zh_CN.org +1 -1
  7. data/auto-set-id-before-save.org +1 -1
  8. data/custom-configurations-zh_CN.org +40 -3
  9. data/custom-configurations.org +71 -32
  10. data/define-associations-zh_CN.org +31 -17
  11. data/define-associations.org +52 -29
  12. data/initializer-structure-zh_CN.org +23 -5
  13. data/initializer-structure.org +46 -18
  14. data/lib/arql/app.rb +98 -71
  15. data/lib/arql/cli.rb +37 -15
  16. data/lib/arql/commands/info.rb +41 -28
  17. data/lib/arql/commands/models.rb +106 -61
  18. data/lib/arql/commands/reconnect.rb +8 -4
  19. data/lib/arql/commands/redefine.rb +3 -1
  20. data/lib/arql/commands/sandbox.rb +6 -4
  21. data/lib/arql/commands.rb +0 -2
  22. data/lib/arql/concerns/global_data_definition.rb +40 -6
  23. data/lib/arql/concerns/model_extension.rb +168 -0
  24. data/lib/arql/concerns/table_data_definition.rb +20 -20
  25. data/lib/arql/concerns.rb +1 -0
  26. data/lib/arql/definition.rb +169 -317
  27. data/lib/arql/ext/active_record/relation.rb +29 -0
  28. data/lib/arql/ext/active_record/result.rb +29 -0
  29. data/lib/arql/ext/array.rb +40 -1
  30. data/lib/arql/ext/kernel.rb +70 -61
  31. data/lib/arql/ext/object.rb +14 -0
  32. data/lib/arql/ext/ransack/search.rb +29 -0
  33. data/lib/arql/mysqldump.rb +0 -1
  34. data/lib/arql/repl.rb +1 -1
  35. data/lib/arql/ssh_proxy.rb +25 -22
  36. data/lib/arql/version.rb +1 -1
  37. data/lib/arql.rb +11 -7
  38. data/oss-files-zh_CN.org +2 -2
  39. data/oss-files.org +2 -2
  40. data/sql-log-zh_CN.org +8 -3
  41. data/sql-log.org +8 -3
  42. metadata +6 -5
  43. data/lib/arql/commands/table.rb +0 -55
  44. data/lib/arql/commands/vd.rb +0 -46
  45. 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 :log_io, :env, :prompt, :instance, :connect_options
6
+ attr_accessor :instance
6
7
 
7
- def config
8
- @@effective_config
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
- if env
13
- env
14
- else
15
- File.basename(@@effective_config[:database])
16
- end
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
- App.env = @options.env
25
- App.connect_options = connect_options
26
- Connection.open(App.connect_options)
45
+
46
+ # env names
47
+ @environments = @options.environments
48
+ @environments ||= ['default']
49
+
27
50
  print "Defining models..."
28
- @definition = Definition.new(effective_config)
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 effective_config[:initializer]
51
- initializer_file = File.expand_path(effective_config[:initializer])
64
+ return unless config[:options][:initializer]
65
+
66
+ initializer_file = File.expand_path(config[:options][:initializer])
52
67
  unless File.exist?(initializer_file)
53
- STDERR.puts "Specified initializer file not found, #{effective_config[:initializer]}"
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 start_ssh_proxy!
60
- ssh_config = effective_config[:ssh]
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
- @config ||= YAML.load(IO.read(File.expand_path(@options.config_file))).with_indifferent_access
77
+ @config_from_file ||= YAML.safe_load(IO.read(File.expand_path(@options.config_file))).with_indifferent_access
75
78
  end
76
79
 
77
- def selected_config
78
- if @options.env.present? && !config[@options.env].present?
79
- STDERR.puts "Specified ENV `#{@options.env}' not exists"
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
- if env = @options.env
82
- config[env]
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
- end
87
-
88
- def effective_config
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
- @@effective_config
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 effective_config[:code].present?
105
- eval(effective_config[:code])
106
- elsif effective_config[:args].present?
107
- effective_config[:args].first.tap { |file| load(file) }
108
- elsif STDIN.isatty
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(STDIN.read)
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
- effective_config[:show_sql]
147
+ @options.show_sql
121
148
  end
122
149
 
123
150
  def should_write_sql?
124
- effective_config[:write_sql]
151
+ @options.write_sql
125
152
  end
126
153
 
127
154
  def should_append_sql?
128
- effective_config[:append_sql]
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 << STDOUT
161
+ App.log_io << $stdout
135
162
  end
136
163
 
137
164
  def write_sql
138
- write_sql_file = effective_config[:write_sql]
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 = effective_config[:append_sql]
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 not a tty, a Pry REPL will be launched,
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.') do |env|
36
- @options.env = env
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
- conf = File.expand_path('~/.arql.yml')
124
- return conf if File.file?(conf)
125
- conf = File.expand_path('~/.arql.yaml')
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
- conf = File.expand_path('~/.arql.rb')
135
- return conf if File.file?(conf)
136
- conf = File.expand_path('~/.arql.d/init.rb')
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
@@ -3,38 +3,49 @@ require 'rainbow'
3
3
  module Arql::Commands
4
4
  module Info
5
5
  class << self
6
- def db_info
7
- <<~EOF
8
-
9
- Database Connection Information:
10
-
11
- Active: #{color_boolean(ActiveRecord::Base.connection.active?)}
12
- Host: #{Arql::App.config[:host]}
13
- Port: #{Arql::App.config[:port]}
14
- Username: #{Arql::App.config[:username]}
15
- Password: #{(Arql::App.config[:password] || '').gsub(/./, '*')}
16
- Database: #{Arql::App.config[:database]}
17
- Adapter: #{Arql::App.config[:adapter]}
18
- Encoding: #{Arql::App.config[:encoding]}
19
- Pool Size: #{Arql::App.config[:pool]}
20
- EOF
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
- <<~EOF
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
- SSH Connection Information:
35
+ #{env_name} SSH Connection Information:
27
36
 
28
- Active: #{color_boolean(Arql::SSHProxy.active?)}
29
- Host: #{Arql::App.config[:ssh][:host]}
30
- Port: #{Arql::App.config[:ssh][:port]}
31
- Username: #{Arql::App.config[:ssh][:user]}
32
- Password: #{(Arql::App.config[:ssh][:password] || '').gsub(/./, '*')}
33
- Local Port: #{Arql::SSHProxy.local_ssh_proxy_port}
34
- EOF
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
- puts Info::db_info
49
- puts Info::ssh_info if Arql::App.config[:ssh].present?
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
@@ -3,84 +3,129 @@ require 'terminal-table'
3
3
  module Arql::Commands
4
4
  module Models
5
5
  class << self
6
- def models
7
- t = []
8
- t << ['Table Name', 'Model Class', 'Abbr', 'Comment']
9
- t << nil
10
- Arql::Definition.models.each do |definition|
11
- t << [definition[:table], definition[:model].name, definition[:abbr] || '', definition[:comment] || '']
12
- end
13
- t
14
- end
15
-
16
- def models_table(table_regexp=nil, column_regexp=nil)
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
- connection = ::ActiveRecord::Base.connection
27
- table = Terminal::Table.new do |t|
28
- t << ['PK', 'Table', 'Model', 'Name', 'SQL Type', 'Ruby Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']
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
- Arql::Definition.models.each do |definition|
31
- model_class = definition[:model]
32
- matched_columns = model_class.columns.select { |column| column.name =~ column_regexp || column.comment =~ column_regexp }
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
- puts table
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.block_command 'm' do |arg|
54
- puts
55
- if arg.start_with?('c=') or arg.start_with?('column=')
56
- column_regexp = arg.sub(/^c(olumn)?=/, '')
57
- Models::models_table(nil, column_regexp.try { |e| e.start_with?('/') ? eval(e) : Regexp.new(e) })
58
- else
59
- puts Models::models_table(arg.try { |e| e.start_with?('/') ? eval(e) : Regexp.new(e) }, nil)
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
- Pry.commands.alias_command 'l', 'm'
64
- end
104
+ def process
65
105
 
66
- module Kernel
67
- def models
68
- Arql::Commands::Models::models
69
- end
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
- def tables
72
- models
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
- def model_classes
76
- ::ArqlModel.subclasses
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
- def table_names
80
- models[2..-1].map(&:first)
81
- end
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::SSHProxy.reconnect if Arql::App.config[:ssh].present?
6
- ActiveRecord::Base.connection.reconnect! unless ActiveRecord::Base.connection.active?
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::SSHProxy.reconnect! if Arql::App.config[:ssh].present?
11
- ActiveRecord::Base.connection.reconnect!
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
 
@@ -2,7 +2,9 @@ module Arql::Commands
2
2
  module Redefine
3
3
  class << self
4
4
  def redefine
5
- Arql::Definition.redefine
5
+ Arql::App.instance.definitions.each do |_, definition|
6
+ definition.redefine
7
+ end
6
8
  end
7
9
  end
8
10