arql 0.3.30 → 0.4.0
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 +712 -429
- data/README.org +3 -0
- data/auto-set-id-before-save-zh_CN.org +1 -1
- data/custom-configurations-zh_CN.org +40 -3
- data/define-associations-zh_CN.org +31 -17
- data/initializer-structure-zh_CN.org +22 -4
- data/lib/arql/app.rb +98 -71
- data/lib/arql/cli.rb +31 -15
- data/lib/arql/commands/info.rb +41 -28
- data/lib/arql/commands/models.rb +108 -33
- 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/ssh_proxy.rb +25 -22
- data/lib/arql/version.rb +1 -1
- data/lib/arql.rb +11 -7
- data/ruby-guides-for-java-developer-zh_CN.org +766 -0
- data/simple-active-record-guide-zh_CN.org +83 -0
- data/simple-pry-guides-zh_CN.org +114 -0
- data/sql-log-zh_CN.org +8 -3
- metadata +9 -5
- data/lib/arql/commands/table.rb +0 -55
- data/lib/arql/commands/vd.rb +0 -46
- 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.
|
10
|
+
unless Arql::App.instance.options.append_sql
|
11
11
|
log_root_dir = File.expand_path('~/.arql.d/logs')
|
12
|
-
|
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.
|
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.
|
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-
|
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
|
data/lib/arql/commands/table.rb
DELETED
@@ -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
|
data/lib/arql/commands/vd.rb
DELETED
@@ -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
|
data/lib/arql/connection.rb
DELETED
@@ -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
|