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/auto-set-id-before-save.org
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
* 配置文件中的自定义配置项
|
2
2
|
|
3
|
-
你可以在配置文件 (如默认的 =~/.arql.yaml= / =~/.arql.d/init.yaml= ) 中定义自己的配置项,然后在代码中通过 =
|
3
|
+
你可以在配置文件 (如默认的 =~/.arql.yaml= / =~/.arql.d/init.yaml= ) 中定义自己的配置项,然后在代码中通过 =env_config(/my_env/)["CONF_KEY"]-= 来获取配置项的值。
|
4
4
|
|
5
5
|
例如,假设系统对 BankAccount 表的 =account_no= 字段进行了加密,你可以在配置文件中定义加密的密钥:
|
6
6
|
|
@@ -23,7 +23,7 @@
|
|
23
23
|
def self.encrypt_account_no(account_no)
|
24
24
|
cipher = OpenSSL::Cipher.new('AES-128-ECB')
|
25
25
|
cipher.encrypt
|
26
|
-
cipher.key =
|
26
|
+
cipher.key = env_config(/my_env/)["encrypt_key"]
|
27
27
|
encrypted = cipher.update(account_no) + cipher.final
|
28
28
|
encrypted.unpack('H*').first
|
29
29
|
end
|
@@ -31,7 +31,7 @@
|
|
31
31
|
def self.decrypt_account_no(encrypted_account_no)
|
32
32
|
cipher = OpenSSL::Cipher.new('AES-128-ECB')
|
33
33
|
cipher.decrypt
|
34
|
-
cipher.key =
|
34
|
+
cipher.key = env_config(/my_env/)["encrypt_key"]
|
35
35
|
decrypted = cipher.update([encrypted_account_no].pack('H*')) + cipher.final
|
36
36
|
decrypted
|
37
37
|
end
|
@@ -48,3 +48,40 @@
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
#+END_SRC
|
51
|
+
|
52
|
+
也可以直接使用 Namespace Module 的 config 方法来获取配置项的值,例如:
|
53
|
+
|
54
|
+
假设 Namespace Module 为 =NS=, 那么上述代码可以改写为:
|
55
|
+
|
56
|
+
#+BEGIN_SRC ruby
|
57
|
+
class BankAccount
|
58
|
+
|
59
|
+
def self.encrypt_account_no(account_no)
|
60
|
+
cipher = OpenSSL::Cipher.new('AES-128-ECB')
|
61
|
+
cipher.encrypt
|
62
|
+
cipher.key = NS::config["encrypt_key"]
|
63
|
+
encrypted = cipher.update(account_no) + cipher.final
|
64
|
+
encrypted.unpack('H*').first
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.decrypt_account_no(encrypted_account_no)
|
68
|
+
cipher = OpenSSL::Cipher.new('AES-128-ECB')
|
69
|
+
cipher.decrypt
|
70
|
+
cipher.key = NS::config["encrypt_key"]
|
71
|
+
decrypted = cipher.update([encrypted_account_no].pack('H*')) + cipher.final
|
72
|
+
decrypted
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# 从数据库查询出数据之后,自动解密 account_no 字段
|
77
|
+
after_find do
|
78
|
+
self.password = decrypt_account_no(self.password)
|
79
|
+
end
|
80
|
+
|
81
|
+
# 保存数据之前,自动加密 account_no 字段
|
82
|
+
before_save do
|
83
|
+
self.password = encrypt_account_no(self.password)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
#+END_SRC
|
87
|
+
|
data/custom-configurations.org
CHANGED
@@ -1,54 +1,93 @@
|
|
1
1
|
* Additional config items in Configuration File
|
2
2
|
|
3
|
-
You can define your own configuration items in
|
4
|
-
=~/.arql.d/init.yaml=), and then get the value of the configuration item in the code
|
5
|
-
=
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
3
|
+
You can define your own configuration items in a configuration file (such as the default =~/.arql.yaml= /
|
4
|
+
=~/.arql.d/init.yaml= ), and then get the value of the configuration item in the code with
|
5
|
+
=env_config(/my_env/)["CONF_KEY"]-= .
|
6
|
+
|
7
|
+
|
8
|
+
For example, let's say the system encrypts the field of the =account_no= BankAccount table, and you can define the key
|
9
|
+
for encryption in the configuration file:
|
10
|
+
|
11
|
+
#+begin_src yaml
|
12
|
+
dev:
|
13
|
+
<<: *default
|
14
|
+
host: 127.0.0.1
|
15
|
+
port: 3306
|
16
|
+
username: test
|
17
|
+
password: test123456
|
18
|
+
database: devel
|
19
|
+
encrypt_key: "1234567890abcdef"
|
20
|
+
#+end_src
|
21
|
+
|
22
|
+
|
23
|
+
You can then read the value of the config item in the Initialzier code ( =~/.arql.rb= / =~/.arql.d/init.rb= ):
|
24
|
+
|
25
|
+
#+begin_src ruby
|
25
26
|
class BankAccount
|
26
|
-
|
27
|
+
|
27
28
|
def self.encrypt_account_no(account_no)
|
28
29
|
cipher = OpenSSL::Cipher.new('AES-128-ECB')
|
29
30
|
cipher.encrypt
|
30
|
-
cipher.key =
|
31
|
+
cipher.key = env_config(/my_env/)["encrypt_key"]
|
31
32
|
encrypted = cipher.update(account_no) + cipher.final
|
32
33
|
encrypted.unpack('H*').first
|
33
34
|
end
|
34
|
-
|
35
|
+
|
35
36
|
def self.decrypt_account_no(encrypted_account_no)
|
36
37
|
cipher = OpenSSL::Cipher.new('AES-128-ECB')
|
37
38
|
cipher.decrypt
|
38
|
-
cipher.key =
|
39
|
+
cipher.key = env_config(/my_env/)["encrypt_key"]
|
39
40
|
decrypted = cipher.update([encrypted_account_no].pack('H*')) + cipher.final
|
40
41
|
decrypted
|
41
42
|
end
|
42
|
-
|
43
|
-
|
44
|
-
#
|
43
|
+
|
44
|
+
|
45
|
+
# 从数据库查询出数据之后,自动解密 account_no 字段
|
45
46
|
after_find do
|
46
47
|
self.password = decrypt_account_no(self.password)
|
47
48
|
end
|
48
|
-
|
49
|
-
#
|
49
|
+
|
50
|
+
# 保存数据之前,自动加密 account_no 字段
|
51
|
+
before_save do
|
52
|
+
self.password = encrypt_account_no(self.password)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
#+end_src
|
56
|
+
|
57
|
+
|
58
|
+
You can also use the config method of the Namespace Module to obtain the value of the configuration item, for example:
|
59
|
+
|
60
|
+
|
61
|
+
Assuming the Namespace Module is , then =NS= the above code can be rewritten as:
|
62
|
+
|
63
|
+
#+begin_src ruby
|
64
|
+
class BankAccount
|
65
|
+
|
66
|
+
def self.encrypt_account_no(account_no)
|
67
|
+
cipher = OpenSSL::Cipher.new('AES-128-ECB')
|
68
|
+
cipher.encrypt
|
69
|
+
cipher.key = NS::config["encrypt_key"]
|
70
|
+
encrypted = cipher.update(account_no) + cipher.final
|
71
|
+
encrypted.unpack('H*').first
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.decrypt_account_no(encrypted_account_no)
|
75
|
+
cipher = OpenSSL::Cipher.new('AES-128-ECB')
|
76
|
+
cipher.decrypt
|
77
|
+
cipher.key = NS::config["encrypt_key"]
|
78
|
+
decrypted = cipher.update([encrypted_account_no].pack('H*')) + cipher.final
|
79
|
+
decrypted
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# 从数据库查询出数据之后,自动解密 account_no 字段
|
84
|
+
after_find do
|
85
|
+
self.password = decrypt_account_no(self.password)
|
86
|
+
end
|
87
|
+
|
88
|
+
# 保存数据之前,自动加密 account_no 字段
|
50
89
|
before_save do
|
51
90
|
self.password = encrypt_account_no(self.password)
|
52
91
|
end
|
53
92
|
end
|
54
|
-
#+
|
93
|
+
#+end_src
|
@@ -5,26 +5,29 @@
|
|
5
5
|
Initializer 文件是一个 Ruby 文件,因此可以在其中定义关联关系,例如:
|
6
6
|
|
7
7
|
#+BEGIN_SRC ruby
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
8
|
+
module Blog
|
9
|
+
class Student
|
10
|
+
has_many :courses, foreign_key: :student_id, class_name: 'Course'
|
11
|
+
belongs_to :school, foreign_key: :school_id, class_name: 'School'
|
12
|
+
|
13
|
+
has_and_belongs_to_many :teachers, join_table: 'students_teachers', foreign_key: :student_id, association_foreign_key: :teacher_id, class_name: 'Teacher'
|
14
|
+
end
|
15
|
+
|
16
|
+
class Course
|
17
|
+
belongs_to :student, foreign_key: :student_id, class_name: 'Student'
|
18
|
+
end
|
19
|
+
|
20
|
+
class School
|
21
|
+
has_many :students, foreign_key: :school_id, class_name: 'Student'
|
22
|
+
end
|
23
|
+
|
24
|
+
class Teacher
|
25
|
+
has_and_belongs_to_many :students, join_table: 'students_teachers', foreign_key: :teacher_id, association_foreign_key: :student_id, class_name: 'Student'
|
26
|
+
end
|
25
27
|
end
|
26
28
|
#+END_SRC
|
27
29
|
|
30
|
+
|
28
31
|
1. =has_one= 表明此表是一对一关系的属主
|
29
32
|
2. =belongs_to= 表明此表是一对多或一对一关系的从属方
|
30
33
|
3. =has_and_belongs_to_many= 表明此表是多对多关系的其中一方
|
@@ -36,3 +39,14 @@
|
|
36
39
|
|
37
40
|
可以参考: https://guides.rubyonrails.org/association_basics.html
|
38
41
|
|
42
|
+
考虑到模型类都是定义在 Namespace module 下面的, 因此这里的 Blog 是必要的。
|
43
|
+
|
44
|
+
当然,不管通过 =-e= 选项选择了哪个环境,Arql 默认都会加载 =~/.arql.rb= 或 =~/.arql.d/init.rb= 文件,
|
45
|
+
因此像上述示例中把固定的 Namespace =Blog= 放在默认的初始化文件中, 不是一个好的选择。
|
46
|
+
|
47
|
+
有两种方案解决这个问题:
|
48
|
+
|
49
|
+
1. 使用 arql 时,对于不同的环境,用 =-i= 选项来指定不同的初始化文件,例如: =arql -e blog -i ~/.arql.d/blog.rb=
|
50
|
+
2. 参考 [[./initializer-structure-zh_CN.org][将不同环境的初始化代码放在不同的文件中]]
|
51
|
+
|
52
|
+
|
data/define-associations.org
CHANGED
@@ -1,37 +1,60 @@
|
|
1
|
-
* Define
|
1
|
+
* 1. Define the relationship in the initializer file
|
2
2
|
|
3
|
-
You can define associations in Initializers. Arql will generate model classes based on the database schema when it starts, and then load the Initializer file.
|
4
3
|
|
5
|
-
|
4
|
+
Associations can be defined in the initializer file, and when Arql starts, it first generates the model class based on
|
5
|
+
the database schema and then loads the initializer file.
|
6
6
|
|
7
|
-
#+BEGIN_SRC ruby
|
8
|
-
class Student
|
9
|
-
has_many :courses, foreign_key: :student_id, class_name: 'Course'
|
10
|
-
belongs_to :school, foreign_key: :school_id, class_name: 'School'
|
11
7
|
|
12
|
-
|
13
|
-
end
|
8
|
+
The initializer file is a Ruby file, so you can define associations within it, for example:
|
14
9
|
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
#+begin_src ruby
|
11
|
+
module Blog
|
12
|
+
class Student
|
13
|
+
has_many :courses, foreign_key: :student_id, class_name: 'Course'
|
14
|
+
belongs_to :school, foreign_key: :school_id, class_name: 'School'
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
has_and_belongs_to_many :teachers, join_table: 'students_teachers', foreign_key: :student_id, association_foreign_key: :teacher_id, class_name: 'Teacher'
|
17
|
+
end
|
18
|
+
|
19
|
+
class Course
|
20
|
+
belongs_to :student, foreign_key: :student_id, class_name: 'Student'
|
21
|
+
end
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
class School
|
24
|
+
has_many :students, foreign_key: :school_id, class_name: 'Student'
|
25
|
+
end
|
26
|
+
|
27
|
+
class Teacher
|
28
|
+
has_and_belongs_to_many :students, join_table: 'students_teachers', foreign_key: :teacher_id, association_foreign_key: :student_id, class_name: 'Student'
|
29
|
+
end
|
25
30
|
end
|
26
|
-
#+
|
27
|
-
|
28
|
-
1.
|
29
|
-
2. =belongs_to=
|
30
|
-
3. =has_and_belongs_to_many=
|
31
|
-
4. =class_name=
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
#+end_src
|
32
|
+
|
33
|
+
1. =has_one= Indicates that this table is a one-to-one relationship with the owner
|
34
|
+
2. =belongs_to= Indicates that this table is a subordinate of a one-to-many or one-to-one relationship
|
35
|
+
3. =has_and_belongs_to_many= Indicates that this table is one of the parties to a many-to-many relationship
|
36
|
+
4. =class_name= The model class name of the other party that indicates the relationship (the model class name is
|
37
|
+
actually the CamelCase form of the table name)
|
38
|
+
5. =foreign_key= Indicates the name of the associated field on the side of the dependent table in the association
|
39
|
+
6. =primary_key= Indicates the name of the association field on the side of the master table in the association
|
40
|
+
7. =join_table= In a many-to-many relationship, the name of the intermediate table that is associated with two tables is
|
41
|
+
indicated
|
42
|
+
8. =association_foreign_key= In a many-to-many relationship, indicates the name of the field associated with the other
|
43
|
+
model's model in the intermediate table
|
44
|
+
|
45
|
+
可以参考: [[https://guides.rubyonrails.org/association_basics.html]]
|
46
|
+
|
47
|
+
|
48
|
+
Considering that the model classes are all defined under the Namespace module, a blog here is necessary.
|
49
|
+
|
50
|
+
|
51
|
+
Of course, Arql will load the =~/.arql.rb= OR =~/.arql.d/init.rb= file by default, regardless of which environment is
|
52
|
+
selected via the =-e= options, so putting a fixed namespace =Blog= in the default initialization file like in the
|
53
|
+
example above is not a good choice.
|
54
|
+
|
55
|
+
There are two ways to solve this problem:
|
56
|
+
|
57
|
+
1.
|
58
|
+
When using arql, for different environments, use =-i= the option to specify different initialization files, such as:
|
59
|
+
=arql -e blog -i ~/.arql.d/blog.rb=
|
60
|
+
2. Refer to Put the initialization code for different environments in different files
|
@@ -19,15 +19,33 @@
|
|
19
19
|
然后在 =~/.arql.d/init.eb= 文件中写入以下代码:
|
20
20
|
|
21
21
|
#+BEGIN_SRC ruby
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
Dir.glob(File.dirname(__FILE__) + '/*.rb').each do |f|
|
23
|
+
Arql::App.instance.definitions.each do |env, definition|
|
24
|
+
if env.starts_with?(File.basename(f, '.rb'))
|
25
|
+
load(f, definition.namespace_module)
|
26
|
+
end
|
26
27
|
end
|
27
28
|
end
|
28
29
|
#+END_SRC
|
29
30
|
|
30
|
-
这样,当执行 =arql -e apollo.dev= 或 =arql
|
31
|
+
这样,当执行 =arql -e apollo.dev= 或 =arql -e apollo.prod= 时,就会加载 =apollo.rb= 文件中的初始化代码;当执行 =arql
|
31
32
|
-e space.dev= 或 =arql -e space.prod= 时,就会加载 =space.rb= 文件中的初始化代码。
|
32
33
|
|
34
|
+
=apollo.rb= 或 =space.rb= 文件中的代码将在对应的 Namespace Module 下执行:
|
35
|
+
|
36
|
+
#+BEGIN_SRC ruby
|
37
|
+
class Astronaut
|
38
|
+
has_many :missions
|
39
|
+
end
|
40
|
+
#+END_SRC
|
41
|
+
|
42
|
+
等价于:
|
43
|
+
|
44
|
+
#+BEGIN_SRC ruby
|
45
|
+
module Apollo
|
46
|
+
class Astronaut
|
47
|
+
has_many :missions
|
48
|
+
end
|
49
|
+
end
|
50
|
+
#+END_SRC
|
33
51
|
|
data/initializer-structure.org
CHANGED
@@ -1,31 +1,59 @@
|
|
1
1
|
* Place your initialization code in a file named after the environment
|
2
2
|
|
3
|
-
If you have multiple environments in your configuration file, you can place the initialization code for each environment in a separate file to avoid conflicts.
|
4
3
|
|
5
|
-
|
4
|
+
There are often multiple environment configurations for multiple databases in the configuration file, so you can use the
|
5
|
+
method here to put the initialization code of different environments in different files to avoid conflicts.
|
6
6
|
|
7
|
-
|
8
|
-
+ apollo.prod
|
9
|
-
+ space.dev
|
10
|
-
+ space.prod
|
7
|
+
Let's say you have 4 database environments configured in the configuration file:
|
11
8
|
|
12
|
-
|
9
|
+
- apollo.dev
|
10
|
+
- apollo.prod
|
11
|
+
- space.dev
|
12
|
+
- space.prod
|
13
13
|
|
14
|
-
+ apollo.rb
|
15
|
-
+ space.rb
|
16
14
|
|
17
|
-
|
15
|
+
Then you can create the following file in the =~/.arql.d/= directory:
|
16
|
+
|
17
|
+
- apollo.rb
|
18
|
+
- space.rb
|
19
|
+
|
20
|
+
|
21
|
+
Place the initialization code for the Apollo project =apollo.rb= in the file; Place the initialization code for the
|
22
|
+
space project =space.rb= in the file.
|
23
|
+
|
18
24
|
|
19
25
|
Then write the following code in the =~/.arql.d/init.eb= file:
|
20
26
|
|
21
|
-
#+
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
27
|
+
#+begin_src ruby
|
28
|
+
Dir.glob(File.dirname(__FILE__) + '/*.rb').each do |f|
|
29
|
+
Arql::App.instance.definitions.each do |env, definition|
|
30
|
+
if env.starts_with?(File.basename(f, '.rb'))
|
31
|
+
load(f, definition.namespace_module)
|
32
|
+
end
|
26
33
|
end
|
27
34
|
end
|
28
|
-
#+
|
35
|
+
#+end_src
|
36
|
+
|
37
|
+
|
38
|
+
In this way, =arql -e apollo.prod= when or is executed, the initialization =apollo.rb= code in the file is loaded, and
|
39
|
+
=arql -e space.prod= when or is executed =arql -e apollo.dev= =arql -e space.dev= , the initialization code in the file
|
40
|
+
is loaded =space.rb= .
|
41
|
+
|
29
42
|
|
30
|
-
|
31
|
-
|
43
|
+
=apollo.rb= The code in the =space.rb= or file will be executed under the corresponding Namespace Module:
|
44
|
+
|
45
|
+
#+begin_src ruby
|
46
|
+
class Astronaut
|
47
|
+
has_many :missions
|
48
|
+
end
|
49
|
+
#+end_src
|
50
|
+
|
51
|
+
Equivalent to:
|
52
|
+
|
53
|
+
#+begin_src ruby
|
54
|
+
module Apollo
|
55
|
+
class Astronaut
|
56
|
+
has_many :missions
|
57
|
+
end
|
58
|
+
end
|
59
|
+
#+end_src
|