arql 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README-zh_CN.org +10 -162
- data/README.org +803 -628
- data/auto-set-id-before-save.org +1 -1
- data/custom-configurations.org +71 -32
- data/define-associations.org +52 -29
- data/initializer-structure-zh_CN.org +1 -1
- data/initializer-structure.org +46 -18
- data/lib/arql/cli.rb +6 -0
- data/lib/arql/repl.rb +1 -1
- data/lib/arql/version.rb +1 -1
- data/oss-files-zh_CN.org +2 -2
- data/oss-files.org +2 -2
- data/sql-log.org +8 -3
- metadata +2 -2
data/auto-set-id-before-save.org
CHANGED
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
|
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
|
@@ -28,7 +28,7 @@
|
|
28
28
|
end
|
29
29
|
#+END_SRC
|
30
30
|
|
31
|
-
这样,当执行 =arql -e apollo.dev= 或 =arql
|
31
|
+
这样,当执行 =arql -e apollo.dev= 或 =arql -e apollo.prod= 时,就会加载 =apollo.rb= 文件中的初始化代码;当执行 =arql
|
32
32
|
-e space.dev= 或 =arql -e space.prod= 时,就会加载 =space.rb= 文件中的初始化代码。
|
33
33
|
|
34
34
|
=apollo.rb= 或 =space.rb= 文件中的代码将在对应的 Namespace Module 下执行:
|
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
|
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
|
|
@@ -96,6 +97,11 @@ module Arql
|
|
96
97
|
@options.code = code
|
97
98
|
end
|
98
99
|
|
100
|
+
opts.on('-b', '--babel', 'Enable compatibility for Org-Mode Babel') do
|
101
|
+
@options.babel_compatable = true
|
102
|
+
end
|
103
|
+
|
104
|
+
|
99
105
|
opts.on('-S', '--show-sql', 'Show SQL on STDOUT') do
|
100
106
|
@options.show_sql = true
|
101
107
|
end
|
data/lib/arql/repl.rb
CHANGED
data/lib/arql/version.rb
CHANGED
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 =
|
69
|
+
bucket = env_config(/./)['oss_bucket']
|
70
70
|
end
|
71
71
|
@bucket = bucket
|
72
72
|
end
|
73
73
|
|
74
74
|
def rclone_name
|
75
|
-
|
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 =
|
69
|
+
bucket = env_config(/./)['oss_bucket']
|
70
70
|
end
|
71
71
|
@bucket = bucket
|
72
72
|
end
|
73
73
|
|
74
74
|
def rclone_name
|
75
|
-
|
75
|
+
env_config(/./)['rclone_name']
|
76
76
|
end
|
77
77
|
|
78
78
|
def info
|
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.
|
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.
|
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-
|
11
|
+
date: 2024-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mysql2
|