model_probe 1.0.7 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/Gemfile +2 -0
- data/Gemfile.lock +48 -5
- data/LICENSE.txt +2 -2
- data/README.md +72 -138
- data/Rakefile +2 -0
- data/lib/model_probe/probes/columns.rb +95 -0
- data/lib/model_probe/probes/indexes.rb +33 -0
- data/lib/model_probe/probes/metadata.rb +47 -0
- data/lib/model_probe/probes/subclasses.rb +67 -0
- data/lib/model_probe/probes.rb +35 -0
- data/lib/model_probe/railtie.rb +2 -0
- data/lib/model_probe/templates/fixture.yml.erb +4 -0
- data/lib/model_probe/templates/model.rb.erb +36 -0
- data/lib/model_probe/version.rb +3 -1
- data/lib/model_probe.rb +27 -98
- data/lib/tasks/model_probe.rake +2 -0
- data/model_probe.gemspec +19 -0
- data/tags +111 -0
- metadata +42 -7
- data/lib/model_probe/color.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fedda5d159cc8bbc6bd0181bf718555437137143a893ca70c0ebacc9cdb1bf50
|
4
|
+
data.tar.gz: ec4be05cd44a4824637e062a538234327beaf5644630565beedbfd2c520becb6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce89a216d52fbace263249b4874c674cc94302305acd38205f2e5f57861cb2af086fb414b7fcd692171732cda07151c8874c4d690579447c25850d30cc700e11
|
7
|
+
data.tar.gz: a30aac6054f3c4beca2d7b745b4628fe9b654fc0265da4c498ceb3e8b9f7385d3f8aac3e19962a4811be5ac487a2ae4f22f66cf1907c8ae5c7a905024e7e0897
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,19 +1,62 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
model_probe (1.
|
4
|
+
model_probe (1.1.1)
|
5
|
+
rainbow
|
5
6
|
|
6
7
|
GEM
|
7
8
|
remote: https://rubygems.org/
|
8
9
|
specs:
|
9
|
-
|
10
|
+
ast (2.4.2)
|
11
|
+
json (2.6.3)
|
12
|
+
language_server-protocol (3.17.0.3)
|
13
|
+
lint_roller (1.0.0)
|
14
|
+
magic_frozen_string_literal (1.2.0)
|
15
|
+
parallel (1.23.0)
|
16
|
+
parser (3.2.2.1)
|
17
|
+
ast (~> 2.4.1)
|
18
|
+
rainbow (3.1.1)
|
19
|
+
regexp_parser (2.8.0)
|
20
|
+
rexml (3.2.5)
|
21
|
+
rubocop (1.52.0)
|
22
|
+
json (~> 2.3)
|
23
|
+
parallel (~> 1.10)
|
24
|
+
parser (>= 3.2.0.0)
|
25
|
+
rainbow (>= 2.2.2, < 4.0)
|
26
|
+
regexp_parser (>= 1.8, < 3.0)
|
27
|
+
rexml (>= 3.2.5, < 4.0)
|
28
|
+
rubocop-ast (>= 1.28.0, < 2.0)
|
29
|
+
ruby-progressbar (~> 1.7)
|
30
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
31
|
+
rubocop-ast (1.29.0)
|
32
|
+
parser (>= 3.2.1.0)
|
33
|
+
rubocop-performance (1.18.0)
|
34
|
+
rubocop (>= 1.7.0, < 2.0)
|
35
|
+
rubocop-ast (>= 0.4.0)
|
36
|
+
ruby-progressbar (1.13.0)
|
37
|
+
standard (1.29.0)
|
38
|
+
language_server-protocol (~> 3.17.0.2)
|
39
|
+
lint_roller (~> 1.0)
|
40
|
+
rubocop (~> 1.52.0)
|
41
|
+
standard-custom (~> 1.0.0)
|
42
|
+
standard-performance (~> 1.1.0)
|
43
|
+
standard-custom (1.0.1)
|
44
|
+
lint_roller (~> 1.0)
|
45
|
+
standard-performance (1.1.0)
|
46
|
+
lint_roller (~> 1.0)
|
47
|
+
rubocop-performance (~> 1.18.0)
|
48
|
+
standardrb (1.0.1)
|
49
|
+
standard
|
50
|
+
unicode-display_width (2.4.2)
|
10
51
|
|
11
52
|
PLATFORMS
|
12
|
-
|
53
|
+
arm64-darwin-21
|
54
|
+
arm64-darwin-22
|
13
55
|
|
14
56
|
DEPENDENCIES
|
57
|
+
magic_frozen_string_literal
|
15
58
|
model_probe!
|
16
|
-
|
59
|
+
standardrb
|
17
60
|
|
18
61
|
BUNDLED WITH
|
19
|
-
|
62
|
+
2.3.5
|
data/LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2023 Nathan Hopkins
|
2
2
|
|
3
3
|
MIT License
|
4
4
|
|
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,140 +1,74 @@
|
|
1
1
|
# ModelProbe
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
```
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
# unlock_token string....character varying NULL
|
76
|
-
# updated_at datetime..timestamp without time zone
|
77
|
-
```
|
78
|
-
|
79
|
-
```sh
|
80
|
-
rails model_probe:print_fixture[User]
|
81
|
-
|
82
|
-
# ---
|
83
|
-
# user:
|
84
|
-
# confirmation_sent_at: value
|
85
|
-
# confirmation_token: value
|
86
|
-
# confirmed_at: value
|
87
|
-
# current_sign_in_at: value
|
88
|
-
# current_sign_in_ip: value
|
89
|
-
# email: ''
|
90
|
-
# encrypted_password: ''
|
91
|
-
# failed_attempts: '0'
|
92
|
-
# last_sign_in_at: value
|
93
|
-
# last_sign_in_ip: value
|
94
|
-
# locked_at: value
|
95
|
-
# payment_platform: value
|
96
|
-
# payment_platform_id: value
|
97
|
-
# phone_number_id: value
|
98
|
-
# reset_password_sent_at: value
|
99
|
-
# reset_password_token: value
|
100
|
-
# sign_in_count: '0'
|
101
|
-
# unconfirmed_email: value
|
102
|
-
# unlock_token: value
|
103
|
-
```
|
104
|
-
|
105
|
-
```sh
|
106
|
-
rails model_probe:print_model[User]
|
107
|
-
|
108
|
-
# class User < ApplicationRecord
|
109
|
-
# # extends ...................................................................
|
110
|
-
# # includes ..................................................................
|
111
|
-
#
|
112
|
-
# # relationships .............................................................
|
113
|
-
# belongs_to :payment_platform
|
114
|
-
# belongs_to :phone_number
|
115
|
-
#
|
116
|
-
# # validations ...............................................................
|
117
|
-
# validates :created_at, presence: true
|
118
|
-
# validates :encrypted_password, presence: true
|
119
|
-
# validates :failed_attempts, presence: true
|
120
|
-
# validates :phone_number_id, presence: true
|
121
|
-
# validates :sign_in_count, presence: true
|
122
|
-
# validates :updated_at, presence: true
|
123
|
-
#
|
124
|
-
# # callbacks .................................................................
|
125
|
-
# # scopes ....................................................................
|
126
|
-
# # additional config (i.e. accepts_nested_attribute_for etc...) ..............
|
127
|
-
#
|
128
|
-
# # class methods .............................................................
|
129
|
-
# class << self
|
130
|
-
# end
|
131
|
-
#
|
132
|
-
# # public instance methods ...................................................
|
133
|
-
#
|
134
|
-
# # protected instance methods ................................................
|
135
|
-
# protected
|
136
|
-
#
|
137
|
-
# # private instance methods ..................................................
|
138
|
-
# private
|
139
|
-
# end
|
140
|
-
```
|
3
|
+
## ActiveRecord schema visualization and model organization made easy 🙌
|
4
|
+
|
5
|
+
Colorized table info for columns, types, nullables, indexes...
|
6
|
+
and the actual DDL used by the database to create the table.
|
7
|
+
_All this and more with ModelProbe!_
|
8
|
+
|
9
|
+
1. Get a clear picture of your model's underlying schema with beautiful and informative schema introspection.
|
10
|
+
1. Generate model class definitions with a well organized, logical structure.
|
11
|
+
1. Create sensible text fixture stubs.
|
12
|
+
|
13
|
+
<!-- Tocer[start]: Auto-generated, don't remove. -->
|
14
|
+
|
15
|
+
## Table of Contents
|
16
|
+
|
17
|
+
- [Quick Start](#quick-start)
|
18
|
+
- [Supported Databases](#supported-databases)
|
19
|
+
- [Videos](#videos)
|
20
|
+
- [Screenshots](#screenshots)
|
21
|
+
|
22
|
+
<!-- Tocer[finish]: Auto-generated, don't remove. -->
|
23
|
+
|
24
|
+
## Quick Start
|
25
|
+
|
26
|
+
1. Add the GEM to your project
|
27
|
+
|
28
|
+
```sh
|
29
|
+
bundle add model_probe
|
30
|
+
```
|
31
|
+
|
32
|
+
_ModelProbe auto initializes in the Rails `development` environment._
|
33
|
+
|
34
|
+
1. Use in a Rails console
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
# examples for a User model
|
38
|
+
User.probe
|
39
|
+
User.print_model
|
40
|
+
User.print_fixture
|
41
|
+
```
|
42
|
+
1. Use with Rails (Rake) tasks
|
43
|
+
|
44
|
+
```sh
|
45
|
+
# examples for a User model
|
46
|
+
bin/rails model_probe:probe[User]
|
47
|
+
bin/rails model_probe:print_model[User]
|
48
|
+
bin/rails model_probe:print_fixture[User]
|
49
|
+
```
|
50
|
+
|
51
|
+
## Supported Databases
|
52
|
+
|
53
|
+
- MySQL
|
54
|
+
- PostgreSQL
|
55
|
+
- SQLite
|
56
|
+
- _...more? contributions welcome ;)_
|
57
|
+
|
58
|
+
## Videos
|
59
|
+
|
60
|
+
[](https://youtu.be/Q3IdyKateQE)
|
61
|
+
|
62
|
+
## Screenshots
|
63
|
+
|
64
|
+
Introspect your ActiveRecord models to build a deep understanding of the underlying database structure.
|
65
|
+
|
66
|
+

|
67
|
+
|
68
|
+
Generate a well organized template for your ActiveRecord model's class definition.
|
69
|
+
|
70
|
+

|
71
|
+
|
72
|
+
Create fixture stubs to use in the test suite.
|
73
|
+
|
74
|
+

|
data/Rakefile
CHANGED
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ModelProbe::Probes::Columns
|
4
|
+
def probe_columns
|
5
|
+
name_pad = columns.map { |c| c.name.length }.max + 2
|
6
|
+
type_pad = columns.map { |c| c.type.length }.max + 2
|
7
|
+
sql_type_pad = columns.map { |c| c.sql_type.length }.max + 1
|
8
|
+
columns.sort_by(&:name).each do |column|
|
9
|
+
probe_column column, name_pad: name_pad, type_pad: type_pad, sql_type_pad: sql_type_pad
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def primary_key_columns
|
16
|
+
columns.select { |column| primary_key_column? column }.sort_by(&:name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def foreign_key_columns
|
20
|
+
columns.select { |column| foreign_key_column? column }.sort_by(&:name)
|
21
|
+
end
|
22
|
+
|
23
|
+
def relation_columns
|
24
|
+
columns.select { |column| relation_column? column }.sort_by(&:name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def required_columns
|
28
|
+
columns.select { |column| required_column? column }.sort_by(&:name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def limit_columns
|
32
|
+
columns.select { |column| limit_column? column }.sort_by(&:name)
|
33
|
+
end
|
34
|
+
|
35
|
+
def validation_columns
|
36
|
+
(required_columns + limit_columns).uniq.sort_by(&:name)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def probe_column(column, name_pad:, type_pad:, sql_type_pad:)
|
42
|
+
name = column.name
|
43
|
+
if primary_key_column?(column)
|
44
|
+
print Rainbow("*#{name}".rjust(name_pad)).magenta.bright
|
45
|
+
else
|
46
|
+
print Rainbow(name.to_s.rjust(name_pad)).magenta
|
47
|
+
end
|
48
|
+
print " "
|
49
|
+
print column.type.to_s.ljust(type_pad, ".")
|
50
|
+
print Rainbow(column.sql_type.to_s.ljust(sql_type_pad)).dimgray
|
51
|
+
print Rainbow("NULLABLE ").dimgray.faint if column.null
|
52
|
+
print Rainbow("REQUIRED ").indianred unless column.null
|
53
|
+
print Rainbow("default=").dimgray + Rainbow("#{column.default} ").skyblue if column.default
|
54
|
+
print "- #{Rainbow(column.comment).dimgray}" if column.comment
|
55
|
+
puts
|
56
|
+
end
|
57
|
+
|
58
|
+
def primary_key_column?(column)
|
59
|
+
column.name == primary_key
|
60
|
+
end
|
61
|
+
|
62
|
+
def foreign_key_column?(column)
|
63
|
+
return false if primary_key_column?(column)
|
64
|
+
column.name.end_with? "_id"
|
65
|
+
end
|
66
|
+
|
67
|
+
def timestamp_column?(column)
|
68
|
+
column.type == :datetime && column.name =~ /(created|updated|modified)/
|
69
|
+
end
|
70
|
+
|
71
|
+
def required_column?(column)
|
72
|
+
return false if primary_key_column?(column)
|
73
|
+
return false if foreign_key_column?(column)
|
74
|
+
return false if timestamp_column?(column)
|
75
|
+
!column.null
|
76
|
+
end
|
77
|
+
|
78
|
+
def limit_column?(column)
|
79
|
+
return false if primary_key_column?(column)
|
80
|
+
return false if foreign_key_column?(column)
|
81
|
+
return false if timestamp_column?(column)
|
82
|
+
%i[text string].include?(column.type) && column.limit.to_i > 0
|
83
|
+
end
|
84
|
+
|
85
|
+
def relation_column?(column)
|
86
|
+
return false if column.name == primary_key
|
87
|
+
column.name.end_with?("_id")
|
88
|
+
end
|
89
|
+
|
90
|
+
def fixture_columns
|
91
|
+
columns.sort_by(&:name).select do |column|
|
92
|
+
!primary_key_column?(column) && !timestamp_column?(column)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ModelProbe::Probes::Indexes
|
4
|
+
def probe_indexes
|
5
|
+
indexes = connection.indexes(table_name)
|
6
|
+
name_pad = indexes.map { |c| c.name.length }.max + 1
|
7
|
+
indexes.sort_by(&:name).each do |index|
|
8
|
+
probe_index index, name_pad: name_pad
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def probe_index(index, name_pad:)
|
15
|
+
print Rainbow(index.name.to_s.rjust(name_pad)).yellow
|
16
|
+
print Rainbow(" [").dimgray
|
17
|
+
index.columns.each_with_index do |column, index|
|
18
|
+
print Rainbow(", ").dimgray if index > 0
|
19
|
+
print Rainbow(column).magenta
|
20
|
+
end
|
21
|
+
print Rainbow("]").dimgray
|
22
|
+
print Rainbow(" UNIQUE").green.bright if index.unique
|
23
|
+
|
24
|
+
if index.where
|
25
|
+
print Rainbow(" where(#{index.where})").dimgray
|
26
|
+
end
|
27
|
+
|
28
|
+
if index.using
|
29
|
+
print Rainbow(" using(#{index.using})").dimgray
|
30
|
+
end
|
31
|
+
puts
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ModelProbe::Probes::Metadata
|
4
|
+
def probe_metadata
|
5
|
+
puts Rainbow(name).green + Rainbow(" < ").dimgray.faint + Rainbow(superclass.name).green.faint
|
6
|
+
puts Rainbow(" Database engine ".ljust(24, ".")).darkgray + " " + Rainbow(connection.adapter_name).skyblue.bright + " " + Rainbow(connection.database_version).skyblue.faint
|
7
|
+
puts Rainbow(" Database name ".ljust(24, ".")).darkgray + " " + Rainbow(connection_db_config.database).skyblue
|
8
|
+
puts Rainbow(" Table name ".ljust(24, ".")).darkgray + " " + Rainbow(table_name).skyblue
|
9
|
+
puts Rainbow(" Default role".ljust(24, ".")).darkgray + " " + Rainbow(default_role).skyblue
|
10
|
+
puts Rainbow(" Connection config ".ljust(24, ".")).darkgray
|
11
|
+
connection_db_config.configuration_hash.to_yaml.split("\n")[1..].each { |line| puts " " + Rainbow(line).skyblue.faint }
|
12
|
+
puts
|
13
|
+
puts Rainbow(" DDL ".ljust(24, ".")).darkgray
|
14
|
+
if /create table/i.match?(ddl)
|
15
|
+
ddl.split("\n").each do |line|
|
16
|
+
line = line.squish
|
17
|
+
next if line.blank?
|
18
|
+
next if line.start_with?("--")
|
19
|
+
next if line.start_with?("/*")
|
20
|
+
next if /error|warning|Couldn't execute/i.match?(line)
|
21
|
+
puts Rainbow(" #{line}").skyblue.faint
|
22
|
+
end
|
23
|
+
else
|
24
|
+
puts Rainbow(" Failed to generate DDL string! #{ddl}").indianred
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def ddl
|
31
|
+
config = connection_db_config.configuration_hash
|
32
|
+
@ddl ||= begin
|
33
|
+
case connection.adapter_name
|
34
|
+
when /sqlite/i
|
35
|
+
`sqlite3 #{config[:database]} '.schema #{table_name}' 2>&1`
|
36
|
+
when /postgresql/i
|
37
|
+
`PGPASSWORD=#{config[:password]} pg_dump --host=#{config[:host]} --port=#{config[:port]} --username=#{config[:username]} --schema-only --table=#{table_name} #{config[:database]} 2>&1`
|
38
|
+
when /mysql/i
|
39
|
+
`mysqldump --host=#{config[:host]} --port=#{config[:port]} --user=#{config[:username]} --password=#{config[:password]} --skip-lock-tables --no-data --compact #{config[:database]} #{table_name} 2>&1`
|
40
|
+
else
|
41
|
+
"DDL output is not yet supported for #{connection.adapter_name}!"
|
42
|
+
end
|
43
|
+
rescue => e
|
44
|
+
"Failed to generate DDL string! #{e.message}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ModelProbe::Probes::Subclasses
|
4
|
+
def probe_subclasses
|
5
|
+
@count = 0
|
6
|
+
@max_name_size = 0
|
7
|
+
puts Rainbow(name).green + Rainbow(" < ").dimgray.faint + Rainbow(superclass.name).green.faint
|
8
|
+
grouped = subclasses.each_with_object({}) do |model, memo|
|
9
|
+
@max_name_size = model.name.size if model.name.size > @max_name_size
|
10
|
+
location = Object.const_source_location(model.name)
|
11
|
+
case location
|
12
|
+
when Array
|
13
|
+
path = location.first
|
14
|
+
type = "First party" if first_party?(path)
|
15
|
+
type = "Third party" if third_party?(path)
|
16
|
+
type ||= "Unknown"
|
17
|
+
memo[type] ||= []
|
18
|
+
memo[type] << {name: model.name, path: path}
|
19
|
+
when NilClass
|
20
|
+
memo["Dynamic"] ||= []
|
21
|
+
memo["Dynamic"] << {name: model.name, path: "defined dynamically at runtime"}
|
22
|
+
else
|
23
|
+
memo["Unknown"] ||= []
|
24
|
+
memo["Unknown"] << {name: model.name, path: nil}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
keys = [
|
29
|
+
"First party",
|
30
|
+
"Dynamic",
|
31
|
+
"Third party",
|
32
|
+
"Unknown"
|
33
|
+
]
|
34
|
+
|
35
|
+
keys.each do |key|
|
36
|
+
next unless grouped[key]&.any?
|
37
|
+
puts Rainbow(" #{key} subclasses ".ljust(35, ".")).dimgray
|
38
|
+
grouped[key].sort_by { |entry| entry[:name] }.each do |entry|
|
39
|
+
probe_subclass entry[:name], entry[:path]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def probe_subclass(name, path)
|
47
|
+
path = path.split(/\/(?=app\/models\/)/i).last if path.include?("/app/models/") && !path.include?("/ruby/gems/")
|
48
|
+
path = path.split(/\/(?=ruby\/gems\/)/i).last if path.include?("/ruby/gems/")
|
49
|
+
prefix = (@count += 1).to_s.rjust(8) + " ..."
|
50
|
+
puts [
|
51
|
+
Rainbow(prefix.to_s.ljust(prefix.size + @max_name_size - name.size, ".")).dimgray.faint,
|
52
|
+
Rainbow(name).mediumslateblue,
|
53
|
+
Rainbow("<").faint,
|
54
|
+
Rainbow(self.name).dimgray.faint,
|
55
|
+
Rainbow(path.to_s).faint
|
56
|
+
].join(" ")
|
57
|
+
end
|
58
|
+
|
59
|
+
def third_party?(path)
|
60
|
+
path.include? "/ruby/gems/"
|
61
|
+
end
|
62
|
+
|
63
|
+
def first_party?(path)
|
64
|
+
return false if third_party?(path)
|
65
|
+
path.include? "/app/models/"
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ModelProbe::Probes; end
|
4
|
+
|
5
|
+
require_relative "probes/metadata"
|
6
|
+
require_relative "probes/columns"
|
7
|
+
require_relative "probes/indexes"
|
8
|
+
require_relative "probes/subclasses"
|
9
|
+
|
10
|
+
module ModelProbe::Probes
|
11
|
+
include Metadata
|
12
|
+
include Columns
|
13
|
+
include Indexes
|
14
|
+
include Subclasses
|
15
|
+
|
16
|
+
def probe
|
17
|
+
if name == "ActiveRecord::Base" || abstract_class?
|
18
|
+
probe_subclasses
|
19
|
+
return nil
|
20
|
+
end
|
21
|
+
|
22
|
+
probe_metadata
|
23
|
+
puts
|
24
|
+
|
25
|
+
puts Rainbow(" Columns ".ljust(24, ".")).darkgray
|
26
|
+
probe_columns
|
27
|
+
puts
|
28
|
+
|
29
|
+
puts Rainbow(" Indexes ".ljust(24, ".")).darkgray
|
30
|
+
probe_indexes
|
31
|
+
puts
|
32
|
+
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
end
|
data/lib/model_probe/railtie.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class <%= name -%> < <%= superclass_name %>
|
4
|
+
# extends ..................................................................................................
|
5
|
+
|
6
|
+
# includes .................................................................................................
|
7
|
+
|
8
|
+
# constants ................................................................................................
|
9
|
+
|
10
|
+
# class methods ............................................................................................
|
11
|
+
class << self
|
12
|
+
end
|
13
|
+
|
14
|
+
# relationships ............................................................................................
|
15
|
+
<% foreign_key_columns.each do |column| -%>
|
16
|
+
<%= "belongs_to :#{column.name.sub(/_id\z/, "")}" %>
|
17
|
+
<% end -%>
|
18
|
+
|
19
|
+
# validations ..............................................................................................
|
20
|
+
<% validation_columns.each do |column| -%>
|
21
|
+
<%= "validates :#{column.name}, presence: true" unless column.null if required_columns.include?(column) %>
|
22
|
+
<%= "validates :#{column.name}, length: {maximum: #{column.limit}}" if limit_columns.include?(column) %>
|
23
|
+
<% end -%>
|
24
|
+
|
25
|
+
# callbacks (caution: side effects) ........................................................................
|
26
|
+
|
27
|
+
# scopes (composable queries) ..............................................................................
|
28
|
+
|
29
|
+
# additional config (accepts_nested_attribute_for, etc.) ...................................................
|
30
|
+
|
31
|
+
# public instance methods ..................................................................................
|
32
|
+
|
33
|
+
# protected instance methods ...............................................................................
|
34
|
+
|
35
|
+
# private instance methods .................................................................................
|
36
|
+
end
|
data/lib/model_probe/version.rb
CHANGED
data/lib/model_probe.rb
CHANGED
@@ -1,114 +1,43 @@
|
|
1
|
-
|
2
|
-
require "model_probe/color"
|
3
|
-
require "model_probe/railtie" if defined?(Rails)
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
name_pad = columns.map { |c| c.name.length }.max + 1
|
11
|
-
type_pad = columns.map { |c| c.type.length }.max + 2
|
12
|
-
sql_type_pad = columns.map { |c| c.sql_type.length }.max + 1
|
3
|
+
require "erb"
|
4
|
+
require "rainbow"
|
5
|
+
require_relative "model_probe/version"
|
6
|
+
require_relative "model_probe/railtie" if defined?(Rails)
|
7
|
+
require_relative "model_probe/probes"
|
13
8
|
|
14
|
-
|
15
|
-
|
16
|
-
name = "* #{name}" if primary_key_column?(column)
|
17
|
-
print yellow(name.to_s.rjust(name_pad))
|
18
|
-
print " "
|
19
|
-
print blue(column.type.to_s.ljust(type_pad, "."))
|
20
|
-
print magenta(column.sql_type.to_s.ljust(sql_type_pad))
|
21
|
-
column.null ? print(red("NULL")) : print(" ")
|
22
|
-
print " [#{column.default}]" if column.default
|
23
|
-
print " #{gray column.comment}" if column.comment
|
24
|
-
puts
|
25
|
-
end
|
26
|
-
nil
|
27
|
-
end
|
9
|
+
module ModelProbe
|
10
|
+
include Probes
|
28
11
|
|
29
12
|
# Prints a stub that can be used for a test fixture
|
30
13
|
def print_fixture
|
31
|
-
|
32
|
-
|
33
|
-
next if timestamp_column?(column)
|
34
|
-
memo[column.name] = column.default || "value"
|
35
|
-
end
|
36
|
-
|
37
|
-
hash = { self.name.underscore => values }
|
38
|
-
puts hash.to_yaml
|
14
|
+
template = erb_template("model_probe/templates/fixture.yml.erb")
|
15
|
+
puts template.result_with_hash(name: name, fixture_columns: fixture_columns)
|
39
16
|
nil
|
40
17
|
end
|
41
18
|
|
42
19
|
# Prints a new model definition based on the database schema
|
43
20
|
def print_model
|
44
|
-
|
45
|
-
puts
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
validation_columns.sort_by(&:name).each do |column|
|
56
|
-
next if primary_key_column?(column)
|
57
|
-
puts " validates :#{column.name}, presence: true" unless column.null
|
58
|
-
if %i(text string).include?(column.type) && column.limit.to_i > 0
|
59
|
-
puts " validates :#{column.name}, length: { maximum: #{column.limit} }"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
puts if validation_columns.size > 0
|
63
|
-
puts " # callbacks ................................................................."
|
64
|
-
puts " # scopes ...................................................................."
|
65
|
-
puts " # additional config (i.e. accepts_nested_attribute_for etc...) .............."
|
66
|
-
puts
|
67
|
-
puts " # class methods ............................................................."
|
68
|
-
puts " class << self"
|
69
|
-
puts " end"
|
70
|
-
puts
|
71
|
-
puts " # public instance methods ..................................................."
|
72
|
-
puts
|
73
|
-
puts " # protected instance methods ................................................"
|
74
|
-
puts " protected"
|
75
|
-
puts
|
76
|
-
puts " # private instance methods .................................................."
|
77
|
-
puts " private"
|
78
|
-
puts "end"
|
21
|
+
template = erb_template("model_probe/templates/model.rb.erb")
|
22
|
+
puts template.result_with_hash(
|
23
|
+
name: name,
|
24
|
+
superclass_name: superclass.name,
|
25
|
+
primary_key_columns: primary_key_columns,
|
26
|
+
foreign_key_columns: foreign_key_columns,
|
27
|
+
relation_columns: relation_columns,
|
28
|
+
required_columns: required_columns,
|
29
|
+
limit_columns: limit_columns,
|
30
|
+
validation_columns: validation_columns
|
31
|
+
)
|
79
32
|
nil
|
80
33
|
end
|
81
34
|
|
82
35
|
private
|
83
36
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
def validation_columns
|
91
|
-
@validation_columns ||= begin
|
92
|
-
columns.select { |column| validation_column? column }
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def primary_key_column?(column)
|
97
|
-
column.name == primary_key
|
98
|
-
end
|
99
|
-
|
100
|
-
def timestamp_column?(column)
|
101
|
-
column.type == :datetime && column.name =~ /(created|updated|modified)/
|
102
|
-
end
|
103
|
-
|
104
|
-
def relation_column?(column)
|
105
|
-
return false if column.name == primary_key
|
106
|
-
column.name.end_with?("_id")
|
107
|
-
end
|
108
|
-
|
109
|
-
def validation_column?(column)
|
110
|
-
return false if column.name == primary_key
|
111
|
-
return true unless column.null
|
112
|
-
%i(text string).include?(column.type) && column.limit.to_i > 0
|
113
|
-
end
|
37
|
+
def erb_template(relative_path)
|
38
|
+
template_path = File.expand_path(relative_path, __dir__)
|
39
|
+
template_text = File.read(template_path)
|
40
|
+
# trim_mode doesn't seem to work regardless of how it's passed with Ruby 2.7.5
|
41
|
+
ERB.new template_text, trim_mode: "-"
|
42
|
+
end
|
114
43
|
end
|
data/lib/tasks/model_probe.rake
CHANGED
data/model_probe.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/model_probe/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "model_probe"
|
7
|
+
s.version = ModelProbe::VERSION
|
8
|
+
s.authors = ["Nathan Hopkins"]
|
9
|
+
s.email = ["natehop@gmail.com"]
|
10
|
+
s.summary = "ActiveRecord schema visualization and model organization made easy"
|
11
|
+
s.homepage = "http://hopsoft.github.com/model_probe/"
|
12
|
+
|
13
|
+
s.files = Dir["lib/**/*rb", "lib/tasks/*rake", "[A-Z]*"]
|
14
|
+
|
15
|
+
s.add_dependency "rainbow"
|
16
|
+
|
17
|
+
s.add_development_dependency "magic_frozen_string_literal"
|
18
|
+
s.add_development_dependency "standardrb"
|
19
|
+
end
|
data/tags
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
!_TAG_EXTRA_DESCRIPTION anonymous /Include tags for non-named objects like lambda/
|
2
|
+
!_TAG_EXTRA_DESCRIPTION fileScope /Include tags of file scope/
|
3
|
+
!_TAG_EXTRA_DESCRIPTION pseudo /Include pseudo tags/
|
4
|
+
!_TAG_EXTRA_DESCRIPTION subparser /Include tags generated by subparsers/
|
5
|
+
!_TAG_FIELD_DESCRIPTION epoch /the last modified time of the input file (only for F\/file kind tag)/
|
6
|
+
!_TAG_FIELD_DESCRIPTION file /File-restricted scoping/
|
7
|
+
!_TAG_FIELD_DESCRIPTION input /input file/
|
8
|
+
!_TAG_FIELD_DESCRIPTION name /tag name/
|
9
|
+
!_TAG_FIELD_DESCRIPTION pattern /pattern/
|
10
|
+
!_TAG_FIELD_DESCRIPTION typeref /Type and name of a variable or typedef/
|
11
|
+
!_TAG_FIELD_DESCRIPTION!Ruby mixin /how the class or module is mixed in (mixin:HOW:MODULE)/
|
12
|
+
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
13
|
+
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
14
|
+
!_TAG_KIND_DESCRIPTION!GemSpec g,gem /gems/
|
15
|
+
!_TAG_KIND_DESCRIPTION!Markdown S,subsection /level 2 sections/
|
16
|
+
!_TAG_KIND_DESCRIPTION!Markdown T,l4subsection /level 4 sections/
|
17
|
+
!_TAG_KIND_DESCRIPTION!Markdown c,chapter /chapters/
|
18
|
+
!_TAG_KIND_DESCRIPTION!Markdown n,footnote /footnotes/
|
19
|
+
!_TAG_KIND_DESCRIPTION!Markdown s,section /sections/
|
20
|
+
!_TAG_KIND_DESCRIPTION!Markdown t,subsubsection /level 3 sections/
|
21
|
+
!_TAG_KIND_DESCRIPTION!Markdown u,l5subsection /level 5 sections/
|
22
|
+
!_TAG_KIND_DESCRIPTION!Rake d,directory /directory tasks/
|
23
|
+
!_TAG_KIND_DESCRIPTION!Rake f,File /file tasks/
|
24
|
+
!_TAG_KIND_DESCRIPTION!Rake m,multitask /multi tasks/
|
25
|
+
!_TAG_KIND_DESCRIPTION!Rake n,namespace /namespaces/
|
26
|
+
!_TAG_KIND_DESCRIPTION!Rake t,task /tasks/
|
27
|
+
!_TAG_KIND_DESCRIPTION!Rake x,xtask /tasks defined with special constructor/
|
28
|
+
!_TAG_KIND_DESCRIPTION!Ruby A,accessor /accessors/
|
29
|
+
!_TAG_KIND_DESCRIPTION!Ruby C,constant /constants/
|
30
|
+
!_TAG_KIND_DESCRIPTION!Ruby L,library /libraries/
|
31
|
+
!_TAG_KIND_DESCRIPTION!Ruby S,singletonMethod /singleton methods/
|
32
|
+
!_TAG_KIND_DESCRIPTION!Ruby a,alias /aliases/
|
33
|
+
!_TAG_KIND_DESCRIPTION!Ruby c,class /classes/
|
34
|
+
!_TAG_KIND_DESCRIPTION!Ruby f,method /methods/
|
35
|
+
!_TAG_KIND_DESCRIPTION!Ruby m,module /modules/
|
36
|
+
!_TAG_KIND_DESCRIPTION!Sh a,alias /aliases/
|
37
|
+
!_TAG_KIND_DESCRIPTION!Sh f,function /functions/
|
38
|
+
!_TAG_KIND_DESCRIPTION!Sh h,heredoc /label for here document/
|
39
|
+
!_TAG_KIND_DESCRIPTION!Sh s,script /script files/
|
40
|
+
!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/
|
41
|
+
!_TAG_OUTPUT_FILESEP slash /slash or backslash/
|
42
|
+
!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/
|
43
|
+
!_TAG_OUTPUT_VERSION 0.0 /current.age/
|
44
|
+
!_TAG_PARSER_VERSION!GemSpec 0.0 /current.age/
|
45
|
+
!_TAG_PARSER_VERSION!Markdown 0.0 /current.age/
|
46
|
+
!_TAG_PARSER_VERSION!Rake 0.0 /current.age/
|
47
|
+
!_TAG_PARSER_VERSION!Ruby 0.0 /current.age/
|
48
|
+
!_TAG_PARSER_VERSION!Sh 0.0 /current.age/
|
49
|
+
!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/
|
50
|
+
!_TAG_PROC_CWD /Users/nate.hopkins/work/hopsoft/model_probe/ //
|
51
|
+
!_TAG_PROGRAM_AUTHOR Universal Ctags Team //
|
52
|
+
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
|
53
|
+
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
|
54
|
+
!_TAG_PROGRAM_VERSION 6.0.0 //
|
55
|
+
!_TAG_ROLE_DESCRIPTION!GemSpec!gem develDep /specifying development dependency/
|
56
|
+
!_TAG_ROLE_DESCRIPTION!GemSpec!gem runtimeDep /specifying runtime dependency/
|
57
|
+
!_TAG_ROLE_DESCRIPTION!Ruby!library loaded /loaded by "load" method/
|
58
|
+
!_TAG_ROLE_DESCRIPTION!Ruby!library required /loaded by "require" method/
|
59
|
+
!_TAG_ROLE_DESCRIPTION!Ruby!library requiredRel /loaded by "require_relative" method/
|
60
|
+
!_TAG_ROLE_DESCRIPTION!Sh!heredoc endmarker /end marker/
|
61
|
+
!_TAG_ROLE_DESCRIPTION!Sh!script loaded /loaded/
|
62
|
+
ActiveRecord schema visualization and model organization made easy 🙌 README.md /^## ActiveRecord schema visualization and model organization made easy 🙌$/;" s chapter:ModelProbe
|
63
|
+
Columns lib/model_probe/probes/columns.rb /^module ModelProbe::Probes::Columns$/;" m module:ModelProbe.Probes
|
64
|
+
Indexes lib/model_probe/probes/indexes.rb /^module ModelProbe::Probes::Indexes$/;" m module:ModelProbe.Probes
|
65
|
+
Metadata lib/model_probe/probes/metadata.rb /^module ModelProbe::Probes::Metadata$/;" m module:ModelProbe.Probes
|
66
|
+
ModelProbe README.md /^# ModelProbe$/;" c
|
67
|
+
ModelProbe lib/model_probe.rb /^module ModelProbe$/;" m mixin:include:Probes
|
68
|
+
ModelProbe lib/model_probe/railtie.rb /^ module ModelProbe$/;" m
|
69
|
+
ModelProbe lib/model_probe/version.rb /^module ModelProbe$/;" m
|
70
|
+
Probes lib/model_probe/probes.rb /^module ModelProbe::Probes$/;" m module:ModelProbe mixin:include:Metadata,include:Columns,include:Indexes,include:Subclasses
|
71
|
+
Probes lib/model_probe/probes.rb /^module ModelProbe::Probes; end$/;" m module:ModelProbe
|
72
|
+
Quick Start README.md /^## Quick Start$/;" s chapter:ModelProbe
|
73
|
+
Railtie lib/model_probe/railtie.rb /^ class Railtie < Rails::Railtie$/;" c module:ModelProbe
|
74
|
+
Screenshots README.md /^## Screenshots$/;" s chapter:ModelProbe
|
75
|
+
Subclasses lib/model_probe/probes/subclasses.rb /^module ModelProbe::Probes::Subclasses$/;" m module:ModelProbe.Probes
|
76
|
+
Supported Databases README.md /^## Supported Databases$/;" s chapter:ModelProbe
|
77
|
+
Table of Contents README.md /^## Table of Contents$/;" s chapter:ModelProbe
|
78
|
+
VERSION lib/model_probe/version.rb /^ VERSION = "1.1.1"$/;" C module:ModelProbe
|
79
|
+
Videos README.md /^## Videos$/;" s chapter:ModelProbe
|
80
|
+
ddl lib/model_probe/probes/metadata.rb /^ def ddl$/;" f module:Metadata
|
81
|
+
erb_template lib/model_probe.rb /^ def erb_template(relative_path)$/;" f module:ModelProbe
|
82
|
+
first_party? lib/model_probe/probes/subclasses.rb /^ def first_party?(path)$/;" f module:Subclasses
|
83
|
+
fixture_columns lib/model_probe/probes/columns.rb /^ def fixture_columns$/;" f module:Columns
|
84
|
+
foreign_key_column? lib/model_probe/probes/columns.rb /^ def foreign_key_column?(column)$/;" f module:Columns
|
85
|
+
foreign_key_columns lib/model_probe/probes/columns.rb /^ def foreign_key_columns$/;" f module:Columns
|
86
|
+
limit_column? lib/model_probe/probes/columns.rb /^ def limit_column?(column)$/;" f module:Columns
|
87
|
+
limit_columns lib/model_probe/probes/columns.rb /^ def limit_columns$/;" f module:Columns
|
88
|
+
model_probe lib/tasks/model_probe.rake /^namespace :model_probe do$/;" n
|
89
|
+
model_probe model_probe.gemspec /^ s.name = "model_probe"$/;" g
|
90
|
+
primary_key_column? lib/model_probe/probes/columns.rb /^ def primary_key_column?(column)$/;" f module:Columns
|
91
|
+
primary_key_columns lib/model_probe/probes/columns.rb /^ def primary_key_columns$/;" f module:Columns
|
92
|
+
print_fixture lib/model_probe.rb /^ def print_fixture$/;" f module:ModelProbe
|
93
|
+
print_fixture lib/tasks/model_probe.rake /^ task :print_fixture, [:klass] => :environment do |task, args|$/;" t namespace:model_probe
|
94
|
+
print_model lib/model_probe.rb /^ def print_model$/;" f module:ModelProbe
|
95
|
+
print_model lib/tasks/model_probe.rake /^ task :print_model, [:klass] => :environment do |task, args|$/;" t namespace:model_probe
|
96
|
+
probe lib/model_probe/probes.rb /^ def probe$/;" f module:Probes
|
97
|
+
probe lib/tasks/model_probe.rake /^ task :probe, [:klass] => :environment do |task, args|$/;" t namespace:model_probe
|
98
|
+
probe_column lib/model_probe/probes/columns.rb /^ def probe_column(column, name_pad:, type_pad:, sql_type_pad:)$/;" f module:Columns
|
99
|
+
probe_columns lib/model_probe/probes/columns.rb /^ def probe_columns$/;" f module:Columns
|
100
|
+
probe_index lib/model_probe/probes/indexes.rb /^ def probe_index(index, name_pad:)$/;" f module:Indexes
|
101
|
+
probe_indexes lib/model_probe/probes/indexes.rb /^ def probe_indexes$/;" f module:Indexes
|
102
|
+
probe_metadata lib/model_probe/probes/metadata.rb /^ def probe_metadata$/;" f module:Metadata
|
103
|
+
probe_subclass lib/model_probe/probes/subclasses.rb /^ def probe_subclass(name, path)$/;" f module:Subclasses
|
104
|
+
probe_subclasses lib/model_probe/probes/subclasses.rb /^ def probe_subclasses$/;" f module:Subclasses
|
105
|
+
relation_column? lib/model_probe/probes/columns.rb /^ def relation_column?(column)$/;" f module:Columns
|
106
|
+
relation_columns lib/model_probe/probes/columns.rb /^ def relation_columns$/;" f module:Columns
|
107
|
+
required_column? lib/model_probe/probes/columns.rb /^ def required_column?(column)$/;" f module:Columns
|
108
|
+
required_columns lib/model_probe/probes/columns.rb /^ def required_columns$/;" f module:Columns
|
109
|
+
third_party? lib/model_probe/probes/subclasses.rb /^ def third_party?(path)$/;" f module:Subclasses
|
110
|
+
timestamp_column? lib/model_probe/probes/columns.rb /^ def timestamp_column?(column)$/;" f module:Columns
|
111
|
+
validation_columns lib/model_probe/probes/columns.rb /^ def validation_columns$/;" f module:Columns
|
metadata
CHANGED
@@ -1,17 +1,45 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: model_probe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Hopkins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-06-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rainbow
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: magic_frozen_string_literal
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: standardrb
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
16
44
|
requirements:
|
17
45
|
- - ">="
|
@@ -37,10 +65,18 @@ files:
|
|
37
65
|
- README.md
|
38
66
|
- Rakefile
|
39
67
|
- lib/model_probe.rb
|
40
|
-
- lib/model_probe/
|
68
|
+
- lib/model_probe/probes.rb
|
69
|
+
- lib/model_probe/probes/columns.rb
|
70
|
+
- lib/model_probe/probes/indexes.rb
|
71
|
+
- lib/model_probe/probes/metadata.rb
|
72
|
+
- lib/model_probe/probes/subclasses.rb
|
41
73
|
- lib/model_probe/railtie.rb
|
74
|
+
- lib/model_probe/templates/fixture.yml.erb
|
75
|
+
- lib/model_probe/templates/model.rb.erb
|
42
76
|
- lib/model_probe/version.rb
|
43
77
|
- lib/tasks/model_probe.rake
|
78
|
+
- model_probe.gemspec
|
79
|
+
- tags
|
44
80
|
homepage: http://hopsoft.github.com/model_probe/
|
45
81
|
licenses: []
|
46
82
|
metadata: {}
|
@@ -59,9 +95,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
95
|
- !ruby/object:Gem::Version
|
60
96
|
version: '0'
|
61
97
|
requirements: []
|
62
|
-
|
63
|
-
rubygems_version: 2.6.13
|
98
|
+
rubygems_version: 3.1.6
|
64
99
|
signing_key:
|
65
100
|
specification_version: 4
|
66
|
-
summary:
|
101
|
+
summary: ActiveRecord schema visualization and model organization made easy
|
67
102
|
test_files: []
|
data/lib/model_probe/color.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
module ModelProbe
|
2
|
-
module Color
|
3
|
-
extend self
|
4
|
-
|
5
|
-
colors = {
|
6
|
-
:gray => "1;30",
|
7
|
-
:red => 31,
|
8
|
-
:green => 32,
|
9
|
-
:yellow => 33,
|
10
|
-
:blue => 34,
|
11
|
-
:magenta => 35,
|
12
|
-
:cyan => 36,
|
13
|
-
:white => 37
|
14
|
-
}
|
15
|
-
|
16
|
-
colors.each do |name, code|
|
17
|
-
define_method name do |text|
|
18
|
-
"\e[#{code}m#{text}\e[0m"
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|