README.org in arql-0.4.0 vs README.org in arql-0.4.1

- old
+ new

@@ -1,42 +1,42 @@ * Arql [[./README-zh_CN.org][中文]] - Arql is a simple utility gem that combines Rails ActiveRecord with Pry and adds useful Pry commands. It can - automatically define model classes based on database table schema. If you are a Ruby guy, you can use this gem - as your database query tool. + Arql is a simple instrumental gem that combines Rails ActiveRecord and Pry, and adds useful Pry commands. It can + automatically define model classes based on information from database tables. If you're a Ruby user, you can use this + Arql as your database query tool. -** Pre-requisite +** Dependencies - + Ruby >= 2.6.0 - + For different types of databases, you need to install the corresponding database adapter or client binary library: - - MySQL: Depending on your operating system, you may need to install: =libmariadb-dev=, =libmysqlclient-dev=, =mysql-devel= - =default-libmysqlclient-dev= ; see the software package guide for your distribution to find the specific package; or refer to [[https://github.com/brianmario/mysql2][mysql2 doc]] - - SQLite3: No additional libraries need to be installed - - PostgreSQL: ~gem install pg~ - - Oracle: ~gem install activerecord-oracle_enhanced-adapter~ - - SQL Server: ~gem install activerecord-sqlserver-adapter~ + - Ruby 2.6.0 or later + - For different types of databases, you need to install the appropriate database adapter or client binary library: + - MySQL: Depending on your operating system, you may need to install: , =libmariadb-dev= =libmysqlclient-dev= + =mysql-devel= , =default-libmysqlclient-dev= ; Refer to your distribution's package guide to find your specific + package, or refer to the mysql2 documentation + - SQLite3: No need to install any additional libraries + - PostgreSQL: =gem install pg= + - Oracle: =gem install activerecord-oracle_enhanced-adapter= + - SQL Server: =gem install activerecord-sqlserver-adapter= ** Installation + + Execute: - Run the following command to install the gem: - #+begin_example $ gem install arql #+end_example - Try using sudo if you encounter system permission issues: + If you're having problems with system permissions, try using sudo: #+begin_example $ sudo gem install arql #+end_example -** Usage - -*** CLI options - +** How to Use +*** Command Line Options + #+begin_example Usage: arql [options] [ruby file] If neither [ruby file] nor -E option is specified, and STDIN is a tty, a Pry REPL will be started, otherwise the specified ruby file or -E option value or ruby code read from STDIN will be executed, @@ -65,45 +65,77 @@ --help Print this message #+end_example **** =-c, --config=CONFIG_FILE= - Specify the configuration file location, default is =$HOME/.arql.yml= or =$HOME/.arql.d/init.yml=. The configuration file - is usually the same as the Rails database configuration file, but with some additional configuration options, such as the - =ssh= option, etc. Refer to the =Configuration file= section. + Specify the profile location, which defaults to =$HOME/.arql.yml= or =$HOME/.arql.d/init.yml= . Configuration files are + usually the same as Rails database configuration files, but there are some additional configuration options, such as + =ssh= options, etc. References =Configuration Files= section. **** =-i, --initializer=INITIALIZER= - Specify a Ruby source file, Arql executes the code in this file after defining the ActiveRecord model class, default is - =$HOME/.arql.rb= or =$HOME/.arql.d/init.rb=. You can add methods and association definitions for ActiveRecord model - classes in this file. - + Specify a Ruby source file and execute the code for Arql after defining the ActiveRecord model class, which defaults to + =$HOME/.arql.rb= or =$HOME/.arql.d/init.rb= . In this file, you can add method and association definitions to the + ActiveRecord model class. + **** =-e, --env=ENVIRON= - Specify an environment name in the configuration file. + Specify one or more environment names in the configuration file, separated by commas/pluses/colons. + The model classes that Arql generates for each environment will be placed in the namespace specified by the =namespace= + configuration for that environment. For example: + + #+BEGIN_SRC yaml + development: + adapter: mysql2 + host: localhost + username: root + database: myapp_development + pool: 5 + namespace: Dev + #+END_SRC + + Suppose there is a table in the =myapp_development= database named =users= , =posts= etc., then the model class + generated in the =development= environment will be: + + - =Dev::User= + - =Dev::Post= + + If no =namespace= configuration is specified, the default namespace is in the form of CamelCase for the environment + name. For example =Development= , here , then the resulting model class would be: + + - =Development::User= + - =Development::Post= + + Arql =Object.const_missing= also defines an "alias" under the top-level namespace for those model classes whose class + names and existing constants do not have the same name, for example, if the class name is not the same as the existing + constant name, it can be directly used =User= . =Post= + + If there are tables with the same names in more than one environment, an alias will be defined for the model classes of + the tables in the previous environments in the order of the specified environments + **** =-E, --eval=CODE= - Specify a Ruby code snippet, if this option is specified, the Pry REPL will not be started. + Specify a Ruby snippet, if specified, the Pry REPL will not be launched. **** =-S, --show-sql= - arql does not display SQL logs by default, use this option to turn it on. + arql does not display SQL logs by default and is turned on with this option. **** =-w, --write-sql=OUTPUT= - You can also use this option to let arql write SQL logs to a file. + You can also use this option to have arql write SQL logs to a file. **** =-A, --append-sql-OUTOUT= - Similar to =-w=, but uses append writing, does not truncate the existing file. + =-w= Similar to , but with append writes, existing files are not truncated. **** Database options - The options described in this section are usually configured in the configuration file. These options are just shortcuts - for the corresponding configuration items in the configuration file, so that certain configuration items can be directly - modified in the CLI. + The options described in this section are typically configured in a configuration file, and these options are + simply shortcuts to the configuration items in the configuration file so that certain configuration items can be + modified directly in the CLI. ***** -a, --db-adapter=DB_ADAPTER Specify the database adapter, available values: @@ -125,62 +157,95 @@ Specify the database name ***** -u, --db-user=DB_USER - Specify the database username + Specify the database user ***** -P, --db-password=DB_PASSWORD Specify the database password ***** -n, --db-encoding=DB_ENCODING - Specify the database character encoding, default is =utf8= + Specify the database encoding, default is =utf8= ***** -o, --db-pool=DB_POOL Specify the database connection pool size, default is =5= ***** -H, --ssh-host=SSH_HOST - Specify the SSH host, when the SSH related options are specified, arql will establish an SSH tunnel and connect to the - database using the SSH tunnel. + Specify the SSH host, when the SSH-related options are specified, arql will establish an SSH tunnel and connect to + the ***** -O, --ssh-port=SSH_PORT Specify the SSH port ***** -U, --ssh-user=SSH_USER - Specify the SSH username + Specify the SSH user ***** -W, --ssh-password=SSH_PASSWORD Specify the SSH password ***** -L, --ssh-local-port=SSH_LOCAL_PORT - Specify the SSH local port, default is a /random/ port + Specify the local SSH proxy port -*** Configuration file +*** Configuration Files - The path of the configuration file defaults to =$HOME/.arql.yml= or =$HOME/.arql.d/init.yml=. The configuration file is - usually the same as the Rails database configuration file, but there are some additional configuration options: + The path to the configuration file defaults to or =$HOME/.arql.yml= =$HOME/.arql.d/init.yml= . The configuration file + is usually the same as the Rails database configuration file, but there are some additional configuration options: - 1. =created_at= : An array of custom column names containing the ActiveRecord =created_at= field, default is =created_at=, if specified, the current timestamp will be used to fill the value of the column when created - 2. =updated_at= : An array of custom column names containing the ActiveRecord =updated_at= field, default is =updated_at=, if specified, the current timestamp will be used to fill the value of the column when updated - 3. =ssh.host= : ssh host, you can use the host name in the =ssh_config= file, or directly use the IP address or host name + 1. =created_at= : An array of custom column names containing the ActiveRecord =created_at= field, with the default value + of , if specified =created_at= , the value of the column will be populated with the current timestamp when created + 2. =updated_at= : An array of custom column names containing the ActiveRecord =updated_at= field, with the default value + of , if specified =updated_at= , the value of the column will be populated with the current timestamp when updated + 3. =ssh.host= : ssh host, you can use the hostname in the =ssh_config= file, or it can be a direct IP address or + hostname 4. =ssh.port= : ssh port, default is =22= - 5. =ssh.user= : ssh username - 6. =ssh.password= : ssh password - 7. =ssh.local_port= : ssh local port - 8. =singularized_table_names=: Whether to use singular table names, default is =false=, if =false=, the =students= table will be defined as the =Student= model, if =true=, the =students= table will be defined as the =Students= model - 9. =table_name_prefixes=: An array of table name prefixes, defaults to an empty array. If specified, these prefixes will be ignored when generating models. For example, if =["t_"]= is specified, then the =t_students= table will be defined as the =Student= model + 5. =ssh.user= : ssh username + 6. =ssh.password= : SSH password + 7. =ssh.local_port= : ssh local port + 8. =singularized_table_names= : Whether to use the singular table name, the default is =false= , if it is =false= , the + =students= table will be defined as a =Student= model, if it is =true= , the =students= table will be defined as a + =Students= model + 9. =table_name_prefixes= : An array of table name prefixes, which default is an empty array, if specified, these + prefixes will be ignored when generating the model, for example =["t_"]= , if , the =t_students= table will be + defined as a =Student= model + 10. =namespace= : The model namespace, which defaults to the CamelCase form of the environment name, and the generated + model will be placed under the specified namespace + 11. =model_names= : The value of this configuration item is a hash(map), the key is the table name, and the value is the + name of the model to be generated for the table. Arql uses ActiveRecord's naming convention to generate model names + by default, and if this configuration item is specified, the table specified by the configuration item will use the + model name specified by the modified configuration itemValue can be an array of strings in addition to a string + representing the model name, with the first element of the array representing the model name and the second element + representing the constant alias (Arql) created for the model By default, aliases are also automatically created for + the generated model class according to certain rules, and if an alias is specified here, the user-provided value + will be used as the alias) -**** Example + =model_names= Examples of configuration items: + #+BEGIN_SRC yaml + development: + host: localhost + database: test + username: root + model_names: + students: Seito + teachers: ["LaoShi", "LS"] + #+END_SRC + + In the above configuration file, a model named for the =students= table will be generated, a model named =LaoShi= for + the =teachers= table will be generated for the table, and a constant alias named =LS= will be created for the =LaoShi= + model. An alias is also generated for the =students= table: =S= + +**** Example configuration file + #+begin_example default: &default adapter: mysql2 encoding: utf8 created_at: ["gmt_created"] @@ -189,233 +254,197 @@ local: <<: *default username: root database: blog - table_name_prefixes: ["t_"] password: + table_name_prefixes: ["t_"] socket: /tmp/mysql.sock + namespace: B dev: <<: *default host: devdb.mycompany.com port: 3306 username: root password: 123456 database: blog table_name_prefixes: ["t_"] + namespace: B ssh: host: dev.mycompany.com port: 22 user: deploy password: 12345678 local_port: 3307 #+end_example + In the example =default= , a generic configuration item is defined, as well as two specific database environments + =local= and =dev= . =local= =dev= =<<: *default= and inherit =default= the configuration items of . - The example defines a common configuration item =default=, and two specific database environments =local= and =dev=. =local= - and =dev= inherit the configuration items of =default= in the way of =<<: *default=. + =arql -e dev= When the command is executed, arql uses the =dev= configuration in the configuration file; =arql -e local= + When the command is executed, arql uses the =local= configuration in the configuration file. + =dev= The environment uses an SSH tunnel, and when you connect to a =devdb.mycompany.com= database, you will first + establish an SSH tunnel to and then connect to =dev.mycompany.com= the database through the SSH tunnel. - When the command =arql -e dev= is executed, arql will use the =dev= configuration in the configuration file; when the command - =arql -e local= is executed, arql will use the =local= configuration in the configuration file. +*** Use as a REPL + If neither the =[ruby file]= Nor the Specify =-E= option is specified, and the STDIN is a =tty= , arql launches a Pry + REPL. For example, execute: - The =dev= environment uses an SSH tunnel. When connecting to the =devdb.mycompany.com= database, an SSH tunnel will be established - to =dev.mycompany.com= first, and then connected to the database through the SSH tunnel. - -*** Use Arql as REPL - - If neither =[ruby file]= nor the =-E= option is specified, and STDIN is a =tty=, arql will start a Pry REPL. For example, execute: - #+BEGIN_EXAMPLE arql -e dev #+END_EXAMPLE - Arql provides some Pry commands: + Arql provides a few Pry commands: + **** =info= - The =info= command prints the current database connection information and SSH proxy information, for example: + =info= The command prints the current database connection information and SSH proxy information, for example: #+begin_example - Database Connection Information: + my_env Database Connection Information: Host: Port: Username: root Password: Database: test Adapter: mysql2 Encoding: utf8 Pool Size: 5 #+end_example + =info= By default, the connection information for all specified environments is displayed, if you only want to display + the connection information of the current environment, the =info= command accepts a regular expression argument and only + displays the matching environment information, for example: + + #+BEGIN_EXAMPLE + info .*dev + #+END_EXAMPLE + **** =m= or =l= - The =m= (or =l=) command prints all table names and their corresponding model class names and abbreviated class names, for example: + =m= (or =l= ) command to print all table names and corresponding model class names and abbreviated class names, for + example: #+begin_example - +--------------------+------------------+------+----------------+ - | Table Name | Model Class | Abbr | Comment | - +--------------------+------------------+------+----------------+ - | post | Post | P | Posts | - | org | Org | O | Orginations | - | user_org | UserOrg | UO | | - | student | Student | S | Students | - | course | Course | C | | - | score | Score | S2 | | - | users | Users | U | | - | posts | Posts | P2 | | - | authors | Authors | A | | - +--------------------+------------------+------+----------------+ + +--------------------+------------------+------+---------+ + | Table Name | Model Class | Abbr | Comment | + +--------------------+------------------+------+---------+ + | post | Post | P | 帖子 | + | org | Org | O | 组织 | + | user_org | UserOrg | UO | | + | student | Student | S | 学生 | + | course | Course | C | | + | score | Score | S2 | | + | users | Users | U | | + | posts | Posts | P2 | | + | authors | Authors | A | | + +--------------------+------------------+------+---------+ #+end_example - Where: + Thereinto: - - =Table Name= : Table name - - =Model Class= : Model class name - - =Abbr= : Abbreviated class name - - =Comment= : Comment + - =Table Name= : Table name + - =Model Class= : Model class name + - =Abbr= : Abbreviated class name + - =Comment= :Exegesis. - The =m= / =l= command can also accept a parameter to filter the list by table name or table comment, for example: + =m= / =l= Command with three optional options: - =m perm= will only list tables that contain =perm= in the table name or table comment; if you want to use regular expressions to match, - you can use =m /perm/i= to match. + - =-e= , =--env= : Specify the environment, regular expression, only display the table name in the matching environment, + and display all environments by default + - =-f= , =--format= : Output Format: + - =terminal= : Default table format + - =md= : markdown table format + - =org= : org mode table format + - =sql= : 输出 create table SQL + - =-c= , =--column= : Regular expression, which lists fields, not tables, and filters by field name or field comment -**** =t= + =m= The / =l= command can also accept an optional regular expression argument that displays only information about + matching tables (by table name or table comment), for example: - The =t= command accepts a table name or model class name as a parameter and prints the table definition information, for example: + #+BEGIN_EXAMPLE + l # Print all table information + l ^post # Only display information about tables whose names start with post + l -e dev -f md # Display table information in the dev environment and output in markdown format + l -c no|num # Display only field information containing no or num in field name or field comment + #+END_EXAMPLE - Executing the =t Person= command will print the definition information of the =person= table: - - #+begin_example - Table: person - +----|------------|------------------|-----------|-------|-----------|-------|---------|----------|---------+ - | PK | Name | SQL Type | Ruby Type | Limit | Precision | Scale | Default | Nullable | Comment | - +----|------------|------------------|-----------|-------|-----------|-------|---------|----------|---------+ - | Y | id | int(11) unsigned | integer | 4 | | | | false | | - | | name | varchar(64) | string | 64 | | | | true | | - | | age | int(11) | integer | 4 | | | | true | | - | | gender | int(4) | integer | 4 | | | | true | | - | | grade | int(4) | integer | 4 | | | | true | | - | | blood_type | varchar(4) | string | 4 | | | | true | | - +----|------------|------------------|-----------|-------|-----------|-------|---------|----------|---------+ - #+end_example - - In addition, =t= is also a class method of the model class. Executing =Person.t= will also print the above information. - - - Where: - - - =PK= : Whether it is a primary key - - =Name= : Column name - - =SQL Type= : Database type - - =Ruby Type= : Ruby type - - =Limit= : Length limit - - =Precision= : Precision - - =Scale= : Number of decimal places - - =Default= : Default value - - =Nullable= : Whether it can be empty - - =Comment= : Comment - -**** =vd= - - - The =t= command prints the table definition information in the terminal in the form of a table. The disadvantage - is that if the number of columns in the table is too large, it will cause the table to wrap, which is not - convenient to view. =vd= (visidata) is a terminal data analysis tool written in Python, which can print the table - definition information in the terminal in the form of a table, but supports horizontal scrolling, which is - convenient for viewing. - - If you want to use the =vd= command of Arql, you need to install visidata first: - - #+begin_src sh - pipx install visidata - #+end_src - - - The =vd= command and usage are basically the same as the =t= command. In addition, objects such as =Array= / - =ActiveRecord::Base= can also use the =vd= method. - **** =show-sql= / =hide-sql= - This pair of commands can switch the display of SQL logs in the Pry REPL. + This pair of commands toggles the display of SQL logs in the Pry REPL. By default, SQL logs are not displayed: #+begin_example ARQL@demo247(main) [2] ❯ Student.count => 0 #+end_example - After opening the SQL log, the SQL statement executed each time will be displayed: + When you open the SQL log, you will see the SQL statement that was executed each time: #+begin_example ARQL@demo247(main) [3] ❯ show-sql ARQL@demo247(main) [4] ❯ Student.count D, [2024-04-07T13:31:32.053903 #20440] DEBUG -- : Student Count (29.8ms) SELECT COUNT(*) FROM `student` => 0 #+end_example **** =reconnect= - The =reconnect= command is used to reconnect the current database connection. When the connection is disconnected - due to network reasons, you can use this command to reconnect. When reconnecting, the objects in the current Pry - session will not be lost. =reconnect= first checks whether the current connection is still valid. If it is valid, - it will not reconnect. If the validity judgment of =reconnect= for the connection is wrong, you can use the - =reconnect!= command to force a reconnection. + =reconnect= The command is used to reconnect the current database connection. When the connection is lost due to network + reasons, you can use the command to reconnect. reconnect, the objects in the current Pry session are not lost. + =reconnect= First, it will determine whether the current connection is still valid, if it is valid, it will not be + reconnected, if =reconnect= the validity of the connection is wrong, you can use =reconnect!= the command to force a + reconnection. **** =redefine= - The =redefine= command is used to redefine the ActiveRecord model class and regenerate the model class based on - the information of the database table. If you have added new relationship definitions in =init.rb= and want the - new definitions to take effect in the current Pry session, you can use the =redefine= command. -**** Sandbox + =redefine= The command is used to redefine the ActiveRecord model class, which regenerates the model class based on the + information from the database table. =init.rb= If you want a new relationship definition to take effect in the current + Pry session, you can use =redefine= the command. - The =sandbox-enter= command is used to enable sandbox mode. In sandbox mode, all database operations are executed - in a transaction, and the transaction is not automatically committed. You need to manually commit or roll back. +**** =sandbox-enter= 和 =sandbox-quit= - 1. Enter sandbox mode: + =sandbox-enter= command to turn on sandbox mode. In sandbox mode, all database operations are executed in a + transaction, which is not automatically committed, and is automatically rolled back when exiting sandbox mode. + + 1. Turn on sandbox mode: + #+begin_example - ARQL@demo247(main) [6] ❯ sandbox-enter - ARQL@demo247 [sandbox] (main) [7] ❯ + ARQL@demo247(main) [6] ❯ sandbox-enter + ARQL@demo247 [sandbox] (main) [7] ❯ #+end_example - 2. Quit sandbox mode: + + 2. To exit sandbox mode: + #+begin_example - ARQL@demo247 [sandbox] (main) [7] ❯ sandbox-quit - begin_transaction callbacks removed. - You still have open 1 transactions open, don't forget commit or rollback them. + ARQL@demo247 [sandbox] (main) [7] ❯ sandbox-quit #+end_example - 3. Commit the transaction: - #+begin_example - ARQL@demo247(main) [7] ❯ $C.commit_transaction - #+end_example - 4. Roll back the transaction: - #+begin_example - ARQL@demo247(main) [7] ❯ $C.rollback_transaction - #+end_example -*** Use Arql as Code Interpreter +*** Use as a Code Interpreter + If a Ruby file is specified as a command-line argument, or if the option is used =-E= , or if STDIN is not a =tty= , + then Arql will not start Pry, but will simply execute the specified file or code snippet (or read code from standard + input). The model class definition is loaded before the code snippet is executed. You can think of this usage as + something like a =runner= subcommand =rails= of . - If a Ruby file is specified as a command-line parameter, or the =-E= option is used, or STDIN is not a tty, Arql - will not start Pry, but will directly execute the specified file or code snippet (or read code from standard - input). Before executing the code snippet, the model class definition will be loaded first. You can think of this - usage as similar to the =runner= subcommand of =rails=. +**** Use =-E= the option -**** Use =-E= option + The =-E= option allows you to execute the code snippet directly without starting Pry: - The =-E= option can be used to execute code snippets directly without starting Pry: - #+begin_example $ arql -e dev -E 'puts Person.count' #+end_example -**** Pass a Ruby file as a command-line parameter +**** Specify a Ruby file as a command-line argument - By specifying a Ruby file as a command-line parameter, you can directly execute the code in the Ruby file: + By specifying a Ruby file as a command-line argument, you can execute code directly from a Ruby file: =test.rb=: #+BEGIN_SRC ruby puts Person.count @@ -423,38 +452,92 @@ #+begin_example $ arql -e dev test.rb #+end_example -**** Read code from standard input +**** Read the code from the standard input - Reading code from standard input, you can directly execute code snippets: + Reading code from standard input, the code snippet can be executed directly: #+begin_example $ echo 'puts Person.count' | arql -e dev #+end_example -*** Additional extensions -**** =to_insert_sql= / =to_upsert_sql= +** Additional Extension Methods +*** Module Methods for Namespace Modules +**** =q= + =q= Used to execute SQL queries - You can call the =to_insert_sql= / =to_upsert_sql= method on any ActiveRecord model instance to get the insert or - update SQL statement for the object. These two methods can also be called on an array object containing ActiveRecord - model instance objects. + #+begin_example + ARQL ❯ rs = Blog::q 'select count(0) from person;' + => #<ActiveRecord::Result:0x00007fd1f8026ad0 @column_types={}, @columns=["count(0)"], @hash_rows=nil, @rows=[[11]]> + ARQL ❯ rs.rows + => [[11]] + #+end_example +**** =models= + + =models= Returns all model classes in that namespace + #+begin_example - ARQL ❯ Person.all.to_a.to_insert_sql - => "INSERT INTO `person` (`id`,`name`,`age`,`gender`,`grade`,`blood_type`) VALUES (1, 'Jack', 30, NULL, NULL, NULL), (2, 'Jack', 11, 1, NULL, NULL), (3, 'Jack', 12, 1, NULL, NULL), (4, 'Jack', 30, 1, NULL, NULL), (5, 'Jack', 12, 2, NULL, NULL), (6, 'Jack', 2, 2, 2, NULL), (7, 'Jack', 3, 2, 2, NULL), (8, 'Jack', 30, 2, 2, 'AB'), (9, 'Jack', 30, 2, 2, 'AB'), (10, 'Jack', 30, 2, 2, 'AB'), (11, 'Jackson', 30, 2, 2, 'AB') ON DUPLICATE KEY UPDATE `id`=`id`;" + ARQL ❯ Blog::models + => [Blog::Person(id: integer, name: string, age: integer, created_at: datetime, updated_at: datetime), Blog::Post(id: integer, title: string, content: text, created_at: datetime, updated_at: datetime)] #+end_example +**** =tables= + =tables= Returns all table names in the namespace + + #+begin_example + ARQL ❯ Blog::tables + => ["people", "posts"] + #+end_example + +**** =model_names= + + =model_names= Returns the names of all model classes in that namespace + + #+begin_example + ARQL ❯ Blog::model_names + => ["Demo::Person", "Demo::Post"] + #+end_example + +**** =create_table= + + =create_table= Used to create tables in the environment corresponding to the namespace + + #+begin_example + ARQL ❯ Blog::create_table :people do |t| + ARQL ❯ t.string :name + ARQL ❯ t.integer :age + ARQL ❯ t.timestamps + ARQL ❯ end + #+end_example + +**** =dump= + + =dump= Export =mysqldump= the database corresponding to the namespace to the specified file with + + #+begin_example + ARQL ❯ Blog::dump('~/data/blog.sql') + #+end_example +*** Class Methods for Models + + Pry has built-in =show-source= (alias =$= ) and =show-doc= (alias =?= ) commands to view the source code and + documentation of the method. You can =show-doc= view the documentation for the method through . For example: + + #+begin_example + ARQL ❯ ? Student.add_column + #+end_example + **** =to_create_sql= - You can call the =to_create_sql= method on any ActiveRecord model class to get the create SQL statement for the table - corresponding to the model class. + You can call =to_create_sql= the method on any ActiveRecord model class to get the SQL statement that creates the + table corresponding to that model class. #+begin_example - ARQL@demo247(main) [16] ❯ puts Post.to_create_sql + ARQL@demo247(main) [16] ❯ puts Blog::Post.to_create_sql D, [2024-04-07T14:15:11.106693 #20440] DEBUG -- : SQL (24.9ms) show create table post CREATE TABLE `post` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `name` varchar(256) DEFAULT NULL, `gender` varchar(256) DEFAULT NULL, @@ -468,14 +551,194 @@ ) ENGINE=InnoDB AUTO_INCREMENT=83 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci #+end_example **** =t= - =t= can be called as a class method on an ActiveRecord model class, or as an instance method on an ActiveRecord model - instance object. + =t= The class method is used to print the table structure of a model class + + + Executing the =Blog::Person.t= command prints the =person= definition information for the table: + #+begin_example + Table: person + +----|------------|------------------|-----------|-------|-----------|-------|---------|----------|---------+ + | PK | Name | SQL Type | Ruby Type | Limit | Precision | Scale | Default | Nullable | Comment | + +----|------------|------------------|-----------|-------|-----------|-------|---------|----------|---------+ + | Y | id | int(11) unsigned | integer | 4 | | | | false | | + | | name | varchar(64) | string | 64 | | | | true | | + | | age | int(11) | integer | 4 | | | | true | | + | | gender | int(4) | integer | 4 | | | | true | | + | | grade | int(4) | integer | 4 | | | | true | | + | | blood_type | varchar(4) | string | 4 | | | | true | | + +----|------------|------------------|-----------|-------|-----------|-------|---------|----------|---------+ + #+end_example + + + =t= Accept an optional =format= named parameter with the following values: + + - =md= + - =org= + - =sql= + - =terminal= (default) + + 例如: + + #+begin_example + ARQL ❯ Blog::Person.t :sql + #+end_example + + 输出: + + #+begin_example + CREATE TABLE `person` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(64) DEFAULT NULL, + `age` int(11) DEFAULT NULL, + `gender` int(4) DEFAULT NULL, + `grade` int(4) DEFAULT NULL, + `blood_type` varchar(4) DEFAULT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='人员表'; + #+end_example + +**** =v= + + + =v= Class methods are used to integrate with Emacs' org babel, and can be called =v= directly in the org file to + obtain the table structure of the model class. + + 例如: + + #+begin_example + ARQL ❯ Blog::Post.v + #+end_example + + 输出: + + #+begin_example + ARQL@demo247(main) [10] ❯ Demo::Post.v + => [["PK", "Name", "SQL Type", "Ruby Type", "Limit", "Precision", "Scale", "Default", "Nullable", "Comment"], + nil, + ["Y", "id", "int(10) unsigned", :integer, 4, "", "", "", false, "ID"], + ["", "name", "varchar(256)", :string, 256, "", "", "", true, ""], + ["", "gender", "varchar(256)", :string, 256, "", "", "", true, ""], + ["", "phone", "varchar(256)", :string, 256, "", "", "", true, ""], + ["", "id_no", "varchar(256)", :string, 256, "", "", "", true, ""], + ["", "note", "varchar(256)", :string, 256, "", "", "", true, ""], + ["", "gmt_created", "datetime", :datetime, "", 0, "", "", false, "创建时间"], + ["", "gmt_modified", "datetime", :datetime, "", 0, "", "", false, "最后修改时间"], + ["", "sasa", "varchar(255)", :string, 255, "", "", "", true, ""]] + #+end_example + +**** =vd= + + + Use the =visidata= display table structure + +**** =table_comment= + + Returns table annotations for the model + + 例如: + + #+begin_example + ARQL ❯ Blog::Post.table_comment + #+end_example + + 输出: + + #+begin_example + "文章表" + #+end_example + +**** Add a field =add_column= + + #+begin_example + Blog::Student.add_column :note, :text, comment: 'Remarks' + #+end_example + +**** Modify Fields =change_column= + + #+begin_example + Blog::Student.change_column :note, :string, comment: 'Remarks' + #+end_example + +**** Delete the field =remove_column= + + #+begin_example + Blog::Student.remove_column :note + #+end_example + +**** Add an index =add_index= + + #+begin_example + Blog::Student.add_index :name + Blog::Student.add_index [:branch_id, :party_id], unique: true, name: 'by_branch_party' + #+end_example + +**** Modify field comments =change_column_comment= + + #+begin_example + Blog::Student.change_column_comment :note, 'Remarks' + #+end_example + +**** Modify the field defaults =change_column_default= + + #+begin_example + Blog::Student.change_column_default :note, 'A note' + #+end_example + +**** Modify the field name =rename_column= + + #+begin_example + Blog::Student.rename_column :note, :remark + #+end_example + +**** Modify the table name =rename_table= + + #+begin_example + Blog::Student.rename_table :seitou + #+end_example + +**** Modify table comments =change_table_comment= + + #+begin_example + Blog::Student.change_table_comment from: '', to: 'students table' + #+end_example + +**** Delete the table =drop_table= + + #+begin_example + Blog::Student.drop_table + #+end_example + +**** Delete the index =remove_index= + + #+begin_example + Blog::Student.remove_index :age + Blog::Student.remove_index name: 'by_branch_party' + #+end_example + +**** Query Table Comments =table_comment= + + #+begin_example + Blog::Student.table_comment + #+end_example + +**** Lists the indexes =indexes= of the table + + #+begin_example + Blog::Student.indexes + #+end_example +*** Instance Methods for Models +**** =t= + + =t= In addition to being called as a class method on an ActiveRecord model class, it can also be called as an instance + method on an ActiveRecord model instance object. + + #+begin_example ARQL ❯ Person.last.t +----------------|-----------------|------------------|---------+ | Attribute Name | Attribute Value | SQL Type | Comment | +----------------|-----------------|------------------|---------+ | id | 11 | int(11) unsigned | | @@ -485,37 +748,51 @@ | grade | 2 | int(4) | | | blood_type | AB | varchar(4) | | +----------------|-----------------|------------------|---------+ #+end_example - The =t= method can accept the following two options: + =t= The method can accept the following two options: - + =:except= option, used to specify the attribute names that are not displayed. The value can be a string or a regular - #+BEGIN_EXAMPLE - Person.last.t(except: 'id') - Student.where(condition).t(except: /id|name/) - #+END_EXAMPLE - + =:compact= option, used to specify whether to display in compact mode. The value can be =true= or =false=. If compact - mode is enabled, columns with all NULL values will not be displayed. This is useful for viewing tables with sparse + - =:compact= option to specify whether to display compactly, the value can be =true= or =false= , if compact display is + enabled, those =NULL= columns with all values will not be displayed, which is useful for viewing tables with sparse + data, such as: - #+BEGIN_EXAMPLE - Person.last.t(compact: true) - Student.where(condition).t(compact: false) - #+END_EXAMPLE + #+begin_example + Person.last.t(compact: true) + Student.where(condition).t(compact: false) + #+end_example + - =:format= option, which is used to specify the output format, the value can be: + - =:terminal= The default output format is suitable for viewing in the terminal + - =:org= org-mode table format + - =:md= Markdown table format + +**** =to_insert_sql= / =to_upsert_sql= + + + You can call =to_insert_sql= the / =to_upsert_sql= method on any instance of the ActiveRecord model to get the insert or + update SQL statement for that object. These two methods can also be called on an array object that contains an + ActiveRecord model instance object. + + #+begin_example + ARQL ❯ Person.all.to_a.to_insert_sql + => "INSERT INTO `person` (`id`,`name`,`age`,`gender`,`grade`,`blood_type`) VALUES (1, 'Jack', 30, NULL, NULL, NULL), (2, 'Jack', 11, 1, NULL, NULL), (3, 'Jack', 12, 1, NULL, NULL), (4, 'Jack', 30, 1, NULL, NULL), (5, 'Jack', 12, 2, NULL, NULL), (6, 'Jack', 2, 2, 2, NULL), (7, 'Jack', 3, 2, 2, NULL), (8, 'Jack', 30, 2, 2, 'AB'), (9, 'Jack', 30, 2, 2, 'AB'), (10, 'Jack', 30, 2, 2, 'AB'), (11, 'Jackson', 30, 2, 2, 'AB') ON DUPLICATE KEY UPDATE `id`=`id`;" + #+end_example + **** =v= - The =v= method is used to integrate with Emacs org babel. -***** =v= as instance method + =v= method is used to integrate with Emacs org babel. +***** =v= as an instance method for a model class - Call the =v= method on any ActiveRecord model instance object to print an array. The first element of the array is - =['Attribute Name', 'Attribute Value', 'SQL Type', 'Comment']=, the second element is =nil=, and the remaining elements - are the attribute names and values of the object. In Emacs org-mode, if the =:result= type is =value= (the default), this - return value will be rendered as a beautiful table. + Calling =v= the method on any ActiveRecord model instance object prints an array of the first element of the array + =['Attribute Name', 'Attribute Value', 'SQL Type', 'Comment']= , the second element =nil= , and the remaining + elements of the object's property name and value. In Emacs org-mode, if =:result= the type is =value= (the default), + this return value will be rendered as a nice table. + #+begin_example ARQL ❯ Person.last.v => [["Attribute Name", "Attribute Value", "SQL Type", "Comment"], nil, ["id", 11, "int(11) unsigned", ""], @@ -524,11 +801,11 @@ ["gender", 2, "int(4)", ""], ["grade", 2, "int(4)", ""], ["blood_type", "AB", "varchar(4)", ""]] #+end_example -***** Array containing only model instances +***** An array that contains only model instances #+begin_example ARQL ❯ Person.all.to_a.v => [["id", "name", "age", "gender", "grade", "blood_type"], nil, @@ -543,575 +820,487 @@ [9, "Jack", 30, 2, 2, "AB"], [10, "Jack", 30, 2, 2, "AB"], [11, "Jackson", 30, 2, 2, "AB"]] #+end_example -***** Array containing only homogeneous Hash objects +***** An array containing only homogeneous hash objects #+begin_example ARQL ❯ arr = [{name: 'Jack', age: 10}, {name: 'Lucy', age: 20}] => [{:name=>"Jack", :age=>10}, {:name=>"Lucy", :age=>20}] ARQL ❯ arr.v => [[:name, :age], nil, ["Jack", 10], ["Lucy", 20]] #+end_example -**** =q= +**** =dump= - #+begin_example - ARQL ❯ rs = q 'select count(0) from person;' - => #<ActiveRecord::Result:0x00007fd1f8026ad0 @column_types={}, @columns=["count(0)"], @hash_rows=nil, @rows=[[11]]> - ARQL ❯ rs.rows - => [[11]] - #+end_example -**** JSON conversion and formatting + To export the instance object as =INSERT= a SQL statement, see the "dump data" section below - Call the =j= method on any object to get a JSON-formatted string, and call the =jj= method to get a formatted JSON string. +**** =write_excel= / =write_csv= - Use the =jp= method to print JSON and the =jjp= method to print formatted JSON. -**** The =$C= Global Variables + To export the instance object as an Excel or CSV file, see the "Reading and Writing Excel and CSV Files" section below +*** =ActiveRecord::Relation= / =ActiveRecord::Result= / =Ransack::Search= / =Array= + =ActiveRecord::Relation= / =ActiveRecord::Result= / =Ransack::Search= Logically they can all be thought of as arrays, so + these methods can be called on these objects: - Arql assigns the =ActiveRecord::Base.connection= object to the globally available =$C= global variable, which represents the +**** =t= + =t= Methods can also be called on an array that contains an ActiveRecord instance, or on a =ActiveRecord::Relation= / + =ActiveRecord::Result= / =Ransack::Search= object. - The =q= method mentioned above is actually the =$C.exec_query= method. Other methods of the =$C= object are also useful: + #+begin_example + ARQL ❯ Person.last(2).t + +----+----------+--------+----------------------------------+-------+------+---------------------------+---------------------------+ + | id | name | gender | id_no | phone | note | gmt_created | gmt_modified | + +----+----------+--------+----------------------------------+-------+------+---------------------------+---------------------------+ + | 90 | Zhangsan | M | f09288fb381cc47dd2e56389cf15f0bf | | | 2021-04-26 15:32:05 +0800 | 2021-04-26 15:32:05 +0800 | + | 91 | Lisi | F | fb6fea4b23b1d3c54739774946246e4c | | | 2021-04-26 15:32:05 +0800 | 2021-04-26 15:32:05 +0800 | + +----+----------+--------+----------------------------------+-------+------+---------------------------+---------------------------+ + #+end_example -***** Create Table - #+begin_example - ARQL ❯ $C.create_table :post, id: false, primary_key: :id do |t| - ARQL ❯ t.column :id, :bigint, precison: 19, comment: 'ID' - ARQL ❯ t.column :name, :string, comment: '名称' - ARQL ❯ t.column :gmt_created, :datetime, comment: '创建时间' - ARQL ❯ t.column :gmt_modified, :datetime, comment: '最后修改时间' - ARQL ❯ end - #+end_example - The =create_table= method is also added to the =Kernel= module, so you can also call the =create_table= method directly: + When used as an array and "array-like" object instance method, =t= the method can accept multiple parameters for + filtering attributes, which can be: - #+begin_example - ARQL ❯ create_table :post, id: false, primary_key: :id do |t| - ARQL ❯ t.column :id, :bigint, precison: 19, comment: 'ID' - ARQL ❯ t.column :name, :string, comment: '名称' - ARQL ❯ t.column :gmt_created, :datetime, comment: '创建时间' - ARQL ❯ t.column :gmt_modified, :datetime, comment: '最后修改时间' - ARQL ❯ end - #+end_example + - string or Symbol, which literally matches the property + - Regular expressions to make regular matches to attributes -***** Add Column - #+begin_example - $C.add_column :post, :note, :string, comment: 'the note' - #+end_example + For example, only =name= show , =gender= and all properties whose names contain the =time= word : - The =add_column= method is also added to the class methods of the model class, so you can also call the - =add_column= method directly on the model class: + #+begin_example + ARQL ❯ Person.last(2).t('name', :gender, /time/i) + #+end_example - #+begin_example - Post.add_column :note, :string, comment: 'the note' - #+end_example -***** Change Column + As an example of an array and an Array-like object, =t= the following three options can also be accepted: - #+begin_example - $C.change_column :post, :note, :text, comment: '备注' - #+end_example + - =:except= option, which allows you to specify a property name that is not displayed, and the value can be a string + or a regular expression, for example: - The =change_column= method is also added to the class methods of the model class, so you can also call the - =change_column= method directly on the model class: + #+begin_example + Person.last(10).t(except: 'id') + Student.where(condition).t(except: /id|name/) + #+end_example - #+begin_example - Post.change_column :note, :text, comment: '备注' - #+end_example + - =:compact= option to specify whether to display compactly, the value can be =true= or =false= , if compact display + is enabled, those =NULL= columns with all values will not be displayed, which is useful for viewing tables with + sparse data, such as: -***** Remove Column + #+begin_example + Person.last(10).t(compact: true) + Student.where(condition).t(compact: false) + #+end_example - #+begin_example - $C.remove_column :post, :note - #+end_example + - =:format= option, which is used to specify the output format, the value can be: + - =:terminal= The default output format is suitable for viewing in the terminal + - =:org= org-mode table format + - =:md= Markdown table format - The =remove_column= method is also added to the class methods of the model class, so you can also call the - =remove_column= method directly on the model class: +**** =v= - #+begin_example - Post.remove_column :note - #+end_example -***** Drop Table + =v= method is used to integrate with Emacs org babel. - #+begin_example - $C.drop_table :post - #+end_example + #+begin_example + ARQL ❯ Person.last.v + => [["Attribute Name", "Attribute Value", "SQL Type", "Comment"], + nil, + ["id", 11, "int(11) unsigned", ""], + ["name", "Jackson", "varchar(64)", ""], + ["age", 30, "int(11)", ""], + ["gender", 2, "int(4)", ""], + ["grade", 2, "int(4)", ""], + ["blood_type", "AB", "varchar(4)", ""]] + #+end_example - The =drop_table= method is also added to the class methods of the model class, so you can also call the - =drop_table= method directly on the model class: +**** =vd= - #+begin_example - Post.drop_table - #+end_example -***** Add Index + Use to =visidata= display "array" data - #+begin_example - ARQL ❯ $C.add_index :post, :name - ARQL ❯ $C.add_index(:accounts, [:branch_id, :party_id], unique: true, name: 'by_branch_party') - #+end_example +**** =write_csv= / =write_excel= - The =add_index= method is also added to the class methods of the model class, so you can also call the - =add_index= method directly on the model class: - #+begin_example - Post.add_index :name - Post.add_index [:branch_id, :party_id], unique: true, name: 'by_branch_party' - #+end_example + =write_csv= and =write_excel= Used to export Array data to CSV or Excel files, see the "Reading and Writing Excel and + CSV Files" section below -**** Kernel Extensions +**** =dump= - The functions under the =Kernel= module can be called directly like built-in functions without specifying the module name. - The following are the =Kernel= methods extended by Arql: - Pry has built-in =show-source= (alias =$= ) and =show-doc= (alias =?= ) commands to view the source code and documentation of methods. You can view the documentation of a method using =show-doc=. For example: + =dump= The method is used to export the ActiveRecord::Relation / ActiveRecord::Result / Ransack::Search object as an + INSERT SQL statement, see the "dump data" section below +*** Extension =Kernel= Methods + + The following methods corresponding to a DDL operation have a limitation when used: if multiple environments are + connected, the environment name must be specified via =:env= the option when calling these methods. For example: + #+begin_src ruby + create_table :users, env: 'development', comment: 'the user table' do |t| + t.string :name, comment: 'User Name' + t.integer :age, comment: 'User Age' + end + #+end_src - #+BEGIN_EXAMPLE - ARQL ❯ ? create_table - #+END_EXAMPLE +**** Create a table =create_table= + #+begin_example + create_table :post, id: false, primary_key: :id do |t| + t.column :id, :bigint, precison: 19, comment: 'ID' + t.column :name, :string, comment: 'Post Name' + t.column :gmt_created, :datetime, comment: 'Created Time' + t.column :gmt_modified, :datetime, comment: 'Modified Time' + end + #+end_example -***** =create_table= - #+BEGIN_EXAMPLE - create_table :post, id: false, primary_key: :id do |t| - t.column :id, :bigint, precison: 19, comment: 'ID' - t.column :name, :string, comment: '名称' - t.column :gmt_created, :datetime, comment: '创建时间' - t.column :gmt_modified, :datetime, comment: '最后修改时间' - end - #+END_EXAMPLE -***** =create_join_table= - #+BEGIN_EXAMPLE - create_join_table :products, :categories do |t| - t.index :product_id - t.index :category_id - end - #+END_EXAMPLE -***** =drop_table= - #+BEGIN_EXAMPLE - drop_table :post - #+END_EXAMPLE -***** =drop_join_table= - #+BEGIN_EXAMPLE - drop_join_table :products, :categories - #+END_EXAMPLE -***** =rename_table= - #+BEGIN_EXAMPLE - rename_table :post, :posts - #+END_EXAMPLE +**** Create an intermediate table =create_join_table= for many-to-many relationships -***** =print_tables= + #+begin_example + create_join_table :products, :categories do |t| + t.index :product_id + t.index :category_id + end + #+end_example - Arql provides a =print_tables= method that exports information about all tables in the current database as: +**** Delete the table =drop_table= - + markdown table format: ~print_tables(:md)~ - + org-mode table format: ~print_tables(:org)~ - + create table SQL: ~print_tables(:sql)~ + #+begin_example + drop_table :post + #+end_example -**** Model Class Methods Extensions +**** Delete intermediate tables =drop_join_table= for many-to-many relationships - Arql adds some class methods to the model class for creating, modifying, and deleting columns, indexes, and other - operations on tables. These methods can be called directly on the model class without the need to call them - through an instance object of the =ActiveRecord::Migration= class. + #+begin_example + drop_join_table :products, :categories + #+end_example - Pry has built-in =show-source= (alias =$= ) and =show-doc= (alias =?= ) commands to view the source code and - documentation of methods. You can view the documentation of a method using =show-doc=. For example: +**** Modify the table name =rename_table= - #+BEGIN_EXAMPLE - ARQL ❯ ? Student.add_column - #+END_EXAMPLE + #+begin_example + rename_table :post, :posts + #+end_example -***** =add_column= - #+BEGIN_EXAMPLE - Student.add_column :note, :text, comment: '备注' - #+END_EXAMPLE +**** =models= -***** =change_column= - #+BEGIN_EXAMPLE - Student.change_column :note, :string, comment: '备注' - #+END_EXAMPLE + Returns the model classes that will be under all environment namespaces -***** =remove_column= - #+BEGIN_EXAMPLE - Student.remove_column :note - #+END_EXAMPLE +**** =table_names= -***** =add_index= - #+BEGIN_EXAMPLE - Student.add_index :name - Student.add_index [:branch_id, :party_id], unique: true, name: 'by_branch_party' - #+END_EXAMPLE + Returns table names for all environments -***** =change_column_comment= - #+BEGIN_EXAMPLE - Student.change_column_comment :note, '备注' - #+END_EXAMPLE +**** =model_names= -***** =change_column_default= - #+BEGIN_EXAMPLE - Student.change_column_default :note, '默认值' - #+END_EXAMPLE + Returns the model class names for all environments -***** =rename_column= - #+BEGIN_EXAMPLE - Student.rename_column :note, :remark - #+END_EXAMPLE +**** =q= -***** =rename_table= - #+BEGIN_EXAMPLE - Student.rename_table :seitou - #+END_EXAMPLE -***** =change_table_comment= - #+BEGIN_EXAMPLE - Student.change_table_comment from: '', to: '学生表' - #+END_EXAMPLE + If you specify only one environment, you can use =q= methods to execute native SQL queries without specifying a + namespace module =q= in =Blog::q= front of +*** Other Extension Methods -***** =drop_table= - #+BEGIN_EXAMPLE - Student.drop_table - #+END_EXAMPLE +**** JSON conversion and formatting -***** =remove_index= - #+BEGIN_EXAMPLE - Student.remove_index :age - Student.remove_index name: 'by_branch_party' - #+END_EXAMPLE + Calling =j= the method on any object will result in a JSON-formatted string, and the calling =jj= method will result in + a formatted JSON string. -***** =table_comment= - #+BEGIN_EXAMPLE - Student.table_comment - #+END_EXAMPLE + Use =jp= the method to print the JSON, and use the method to =jjp= print the formatted JSON. -***** =indexes= - #+BEGIN_EXAMPLE - Student.indexes - #+END_EXAMPLE +**** =String= -**** Read and Write Excel and CSV Files + 1. =Srting#p= + =p= The method is defined as follows: + #+begin_example + class String + def p + puts self + end + end + #+end_example + =​"hello".p= Equivalent to =puts "hello"​= . - Arql integrates two Excel libraries, =roo= and =caxlsx= to provide methods for parsing and generating Excel files. - Arql also provides methods for reading and writing CSV files. + 2. =String#parse= + For a string representing a file path, you can call =parse= the method to parse Excel, CSV, and + JSON files by the suffix in the file path. + #+begin_example + excel = 'path/to/excel.xlsx'.parse + csv = 'path/to/csv.csv'.parse + json = 'path/to/json.json'.parse + #+end_example -***** Parse Excel +**** =ID= - Arql adds a =parse_excel= method to the =Kernel= module, which can be used to parse Excel files. For example: - #+BEGIN_EXAMPLE - ARQL ❯ parse_excel 'path/to/excel.xlsx' - #+END_EXAMPLE + Arql provides a =ID= class that generates snowflake algorithm IDs and UUIDs. - You can use =~/= in the file path to represent the user's home directory, and Arql will automatically expand it. + #+begin_example + id = ID.long # Generate a snowflake algorithm ID + id = ID.uuid # Generate a UUID + #+end_example +*** Read and write Excel and CSV files - You can also call the =parse_excel= method on a String object representing a file path: + Arql integrates =caxlsx= with =roo= the and two Excel libraries, providing a way to parse and generate Excel files. Arql + also provides methods for reading and writing CSV files. - #+BEGIN_EXAMPLE - ARQL ❯ 'path/to/excel.xlsx'.parse_excel - #+END_EXAMPLE +**** Parse Excel - The =parse_excel= method returns a Hash object, where the key is the sheet name and the value is the data of the - sheet, which is a two-dimensional array. For example: + Arql adds =parse_excel= methods to the =Kernel= module that can be used to parse Excel files. For example: - #+BEGIN_EXAMPLE - { - 'Sheet1' => [ - ['A1', 'B1', 'C1'], - ['A2', 'B2', 'C2'], - ['A3', 'B3', 'C3'] - ], - 'Sheet2' => [ - ['A1', 'B1', 'C1'], - ['A2', 'B2', 'C2'], - ['A3', 'B3', 'C3'] - ] - } - #+END_EXAMPLE + #+BEGIN_EXAMPLE + ARQL ❯ parse_excel 'path/to/excel.xlsx' + #+END_EXAMPLE -***** Generate Excel + You can use in the file path to =~/= represent the user's home directory, and Arql will be automatically expanded. - Arql adds a =write_excel= method to Hash / Array / ActiveRecord::Relation / ActiveRecord::Base objects, which can - be used to generate Excel files: + You can also call =parse_excel= the Method on an object that represents the path to the =String= file: + #+BEGIN_EXAMPLE + ARQL ❯ 'path/to/excel.xlsx'.parse_excel + #+END_EXAMPLE -****** Genrate Excel from =Hash= Object + =parse_excel= The method returns an =Hash= object, Key is the name of the Sheet, Value is the data for the Sheet, and + Value is a two-dimensional array. For example: - #+BEGIN_EXAMPLE - ARQL ❯ obj.write_excel 'path/to/excel.xlsx' - #+END_EXAMPLE + #+BEGIN_EXAMPLE + { + 'Sheet1' => [ + ['A1', 'B1', 'C1'], + ['A2', 'B2', 'C2'], + ['A3', 'B3', 'C3'] + ], + 'Sheet2' => [ + ['A1', 'B1', 'C1'], + ['A2', 'B2', 'C2'], + ['A3', 'B3', 'C3'] + ] + } + #+END_EXAMPLE - =Hash#write_excel= requires that the key of the Hash object is the sheet name and the value is the data of the - sheet. The type of the value can be: +**** Generate Excel - + An array, where the elements of the array can be: - + An array, representing a row of data - + A Hash object, representing a row of data, where the key is the column name and the value is the column value - + An =ActiveRecord::Base= object, representing a row of data - + A Hash object, which contains two key-value pairs: - + =:fields=, an array representing the column names - + =:data=, a two-dimensional array representing the data + Arql adds a =write_excel= method for =Hash= the / =Array= / =ActiveRecord::Relation= =ActiveRecord::Base= / object, + which can be used to generate an Excel file: -****** Generate Excel from =Array= Object +***** Generate Excel from Hash objects - #+BEGIN_EXAMPLE - ARQL ❯ obj.write_excel 'path/to/excel.xlsx', :name, :age, :gender, sheet_name: '订单数据' - #+END_EXAMPLE + #+BEGIN_EXAMPLE + ARQL ❯ obj.write_excel 'path/to/excel.xlsx' + #+END_EXAMPLE - Where: + =Hash#write_excel= The key of the hash object is the name of the sheet, the value is the data of the sheet, and the type + of value can be: - + =:name, :age, :gender= These parameters are column names. If not specified, the column names will be determined - based on the first element of the array: - - If the element is an ActiveRecord::Base object, all attribute names of the object (i.e., the database field - list) will be used as column names - - If the element is a Hash object, all keys of the Hash will be used as column names - + =sheet_name= Specifies the sheet name. If not specified, the default sheet name =Sheet1= will be used + - An array, the elements of which can be: + - An array representing a row of data + - A hash object that represents a row of data, with Key being the column name and Value being the column value + - An ActiveRecord::Base object that represents a row of data + - A hash object that contains two key-value pairs: + - =:fields= , an array representing the column name + - =:data= , a two-dimensional array that represents data - Each element of the Array object represents a row of data. =Array#write_excel= requires that each element of the - Array object: +***** Generate Excel from Array objects - + An =ActiveRecord::Base= object - + A =Hash= object, representing a row of data, where the key is the column name and the value is the column value - + An array, representing a row of data + #+BEGIN_EXAMPLE + ARQL ❯ obj.write_excel 'path/to/excel.xlsx', :name, :age, :gender, sheet_name: 'Order Data' + #+END_EXAMPLE -****** Generate Excel from =ActiveRecord::Base= Object + Thereinto: - #+BEGIN_EXAMPLE - ARQL ❯ Student.find(123).write_excel 'path/to/excel.xlsx', sheet_name: '学生数据' - #+END_EXAMPLE + - =:name, :age, :gender= These parameters are column names, and if not specified, the column names will be determined + based on the first element of the array: + - If the element is =ActiveRecord::Base= an object, all of the object's property names (i.e., a list of database + fields) are used as the column names + - If the element is =Hash= an object, the All Keys are used =Hash= as the column name + - =sheet_name= Specify a sheet name, or if you don't =Sheet1= , the default sheet name is used - The =write_excel= method of =ActiveRecord::Base= actually wraps the =ActiveRecord::Base= object into an =Array= object with - only one element, and then calls the =write_excel= method of Array. -****** Generate Excel from =ActiveRecord::Relation= Object + =Array= Each element of the object represents a row of data, requiring =Array#write_excel= each element of the Array + object to: - #+BEGIN_EXAMPLE - ARQL ❯ Student.where(gender: 'M').write_excel 'path/to/excel.xlsx', sheet_name: '男学生' - #+END_EXAMPLE + - An =ActiveRecord::Base= object + - An =Hash= object that represents a row of data, with Key being the column name and Value being the column value + - An array representing a row of data - The =write_excel= method of =ActiveRecord::Relation= actually converts the =ActiveRecord::Relation= object into an Array - object, and then calls the =write_excel= method of =Array=. +***** Generate Excel from =ActiveRecord::Base= objects -***** Parse CSV - - Arql provides the =parse_csv= method, which can be used to parse CSV files: - #+BEGIN_EXAMPLE - ARQL ❯ parse_csv 'path/to/csv.csv' + ARQL ❯ Student.find(123).write_excel 'path/to/excel.xlsx', sheet_name: 'Student Data' #+END_EXAMPLE + =ActiveRecord::Base= The =write_excel= object is actually the method that wraps the =ActiveRecord::Base= object into an + object with =Array= only one element, and then calls =Array= the =write_excel= method. - The =parse_csv= method returns a CSV object in the standard library. +***** Generate Excel from =ActiveRecord::Relation= objects - =parse_csv= can have the following optional parameters: - - - =encoding=, specifies the encoding of the CSV file, which is =UTF-16= (with BOM) by default - - =headers=, specifies whether to include the header, which is =false= by default - - =col_sep=, specifies the column separator, which is =\t= by default - - =row_sep=, specifies the row separator, which is =\r\n= by default - - - (The default values above are actually the configurations used by Microsoft Office Excel when saving CSV files) - - - You can also call the =parse_csv= method on a String object representing the file path: - #+BEGIN_EXAMPLE - ARQL ❯ 'path/to/csv.csv'.parse_csv + ARQL ❯ Student.where(gender: 'M').write_excel 'path/to/excel.xlsx', sheet_name: 'Male Students' #+END_EXAMPLE + =ActiveRecord::Relation= The =write_excel= object is actually the =write_excel= method =Array= that converts the + =ActiveRecord::Relation= object into an =Array= object and then calls it. -***** Generate CSV +**** Parse CSV - Arql adds the =write_csv= method to =Array= / =ActiveRecord::Relation= / =ActiveRecord::Base= objects, which can be used to - generate CSV files: + Arql provides =parse_csv= methods that can be used to parse CSV files: -****** Generate CSV from =Array= Object + #+begin_example + ARQL ❯ parse_csv 'path/to/csv.csv' + #+end_example - #+BEGIN_EXAMPLE - ARQL ❯ obj.write_csv 'path/to/csv.csv', :name, :age, :gender, sheet_name: '订单数据' - #+END_EXAMPLE + =parse_csv= The method returns a CSV object from a standard library. - The usage is similar to the write_excel method of =Array= objects. + =parse_csv= There can be the following optional parameters: + - =encoding= , specifies the encoding of the CSV file, default is =UTF-16= (with BOM) + - =headers= , specifies whether to include a table header, which is the default value =false= + - =col_sep= to specify the column separator, which defaults to =\t= + - =row_sep= , specifies the row separator, which is =\r\n= the default -****** Generate CSV from =ActiveRecord::Base= Object + (The above default values are actually the default configuration used by Microsoft Office Excel when saving CSV files) - #+BEGIN_EXAMPLE - ARQL ❯ Student.find(123).write_csv 'path/to/csv.csv', sheet_name: '学生数据' - #+END_EXAMPLE + You can also call =parse_csv= the Method on an object that represents the path to the =String= file: - The usage is similar to the =write_excel= method of =ActiveRecord::Base= objects. + #+BEGIN_EXAMPLE + ARQL ❯ 'path/to/csv.csv'.parse_csv + #+END_EXAMPLE -****** Generate CSV from =ActiveRecord::Relation= Object +**** Generate a CSV + Arql adds a method for =Array= the / =ActiveRecord::Relation= / =ActiveRecord::Base= object, which can be used to + generate a CSV =write_csv= file: +***** Generate a CSV from an Array object - #+BEGIN_EXAMPLE - ARQL ❯ Student.where(gender: 'M').write_csv 'path/to/csv.csv', sheet_name: '男学生' - #+END_EXAMPLE - - - The usage is similar to the =write_excel= method of =ActiveRecord::Relation= objects. - -**** dump data from database - - Note: Only MySQL databases are supported - - Arql adds the =dump= method to =Array= / =ActiveRecord::Base= / =ActiveRecord::Relation= objects, which can be used to - export data to SQL files: - - -***** Dump data from =Array= Object - #+BEGIN_EXAMPLE - ARQL ❯ obj.dump 'path/to/dump.sql', batch_size: 5000 + ARQL ❯ obj.write_csv 'path/to/csv.csv', :name, :age, :gender, sheet_name: 'Order Data' #+END_EXAMPLE + The usage is similar to the =Array= object's =write_excel= method. - Each element of the =Array= object must be an =ActiveRecord::Base= object +***** Generate a CSV from an =ActiveRecord::Base= object - The =batch_size= parameter specifies the data queried in each batch, with a default value of 500 - -***** Dump data from =ActiveRecord::Base= Object - #+BEGIN_EXAMPLE - ARQL ❯ Student.find(123).dump 'path/to/dump.sql', batch_size: 5000 + ARQL ❯ Student.find(123).write_csv 'path/to/csv.csv', sheet_name: 'Student Data' #+END_EXAMPLE + The usage is similar to the =ActiveRecord::Base= object's =write_excel= method. - The =dump= method of =ActiveRecord::Base= objects actually wraps the =ActiveRecord::Base= object into an =Array= object - with only one element, and then calls the =dump= method of =Array=. +***** Generate a CSV from an =ActiveRecord::Relation= object -***** Dump data from =ActiveRecord::Relation= Object - #+BEGIN_EXAMPLE - ARQL ❯ Student.where(gender: 'M').dump 'path/to/dump.sql', batch_size: 5000 + ARQL ❯ Student.where(gender: 'M').write_csv 'path/to/csv.csv', sheet_name: 'Make Students' #+END_EXAMPLE + The usage is similar to the =ActiveRecord::Relation= object's =write_excel= method. - The =dump= method of =ActiveRecord::Relation= objects actually converts the =ActiveRecord::Relation= object into an =Array= object, - and then calls the =dump= method of Array. +*** dump data -***** Use the =dump= class method of =ActiveRecord::Base= + Note: Only MySQL databases are supported - #+BEGIN_EXAMPLE - ARQL ❯ Student.dump 'path/to/dump.sql', no_create_table: false - #+END_EXAMPLE - This method will export all data in the Student table to the SQL file using the =mysqldump= command. + Arql adds =dump= methods for objects such as =Array= / =ActiveRecord::Base= / =ActiveRecord::Relation= that can be used + to export data to a SQL file: - The =no_create_table= parameter specifies whether to include the create table statement in the SQL file, with a default value of =false=. +**** Export data from an Array object + #+begin_example + ARQL ❯ obj.dump 'path/to/dump.sql', batch_size: 5000 + #+end_example -***** Use the dump method on the global connection object =$C= + =Array= Each element of an object must be an =ActiveRecord::Base= object - #+BEGIN_EXAMPLE - ARQL ❯ $C.dump 'path/to/dump.sql', no_create_db: false - #+END_EXAMPLE + =batch_size= The parameter specifies the data queried out for each batch, and the default value is 500 - This method will export the data of all tables in the current database to the SQL file using the =mysqldump= command. +**** Export data from the ActiveRecord::Base object - The =no_create_db= parameter specifies whether to include the create database statement in the SQL file, with a default value of =false=. + #+begin_example + ARQL ❯ Student.find(123).dump 'path/to/dump.sql', batch_size: 5000 + #+end_example -**** Plot + =ActiveRecord::Base= An object's =dump= method is actually a =dump= method that wraps the =ActiveRecord::Base= object + into an =Array= object with only one element, and then calls =Array= the method. - Arql integrates the youplot library of Ruby and adds some methods to Array that can be used to draw charts: +**** Export data from the ActiveRecord::Relation object - + =barplot= - + =countplot= - + =histo= - + =lineplot= - + =lineplots= - + =scatter= - + =density= - + =boxplot= + #+begin_example + ARQL ❯ Student.where(gender: 'M').dump 'path/to/dump.sql', batch_size: 5000 + #+end_example - Example: - Count plot: + =ActiveRecord::Relation= The =dump= object is actually the =dump= method =Array= that converts the + =ActiveRecord::Relation= object into an =Array= object and then calls it. - #+BEGIN_EXAMPLE - ARQL@demo247(main) [44] ❯ Student.pluck(:gender) - => ["M", "M", "M", "M", "M", "M", "M", "F", "M", "F", "M", "M", "M", "M", "M"] - ARQL@demo247(main) [45] ❯ Student.pluck(:gender).countplot - ┌ ┐ - M ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 13.0 - F ┤■■■■■ 2.0 - └ ┘ - #+END_EXAMPLE +**** Call the dump class method of ActiveRecord::Base - Histo plot: + #+begin_example + ARQL ❯ Student.dump 'path/to/dump.sql', no_create_table: false + #+end_example - #+BEGIN_EXAMPLE - ARQL@jicai.dev(main) [18] ❯ Order.last(20).pluck(:order_sum) - => [0.21876e5, 0.336571e5, 0.1934e5, 0.966239e4, 0.38748e3, 0.31092e4, 0.483e5, 0.445121e5, 0.1305e4, 0.2296e6, 0.943e5, 0.352e4, 0.3756e5, 0.323781e5, 0.7937622e5, 0.982e4, 0.338393e5, 0.316597e5, 0.213678e5, 0.336845e5] - ARQL@jicai.dev(main) [19] ❯ Order.last(20).pluck(:order_sum).histo - ┌ ┐ - [ 0.0, 50000.0) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 17 - [ 50000.0, 100000.0) ┤▇▇▇▇ 2 - [100000.0, 150000.0) ┤ 0 - [150000.0, 200000.0) ┤ 0 - [200000.0, 250000.0) ┤▇▇ 1 - └ ┘ - Frequency - #+END_EXAMPLE + This method will export all the data in the =Student= table to a SQL file via =mysqldump= the command. -**** =String= -***** =Srting#p= + =no_create_table= parameter specifies whether to include a statement to create a table in the SQL file, and the + default value is =false= . - The definition of the =p= method is as follows: +*** Plot - #+begin_example - class String - def p - puts self - end - end - #+end_example + Arql integrates the youplot library of Ruby and adds some methods to Array that can be used to draw charts: + + =barplot= + + =countplot= + + =histo= + + =lineplot= + + =lineplots= + + =scatter= + + =density= + + =boxplot= - =​"hello".p= is equivalent to =puts "hello"​=. + Example: -***** =String#parse= + Count plot: - For a string representing a file path, you can call the =parse= method to parse Excel, CSV, and JSON files based - on the file extension in the file path. + #+BEGIN_EXAMPLE + ARQL@demo247(main) [44] ❯ Student.pluck(:gender) + => ["M", "M", "M", "M", "M", "M", "M", "F", "M", "F", "M", "M", "M", "M", "M"] + ARQL@demo247(main) [45] ❯ Student.pluck(:gender).countplot + ┌ ┐ + M ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 13.0 + F ┤■■■■■ 2.0 + └ ┘ + #+END_EXAMPLE - #+BEGIN_EXAMPLE - excel = 'path/to/excel.xlsx'.parse - csv = 'path/to/csv.csv'.parse - json = 'path/to/json.json'.parse - #+END_EXAMPLE + Histo plot: -**** =ID= + #+BEGIN_EXAMPLE + ARQL@jicai.dev(main) [18] ❯ Order.last(20).pluck(:order_sum) + => [0.21876e5, 0.336571e5, 0.1934e5, 0.966239e4, 0.38748e3, 0.31092e4, 0.483e5, 0.445121e5, 0.1305e4, 0.2296e6, 0.943e5, 0.352e4, 0.3756e5, 0.323781e5, 0.7937622e5, 0.982e4, 0.338393e5, 0.316597e5, 0.213678e5, 0.336845e5] + ARQL@jicai.dev(main) [19] ❯ Order.last(20).pluck(:order_sum).histo + ┌ ┐ + [ 0.0, 50000.0) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 17 + [ 50000.0, 100000.0) ┤▇▇▇▇ 2 + [100000.0, 150000.0) ┤ 0 + [150000.0, 200000.0) ┤ 0 + [200000.0, 250000.0) ┤▇▇ 1 + └ ┘ + Frequency - Arql provides an ID class for generating snowflake algorithm IDs and UUIDs. + #+END_EXAMPLE - #+BEGIN_EXAMPLE - id = ID.long # 生成一个雪花算法 ID - id = ID.uuid # 生成一个 UUID - #+END_EXAMPLE +*** Ransack -**** Ransack + Arql integrates Ransack: - Arql integrates Ransack: + #+BEGIN_EXAMPLE + Student.ransack(name_cont: 'Tom').result # query students whose name contains 'Tom' + Student.ransack(name_start: 'Tom').result # query students whose name starts with 'Tom' + #+END_EXAMPLE - #+BEGIN_EXAMPLE - Student.ransack(name_cont: 'Tom').result # 模糊查询名字中包含 'Tom' 的学生 - Student.ransack(name_start: 'Tom').result # 模糊查询名字以 'Tom' 开头的学生 - #+END_EXAMPLE - *** Emacs Org Babel Integration Here is an [[https://github.com/lululau/spacemacs-layers/blob/master/ob-arql/local/ob-arql/ob-arql.el][ob-arql]], which is used to integrate Emacs org babel. ** Guides and Tips @@ -1128,23 +1317,9 @@ You can use Arql to view SQLite3 database files, for example: #+BEGIN_EXAMPLE arql -d db/development.sqlite3 #+END_EXAMPLE - -*** Find fields by name or comment - - When we are familiar with a project, we often encounter the following situation: we know the name or comment of a - field, but we do not know the corresponding table name and field name. At this time, we can use the following method - to find: - - #+BEGIN_SRC ruby - puts model_classes.flat_map { |m| m.columns.select {|c| c.name =~ /amount/ || c.comment =~ /金额/ }.map {|c| "Table: #{m.table_name}, Column: #{c.name} (#{c.comment})"} } - - # 输出: - # Table: order, Column: entry_amount (订单金额) - # Table: sub_order, Column: entry_price (金额) - #+END_SRC ** Development After checking out the code, run =bin/setup= to install dependencies. You can also run =bin/console= for an interactive prompt that will allow you to experiment.