active_record_mysql_repl 0.1.3 → 0.1.5
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/README.md +729 -13
- data/lib/active_record_mysql_repl/cli/erd.rb +1 -1
- data/lib/active_record_mysql_repl/cli/main.rb +19 -14
- data/lib/active_record_mysql_repl/cli/zsh_completion.rb +23 -23
- data/lib/active_record_mysql_repl/cli.rb +4 -4
- data/lib/active_record_mysql_repl/config.rb +7 -7
- data/lib/active_record_mysql_repl/database/association.rb +10 -10
- data/lib/active_record_mysql_repl/database/configs.rb +2 -2
- data/lib/active_record_mysql_repl/database/connection.rb +11 -13
- data/lib/active_record_mysql_repl/database/loader.rb +10 -5
- data/lib/active_record_mysql_repl/database.rb +4 -4
- data/lib/active_record_mysql_repl/extensions/active_record.rb +8 -8
- data/lib/active_record_mysql_repl/extensions/global.rb +0 -1
- data/lib/active_record_mysql_repl/extensions/hash.rb +8 -5
- data/lib/active_record_mysql_repl/extensions/object.rb +53 -54
- data/lib/active_record_mysql_repl/extensions/tabler.rb +2 -3
- data/lib/active_record_mysql_repl/extensions.rb +5 -6
- data/lib/active_record_mysql_repl/ssh_tunnel.rb +5 -3
- data/lib/active_record_mysql_repl/version.rb +1 -1
- data/lib/active_record_mysql_repl.rb +4 -5
- data/sample_config/{.pryrc.sample → .army.sample/.pryrc.sample} +2 -0
- data/sample_config/{associations.sample.yml → .army.sample/associations.sample.yml} +1 -1
- data/sample_config/{databases.sample.yml → .army.sample/databases.sample.yml} +2 -2
- data/sample_config/.army.sample/extensions/hello.rb +9 -0
- data/sample_config/.army.sample.yml +4 -4
- metadata +20 -5
data/README.md
CHANGED
@@ -1,38 +1,754 @@
|
|
1
1
|
# ActiveRecordMysqlRepl
|
2
2
|
|
3
|
-
|
3
|
+
## Prerequisites
|
4
4
|
|
5
|
-
|
5
|
+
### Ruby version 3.0.0 or higher
|
6
6
|
|
7
|
-
|
7
|
+
e.g) Using rbenv
|
8
|
+
|
9
|
+
```bash
|
10
|
+
$ rbenv install 3.3.6
|
11
|
+
```
|
8
12
|
|
9
|
-
|
13
|
+
### mysql-client 8.0
|
10
14
|
|
11
|
-
|
15
|
+
e.g) on macOS
|
12
16
|
|
13
17
|
```bash
|
14
|
-
|
18
|
+
$ brew install mysql-client@8.0
|
19
|
+
$ gem install mysql2 -v 0.5.6 -- --with-ldflags=-L$(brew --prefix zstd)/lib --with-mysql-dir=/opt/homebrew/opt/mysql-client@8.4
|
15
20
|
```
|
16
21
|
|
17
|
-
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
Just by installing the gem, you can use the `army` command.
|
18
25
|
|
19
26
|
```bash
|
20
|
-
gem install
|
27
|
+
$ gem install active_record_mysql_repl
|
28
|
+
Successfully installed active_record_mysql_repl-x.x.x
|
29
|
+
Parsing documentation for active_record_mysql_repl-x.x.x
|
30
|
+
Installing ri documentation for active_record_mysql_repl-x.x.x
|
31
|
+
Done installing documentation for active_record_mysql_repl after 0 seconds
|
32
|
+
1 gem installed
|
33
|
+
```
|
34
|
+
|
35
|
+
```
|
36
|
+
$ army
|
37
|
+
ActiveRecordMysqlRepl Version: x.x.x
|
38
|
+
```
|
39
|
+
|
40
|
+
If you want to use the zsh completion, you can add the following line to your `.zshrc` file.
|
41
|
+
|
42
|
+
```sh
|
43
|
+
$ eval "$(army --zsh-completion)"
|
44
|
+
```
|
45
|
+
|
46
|
+
Then you can use the completion feature like below.
|
47
|
+
|
48
|
+
```sh
|
49
|
+
$ army [TAB]
|
50
|
+
option
|
51
|
+
-c -- path to .armyrc file
|
52
|
+
-d -- Database name
|
53
|
+
-e -- output erd
|
21
54
|
```
|
22
55
|
|
23
56
|
## Usage
|
24
57
|
|
25
|
-
|
58
|
+
### Sample Configurations
|
26
59
|
|
27
|
-
|
60
|
+
From the following link, you can Download the sample configuration files
|
61
|
+
https://github.com/nogahighland/active_record_mysql_repl/tree/main/sample_config
|
62
|
+
|
63
|
+
Also you can try with sample database on your local MySQL server
|
64
|
+
https://github.com/nogahighland/active_record_mysql_repl/blob/main/sample_config/sample_db.sql
|
65
|
+
|
66
|
+
### Sample Database
|
67
|
+
|
68
|
+
```sql
|
69
|
+
CREATE DATABASE test;
|
70
|
+
```
|
71
|
+
|
72
|
+
The sample configuration assumes the sample database is running on
|
73
|
+
127.0.0.1:3306/test (user: root, password: root)
|
74
|
+
|
75
|
+
```
|
76
|
+
$ mysql -u root -p test < sample_db.sql
|
77
|
+
```
|
78
|
+
|
79
|
+

|
80
|
+
|
81
|
+
This ER Diagram can be generated by the following command
|
82
|
+
|
83
|
+
```sh
|
84
|
+
army -c sample_config/.army.sample.yml -d test -e erd
|
85
|
+
```
|
86
|
+
|
87
|
+
### Showcases
|
88
|
+
|
89
|
+
```sh
|
90
|
+
army -c /path/to/sample_config/.army.sample.yml -d test
|
91
|
+
Ensureing connection to test on port 127.0.0.1:33060
|
92
|
+
Loading tables
|
93
|
+
Loading custom extensions from /path/to/sample_config/./.army.sample/extensions
|
94
|
+
```
|
95
|
+
|
96
|
+
Now you can access to the table classes as `User` if the table name is `users`.
|
97
|
+
|
98
|
+
```rb
|
99
|
+
[1] test(main)> User.all
|
100
|
+
```
|
101
|
+
|
102
|
+
<details><summary>output:</summary>
|
103
|
+
|
104
|
+
```rb
|
105
|
+
D, [2024-12-12T12:57:38.581127 #2816] DEBUG -- : User Load (10.5ms) SELECT `users`.* FROM `users`
|
106
|
+
[
|
107
|
+
[0] #<User:0x0000000123188de0> {
|
108
|
+
:id => "1",
|
109
|
+
:login_id => "user1",
|
110
|
+
:profile_id => 1
|
111
|
+
}
|
112
|
+
]
|
113
|
+
```
|
114
|
+
|
115
|
+
</details>
|
116
|
+
|
117
|
+
---
|
118
|
+
|
119
|
+
`.d` method shows the schema of the table. Let's see the `Order` table schema.
|
120
|
+
|
121
|
+
```rb
|
122
|
+
[8] test(main)> Order.d
|
123
|
+
```
|
124
|
+
|
125
|
+
<details><summary>output:</summary>
|
126
|
+
|
127
|
+
```
|
128
|
+
D, [2024-12-12T12:32:20.100309 #2816] DEBUG -- : (10.6ms) DESCRIBE orders
|
129
|
+
D, [2024-12-12T12:32:20.107976 #2816] DEBUG -- : (6.9ms) SHOW INDEX FROM orders
|
130
|
+
# orders
|
131
|
+
+---------+-------------+------+-----+---------+-------+
|
132
|
+
| Field | Type | Null | Key | Default | Extra |
|
133
|
+
+---------+-------------+------+-----+---------+-------+
|
134
|
+
| id | varchar(64) | NO | PRI | | |
|
135
|
+
| user_id | varchar(64) | NO | | | |
|
136
|
+
| item_id | varchar(64) | NO | | | |
|
137
|
+
+---------+-------------+------+-----+---------+-------+
|
138
|
+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
139
|
+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
140
|
+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
141
|
+
| orders | 0 | PRIMARY | 1 | id | A | 1 | | | | BTREE | | | YES | |
|
142
|
+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
143
|
+
```
|
144
|
+
|
145
|
+
</details>
|
146
|
+
|
147
|
+
---
|
148
|
+
|
149
|
+
`.ddl` method shows the DDL of the table.
|
150
|
+
|
151
|
+
```rb
|
152
|
+
[9] test(main)> Order.ddl
|
153
|
+
```
|
154
|
+
|
155
|
+
<details><summary>output:</summary>
|
156
|
+
|
157
|
+
```
|
158
|
+
D, [2024-12-12T12:32:21.878444 #2816] DEBUG -- : (8.7ms) SHOW CREATE TABLE orders
|
159
|
+
CREATE TABLE `orders` (
|
160
|
+
`id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
|
161
|
+
`user_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
|
162
|
+
`item_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
|
163
|
+
PRIMARY KEY (`id`)
|
164
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
|
165
|
+
```
|
166
|
+
|
167
|
+
</details>
|
168
|
+
|
169
|
+
---
|
170
|
+
|
171
|
+
`models` is globally defined to get and array of all the table classes. By `.map(&:d)` you can see the schema of all the tables.
|
172
|
+
|
173
|
+
https://github.com/nogahighland/active_record_mysql_repl/blob/main/lib/active_record_mysql_repl/extensions/global.rb#L10-L12
|
174
|
+
|
175
|
+
```rb
|
176
|
+
[6] test(main)> puts models.map(&:d)
|
177
|
+
```
|
178
|
+
|
179
|
+
<details><summary>output:</summary>
|
180
|
+
|
181
|
+
```
|
182
|
+
D, [2024-12-12T01:26:36.677988 #25446] DEBUG -- : Brand Load (2.1ms) SELECT `brands`.* FROM `brands`
|
183
|
+
D, [2024-12-12T01:26:36.681307 #25446] DEBUG -- : Category Load (2.8ms) SELECT `categories`.* FROM `categories`
|
184
|
+
D, [2024-12-12T01:26:36.683967 #25446] DEBUG -- : Item Load (2.0ms) SELECT `items`.* FROM `items`
|
185
|
+
D, [2024-12-12T01:26:36.687282 #25446] DEBUG -- : Order Load (3.0ms) SELECT `orders`.* FROM `orders`
|
186
|
+
D, [2024-12-12T01:26:36.691204 #25446] DEBUG -- : UserProfile Load (3.6ms) SELECT `user_profiles`.* FROM `user_profiles`
|
187
|
+
D, [2024-12-12T01:26:36.694081 #25446] DEBUG -- : User Load (2.2ms) SELECT `users`.* FROM `users`
|
188
|
+
# users
|
189
|
+
+------------+-------------+------+-----+---------+-------+
|
190
|
+
| Field | Type | Null | Key | Default | Extra |
|
191
|
+
+------------+-------------+------+-----+---------+-------+
|
192
|
+
| id | varchar(64) | NO | PRI | | |
|
193
|
+
| login_id | varchar(64) | NO | | | |
|
194
|
+
| profile_id | int | YES | | | |
|
195
|
+
+------------+-------------+------+-----+---------+-------+
|
196
|
+
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
197
|
+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
198
|
+
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
199
|
+
| users | 0 | PRIMARY | 1 | id | A | 1 | | | | BTREE | | | YES | |
|
200
|
+
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
201
|
+
# user_profiles
|
202
|
+
+-------+-------------+------+-----+---------+-------+
|
203
|
+
| Field | Type | Null | Key | Default | Extra |
|
204
|
+
+-------+-------------+------+-----+---------+-------+
|
205
|
+
| id | varchar(64) | NO | PRI | | |
|
206
|
+
| name | varchar(64) | NO | | | |
|
207
|
+
+-------+-------------+------+-----+---------+-------+
|
208
|
+
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
209
|
+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
210
|
+
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
211
|
+
| user_profiles | 0 | PRIMARY | 1 | id | A | 1 | | | | BTREE | | | YES | |
|
212
|
+
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
213
|
+
# orders
|
214
|
+
+---------+-------------+------+-----+---------+-------+
|
215
|
+
| Field | Type | Null | Key | Default | Extra |
|
216
|
+
+---------+-------------+------+-----+---------+-------+
|
217
|
+
| id | varchar(64) | NO | PRI | | |
|
218
|
+
| user_id | varchar(64) | NO | | | |
|
219
|
+
| item_id | varchar(64) | NO | | | |
|
220
|
+
+---------+-------------+------+-----+---------+-------+
|
221
|
+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
222
|
+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
223
|
+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
224
|
+
| orders | 0 | PRIMARY | 1 | id | A | 1 | | | | BTREE | | | YES | |
|
225
|
+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
226
|
+
# items
|
227
|
+
+-------------+-------------+------+-----+---------+-------+
|
228
|
+
| Field | Type | Null | Key | Default | Extra |
|
229
|
+
+-------------+-------------+------+-----+---------+-------+
|
230
|
+
| id | varchar(64) | NO | PRI | | |
|
231
|
+
| category_id | varchar(64) | NO | | | |
|
232
|
+
| brand_id | varchar(64) | NO | | | |
|
233
|
+
+-------------+-------------+------+-----+---------+-------+
|
234
|
+
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
235
|
+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
236
|
+
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
237
|
+
| items | 0 | PRIMARY | 1 | id | A | 1 | | | | BTREE | | | YES | |
|
238
|
+
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
239
|
+
# categories
|
240
|
+
+-----------+-------------+------+-----+---------+-------+
|
241
|
+
| Field | Type | Null | Key | Default | Extra |
|
242
|
+
+-----------+-------------+------+-----+---------+-------+
|
243
|
+
| id | varchar(64) | NO | PRI | | |
|
244
|
+
| name | varchar(64) | NO | | | |
|
245
|
+
| parent_id | varchar(64) | NO | | | |
|
246
|
+
+-----------+-------------+------+-----+---------+-------+
|
247
|
+
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
248
|
+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
249
|
+
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
250
|
+
| categories | 0 | PRIMARY | 1 | id | A | 2 | | | | BTREE | | | YES | |
|
251
|
+
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
252
|
+
# brands
|
253
|
+
+-------+-------------+------+-----+---------+-------+
|
254
|
+
| Field | Type | Null | Key | Default | Extra |
|
255
|
+
+-------+-------------+------+-----+---------+-------+
|
256
|
+
| id | varchar(64) | NO | PRI | | |
|
257
|
+
| name | varchar(64) | NO | | | |
|
258
|
+
+-------+-------------+------+-----+---------+-------+
|
259
|
+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
260
|
+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|
261
|
+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
262
|
+
| brands | 0 | PRIMARY | 1 | id | A | 1 | | | | BTREE | | | YES | |
|
263
|
+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
|
264
|
+
```
|
265
|
+
|
266
|
+
</details>
|
267
|
+
|
268
|
+
---
|
269
|
+
|
270
|
+
To get the last record of order,
|
271
|
+
|
272
|
+
```rb
|
273
|
+
[1] test(main)> Order.last
|
274
|
+
```
|
275
|
+
|
276
|
+
<details><summary>output:</summary>
|
277
|
+
|
278
|
+
```rb
|
279
|
+
D, [2024-12-11T23:45:49.743857 #96076] DEBUG -- : Order Load (5.5ms) SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
|
280
|
+
#<Order:0x00000001293677c8> {
|
281
|
+
:id => "1",
|
282
|
+
:user_id => "1",
|
283
|
+
:item_id => "1"
|
284
|
+
}
|
285
|
+
```
|
286
|
+
|
287
|
+
</details>
|
288
|
+
|
289
|
+
---
|
290
|
+
|
291
|
+
You can get the last order's user because `user_id` column exists on `orders` table. For the same reason you can get the order's item and its category too.
|
292
|
+
All the associations are chainable by the native functionality of ActiveRecord.
|
293
|
+
|
294
|
+
```rb
|
295
|
+
[5] test(main)> Order.last.user
|
296
|
+
```
|
297
|
+
|
298
|
+
<details><summary>output:</summary>
|
299
|
+
|
300
|
+
```rb
|
301
|
+
D, [2024-12-11T23:46:11.154678 #96076] DEBUG -- : Order Load (6.9ms) SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
|
302
|
+
D, [2024-12-11T23:46:11.176424 #96076] DEBUG -- : User Load (2.9ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = '1' LIMIT 1
|
303
|
+
#<User:0x000000012961fda8> {
|
304
|
+
:id => "1",
|
305
|
+
:login_id => "user1",
|
306
|
+
:profile_id => 1
|
307
|
+
}
|
308
|
+
```
|
309
|
+
|
310
|
+
</details>
|
311
|
+
|
312
|
+
```rb
|
313
|
+
[7] test(main)> Order.last.item
|
314
|
+
```
|
315
|
+
|
316
|
+
<details><summary>output:</summary>
|
317
|
+
|
318
|
+
```rb
|
319
|
+
D, [2024-12-11T23:46:17.098874 #96076] DEBUG -- : Order Load (3.5ms) SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
|
320
|
+
D, [2024-12-11T23:46:17.112940 #96076] DEBUG -- : Item Load (2.2ms) SELECT `items`.* FROM `items` WHERE `items`.`id` = '1' LIMIT 1
|
321
|
+
#<Item:0x000000012a416c40> {
|
322
|
+
:id => "1",
|
323
|
+
:category_id => "2",
|
324
|
+
:brand_id => "1"
|
325
|
+
}
|
326
|
+
```
|
327
|
+
|
328
|
+
</details>
|
329
|
+
|
330
|
+
```rb
|
331
|
+
[8] test(main)> Order.last.item.category
|
332
|
+
```
|
333
|
+
|
334
|
+
<details><summary>output:</summary>
|
335
|
+
|
336
|
+
```rb
|
337
|
+
D, [2024-12-11T23:46:21.104696 #96076] DEBUG -- : Order Load (2.1ms) SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
|
338
|
+
D, [2024-12-11T23:46:21.106696 #96076] DEBUG -- : Item Load (1.5ms) SELECT `items`.* FROM `items` WHERE `items`.`id` = '1' LIMIT 1
|
339
|
+
D, [2024-12-11T23:46:21.117169 #96076] DEBUG -- : Category Load (2.5ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = '2' LIMIT 1
|
340
|
+
#<Category:0x000000012a5d7b38> {
|
341
|
+
:id => "2",
|
342
|
+
:name => "category2",
|
343
|
+
:parent_id => "1"
|
344
|
+
}
|
345
|
+
```
|
346
|
+
|
347
|
+
</details>
|
348
|
+
|
349
|
+
---
|
350
|
+
|
351
|
+
A category's parent is fetched from the same table because `parent_id`'s `parent` is treated by `ActiveRecordMysqlRepl` as inplicitly pointing to the same table.
|
352
|
+
|
353
|
+
```rb
|
354
|
+
[9] test(main)> Order.last.item.category.parent
|
355
|
+
```
|
356
|
+
|
357
|
+
<details><summary>output:</summary>
|
358
|
+
|
359
|
+
```rb
|
360
|
+
D, [2024-12-11T23:46:23.553443 #96076] DEBUG -- : Order Load (2.0ms) SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
|
361
|
+
D, [2024-12-11T23:46:23.555918 #96076] DEBUG -- : Item Load (2.1ms) SELECT `items`.* FROM `items` WHERE `items`.`id` = '1' LIMIT 1
|
362
|
+
D, [2024-12-11T23:46:23.560142 #96076] DEBUG -- : Category Load (3.8ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = '2' LIMIT 1
|
363
|
+
D, [2024-12-11T23:46:23.562496 #96076] DEBUG -- : Category Load (1.3ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = '1' LIMIT 1
|
364
|
+
#<Category:0x000000012a73dd60> {
|
365
|
+
:id => "1",
|
366
|
+
:name => "category1",
|
367
|
+
:parent_id => ""
|
368
|
+
}
|
369
|
+
```
|
370
|
+
|
371
|
+
</details>
|
372
|
+
|
373
|
+
---
|
374
|
+
|
375
|
+
You can get user's profile by `.profile` because the custom association is defined here
|
376
|
+
|
377
|
+
https://github.com/nogahighland/active_record_mysql_repl/blob/main/sample_config/.army.sample/associations.sample.yml#L4-L8
|
378
|
+
|
379
|
+
```rb
|
380
|
+
[6] test(main)> Order.last.user.profile
|
381
|
+
```
|
382
|
+
|
383
|
+
<details><summary>output:</summary>
|
384
|
+
|
385
|
+
```rb
|
386
|
+
D, [2024-12-12T18:23:41.382606 #2816] DEBUG -- : Order Load (8.6ms) SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
|
387
|
+
D, [2024-12-12T18:23:41.389954 #2816] DEBUG -- : User Load (2.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = '1' LIMIT 1
|
388
|
+
D, [2024-12-12T18:23:41.392060 #2816] DEBUG -- : UserProfile Load (1.8ms) SELECT `user_profiles`.* FROM `user_profiles` WHERE `user_profiles`.`id` = '1' LIMIT 1
|
389
|
+
#<UserProfile:0x000000012330a010> {
|
390
|
+
:id => "1",
|
391
|
+
:name => "user1"
|
392
|
+
}
|
393
|
+
```
|
394
|
+
|
395
|
+
</details>
|
396
|
+
|
397
|
+
---
|
398
|
+
|
399
|
+
Even though `users.login_id` column exists, because the column is not an external key it should be ignored from the association.
|
400
|
+
The column is ignored because the custom association is defined here and `User#login` causes a `NoMethodError`
|
401
|
+
|
402
|
+
https://github.com/nogahighland/active_record_mysql_repl/blob/f52f04770425723f632220bb8031bf4b402020a6/sample_config/.army.sample/associations.sample.yml#L10-L13
|
403
|
+
|
404
|
+
```rb
|
405
|
+
[1] test(main)> User.last.login
|
406
|
+
```
|
407
|
+
|
408
|
+
<details><summary>output:</summary>
|
409
|
+
|
410
|
+
```rb
|
411
|
+
D, [2024-12-12T22:17:49.291618 #37808] DEBUG -- : User Load (2.5ms) SELECT `users`.* FROM `users` ORDER BY `users`.`id` DESC LIMIT 1
|
412
|
+
NoMethodError: undefined method `login' for an instance of User
|
413
|
+
from /Users/hiroki.kishi/develop/private/active_record_mysql_repl/vendor/bundle/ruby/3.3.0/gems/activemodel-7.2.2/lib/active_model/attribute_methods.rb:512:in `method_missing'
|
414
|
+
```
|
415
|
+
|
416
|
+
</details>
|
28
417
|
|
29
|
-
|
418
|
+
---
|
419
|
+
|
420
|
+
You can use transaction by globally defined `transaction`.
|
421
|
+
|
422
|
+
```rb
|
423
|
+
[7] test(main)> u2 = User.new(id:2, profile_id: up2, login_id: 'login2')
|
424
|
+
[9] test(main)> up2 = UserProfile.new(id:2, name: 'user2');
|
425
|
+
[10] test(main)> transaction { [u2, up2].map(&:save) }
|
426
|
+
```
|
427
|
+
|
428
|
+
<details><summary>output:</summary>
|
429
|
+
|
430
|
+
```sql
|
431
|
+
[9] test(main)> up2 = UserProfile.new(id:2, name: 'user2');
|
432
|
+
[10] test(main)> transaction { [u2, up2].map(&:save) }
|
433
|
+
D, [2024-12-12T22:25:32.266790 #37808] DEBUG -- : TRANSACTION (2.2ms) BEGIN
|
434
|
+
D, [2024-12-12T22:25:32.272857 #37808] DEBUG -- : User Create (8.3ms) INSERT INTO `users` (`id`, `login_id`) VALUES ('2', 'login2')
|
435
|
+
D, [2024-12-12T22:25:32.275213 #37808] DEBUG -- : UserProfile Create (2.1ms) INSERT INTO `user_profiles` (`id`, `name`) VALUES ('2', 'user2')
|
436
|
+
D, [2024-12-12T22:25:32.281765 #37808] DEBUG -- : TRANSACTION (6.4ms) COMMIT
|
437
|
+
[
|
438
|
+
[0] true,
|
439
|
+
[1] true
|
440
|
+
]
|
441
|
+
```
|
442
|
+
|
443
|
+
</details>
|
444
|
+
|
445
|
+
---
|
446
|
+
|
447
|
+
The following example shows the following steps:
|
448
|
+
|
449
|
+
1. Find the users with id 1 and 2
|
450
|
+
2. Change the login_id of the users
|
451
|
+
3. Show the changes
|
452
|
+
4. Save the changes in a transaction
|
453
|
+
|
454
|
+
```rb
|
455
|
+
[11] test(main)> u1, u2 = User.find([1, 2])
|
456
|
+
```
|
457
|
+
|
458
|
+
<details><summary>Output:</summary>
|
459
|
+
|
460
|
+
```rb
|
461
|
+
D, [2024-12-12T22:27:55.979311 #37808] DEBUG -- : User Load (11.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IN ('1', '2')
|
462
|
+
[
|
463
|
+
[0] #<User:0x0000000144b325a0> {
|
464
|
+
:id => "1",
|
465
|
+
:login_id => "user1",
|
466
|
+
:profile_id => 1
|
467
|
+
},
|
468
|
+
[1] #<User:0x0000000144b32460> {
|
469
|
+
:id => "2",
|
470
|
+
:login_id => "login2",
|
471
|
+
:profile_id => nil
|
472
|
+
}
|
473
|
+
]
|
474
|
+
```
|
475
|
+
|
476
|
+
</details>
|
477
|
+
|
478
|
+
```rb
|
479
|
+
[12] test(main)> [u1, u2].each { |u| u.login_id = "login_id#{u.id}" }
|
480
|
+
```
|
481
|
+
|
482
|
+
<details><summary>Output:</summary>
|
483
|
+
|
484
|
+
```rb
|
485
|
+
[
|
486
|
+
[0] #<User:0x0000000144b325a0> {
|
487
|
+
:id => "1",
|
488
|
+
:login_id => "login_id1",
|
489
|
+
:profile_id => 1
|
490
|
+
},
|
491
|
+
[1] #<User:0x0000000144b32460> {
|
492
|
+
:id => "2",
|
493
|
+
:login_id => "login_id2",
|
494
|
+
:profile_id => nil
|
495
|
+
}
|
496
|
+
]
|
497
|
+
```
|
498
|
+
|
499
|
+
</details>
|
500
|
+
|
501
|
+
```rb
|
502
|
+
[13] test(main)> [u1, u2].map(&:changes)
|
503
|
+
```
|
504
|
+
|
505
|
+
<details><summary>Output:</summary>
|
506
|
+
|
507
|
+
```rb
|
508
|
+
[
|
509
|
+
[0] {
|
510
|
+
"login_id" => [
|
511
|
+
[0] "user1",
|
512
|
+
[1] "login_id1"
|
513
|
+
]
|
514
|
+
},
|
515
|
+
[1] {
|
516
|
+
"login_id" => [
|
517
|
+
[0] "login2",
|
518
|
+
[1] "login_id2"
|
519
|
+
]
|
520
|
+
}
|
521
|
+
]
|
522
|
+
```
|
523
|
+
|
524
|
+
</details>
|
525
|
+
|
526
|
+
```rb
|
527
|
+
[14] test(main)> transaction { [u1, u2].map(&:save) }
|
528
|
+
```
|
529
|
+
|
530
|
+
<details><summary>Output:</summary>
|
531
|
+
|
532
|
+
```rb
|
533
|
+
D, [2024-12-12T22:29:14.179176 #37808] DEBUG -- : TRANSACTION (1.2ms) BEGIN
|
534
|
+
D, [2024-12-12T22:29:14.188392 #37808] DEBUG -- : User Update (9.1ms) UPDATE `users` SET `users`.`login_id` = 'login_id1' WHERE `users`.`id` = '1'
|
535
|
+
D, [2024-12-12T22:29:14.191429 #37808] DEBUG -- : User Update (2.6ms) UPDATE `users` SET `users`.`login_id` = 'login_id2' WHERE `users`.`id` = '2'
|
536
|
+
D, [2024-12-12T22:29:14.196802 #37808] DEBUG -- : TRANSACTION (5.2ms) COMMIT
|
537
|
+
[
|
538
|
+
[0] true,
|
539
|
+
[1] true
|
540
|
+
]
|
541
|
+
```
|
542
|
+
|
543
|
+
</details>
|
544
|
+
|
545
|
+
---
|
546
|
+
|
547
|
+
By `tab` (an alias to `tabulate`), the filtered records are shown in a table format. `.tab(orientation)` accepts the `:h(orizontal)` (default when <5 columns), and `:v(ertival)` (default when >=5 columns)
|
548
|
+
|
549
|
+
https://github.com/nogahighland/active_record_mysql_repl/blob/9f7c91774b176e1204ed434dad2867721982c660/lib/active_record_mysql_repl/extensions/object.rb#L11
|
550
|
+
|
551
|
+
```rb
|
552
|
+
[3] test(main)> Order.all.tab
|
553
|
+
```
|
554
|
+
|
555
|
+
<details><summary>output:</summary>
|
556
|
+
|
557
|
+
```rb
|
558
|
+
D, [2024-12-11T23:48:46.013935 #96381] DEBUG -- : Order Load (2.2ms) SELECT `orders`.* FROM `orders`
|
559
|
+
+----+---------+---------+
|
560
|
+
| id | user_id | item_id |
|
561
|
+
+----+---------+---------+
|
562
|
+
| 1 | 1 | 1 |
|
563
|
+
+----+---------+---------+
|
564
|
+
```
|
565
|
+
|
566
|
+
</details>
|
567
|
+
|
568
|
+
---
|
569
|
+
|
570
|
+
```rb
|
571
|
+
[4] test(main)> Order.all.tab(:v)
|
572
|
+
```
|
573
|
+
|
574
|
+
<details><summary>output:</summary>
|
575
|
+
|
576
|
+
```rb
|
577
|
+
D, [2024-12-11T23:48:49.461243 #96381] DEBUG -- : Order Load (3.2ms) SELECT `orders`.* FROM `orders`
|
578
|
+
+---------+-------+
|
579
|
+
| Name | Value |
|
580
|
+
+---------+-------+
|
581
|
+
| id | 1 |
|
582
|
+
| user_id | 1 |
|
583
|
+
| item_id | 1 |
|
584
|
+
+---------+-------+
|
585
|
+
```
|
586
|
+
|
587
|
+
</details>
|
588
|
+
|
589
|
+
---
|
590
|
+
|
591
|
+
`.j` is aliased to `.to_json` and `.jp` is defined to generate pretty json.
|
592
|
+
|
593
|
+
https://github.com/nogahighland/active_record_mysql_repl/blob/9f7c91774b176e1204ed434dad2867721982c660/lib/active_record_mysql_repl/extensions/object.rb#L128-L132
|
594
|
+
|
595
|
+
```rb
|
596
|
+
[5] test(main)> Order.all.j
|
597
|
+
```
|
598
|
+
|
599
|
+
<details><summary>output:</summary>
|
600
|
+
|
601
|
+
```rb
|
602
|
+
D, [2024-12-11T23:48:55.267761 #96381] DEBUG -- : Order Load (4.4ms) SELECT `orders`.* FROM `orders`
|
603
|
+
[{"id":"1","user_id":"1","item_id":"1"}]
|
604
|
+
```
|
605
|
+
|
606
|
+
</details>
|
607
|
+
|
608
|
+
```rb
|
609
|
+
[6] test(main)> Order.all.jp
|
610
|
+
```
|
611
|
+
|
612
|
+
<details><summary>output:</summary>
|
613
|
+
|
614
|
+
```rb
|
615
|
+
D, [2024-12-11T23:48:57.250492 #96381] DEBUG -- : Order Load (1.8ms) SELECT `orders`.* FROM `orders`
|
616
|
+
[
|
617
|
+
{
|
618
|
+
"id": "1",
|
619
|
+
"user_id": "1",
|
620
|
+
"item_id": "1"
|
621
|
+
}
|
622
|
+
]
|
623
|
+
```
|
624
|
+
|
625
|
+
</details>
|
626
|
+
|
627
|
+
---
|
628
|
+
|
629
|
+
`.csv(orientation)` is defined to generate csv format. The default orientation is same as `.tab`.
|
630
|
+
|
631
|
+
https://github.com/nogahighland/active_record_mysql_repl/blob/9f7c91774b176e1204ed434dad2867721982c660/lib/active_record_mysql_repl/extensions/object.rb#L71
|
632
|
+
|
633
|
+
```rb
|
634
|
+
[1] test(main)> Order.all.csv
|
635
|
+
```
|
636
|
+
|
637
|
+
<details><summary>output:</summary>
|
638
|
+
|
639
|
+
```
|
640
|
+
D, [2024-12-12T01:29:12.844339 #26252] DEBUG -- : Order Load (2.7ms) SELECT `orders`.* FROM `orders`
|
641
|
+
id,user_id,item_id
|
642
|
+
1,1,1
|
643
|
+
```
|
644
|
+
|
645
|
+
</details>
|
646
|
+
|
647
|
+
---
|
648
|
+
|
649
|
+
`.cp` is defined to copy to clipboard the receiver object's `.to_s` representation.
|
650
|
+
|
651
|
+
```rb
|
652
|
+
[7] test(main)> Order.all.jp.cp
|
653
|
+
```
|
654
|
+
|
655
|
+
<details><summary>output:</summary>
|
656
|
+
|
657
|
+
```rb
|
658
|
+
D, [2024-12-11T23:48:59.443202 #96381] DEBUG -- : Order Load (2.0ms) SELECT `orders`.* FROM `orders`
|
659
|
+
true
|
660
|
+
```
|
661
|
+
|
662
|
+
</details>
|
663
|
+
|
664
|
+
---
|
665
|
+
|
666
|
+
`.exec_sql` is defined to execute the sql query and return the result as an array of hash.
|
667
|
+
|
668
|
+
```rb
|
669
|
+
[8] test(main)> exec_sql('select 1')
|
670
|
+
```
|
671
|
+
|
672
|
+
<details><summary>output:</summary>
|
673
|
+
|
674
|
+
```rb
|
675
|
+
D, [2024-12-11T23:49:15.879841 #96381] DEBUG -- : (1.2ms) select 1
|
676
|
+
[
|
677
|
+
[0] {
|
678
|
+
"1" => 1
|
679
|
+
}
|
680
|
+
]
|
681
|
+
```
|
682
|
+
|
683
|
+
</details>
|
684
|
+
|
685
|
+
---
|
686
|
+
|
687
|
+
```rb
|
688
|
+
[9] test(main)> exec_sql('select 1').tab
|
689
|
+
```
|
690
|
+
|
691
|
+
<details><summary>output:</summary>
|
692
|
+
|
693
|
+
```rb
|
694
|
+
D, [2024-12-11T23:49:17.187358 #96381] DEBUG -- : (2.1ms) select 1
|
695
|
+
+---+
|
696
|
+
| 1 |
|
697
|
+
+---+
|
698
|
+
| 1 |
|
699
|
+
+---+
|
700
|
+
```
|
701
|
+
|
702
|
+
</details>
|
703
|
+
|
704
|
+
---
|
705
|
+
|
706
|
+
```rb
|
707
|
+
[10] test(main)> exec_sql('select 1 as num').tab
|
708
|
+
```
|
709
|
+
|
710
|
+
<details><summary>output:</summary>
|
711
|
+
|
712
|
+
```
|
713
|
+
D, [2024-12-11T23:49:22.406631 #96381] DEBUG -- : (1.3ms) select 1 as num
|
714
|
+
+-----+
|
715
|
+
| num |
|
716
|
+
+-----+
|
717
|
+
| 1 |
|
718
|
+
+-----+
|
719
|
+
```
|
720
|
+
|
721
|
+
</details>
|
722
|
+
|
723
|
+
---
|
724
|
+
|
725
|
+
You can define your own extension script. For example `.upcase_name` is defined on `UserProfile` by the sample extension which is specified in the `.army.sample.yml` file.
|
726
|
+
|
727
|
+
- https://github.com/nogahighland/active_record_mysql_repl/blob/9f7c91774b176e1204ed434dad2867721982c660/sample_config/.army.sample.yml#L5
|
728
|
+
- https://github.com/nogahighland/active_record_mysql_repl/blob/acaa44684ea4fd135225580431417d6ccd41a988/sample_config/.army.sample/extensions/hello.rb#L1-L9
|
729
|
+
|
730
|
+
```rb
|
731
|
+
[3] test(main)> UserProfile.last.upcase_name
|
732
|
+
```
|
733
|
+
|
734
|
+
<details><summary>output:</summary>
|
735
|
+
|
736
|
+
```
|
737
|
+
D, [2024-12-12T12:09:10.987656 #60808] DEBUG -- : UserProfile Load (1.7ms) SELECT `user_profiles`.* FROM `user_profiles` ORDER BY `user_profiles`.`id` DESC LIMIT 1
|
738
|
+
USER1
|
739
|
+
```
|
740
|
+
|
741
|
+
</details>
|
742
|
+
|
743
|
+
---
|
744
|
+
|
745
|
+
## Development
|
30
746
|
|
31
|
-
|
747
|
+
TODO
|
32
748
|
|
33
749
|
## Contributing
|
34
750
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
751
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/nogahifhland/active_record_mysql_repl. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/nogahighland/active_record_mysql_repl/blob/main/CODE_OF_CONDUCT.md).
|
36
752
|
|
37
753
|
## License
|
38
754
|
|