arql 0.3.30 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) 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 +712 -429
  5. data/README.org +3 -0
  6. data/auto-set-id-before-save-zh_CN.org +1 -1
  7. data/custom-configurations-zh_CN.org +40 -3
  8. data/define-associations-zh_CN.org +31 -17
  9. data/initializer-structure-zh_CN.org +22 -4
  10. data/lib/arql/app.rb +98 -71
  11. data/lib/arql/cli.rb +31 -15
  12. data/lib/arql/commands/info.rb +41 -28
  13. data/lib/arql/commands/models.rb +108 -33
  14. data/lib/arql/commands/reconnect.rb +8 -4
  15. data/lib/arql/commands/redefine.rb +3 -1
  16. data/lib/arql/commands/sandbox.rb +6 -4
  17. data/lib/arql/commands.rb +0 -2
  18. data/lib/arql/concerns/global_data_definition.rb +40 -6
  19. data/lib/arql/concerns/model_extension.rb +168 -0
  20. data/lib/arql/concerns/table_data_definition.rb +20 -20
  21. data/lib/arql/concerns.rb +1 -0
  22. data/lib/arql/definition.rb +169 -317
  23. data/lib/arql/ext/active_record/relation.rb +29 -0
  24. data/lib/arql/ext/active_record/result.rb +29 -0
  25. data/lib/arql/ext/array.rb +40 -1
  26. data/lib/arql/ext/kernel.rb +70 -61
  27. data/lib/arql/ext/object.rb +14 -0
  28. data/lib/arql/ext/ransack/search.rb +29 -0
  29. data/lib/arql/mysqldump.rb +0 -1
  30. data/lib/arql/ssh_proxy.rb +25 -22
  31. data/lib/arql/version.rb +1 -1
  32. data/lib/arql.rb +11 -7
  33. data/ruby-guides-for-java-developer-zh_CN.org +766 -0
  34. data/simple-active-record-guide-zh_CN.org +83 -0
  35. data/simple-pry-guides-zh_CN.org +114 -0
  36. data/sql-log-zh_CN.org +8 -3
  37. metadata +9 -5
  38. data/lib/arql/commands/table.rb +0 -55
  39. data/lib/arql/commands/vd.rb +0 -46
  40. data/lib/arql/connection.rb +0 -16
@@ -0,0 +1,83 @@
1
+ * ActiveRecord 简明教程
2
+
3
+ ActiveRecord 是 Rails 中的 ORM 框架,它将数据库表映射到 Ruby 对象,让我们可以通过 Ruby 对象来操作数据库。
4
+
5
+
6
+ ** 定义模型类
7
+
8
+ 模型类是继承自 ActiveRecord::Base 的类,它们是数据库中的表在 Ruby 语言中的映射。
9
+
10
+ #+BEGIN_SRC ruby
11
+ class User < ActiveRecord::Base
12
+ end
13
+ #+END_SRC
14
+
15
+ 而 User 对象的属性和数据库表的字段的对应关系,是 ActiveRecord 根据数据库中的表信息,自动完成的。
16
+
17
+ 在 Arql 中,模型类的定义是 Arql 根据数据库表的表信息自动生成的,所以我们不需要像这里一样手动定义模型类。
18
+
19
+ ** 定义关联关系
20
+
21
+ 在 ActiveRecord 中,我们可以通过 has_many, belongs_to, has_one 等方法来定义模型类之间的关联关系。
22
+
23
+ - =has_many= 表明此表是一对多关系的“一”方
24
+ - =has_one= 表明此表是一对一关系的属主
25
+ - =belongs_to= 表明此表是一对多或一对一关系的从属方
26
+ - =has_and_belongs_to_many= 表明此表是多对多关系的其中一方
27
+
28
+
29
+ 使用 Arql 查询数据库时,我们希望也可以通过定义好的关联关系来查询数据。
30
+
31
+ 例如,我们有两个模型类 User 和 Post,User 有多个 Post,Post 属于一个 User, 如果我们希望查询张三的所有文章,
32
+
33
+ 在不使用关联关系的情况下,我们需要这样查询:
34
+
35
+ #+BEGIN_SRC ruby
36
+ user = User.find_by(name: '张三')
37
+ posts = Post.where(user_id: user.id)
38
+ #+END_SRC
39
+
40
+ 而如果我们定义了关联关系,我们可以这样查询:
41
+
42
+ #+BEGIN_SRC ruby
43
+ user = User.find_by(name: '张三')
44
+ posts = user.posts
45
+ #+END_SRC
46
+
47
+ 关联关系是在模型类中定义的,而 Arql 中模型类是 Arql 替我们自动生成的,那么我们要在哪里定义关联关系呢?
48
+
49
+ 别忘了 Ruby 的类是可以重新打开的,我们可以在 Arql 中重新打开模型类,定义关联关系:
50
+
51
+ #+BEGIN_SRC ruby
52
+ class User < ActiveRecord::Base
53
+ has_many :posts
54
+ end
55
+ #+END_SRC
56
+
57
+ 像 has_many, belongs_to, has_one 这样的方法,ActiveRecord 会根据默认的规则,来关联关系关联到的是哪个表的哪个字段。这也就是 Rails 中所谓的约定大于配置的体现。
58
+
59
+ 使用 Arql 查询既有系统的数据库时,数据库中的表、字段名称往往不符合 Rails 的规则约定,这时我们可以通过传递参数来指定关联关系的关联字段:
60
+
61
+ #+BEGIN_SRC ruby
62
+ class User < ActiveRecord::Base
63
+ has_many :posts, foreign_key: 'author_id', class_name: 'Article', primary_key: 'uid'
64
+ end
65
+ #+END_SRC
66
+
67
+ =has_many=, =belongs_to=, =has_one= 方法常用的参数如下:
68
+
69
+ - =class_name=: 表明此关联关系对应的对方的 Model 类名
70
+ - =foreign_key=: 表明此关联关系中,从属表一侧的关联字段名
71
+ - =primary_key=: 表明此关联关系中,属主表一侧的关联字段名
72
+ - =join_table=: 在多对多关系中,表明关联两个表的中间表名
73
+ - =association_foreign_key=: 在多对多关系中,表明对方 Model 在中间表中的关联字段名
74
+
75
+ ** 简单 CRUD
76
+
77
+ 参考:https://guides.rubyonrails.org/active_record_querying.html
78
+
79
+ ** 参考
80
+
81
+ - https://guides.rubyonrails.org/active_record_basics.html
82
+ - https://guides.rubyonrails.org/active_record_querying.html
83
+ - https://guides.rubyonrails.org/association_basics.html
@@ -0,0 +1,114 @@
1
+ * Pry 简明教程
2
+
3
+ ** Pry 是什么?
4
+
5
+ 和 Python 一样,Ruby 也有自己的 REPL 工具,叫做 irb(Interactive Ruby)。
6
+
7
+ Pry 是另外一个功能更加强大的 Ruby REPL 工具,它可以让你在 Ruby REPL 中做很多事情,比如查看源码、查看文档、调试等等。
8
+
9
+ Arql 的主要功能就是基于 Pry 实现的,所以你可以把 Pry 当做 Arql 的一个子集。Pry 的命令和功能在 Arql 中都是可以使用的。而且 Arql 还提供了一些额外的 Pry 命令。
10
+
11
+
12
+ 当然也可以单独安装和使用 Pry。
13
+
14
+
15
+ ** 单独安装 Pry
16
+
17
+ #+BEGIN_EXAMPLE
18
+ $ gem install pry
19
+ #+END_EXAMPLE
20
+
21
+ Pry 本身也支持扩展,你可以安装一些 Pry 的插件,比如 pry-doc、pry-byebug 等等。
22
+
23
+ #+BEGIN_EXAMPLE
24
+ $ gem install pry-doc
25
+ $ gem install pry-byebug
26
+ #+END_EXAMPLE
27
+
28
+
29
+ ** 单独使用 Pry
30
+
31
+ #+BEGIN_EXAMPLE
32
+ $ pry
33
+ #+END_EXAMPLE
34
+
35
+
36
+ ** 常用的 Pry 命令
37
+
38
+
39
+ *** 查看帮助
40
+
41
+ #+BEGIN_EXAMPLE
42
+ [1] pry(main)> help
43
+ #+END_EXAMPLE
44
+
45
+
46
+ *** 查看变量
47
+
48
+ #+BEGIN_EXAMPLE
49
+ [2] pry(main)> ls
50
+ #+END_EXAMPLE
51
+
52
+
53
+ *** 查看一个实例方法的源码
54
+
55
+ #+BEGIN_EXAMPLE
56
+ [3] pry(main)> show-source ActiveRecord::Base#save
57
+ #+END_EXAMPLE
58
+
59
+
60
+ *** 查看一个实例方法的文档
61
+
62
+ #+BEGIN_EXAMPLE
63
+ [4] pry(main)> show-doc ActiveRecord::Base#save
64
+ #+END_EXAMPLE
65
+
66
+
67
+ *** 查看一个类的的源码
68
+
69
+ #+BEGIN_EXAMPLE
70
+ [5] pry(main)> show-source ActiveRecord::Base
71
+ #+END_EXAMPLE
72
+
73
+
74
+ *** 查看一个类的文档
75
+
76
+ #+BEGIN_EXAMPLE
77
+ [6] pry(main)> show-doc ActiveRecord::Base
78
+ #+END_EXAMPLE
79
+
80
+
81
+ *** 在 Pry 中直接修改代码
82
+
83
+ 你甚至可以在 Pry 中用 edit 命令直接修改代码,然后 Pry 会自动保存修改后的代码到一个临时文件中,然后你可以在 Pry 中直接调用修改后的代码。
84
+
85
+ #+BEGIN_EXAMPLE
86
+ [7] pry(main)> edit ActiveRecord::Base#save
87
+ #+END_EXAMPLE
88
+
89
+ ** 分号
90
+
91
+ 在 Ruby 语言中, 行尾的分号是可以省略的。
92
+
93
+
94
+ Pry 中每次执行一个 Ruby 表达式,都会自动打印出这个表达式的值:
95
+
96
+ #+BEGIN_EXAMPLE
97
+ [7] pry(main)> user.posts = Post.all
98
+ => [#<Post id: 1, title: "Hello World", content: "Hello World", created_at: "2016 -12-12 12:12:12", updated_at: "2016-12-12 12:12:12">,
99
+ #<Post id: 2, title: "Hello Ruby", content: "Hello Ruby", created_at: "2016-12-12 12:12:12", updated_at: "2016-12-12 12:12:12">,
100
+ ... ...]
101
+ #+END_EXAMPLE
102
+
103
+ 这是通过调用 Ruby 的 表达式的值对象的 inspect 方法 (Object#inspect 方法)实现的。如果你不想打印出这个值,可以在表达式后面加上分号:
104
+
105
+ #+BEGIN_EXAMPLE
106
+ [8] pry(main)> user.posts = Post.all;
107
+ #+END_EXAMPLE
108
+
109
+ 我们知道在 ActiveRecord 中,像 =User.where(gender: 'Male')= 这样的表达式,返回结果是一个 ActiveRecord::Relation 对象,而不是一个数组。
110
+ 这样设计的目的是为了支持 Lazy Loading,只有在需要的时候才会去执行 SQL 查询。但是当我们在 Pry 中直接对 =User.where(gender: 'Male')= 的时候,却发现
111
+ 它立即执行了 SQL 查询,并且输出的是一个数组对象;这就是因为 Pry 在打印对象的时候,会调用对象的 inspect 方法,而 ActiveRecord::Relation 对象的 inspect 方法
112
+ 会立即执行 SQL 查询并返回一个数组对象。如果你不想立即执行 SQL 查询,就可以在表达式后面加上分号。
113
+
114
+
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
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.30
4
+ version: 0.4.0
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-16 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
@@ -360,6 +361,9 @@ files:
360
361
  - lib/arql/version.rb
361
362
  - oss-files-zh_CN.org
362
363
  - oss-files.org
364
+ - ruby-guides-for-java-developer-zh_CN.org
365
+ - simple-active-record-guide-zh_CN.org
366
+ - simple-pry-guides-zh_CN.org
363
367
  - sql-log-zh_CN.org
364
368
  - sql-log.org
365
369
  homepage: https://github.com/lululau/arql
@@ -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