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
@@ -5,67 +5,11 @@ module Kernel
5
5
  include ::Arql::Concerns::GlobalDataDefinition
6
6
 
7
7
  def q(sql)
8
- ActiveRecord::Base.connection.exec_query(sql)
9
- end
10
-
11
- def print_tables(format = :md)
12
- require 'terminal-table'
13
-
14
- tables = ActiveRecord::Base.connection.tables.map do |table_name|
15
- {
16
- table: table_name,
17
- table_comment: ActiveRecord::Base.connection.table_comment(table_name) || '',
18
- columns: ::ActiveRecord::Base.connection.columns(table_name)
19
- }
20
- end
21
-
22
- outputs = tables.map do |table|
23
- table_name = table[:table]
24
- table_comment = table[:table_comment]
25
- case format
26
- when :md
27
- "# #{table_name} #{table_comment}\n\n" +
28
- Terminal::Table.new { |t|
29
- t.headings = ['PK', 'Name', 'SQL Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']
30
- t.rows = table[:columns].map { |column|
31
- pk = if [::ActiveRecord::Base.connection.primary_key(table_name)].flatten.include?(column)
32
- 'Y'
33
- else
34
- ''
35
- end
36
- [pk, "`#{column.name}`", column.sql_type, column.sql_type_metadata.limit || '', column.sql_type_metadata.precision || '',
37
- column.sql_type_metadata.scale || '', column.default || '', column.null, column.comment || '']
38
- }
39
- t.style = {
40
- border_top: false,
41
- border_bottom: false,
42
- border_i: '|'
43
- }
44
- }.to_s.lines.map { |l| ' ' + l }.join
45
- when :org
46
- "* #{table_name} #{table_comment}\n\n" +
47
- Terminal::Table.new { |t|
48
- t.headings = ['PK', 'Name', 'SQL Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']
49
- t.rows = table[:columns].map { |column|
50
- pk = if [::ActiveRecord::Base.connection.primary_key(table_name)].flatten.include?(column)
51
- 'Y'
52
- else
53
- ''
54
- end
55
- [pk, "=#{column.name}=", column.sql_type, column.sql_type_metadata.limit || '', column.sql_type_metadata.precision || '',
56
- column.sql_type_metadata.scale || '', column.default || '', column.null, column.comment || '']
57
- }
58
- t.style = {
59
- border_top: false,
60
- border_bottom: false,
61
- }
62
- }.to_s.lines.map { |l| ' ' + l.gsub(/^\+|\+$/, '|') }.join
63
- when :sql
64
- "-- Table: #{table_name}\n\n" + ActiveRecord::Base.connection.exec_query("show create table `#{table_name}`").rows.last.last + ';'
65
- end
8
+ if Arql::App.instance.environments.size > 1
9
+ $stderr.puts "Multiple environments are defined. Please use Namespace::q() instread, where Namespace is the namespace module of one of the environments."
10
+ return
66
11
  end
67
-
68
- outputs.each { |out| puts out; puts }
12
+ Arql::App.instance.definitions.first.connection.exec_query(sql)
69
13
  end
70
14
 
71
15
  def generate_csv(filename, **options, &block)
@@ -113,4 +57,69 @@ module Kernel
113
57
  JSON.parse(IO.read(File.expand_path(filename)))
114
58
  end
115
59
 
116
- end
60
+ def within_namespace(namespace_pattern, &blk)
61
+ if namespace_pattern.is_a?(Module)
62
+ namespace_pattern.module_eval(&blk)
63
+ return
64
+ end
65
+ definition = Arql::App.instance.definitions.find do |_, defi|
66
+ case namespace_pattern
67
+ when Symbol
68
+ defi.namespace.to_s == namespace_pattern.to_s
69
+ when String
70
+ defi.namespace.to_s == namespace_pattern
71
+ when Regexp
72
+ defi.namespace.to_s =~ namespace_pattern
73
+ end
74
+ end
75
+ if definition
76
+ definition.last.namespace_module.module_eval(&blk)
77
+ return
78
+ end
79
+
80
+ $stderr.puts "Namespace #{namespace_pattern.inspect} not found"
81
+ end
82
+
83
+ def within_env(env_name_pattern, &blk)
84
+ definition = Arql::App.instance.definitions.find do |env_name, defi|
85
+ case env_name_pattern
86
+ when Symbol
87
+ env_name == env_name_pattern.to_s
88
+ when String
89
+ env_name == env_name_pattern
90
+ when Regexp
91
+ env_name =~ env_name_pattern
92
+ end
93
+ end
94
+ if definition
95
+ definition.last.namespace_module.module_eval(&blk)
96
+ return
97
+ end
98
+
99
+ $stderr.puts "Environment #{env_name_pattern.inspect} not found"
100
+ end
101
+
102
+ def models
103
+ Arql::App.instance.definitions.flat_map do |_, definition|
104
+ definition.namespace_module.models
105
+ end
106
+ end
107
+
108
+ def table_names
109
+ Arql::App.instance.definitions.flat_map do |_, definition|
110
+ definition.namespace_module.tables
111
+ end
112
+ end
113
+
114
+ def model_names
115
+ Arql::App.instance.definitions.flat_map do |_, definition|
116
+ definition.namespace_module.model_names
117
+ end
118
+ end
119
+
120
+ def env_config(env_regexp)
121
+ Arql::App.instance.definitions.find do |env_name, _|
122
+ env_name =~ env_regexp
123
+ end.last.options
124
+ end
125
+ end
@@ -19,4 +19,18 @@ class Object
19
19
  def a
20
20
  [self]
21
21
  end
22
+
23
+ class << self
24
+ def const_missing(name)
25
+ return super unless const_defined?(:Arql)
26
+ return super unless Arql.const_defined?(:App)
27
+ return super unless Arql::App.instance&.definitions&.present?
28
+
29
+ Arql::App.instance.definitions.lazy.filter do |_, definition|
30
+ definition.namespace_module.const_defined?(name)
31
+ end.map do |_, definition|
32
+ definition.namespace_module.const_get(name)
33
+ end.first || super
34
+ end
35
+ end
22
36
  end
@@ -0,0 +1,29 @@
1
+ Ransack::Search.class_eval do
2
+ def t(*attrs, **options)
3
+ result.t(*attrs, **options)
4
+ end
5
+
6
+ def vd(*attrs, **options)
7
+ result.vd(*attrs, **options)
8
+ end
9
+
10
+ def v
11
+ result.v
12
+ end
13
+
14
+ def a
15
+ result.a
16
+ end
17
+
18
+ def write_csv(filename, *fields, **options)
19
+ result.write_csv(filename, *fields, **options)
20
+ end
21
+
22
+ def write_excel(filename, *fields, **options)
23
+ result.write_excel(filename, *fields, **options)
24
+ end
25
+
26
+ def dump(filename, batch_size=500)
27
+ result.dump(filename, batch_size)
28
+ end
29
+ end
@@ -2,7 +2,6 @@ module Arql
2
2
  class Mysqldump
3
3
 
4
4
  def initialize(options = nil)
5
- options ||= App.connect_options
6
5
  @options = options
7
6
  if options[:socket]
8
7
  port_or_sock = "-S #{options[:socket]}"
data/lib/arql/repl.rb CHANGED
@@ -6,7 +6,7 @@ require 'rainbow'
6
6
  module Arql
7
7
  class Repl
8
8
  def initialize
9
- Pry.config.prompt = Pry::Prompt.new("", "", prompt)
9
+ Pry.config.prompt = Pry::Prompt.new('', '', prompt) unless App.instance.options.babel_compatable
10
10
  Pry.start
11
11
  end
12
12
 
@@ -3,33 +3,36 @@ require 'arql/ssh_proxy_patch'
3
3
 
4
4
  module Arql
5
5
  class SSHProxy
6
- class << self
6
+ attr_accessor :config, :ssh_gateway, :local_ssh_proxy_port
7
7
 
8
- attr_accessor :config, :ssh_gateway, :local_ssh_proxy_port
8
+ def initialize(config)
9
+ print "Establishing SSH connection to #{config[:host]}:#{config[:port]}"
10
+ @config = config
11
+ @ssh_gateway = Net::SSH::Gateway.new(config[:host], config[:user], config.slice(:port, :password).symbolize_keys.merge(keepalive: true, keepalive_interval: 30, loop_wait: 1))
12
+ @local_ssh_proxy_port = @ssh_gateway.open(config[:forward_host], config[:forward_port], config[:local_port])
13
+ print "\u001b[2K"
14
+ puts "\rSSH connection to #{config[:host]}:#{config[:port]} established"
15
+ end
9
16
 
10
- def connect(config)
11
- print "Establishing SSH connection to #{config[:host]}:#{config[:port]}"
12
- @config = config
13
- @ssh_gateway = Net::SSH::Gateway.new(config[:host], config[:user], config.slice(:port, :password).symbolize_keys.merge(keepalive: true, keepalive_interval: 30, loop_wait: 1))
14
- @local_ssh_proxy_port = @ssh_gateway.open(config[:forward_host], config[:forward_port], config[:local_port])
15
- print "\u001b[2K"
16
- puts "\rSSH connection to #{config[:host]}:#{config[:port]} established"
17
- @local_ssh_proxy_port
18
- end
17
+ def reconnect
18
+ reconnect! unless @ssh_gateway.active?
19
+ end
19
20
 
20
- def reconnect
21
- reconnect! unless @ssh_gateway.active?
22
- end
21
+ def reconnect!
22
+ @ssh_gateway.shutdown!
23
+ @ssh_gateway = Net::SSH::Gateway.new(@config[:host], @config[:user], @config.slice(:port, :password).symbolize_keys)
24
+ @ssh_gateway.open(config[:forward_host], config[:forward_port], @local_ssh_proxy_port)
25
+ end
23
26
 
24
- def reconnect!
25
- @ssh_gateway.shutdown!
26
- @ssh_gateway = Net::SSH::Gateway.new(@config[:host], @config[:user], @config.slice(:port, :password).symbolize_keys)
27
- @ssh_gateway.open(config[:forward_host], config[:forward_port], @local_ssh_proxy_port)
28
- end
27
+ def active?
28
+ @ssh_gateway.active?
29
+ end
29
30
 
30
- def active?
31
- @ssh_gateway.active?
32
- end
31
+ def database_host_port
32
+ {
33
+ host: '127.0.0.1',
34
+ port: @local_ssh_proxy_port
35
+ }
33
36
  end
34
37
  end
35
38
  end
data/lib/arql/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Arql
2
- VERSION = "0.3.31"
2
+ VERSION = "0.4.1"
3
3
  end
data/lib/arql.rb CHANGED
@@ -3,21 +3,25 @@ require 'roo'
3
3
  require 'caxlsx'
4
4
  require 'csv'
5
5
  require 'net/ssh/gateway'
6
- require "arql/version"
6
+ require 'arql/version'
7
7
  require 'arql/id'
8
8
  require 'arql/multi_io'
9
9
  require 'arql/ext'
10
- require "arql/repl"
11
- require "arql/ssh_proxy"
12
- require "arql/app"
13
- require "arql/cli"
14
- require "arql/mysqldump"
15
- require "arql/vd"
10
+ require 'arql/repl'
11
+ require 'arql/ssh_proxy'
12
+ require 'arql/app'
13
+ require 'arql/cli'
14
+ require 'arql/mysqldump'
15
+ require 'arql/vd'
16
16
  require 'active_support/all'
17
17
  require 'active_record'
18
18
  require 'kaminari/activerecord'
19
19
  require 'composite_primary_keys'
20
20
  require 'ransack'
21
21
 
22
+ require 'arql/ext/active_record/relation'
23
+ require 'arql/ext/active_record/result'
24
+ require 'arql/ext/ransack/search'
25
+
22
26
  module Arql
23
27
  end
data/oss-files-zh_CN.org CHANGED
@@ -66,13 +66,13 @@
66
66
  def initialize(path, bucket: nil)
67
67
  @path = path
68
68
  unless bucket
69
- bucket = Arql::App.config['oss_bucket']
69
+ bucket = env_config(/./)['oss_bucket']
70
70
  end
71
71
  @bucket = bucket
72
72
  end
73
73
 
74
74
  def rclone_name
75
- Arql::App.config['rclone_name']
75
+ env_config(/./)['rclone_name']
76
76
  end
77
77
 
78
78
  def info
data/oss-files.org CHANGED
@@ -66,13 +66,13 @@
66
66
  def initialize(path, bucket: nil)
67
67
  @path = path
68
68
  unless bucket
69
- bucket = Arql::App.config['oss_bucket']
69
+ bucket = env_config(/./)['oss_bucket']
70
70
  end
71
71
  @bucket = bucket
72
72
  end
73
73
 
74
74
  def rclone_name
75
- Arql::App.config['rclone_name']
75
+ env_config(/./)['rclone_name']
76
76
  end
77
77
 
78
78
  def info
data/sql-log-zh_CN.org CHANGED
@@ -7,13 +7,18 @@
7
7
  创建一个文件 =~/.arql.d/sql_log.rb= ,内容如下:
8
8
 
9
9
  #+BEGIN_SRC ruby
10
- unless Arql::App.config[:append_sql]
10
+ unless Arql::App.instance.options.append_sql
11
11
  log_root_dir = File.expand_path('~/.arql.d/logs')
12
- log_dir = "#{log_root_dir}/%s" % Arql::App.env
12
+ if Arql::App.instance.environments.present?
13
+ log_dir = "#{log_root_dir}/%s" % Arql::App.instance.environments.join('_')
14
+ elsif File.file?(Arql::App.instance.options[:database])
15
+ log_dir = "#{log_root_dir}/%s" % File.basename(Arql::App.instance.options[:database])
16
+ end
17
+
13
18
  FileUtils.mkdir_p(log_dir)
14
19
  now = Time.now
15
20
  log_file = "#{log_dir}/%s.%s.%s.log" % [Time.now.strftime('%Y_%m%d_%H%M%S'), `hostname -s`.chomp.downcase, Process.pid]
16
- Arql::App.config[:append_sql] = log_file
21
+ Arql::App.instance.options.append_sql = log_file
17
22
 
18
23
  lfile = File.new(log_file, 'a')
19
24
  lfile.sync = true
data/sql-log.org CHANGED
@@ -7,13 +7,18 @@
7
7
  Create a file =~/.arql.d/sql_log.rb= with the following content:
8
8
 
9
9
  #+BEGIN_SRC ruby
10
- unless Arql::App.config[:append_sql]
10
+ unless Arql::App.instance.options.append_sql
11
11
  log_root_dir = File.expand_path('~/.arql.d/logs')
12
- log_dir = "#{log_root_dir}/%s" % Arql::App.env
12
+ if Arql::App.instance.environments.present?
13
+ log_dir = "#{log_root_dir}/%s" % Arql::App.instance.environments.join('_')
14
+ elsif File.file?(Arql::App.instance.options[:database])
15
+ log_dir = "#{log_root_dir}/%s" % File.basename(Arql::App.instance.options[:database])
16
+ end
17
+
13
18
  FileUtils.mkdir_p(log_dir)
14
19
  now = Time.now
15
20
  log_file = "#{log_dir}/%s.%s.%s.log" % [Time.now.strftime('%Y_%m%d_%H%M%S'), `hostname -s`.chomp.downcase, Process.pid]
16
- Arql::App.config[:append_sql] = log_file
21
+ Arql::App.instance.options.append_sql = log_file
17
22
 
18
23
  lfile = File.new(log_file, 'a')
19
24
  lfile.sync = true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.31
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Liu Xiang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-12 00:00:00.000000000 Z
11
+ date: 2024-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mysql2
@@ -334,20 +334,21 @@ files:
334
334
  - lib/arql/commands/redefine.rb
335
335
  - lib/arql/commands/sandbox.rb
336
336
  - lib/arql/commands/show_sql.rb
337
- - lib/arql/commands/table.rb
338
- - lib/arql/commands/vd.rb
339
337
  - lib/arql/concerns.rb
340
338
  - lib/arql/concerns/global_data_definition.rb
339
+ - lib/arql/concerns/model_extension.rb
341
340
  - lib/arql/concerns/table_data_definition.rb
342
- - lib/arql/connection.rb
343
341
  - lib/arql/definition.rb
344
342
  - lib/arql/ext.rb
345
343
  - lib/arql/ext/active_record/connection_adapters/abstract_mysql_adapter.rb
346
344
  - lib/arql/ext/active_record/connection_adapters/postgresql/schema_statements.rb
345
+ - lib/arql/ext/active_record/relation.rb
346
+ - lib/arql/ext/active_record/result.rb
347
347
  - lib/arql/ext/array.rb
348
348
  - lib/arql/ext/hash.rb
349
349
  - lib/arql/ext/kernel.rb
350
350
  - lib/arql/ext/object.rb
351
+ - lib/arql/ext/ransack/search.rb
351
352
  - lib/arql/ext/string.rb
352
353
  - lib/arql/ext/time.rb
353
354
  - lib/arql/id.rb
@@ -1,55 +0,0 @@
1
- require 'terminal-table'
2
-
3
- module Arql::Commands
4
- module Table
5
- class << self
6
- def get_table_name(name)
7
- name = name.to_s
8
- return name if name =~ /^[a-z]/
9
- if Object.const_defined?(name)
10
- klass = Object.const_get(name)
11
- return klass.table_name if klass < ActiveRecord::Base
12
- end
13
- name
14
- end
15
-
16
- def table_info_table(table_name)
17
- Terminal::Table.new do |t|
18
- table_info(table_name).each { |row| t << (row || :separator) }
19
- end
20
- end
21
-
22
- def table_info(table_name)
23
- t = []
24
- t << ['PK', 'Name', 'SQL Type', 'Ruby Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']
25
- t << nil
26
- connection = ::ActiveRecord::Base.connection
27
- connection.columns(table_name).each do |column|
28
- pk = if [connection.primary_key(table_name)].flatten.include?(column.name)
29
- 'Y'
30
- else
31
- ''
32
- end
33
- t << [pk, column.name, column.sql_type,
34
- column.sql_type_metadata.type, column.sql_type_metadata.limit || '',
35
- column.sql_type_metadata.precision || '', column.sql_type_metadata.scale || '', column.default || '',
36
- column.null, column.comment || '']
37
- end
38
- t
39
- end
40
- end
41
-
42
- Pry.commands.block_command 't' do |name|
43
- table_name = Table::get_table_name(name)
44
- puts
45
- puts "Table: #{table_name}"
46
- puts Table::table_info_table(table_name)
47
- end
48
- end
49
- end
50
-
51
- module Kernel
52
- def table(name)
53
- Arql::Commands::Table::table_info(Arql::Commands::Table::get_table_name(name))
54
- end
55
- end
@@ -1,46 +0,0 @@
1
- require 'arql/vd'
2
-
3
- module Arql::Commands
4
- module VD
5
- class << self
6
- def get_table_name(name)
7
- name = name.to_s
8
- return name if name =~ /^[a-z]/
9
- if Object.const_defined?(name)
10
- klass = Object.const_get(name)
11
- return klass.table_name if klass < ActiveRecord::Base
12
- end
13
- name
14
- end
15
-
16
- def table_info_vd(table_name)
17
- Arql::VD.new do |vd|
18
- table_info(table_name).each { |row| vd << row }
19
- end
20
- end
21
-
22
- def table_info(table_name)
23
- t = []
24
- t << ['PK', 'Name', 'SQL Type', 'Ruby Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']
25
- connection = ::ActiveRecord::Base.connection
26
- connection.columns(table_name).each do |column|
27
- pk = if [connection.primary_key(table_name)].flatten.include?(column.name)
28
- 'Y'
29
- else
30
- ''
31
- end
32
- t << [pk, column.name, column.sql_type,
33
- column.sql_type_metadata.type, column.sql_type_metadata.limit || '',
34
- column.sql_type_metadata.precision || '', column.sql_type_metadata.scale || '', column.default || '',
35
- column.null, column.comment || '']
36
- end
37
- t
38
- end
39
- end
40
-
41
- Pry.commands.block_command 'vd' do |name|
42
- table_name = VD::get_table_name(name)
43
- VD::table_info_vd(table_name)
44
- end
45
- end
46
- end
@@ -1,16 +0,0 @@
1
- module Arql
2
- class Connection
3
- class << self
4
- def open(options)
5
- print "Establishing DB connection to #{options[:host]}:#{options[:port]}"
6
- ActiveRecord::Base.establish_connection(options)
7
- print "\u001b[2K"
8
- puts "\rDB connection to #{options[:host]}:#{options[:port]} established\n"
9
- $C = ActiveRecord::Base.connection
10
- $C.define_singleton_method(:dump) do |filename, no_create_db=false|
11
- Arql::Mysqldump.new.dump_database(filename, no_create_db)
12
- end
13
- end
14
- end
15
- end
16
- end