The project is in a healthy, maintained state
MySQL REPL featured by ActiveRecord and Pry
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

~> 11.1.3
~> 0.50.0

Runtime

~> 2.0
~> 0.5.6
~> 0.14.2
~> 1.7
~> 1.1
~> 3.3.0
~> 7.3
 Project Readme

ActiveRecordMysqlRepl

Prerequisites

Ruby version 3.0.0 or higher

e.g) Using rbenv

$ rbenv install 3.3.6

mysql-client 8.0

e.g) on macOS

$ brew install mysql-client@8.0
$ gem install mysql2 -v 0.5.6 -- --with-ldflags=-L$(brew --prefix zstd)/lib --with-mysql-dir=/opt/homebrew/opt/mysql-client@8.4

Installation

Just by installing the gem, you can use the army command.

$ gem install active_record_mysql_repl
Successfully installed active_record_mysql_repl-x.x.x
Parsing documentation for active_record_mysql_repl-x.x.x
Installing ri documentation for active_record_mysql_repl-x.x.x
Done installing documentation for active_record_mysql_repl after 0 seconds
1 gem installed
$ army
ActiveRecordMysqlRepl Version: x.x.x

If you want to use the zsh completion, you can add the following line to your .zshrc file.

$ eval "$(army --zsh-completion)"

Then you can use the completion feature like below.

$ army [TAB]
option
-c  -- path to .armyrc file
-d  -- Database name
-e  -- output erd

Usage

Sample Configurations

From the following link, you can Download the sample configuration files https://github.com/nogahighland/active_record_mysql_repl/tree/main/sample_config

Also you can try with sample database on your local MySQL server https://github.com/nogahighland/active_record_mysql_repl/blob/main/sample_config/sample_db.sql

Sample Database

CREATE DATABASE test;

The sample configuration assumes the sample database is running on 127.0.0.1:3306/test (user: root, password: root)

$ mysql -u root -p test < sample_db.sql

image

This ER Diagram can be generated by the following command

army -c sample_config/.army.sample.yml -d test -e erd

Showcases

army -c /path/to/sample_config/.army.sample.yml -d test
Ensureing connection to test on port 127.0.0.1:33060
Loading tables
Loading custom extensions from /path/to/sample_config/./.army.sample/extensions

Now you can access to the table classes as User if the table name is users.

[1] test(main)> User.all
output:
D, [2024-12-12T12:57:38.581127 #2816] DEBUG -- :   User Load (10.5ms)  SELECT `users`.* FROM `users`
[
  [0] #<User:0x0000000123188de0> {
    :id         => "1",
    :login_id   => "user1",
    :profile_id => 1
  }
]

.d method shows the schema of the table. Let's see the Order table schema.

[8] test(main)> Order.d
output:
D, [2024-12-12T12:32:20.100309 #2816] DEBUG -- :    (10.6ms)  DESCRIBE orders
D, [2024-12-12T12:32:20.107976 #2816] DEBUG -- :    (6.9ms)  SHOW INDEX FROM orders
# orders
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | varchar(64) | NO   | PRI |         |       |
| user_id | varchar(64) | NO   |     |         |       |
| item_id | varchar(64) | NO   |     |         |       |
+---------+-------------+------+-----+---------+-------+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| orders | 0          | PRIMARY  | 1            | id          | A         | 1           |          |        |      | BTREE      |         |               | YES     |            |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+

.ddl method shows the DDL of the table.

[9] test(main)> Order.ddl
output:
D, [2024-12-12T12:32:21.878444 #2816] DEBUG -- :    (8.7ms)  SHOW CREATE TABLE orders
CREATE TABLE `orders` (
  `id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  `user_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  `item_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin

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.

https://github.com/nogahighland/active_record_mysql_repl/blob/main/lib/active_record_mysql_repl/extensions/global.rb#L10-L12

[6] test(main)> puts models.map(&:d)
output:
D, [2024-12-12T01:26:36.677988 #25446] DEBUG -- :   Brand Load (2.1ms)  SELECT `brands`.* FROM `brands`
D, [2024-12-12T01:26:36.681307 #25446] DEBUG -- :   Category Load (2.8ms)  SELECT `categories`.* FROM `categories`
D, [2024-12-12T01:26:36.683967 #25446] DEBUG -- :   Item Load (2.0ms)  SELECT `items`.* FROM `items`
D, [2024-12-12T01:26:36.687282 #25446] DEBUG -- :   Order Load (3.0ms)  SELECT `orders`.* FROM `orders`
D, [2024-12-12T01:26:36.691204 #25446] DEBUG -- :   UserProfile Load (3.6ms)  SELECT `user_profiles`.* FROM `user_profiles`
D, [2024-12-12T01:26:36.694081 #25446] DEBUG -- :   User Load (2.2ms)  SELECT `users`.* FROM `users`
# users
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| id         | varchar(64) | NO   | PRI |         |       |
| login_id   | varchar(64) | NO   |     |         |       |
| profile_id | int         | YES  |     |         |       |
+------------+-------------+------+-----+---------+-------+
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| users | 0          | PRIMARY  | 1            | id          | A         | 1           |          |        |      | BTREE      |         |               | YES     |            |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
# user_profiles
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | varchar(64) | NO   | PRI |         |       |
| name  | varchar(64) | NO   |     |         |       |
+-------+-------------+------+-----+---------+-------+
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table         | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| user_profiles | 0          | PRIMARY  | 1            | id          | A         | 1           |          |        |      | BTREE      |         |               | YES     |            |
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
# orders
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | varchar(64) | NO   | PRI |         |       |
| user_id | varchar(64) | NO   |     |         |       |
| item_id | varchar(64) | NO   |     |         |       |
+---------+-------------+------+-----+---------+-------+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| orders | 0          | PRIMARY  | 1            | id          | A         | 1           |          |        |      | BTREE      |         |               | YES     |            |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
# items
+-------------+-------------+------+-----+---------+-------+
| Field       | Type        | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| id          | varchar(64) | NO   | PRI |         |       |
| category_id | varchar(64) | NO   |     |         |       |
| brand_id    | varchar(64) | NO   |     |         |       |
+-------------+-------------+------+-----+---------+-------+
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| items | 0          | PRIMARY  | 1            | id          | A         | 1           |          |        |      | BTREE      |         |               | YES     |            |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
# categories
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| id        | varchar(64) | NO   | PRI |         |       |
| name      | varchar(64) | NO   |     |         |       |
| parent_id | varchar(64) | NO   |     |         |       |
+-----------+-------------+------+-----+---------+-------+
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table      | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| categories | 0          | PRIMARY  | 1            | id          | A         | 2           |          |        |      | BTREE      |         |               | YES     |            |
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
# brands
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | varchar(64) | NO   | PRI |         |       |
| name  | varchar(64) | NO   |     |         |       |
+-------+-------------+------+-----+---------+-------+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| brands | 0          | PRIMARY  | 1            | id          | A         | 1           |          |        |      | BTREE      |         |               | YES     |            |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+

To get the last record of order,

[1] test(main)> Order.last
output:
D, [2024-12-11T23:45:49.743857 #96076] DEBUG -- :   Order Load (5.5ms)  SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
#<Order:0x00000001293677c8> {
  :id      => "1",
  :user_id => "1",
  :item_id => "1"
}

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. All the associations are chainable by the native functionality of ActiveRecord.

[5] test(main)> Order.last.user
output:
D, [2024-12-11T23:46:11.154678 #96076] DEBUG -- :   Order Load (6.9ms)  SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
D, [2024-12-11T23:46:11.176424 #96076] DEBUG -- :   User Load (2.9ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = '1' LIMIT 1
#<User:0x000000012961fda8> {
  :id         => "1",
  :login_id   => "user1",
  :profile_id => 1
}
[7] test(main)> Order.last.item
output:
D, [2024-12-11T23:46:17.098874 #96076] DEBUG -- :   Order Load (3.5ms)  SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
D, [2024-12-11T23:46:17.112940 #96076] DEBUG -- :   Item Load (2.2ms)  SELECT `items`.* FROM `items` WHERE `items`.`id` = '1' LIMIT 1
#<Item:0x000000012a416c40> {
  :id          => "1",
  :category_id => "2",
  :brand_id    => "1"
}
[8] test(main)> Order.last.item.category
output:
D, [2024-12-11T23:46:21.104696 #96076] DEBUG -- :   Order Load (2.1ms)  SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
D, [2024-12-11T23:46:21.106696 #96076] DEBUG -- :   Item Load (1.5ms)  SELECT `items`.* FROM `items` WHERE `items`.`id` = '1' LIMIT 1
D, [2024-12-11T23:46:21.117169 #96076] DEBUG -- :   Category Load (2.5ms)  SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = '2' LIMIT 1
#<Category:0x000000012a5d7b38> {
  :id        => "2",
  :name      => "category2",
  :parent_id => "1"
}

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.

[9] test(main)> Order.last.item.category.parent
output:
D, [2024-12-11T23:46:23.553443 #96076] DEBUG -- :   Order Load (2.0ms)  SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
D, [2024-12-11T23:46:23.555918 #96076] DEBUG -- :   Item Load (2.1ms)  SELECT `items`.* FROM `items` WHERE `items`.`id` = '1' LIMIT 1
D, [2024-12-11T23:46:23.560142 #96076] DEBUG -- :   Category Load (3.8ms)  SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = '2' LIMIT 1
D, [2024-12-11T23:46:23.562496 #96076] DEBUG -- :   Category Load (1.3ms)  SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = '1' LIMIT 1
#<Category:0x000000012a73dd60> {
  :id        => "1",
  :name      => "category1",
  :parent_id => ""
}

You can get user's profile by .profile because the custom association is defined here

https://github.com/nogahighland/active_record_mysql_repl/blob/main/sample_config/.army.sample/associations.sample.yml#L4-L8

[6] test(main)> Order.last.user.profile
output:
D, [2024-12-12T18:23:41.382606 #2816] DEBUG -- :   Order Load (8.6ms)  SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` DESC LIMIT 1
D, [2024-12-12T18:23:41.389954 #2816] DEBUG -- :   User Load (2.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = '1' LIMIT 1
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
#<UserProfile:0x000000012330a010> {
  :id   => "1",
  :name => "user1"
}

Even though users.login_id column exists, because the column is not an external key it should be ignored from the association. The column is ignored because the custom association is defined here and User#login causes a NoMethodError

ignore_columns:
users:
- login_id

[1] test(main)> User.last.login
output:
D, [2024-12-12T22:17:49.291618 #37808] DEBUG -- :   User Load (2.5ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` DESC LIMIT 1
NoMethodError: undefined method `login' for an instance of User
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'

You can use transaction by globally defined transaction.

[7] test(main)> u2 = User.new(id:2, profile_id: up2, login_id: 'login2')
[9] test(main)> up2 = UserProfile.new(id:2, name: 'user2');
[10] test(main)> transaction { [u2, up2].map(&:save) }
output:
[9] test(main)> up2 = UserProfile.new(id:2, name: 'user2');
[10] test(main)> transaction { [u2, up2].map(&:save) }
D, [2024-12-12T22:25:32.266790 #37808] DEBUG -- :   TRANSACTION (2.2ms)  BEGIN
D, [2024-12-12T22:25:32.272857 #37808] DEBUG -- :   User Create (8.3ms)  INSERT INTO `users` (`id`, `login_id`) VALUES ('2', 'login2')
D, [2024-12-12T22:25:32.275213 #37808] DEBUG -- :   UserProfile Create (2.1ms)  INSERT INTO `user_profiles` (`id`, `name`) VALUES ('2', 'user2')
D, [2024-12-12T22:25:32.281765 #37808] DEBUG -- :   TRANSACTION (6.4ms)  COMMIT
[
  [0] true,
  [1] true
]

The following example shows the following steps:

  1. Find the users with id 1 and 2
  2. Change the login_id of the users
  3. Show the changes
  4. Save the changes in a transaction
[11] test(main)> u1, u2 = User.find([1, 2])
Output:
D, [2024-12-12T22:27:55.979311 #37808] DEBUG -- :   User Load (11.7ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` IN ('1', '2')
[
  [0] #<User:0x0000000144b325a0> {
    :id         => "1",
    :login_id   => "user1",
    :profile_id => 1
  },
  [1] #<User:0x0000000144b32460> {
    :id         => "2",
    :login_id   => "login2",
    :profile_id => nil
  }
]
[12] test(main)> [u1, u2].each { |u| u.login_id = "login_id#{u.id}" }
Output:
[
  [0] #<User:0x0000000144b325a0> {
    :id         => "1",
    :login_id   => "login_id1",
    :profile_id => 1
  },
  [1] #<User:0x0000000144b32460> {
    :id         => "2",
    :login_id   => "login_id2",
    :profile_id => nil
  }
]
[13] test(main)> [u1, u2].map(&:changes)
Output:
[
  [0] {
    "login_id" => [
      [0] "user1",
      [1] "login_id1"
    ]
  },
  [1] {
    "login_id" => [
      [0] "login2",
      [1] "login_id2"
    ]
  }
]
[14] test(main)> transaction { [u1, u2].map(&:save)  }
Output:
D, [2024-12-12T22:29:14.179176 #37808] DEBUG -- :   TRANSACTION (1.2ms)  BEGIN
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'
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'
D, [2024-12-12T22:29:14.196802 #37808] DEBUG -- :   TRANSACTION (5.2ms)  COMMIT
[
  [0] true,
  [1] true
]

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)

[3] test(main)> Order.all.tab
output:
D, [2024-12-11T23:48:46.013935 #96381] DEBUG -- :   Order Load (2.2ms)  SELECT `orders`.* FROM `orders`
+----+---------+---------+
| id | user_id | item_id |
+----+---------+---------+
| 1  | 1       | 1       |
+----+---------+---------+

[4] test(main)> Order.all.tab(:v)
output:
D, [2024-12-11T23:48:49.461243 #96381] DEBUG -- :   Order Load (3.2ms)  SELECT `orders`.* FROM `orders`
+---------+-------+
| Name    | Value |
+---------+-------+
| id      | 1     |
| user_id | 1     |
| item_id | 1     |
+---------+-------+

.j is aliased to .to_json and .jp is defined to generate pretty json.

alias j to_json
def jp
JSON.pretty_generate(JSON.parse(to_json))
end

[5] test(main)> Order.all.j
output:
D, [2024-12-11T23:48:55.267761 #96381] DEBUG -- :   Order Load (4.4ms)  SELECT `orders`.* FROM `orders`
[{"id":"1","user_id":"1","item_id":"1"}]
[6] test(main)> Order.all.jp
output:
D, [2024-12-11T23:48:57.250492 #96381] DEBUG -- :   Order Load (1.8ms)  SELECT `orders`.* FROM `orders`
[
  {
    "id": "1",
    "user_id": "1",
    "item_id": "1"
  }
]

Convenient syntax sugar such as 'value'.{table_name} 'value'.{table_name}s 'value'.{table_name}_by_{column_name} are available as dynamically defined methods.

[1] test(main)> :'1'.order
output:
D, [2024-12-13T11:40:17.290699 #48059] DEBUG -- :   Order Load (2.2ms)  SELECT `orders`.* FROM `orders` WHERE `orders`.`id` = '1' LIMIT 1
#<Order:0x0000000122e7f0e0> {
  :id      => "1",
  :user_id => "1",
  :item_id => "1"
}
[2] test(main)> '1'.order
output:
D, [2024-12-13T11:40:21.217724 #48059] DEBUG -- :   Order Load (2.4ms)  SELECT `orders`.* FROM `orders` WHERE `orders`.`id` = '1' LIMIT 1
#<Order:0x000000010512c450> {
  :id      => "1",
  :user_id => "1",
  :item_id => "1"
}
[3] test(main)> '1'.orders
output:
D, [2024-12-13T11:40:22.781925 #48059] DEBUG -- :   Order Load (2.7ms)  SELECT `orders`.* FROM `orders` WHERE `orders`.`id` = '1' LIMIT 1
#<Order:0x0000000105129750> {
  :id      => "1",
  :user_id => "1",
  :item_id => "1"
}
[4] test(main)> '1'.user_by_profile_id
output:
D, [2024-12-13T11:40:47.497002 #48059] DEBUG -- :   User Load (7.9ms)  SELECT `users`.* FROM `users` WHERE `users`.`profile_id` = 1
[
  [0] #<User:0x00000001243fc0f8> {
    :id         => "1",
    :login_id   => "login_id1",
    :profile_id => 1
  }
]
---

.csv(orientation) is defined to generate csv format. The default orientation is same as .tab.

[1] test(main)> Order.all.csv
output:
D, [2024-12-12T01:29:12.844339 #26252] DEBUG -- :   Order Load (2.7ms)  SELECT `orders`.* FROM `orders`
id,user_id,item_id
1,1,1

.cp is defined to copy to clipboard the receiver object's .to_s representation.

[7] test(main)> Order.all.jp.cp
output:
D, [2024-12-11T23:48:59.443202 #96381] DEBUG -- :   Order Load (2.0ms)  SELECT `orders`.* FROM `orders`
true

.exec_sql is defined to execute the sql query and return the result as an array of hash.

[8] test(main)> exec_sql('select 1')
output:
D, [2024-12-11T23:49:15.879841 #96381] DEBUG -- :    (1.2ms)  select 1
[
  [0] {
    "1" => 1
  }
]

[9] test(main)> exec_sql('select 1').tab
output:
D, [2024-12-11T23:49:17.187358 #96381] DEBUG -- :    (2.1ms)  select 1
+---+
| 1 |
+---+
| 1 |
+---+

[10] test(main)> exec_sql('select 1 as num').tab
output:
D, [2024-12-11T23:49:22.406631 #96381] DEBUG -- :    (1.3ms)  select 1 as num
+-----+
| num |
+-----+
| 1   |
+-----+

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.

[3] test(main)> UserProfile.last.upcase_name
output:
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
USER1

Development

TODO

Contributing

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.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the ActiveRecordMysqlRepl project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.