table_inspector 0.5.5 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83143bbf7fb6d4ce752da10da85b265037f75fad9417f104ab761660d638db1b
4
- data.tar.gz: 6268b3194f9eef7ec25c830cae63cad79d0fa29ed8b98f27c77049b450d31def
3
+ metadata.gz: a7b361cd6519e4f22acd13f7414daa56d361f83b2bc742679fd7413bc3a3e9d3
4
+ data.tar.gz: efebb7e0def5dc75c974a06d7504efaa462068d009438885c16d9a0e6ed73ba1
5
5
  SHA512:
6
- metadata.gz: 5e5df809d52919113556d0048e91e633663bcba444b4d2cff13919bb0670f01a51a9460de7789ef556f661c5fc25aa213eff3fb38547a0566331300cd17dd5f4
7
- data.tar.gz: a137cf1372c765da06bcfc459f4ab0d5b7f9e09f947bbaa0908c560f8cbea24e3e6ab45a5dad043527e7b6f57328d4541876f1acae10394faf2d5435888bf344
6
+ metadata.gz: cfb17c67a0091dbaccbad92a638bd22de4f7361458baf0bcc25902ce97709d6d15b69d7e01ec51112d5b649f2d89e1c24e762ce3dd2d536055ad9d1b8ab15fe8
7
+ data.tar.gz: dd4b194ebf0c45c0b76c18b447ca77460fc84cc74343673cfe250a561e381efc8bccabd4628ec46c2a42262745e7485d8861c498be8f81f2b2cff82d332bc6f4
data/README.md CHANGED
@@ -1,9 +1,34 @@
1
1
  # TableInspector
2
- This is a Rails gem that allows you to print the definition of a table. While some gems (like [annotate_models](https://github.com/ctran/annotate_models)) are used to embed the table schema in the model file, they can be difficult to maintain and add unnecessary noise. This gem provides an alternative way to check the schema of a table without using `annotate_models`.
2
+ ![Test coverage](https://img.shields.io/badge/Test_coverage-99.65-green)
3
+ ![Release version](https://img.shields.io/badge/Release-v0.6.0-green)
4
+ ![Workflow badge](https://github.com/otorain/table_inspector/actions/workflows/run_test.yml/badge.svg)
5
+
6
+ This is a Rails gem that allows you to print the structure of a database table by providing a model class.
7
+ It functions similar to [annotate_models](https://github.com/ctran/annotate_models), but offers an alternative way to checking the table schema.
8
+ The print function is based on [terminal-table](https://github.com/tj/terminal-table)
9
+
10
+ This doc is about version 0.6.0. For version 0.5.0, please see [here](https://github.com/otorain/table_inspector/tree/v0.5.5)
11
+
12
+ ## Installation
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem "table_inspector", "~> 0.6.0"
17
+ ```
18
+
19
+ And then execute:
20
+ ```bash
21
+ $ bundle
22
+ ```
23
+
24
+ Or install it yourself as:
25
+ ```bash
26
+ $ gem install table_inspector
27
+ ```
3
28
 
4
29
  ## Usage
5
30
  Assuming there is a model call `User` which has `id` and `name` column, and has a unique index for `name`.
6
- For print the definition of User, we can use:
31
+ For print the table structure of User, we can use:
7
32
  ```ruby
8
33
  require "table_inspector"
9
34
 
@@ -12,7 +37,9 @@ TableInspector.scan User
12
37
 
13
38
  ![TableInspect scan table](/img/table_inspector_scan_table_3.png)
14
39
 
15
- It will print the all table definition and all indexes.
40
+ It will print the scheme of table and indexes.
41
+ (If the table content is too long, It may be printed messy. You can adjust the scaling of the terminal window to fix it.
42
+ Alternatively, you can use `TableInspector.scan(User, :name)` to print a specific column)
16
43
 
17
44
  Or you can use `TableInspector.ascan` to print more colorful table(`ascan` means `awesome scan`) :
18
45
  ```ruby
@@ -29,29 +56,57 @@ TableInspector.scan User, :name
29
56
 
30
57
  It will print the column definition and which indexes that contains this column.
31
58
 
32
- Also, you can print `sql_type` which type of column in database by provide `sql_type: true` option:
59
+ **It is recommended to include `TableInspector::Inspectable` in `app/models/application_record.rb` and use `ti` or `ati` method to print the table definition: **
60
+ ```ruby
61
+ # app/models/application_record.rb
62
+ class ApplicationRecord < ActiveRecord::Base
63
+ self.abstract_class = true
64
+
65
+ # Add this line
66
+ include TableInspector::Inspectable
67
+
68
+ # ...
69
+ end
70
+ ```
71
+ and call:
72
+ ```ruby
73
+ # Same as TableInspector.scan User
74
+ User.ti
33
75
 
76
+ # Same as TableInspector.ascan User
77
+ User.ati
78
+ ```
79
+ The module `TableInspector::Inspectable` only defines two class methods: `ti` and `ati`, which delegate to `TableInspector.scan` and `TableInspector.ascan` respectively.
80
+
81
+ You can print the database column type by providing the `sql_type: true` option:
34
82
  ```ruby
83
+ User.ti sql_type: true
84
+ # or
35
85
  TableInspector.scan User, sql_type: true
36
86
  ```
37
87
  ![Table Inspector scan table column with sql type](/img/table_inspector_scan_table_with_sql_type_3.png)
38
88
 
39
- ## Installation
40
- Add this line to your application's Gemfile:
41
-
89
+ To print comment column only for the table, use `comment_only: true` option:
42
90
  ```ruby
43
- gem "table_inspector"
91
+ User.ti comment_only: true
92
+ # or
93
+ TableInspector.scan User, comment_only: true
44
94
  ```
95
+ ![Table Inspector scan table comment only](/img/table_inspector_scan_table_comment_only.png)
96
+ If the `sql_type: true` option is also provided, the sql_type option will be omitted.
45
97
 
46
- And then execute:
47
- ```bash
48
- $ bundle
49
- ```
98
+ ## Style
99
+ You can change the style of the table by setting the `TableInspector.style` in `config/initalizers/table_inspector.rb`(create it if not exists):
100
+ ```ruby
101
+ # config/initializers/table_inspector.rb
50
102
 
51
- Or install it yourself as:
52
- ```bash
53
- $ gem install table_inspector
103
+ TableInspector.style = { border: :unicode }
104
+ # TableInspector.style = { border: :ascii } # default border style
105
+ # TableInspector.style = { border: :unicode_round }
106
+ # TableInspector.style = { border: :unicode_thick_edge }
107
+ # TableInspector.style = { border: :markdown }
54
108
  ```
109
+ You can use other options available in `TerminalTable#style` of the [terminal-table](https://github.com/tj/terminal-table)
55
110
 
56
111
  ## Contributing
57
112
  Contribution directions go here.
@@ -1,37 +1,42 @@
1
1
 
2
2
  module TableInspector
3
3
  class Column
4
- attr_reader :column, :klass, :sql_type, :presenter
4
+ attr_reader :column, :klass, :presenter
5
+ delegate :break_line, :bold, to: TableInspector::Text
5
6
 
6
- def initialize(klass, column_name, sql_type: false, colorize: false )
7
- @column = klass.columns.find {|column| column.name == column_name.to_s}
7
+ def initialize(klass, column_name, presenter_option)
8
+ @column = klass.columns.find { |column| column.name == column_name.to_s }
8
9
  @klass = klass
9
- @sql_type = sql_type
10
- @colorize = colorize
11
- @presenter = Presenter.new(klass, sql_type: sql_type, colorize: colorize)
10
+ @presenter = Presenter.new(klass, presenter_option)
12
11
  end
13
12
 
14
13
  def render
15
- Text.break_line
14
+ break_line # empty line
16
15
  render_title
17
16
  render_body
18
- Text.break_line
19
- Indexes.new(klass, column.name, colorize: @colorize).render
20
- Text.break_line
17
+ break_line # empty line
18
+ render_indexes
19
+ break_line # empty line
21
20
  end
22
21
 
23
22
  private
24
23
 
25
24
  def render_title
26
- Grid.new do |grid|
27
- grid.add_row(["#{Text.bold('Table')}: #{klass.table_name}", "#{Text.bold('Column')}: #{column.name}"])
25
+ TerminalTable.new do |terminal_table|
26
+ table_name = bold('Table') + ": " + klass.table_name
27
+ column_name = bold('Column') + ": " + column.name
28
+ terminal_table.add_row([table_name, column_name])
28
29
  end.render
29
30
  end
30
31
 
31
32
  def render_body
32
- Grid.new(headings: presenter.headings) do |grid|
33
- grid.add_row(@presenter.extract_meta(column).values)
33
+ TerminalTable.new(headings: presenter.headings) do |terminal_table|
34
+ terminal_table.add_row(@presenter.extract_meta(column).values)
34
35
  end.render
35
36
  end
37
+
38
+ def render_indexes
39
+ Indexes.new(klass, column.name, colorize: presenter.option.colorize).render
40
+ end
36
41
  end
37
42
  end
@@ -22,7 +22,7 @@ module TableInspector
22
22
  end
23
23
 
24
24
  def column_is_not_exists_hint
25
- puts "Column '#{column_name}' doesn't exists in table '#{klass.table_name}'!"
25
+ puts "Column '#{column_name}' doesn't exist in table '#{klass.table_name}'!"
26
26
  end
27
27
  end
28
28
  end
@@ -13,7 +13,7 @@ module TableInspector
13
13
  render_title
14
14
 
15
15
  if column_name
16
- render_indexes_with_specific_column
16
+ render_indexes_of_column
17
17
  else
18
18
  render_indexes
19
19
  end
@@ -22,48 +22,53 @@ module TableInspector
22
22
  private
23
23
 
24
24
  def render_title
25
- Grid.new do |grid|
26
- grid.add_row([Text.bold("Indexes")])
25
+ TerminalTable.new do |terminal_table|
26
+ terminal_table.add_row([Text.bold("Indexes")])
27
27
  end.render
28
28
  end
29
29
 
30
- def render_indexes_with_specific_column
31
- Grid.new(headings: headings) do |grid|
32
- indexes_with_specific_column.each do |index|
33
- grid.add_row(compose_index_data(index))
30
+ def render_indexes_of_column
31
+ TerminalTable.new(headings: headings) do |terminal_table|
32
+ indexes_of_column.each do |index|
33
+ terminal_table.add_row(compose_index_data(index))
34
34
  end
35
35
  end.render
36
36
  end
37
37
 
38
38
  def render_indexes
39
- Grid.new(headings: headings) do |grid|
39
+ TerminalTable.new(headings: headings) do |terminal_table|
40
40
  indexes.each do |index|
41
- grid.add_row(compose_index_data(index))
41
+ terminal_table.add_row(compose_index_data(index))
42
42
  end
43
43
  end.render
44
44
  end
45
45
 
46
46
  def compose_index_data(index)
47
47
  if @colorize
48
- compose_index_data_with_highlight(index)
48
+ compose_index_data_with_color(index)
49
49
  else
50
- compose_index_data_without_highlight(index)
50
+ compose_index_data_without_color(index)
51
51
  end
52
52
  end
53
53
 
54
- def compose_index_data_with_highlight(index)
54
+ def compose_index_data_with_color(index)
55
+ index_columns_text = index.columns.join(', ')
56
+ unique_text = index.unique ? "UNIQUE" : ""
57
+
55
58
  [
56
59
  index.name,
57
- "[#{Text.yellow(index.columns.join(', '))}]",
58
- index.unique ? "UNIQUE" : ""
60
+ "[#{Text.yellow(index_columns_text)}]",
61
+ unique_text
59
62
  ]
60
63
  end
61
64
 
62
- def compose_index_data_without_highlight(index)
65
+ def compose_index_data_without_color(index)
66
+ index_columns_text = index.columns.join(', ')
67
+ unique_text = index.unique ? "UNIQUE" : ""
63
68
  [
64
69
  index.name,
65
- "[#{index.columns.join(', ')}]",
66
- index.unique ? "UNIQUE" : ""
70
+ "[#{index_columns_text}]",
71
+ unique_text
67
72
  ]
68
73
  end
69
74
 
@@ -75,8 +80,8 @@ module TableInspector
75
80
  @indexes ||= connection.indexes(klass.table_name)
76
81
  end
77
82
 
78
- def indexes_with_specific_column
79
- indexes.select{|index| index.columns.include?(column_name.to_s) }
83
+ def indexes_of_column
84
+ indexes.select{ |index| index.columns.include?(column_name.to_s) }
80
85
  end
81
86
 
82
87
  def connection
@@ -0,0 +1,16 @@
1
+
2
+ module TableInspector
3
+ module Inspectable
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def ti(*args, **kwargs, &block)
8
+ TableInspector.scan(self, *args, **kwargs, &block)
9
+ end
10
+
11
+ def ati(*args, **kwargs, &block)
12
+ TableInspector.ascan(self, *args, **kwargs, &block)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,16 +1,16 @@
1
1
 
2
2
  module TableInspector
3
3
  class Presenter
4
- attr_reader :klass, :sql_type
4
+ attr_reader :klass, :option
5
+ delegate :green, :yellow, :red, :blue, :cyan, to: Text
5
6
 
6
- def initialize(klass, sql_type:, colorize: false)
7
+ def initialize(klass, option)
7
8
  @klass = klass
8
- @sql_type = sql_type
9
- @colorize = colorize
9
+ @option = option
10
10
  end
11
11
 
12
12
  def extract_meta(column)
13
- if @colorize
13
+ if option.colorize
14
14
  extract_meta_with_highlight(column)
15
15
  else
16
16
  extract_meta_without_highlight(column)
@@ -18,8 +18,7 @@ module TableInspector
18
18
  end
19
19
 
20
20
  def headings
21
- first_column = klass.columns.first
22
- extract_meta(first_column).keys.map(&:humanize)
21
+ ordered_keys.map(&:humanize)
23
22
  end
24
23
 
25
24
  private
@@ -48,23 +47,27 @@ module TableInspector
48
47
  end
49
48
 
50
49
  def ordered_keys
51
- %w[name type limit null default precision scale comment].tap do |keys|
52
- keys << "sql_type" if sql_type
50
+ if option.comment_only
51
+ %w[name comment]
52
+ else
53
+ %w[name type limit null default precision scale comment].tap do |keys|
54
+ keys << "sql_type" if option.sql_type
55
+ end
53
56
  end
54
57
  end
55
58
 
56
59
  def colorize(value)
57
60
  case value
58
61
  when TrueClass, DateTime, 'datetime'
59
- Text.green(value)
62
+ green(value)
60
63
  when FalseClass
61
- Text.red(value)
64
+ red(value)
62
65
  when Numeric, 'integer', 'decimal'
63
- Text.blue(value)
66
+ blue(value)
64
67
  when 'boolean'
65
- Text.cyan(value)
68
+ cyan(value)
66
69
  when String
67
- Text.yellow(value)
70
+ yellow(value)
68
71
  else
69
72
  value
70
73
  end
@@ -0,0 +1,12 @@
1
+
2
+ module TableInspector
3
+ class PresenterOption
4
+ attr_accessor :sql_type, :comment_only, :colorize
5
+
6
+ def initialize(options = {})
7
+ @sql_type = options.fetch(:sql_type, false)
8
+ @comment_only = options.fetch(:comment_only, false)
9
+ @colorize = options.fetch(:colorize, false)
10
+ end
11
+ end
12
+ end
@@ -1,42 +1,43 @@
1
1
 
2
2
  module TableInspector
3
3
  class Table
4
- attr_reader :klass, :sql_type, :presenter
4
+ attr_reader :klass, :presenter, :presenter_option
5
+ delegate :break_line, :bold, to: TableInspector::Text
5
6
 
6
- def initialize(klass, sql_type: false, colorize: false)
7
+ def initialize(klass, presenter_option)
7
8
  @klass = klass
8
- @sql_type = sql_type
9
- @presenter = Presenter.new(klass, sql_type: sql_type, colorize: colorize)
10
- @colorize = colorize
9
+ @presenter = Presenter.new(klass, presenter_option)
10
+ @presenter_option = presenter_option
11
11
  end
12
12
 
13
13
  def render
14
- Text.break_line
14
+ break_line # empty line
15
15
  render_title
16
16
  render_body
17
- Text.break_line
17
+ break_line # empty line
18
18
  render_indexes
19
- Text.break_line
19
+ break_line # empty line
20
20
  end
21
21
 
22
22
  private
23
23
 
24
24
  def render_title
25
- Grid.new do |grid|
26
- grid.add_row(["#{Text.bold('Table')}: #{klass.table_name}"])
25
+ TerminalTable.new do |terminal_table|
26
+ table_name = bold('Table') + ": " + klass.table_name
27
+ terminal_table.add_row([table_name])
27
28
  end.render
28
29
  end
29
30
 
30
31
  def render_body
31
- Grid.new(headings: presenter.headings) do |grid|
32
+ TerminalTable.new(headings: presenter.headings) do |terminal_table|
32
33
  klass.columns.each do |column|
33
- grid.add_row(presenter.extract_meta(column).values)
34
+ terminal_table.add_row(presenter.extract_meta(column).values)
34
35
  end
35
36
  end.render
36
37
  end
37
38
 
38
39
  def render_indexes
39
- Indexes.new(klass, colorize: @colorize).render
40
+ Indexes.new(klass, colorize: presenter.option.colorize).render
40
41
  end
41
42
  end
42
43
  end
@@ -1,6 +1,6 @@
1
1
 
2
2
  module TableInspector
3
- class Grid
3
+ class TerminalTable
4
4
  attr_reader :terminal_table
5
5
 
6
6
  delegate :add_row,
@@ -9,13 +9,15 @@ module TableInspector
9
9
 
10
10
  def initialize(**options, &block)
11
11
  @terminal_table = ::Terminal::Table.new(**options)
12
+ style = TableInspector.style || { border: :ascii }
13
+ @terminal_table.style = style
12
14
  yield self if block_given?
13
15
  end
14
16
 
15
17
  def render
16
18
  if rows.empty?
17
19
  Text.break_line
18
- puts " Empty."
20
+ puts " Empty."
19
21
  else
20
22
  puts self
21
23
  end
@@ -1,3 +1,3 @@
1
1
  module TableInspector
2
- VERSION = "0.5.5"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -1,70 +1,68 @@
1
1
  require "table_inspector/version"
2
2
  require "table_inspector/railtie"
3
3
  require "terminal-table"
4
+ require "table_inspector/text"
4
5
  require "table_inspector/table"
5
- require "table_inspector/grid"
6
+ require "table_inspector/terminal_table"
6
7
  require "table_inspector/indexes"
7
- require "table_inspector/text"
8
8
  require "table_inspector/column"
9
9
  require "table_inspector/presenter"
10
10
  require "table_inspector/model_validator"
11
11
  require "table_inspector/column_validator"
12
+ require "table_inspector/presenter_option"
13
+ require "table_inspector/inspectable"
12
14
 
13
15
  module TableInspector
14
16
  extend self
17
+ mattr_accessor :style
15
18
 
16
- def ascan(klass, column_name = nil, sql_type: false)
17
- klass = classify!(klass)
18
-
19
- return unless klass
20
- return unless validate!(klass, column_name)
21
-
22
- render(klass, column_name, sql_type, colorize: true)
19
+ # options:
20
+ # - sql_type: pass "true" print sql type, pass "false" not print sql type, default is false
21
+ # - comment_only: pass "true" print comment only, pass "false" will print all column info, default is false
22
+ def ascan(klass, column_name = nil, **options)
23
+ scan(klass, column_name, colorize: true, **options)
23
24
  end
24
25
 
25
- def scan(klass, column_name = nil, sql_type: false)
26
+ # options:
27
+ # - sql_type: pass "true" print sql type, pass "false" not print sql type, default is false
28
+ # - comment_only: pass "true" print comment only, pass "false" will print all column info, default is false
29
+ # - colorize: pass "true" print colorful scheme, pass "false" will print scheme without color, default is false
30
+ def scan(klass, column_name = nil, colorize: false, **options)
26
31
  klass = classify!(klass)
27
32
 
28
33
  return unless klass
29
34
  return unless validate!(klass, column_name)
30
35
 
31
- render(klass, column_name, sql_type)
36
+ presenter_options = PresenterOption.new({ **options, colorize: colorize })
37
+ render(klass, column_name, presenter_options)
32
38
  end
33
39
 
34
40
  private
35
41
 
36
42
  def classify!(klass)
37
- begin
38
- unless klass.is_a?(Class)
39
- klass = klass.to_s.classify.constantize
40
- end
41
- rescue NameError
42
- puts invalid_model_name_hint(klass.inspect)
43
- return
44
- end
45
-
46
- klass
43
+ return klass if klass.is_a?(Class)
44
+ klass.to_s.classify.constantize
45
+ rescue NameError
46
+ puts invalid_model_name_hint(klass.inspect)
47
47
  end
48
48
 
49
49
  def validate!(klass, column_name)
50
50
  model_validator = ModelValidator.new(klass)
51
- unless column_name
52
- return model_validator.validate!
53
- end
51
+ return model_validator.validate! unless column_name
54
52
 
55
53
  column_validator = ColumnValidator.new(klass, column_name)
56
54
  model_validator.validate! && column_validator.validate!
57
55
  end
58
56
 
59
- def render(klass, column_name, sql_type, colorize: false)
57
+ def render(klass, column_name, presenter_option)
60
58
  if column_name
61
- Column.new(klass, column_name, sql_type: sql_type, colorize: colorize).render
59
+ Column.new(klass, column_name, presenter_option).render
62
60
  else
63
- Table.new(klass, sql_type: sql_type, colorize: colorize).render
61
+ Table.new(klass, presenter_option).render
64
62
  end
65
63
  end
66
64
 
67
65
  def invalid_model_name_hint(klass)
68
- "'#{klass}' can be transform to a model class."
66
+ "'#{klass}' cannot be transformed to a valid model class."
69
67
  end
70
68
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: table_inspector
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ian
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-04 00:00:00.000000000 Z
11
+ date: 2023-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 3.0.2
41
- description: Inspect table structure of ActiveRecord class
41
+ description: Print table structure of ActiveRecord class
42
42
  email:
43
43
  - ianlynxk@gmail.com
44
44
  executables: []
@@ -51,12 +51,14 @@ files:
51
51
  - lib/table_inspector.rb
52
52
  - lib/table_inspector/column.rb
53
53
  - lib/table_inspector/column_validator.rb
54
- - lib/table_inspector/grid.rb
55
54
  - lib/table_inspector/indexes.rb
55
+ - lib/table_inspector/inspectable.rb
56
56
  - lib/table_inspector/model_validator.rb
57
57
  - lib/table_inspector/presenter.rb
58
+ - lib/table_inspector/presenter_option.rb
58
59
  - lib/table_inspector/railtie.rb
59
60
  - lib/table_inspector/table.rb
61
+ - lib/table_inspector/terminal_table.rb
60
62
  - lib/table_inspector/text.rb
61
63
  - lib/table_inspector/version.rb
62
64
  - lib/tasks/table_inspector_tasks.rake
@@ -85,5 +87,5 @@ requirements: []
85
87
  rubygems_version: 3.4.10
86
88
  signing_key:
87
89
  specification_version: 4
88
- summary: Inspect table structure of ActiveRecord class
90
+ summary: Print table structure of ActiveRecord class
89
91
  test_files: []