commento 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +28 -2
- data/lib/commento/adapters/active_record.rb +67 -9
- data/lib/commento/configuration.rb +5 -1
- data/lib/commento/dsl.rb +17 -2
- data/lib/commento/helpers.rb +10 -2
- data/lib/commento/report.rb +77 -0
- data/lib/commento/reports/html.rb +75 -0
- data/lib/commento/services/data_collect.rb +54 -0
- data/lib/commento/version.rb +1 -1
- data/lib/commento.rb +6 -3
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3088eb93d7f0b937169a65a8c95efc36eecb202be76a6cd7c98ec5adc5b945e
|
4
|
+
data.tar.gz: d1ce5f3eaad3ccc2fead78cecde406a20067f4304364948f09027d66ff26b789
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47cd00bf0babcd8ab1c10db8d3edcd4be3330e99c5233b4241fe9552f5a65df96d6494349cc60530781f6d41cead7e05b74c76e7fccff191c9e02de4d78a2031
|
7
|
+
data.tar.gz: 3d7dbf40b8b2783a32dd86208b32e452d142b3d13b3e4ce5e9325472d5e04343d4f594b707aa8454eca2adf014b7e59fbb3f8dc9a72a42d557377f3c2d0d4783
|
data/README.md
CHANGED
@@ -32,16 +32,42 @@ end
|
|
32
32
|
|
33
33
|
### Models
|
34
34
|
|
35
|
-
Update
|
35
|
+
Update your application model
|
36
|
+
|
36
37
|
```ruby
|
37
38
|
class ApplicationRecord < ActiveRecord::Base
|
38
39
|
include Commento::Helpers
|
39
40
|
end
|
40
41
|
```
|
41
42
|
|
43
|
+
## Generating reports
|
44
|
+
|
45
|
+
You can generate different types of reports
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
Commento::Reports::Html.new.create_report
|
49
|
+
```
|
50
|
+
|
42
51
|
## Usage
|
43
52
|
|
44
|
-
Commento provides helpers for models for setting and getting
|
53
|
+
Commento provides helpers for models for setting and getting comments.
|
54
|
+
|
55
|
+
### Set table's comment
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
User.set_table_comment('Users table')
|
59
|
+
```
|
60
|
+
|
61
|
+
or reset comment by skiping value
|
62
|
+
```ruby
|
63
|
+
User.set_table_comment
|
64
|
+
```
|
65
|
+
|
66
|
+
### Read table's column comment
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
User.get_table_comment
|
70
|
+
```
|
45
71
|
|
46
72
|
### Set table's column comment
|
47
73
|
|
@@ -15,6 +15,19 @@ module Commento
|
|
15
15
|
@name = options.fetch(:name, :active_record)
|
16
16
|
end
|
17
17
|
|
18
|
+
# Public: Sets comment for table.
|
19
|
+
def set_table_comment(table_name, value)
|
20
|
+
sql = "COMMENT ON TABLE #{table_name} IS "
|
21
|
+
sql += value ? "'#{value}'" : 'NULL'
|
22
|
+
execute(sql)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Public: Returns comment for table.
|
26
|
+
def table_comment(table_name)
|
27
|
+
table_data = execute(tables_comments_sql).to_a.find { |data| data['table_name'] == table_name }
|
28
|
+
table_data.present? ? table_data['obj_description'] : nil
|
29
|
+
end
|
30
|
+
|
18
31
|
# Public: Sets comment for table's column.
|
19
32
|
def set_column_comment(table_name, column_name, value)
|
20
33
|
sql = "COMMENT ON COLUMN #{table_name}.#{column_name} IS "
|
@@ -23,27 +36,72 @@ module Commento
|
|
23
36
|
end
|
24
37
|
|
25
38
|
# Public: Returns comment for table's column.
|
26
|
-
def
|
27
|
-
sql =
|
39
|
+
def column_comment(table_name, column_name)
|
40
|
+
sql = columns_comments_sql(table_name)
|
41
|
+
column_data = execute(sql).to_a.find { |data| data['column_name'].to_sym == column_name }
|
42
|
+
column_data.present? ? column_data['col_description'] : nil
|
43
|
+
end
|
44
|
+
|
45
|
+
# Public: Returns comments for tables and columns.
|
46
|
+
def comments_for_database
|
47
|
+
execute(tables_comments_sql).to_a.filter_map do |table_data|
|
48
|
+
next if configuration.skip_table_names.include?(table_data['table_name'])
|
49
|
+
|
50
|
+
parse_data(table_data)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def parse_data(table_data)
|
57
|
+
{
|
58
|
+
table_name: table_data['table_name'],
|
59
|
+
table_comment: table_data['obj_description'],
|
60
|
+
columns: execute(columns_comments_sql(table_data['table_name'])).to_a.filter_map do |column_data|
|
61
|
+
next if configuration.skip_column_names.include?(column_data['column_name'])
|
62
|
+
|
63
|
+
{
|
64
|
+
column_name: column_data['column_name'],
|
65
|
+
column_comment: column_data['col_description']
|
66
|
+
}
|
67
|
+
end
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def tables_comments_sql
|
72
|
+
<<-SQL.squish
|
73
|
+
SELECT
|
74
|
+
tables.table_name,
|
75
|
+
pg_catalog.obj_description(pgc.oid, 'pg_class')
|
76
|
+
FROM information_schema.tables tables
|
77
|
+
INNER JOIN pg_catalog.pg_class pgc ON tables.table_name = pgc.relname
|
78
|
+
WHERE
|
79
|
+
tables.table_type='BASE TABLE' AND
|
80
|
+
tables.table_schema='public'
|
81
|
+
SQL
|
82
|
+
end
|
83
|
+
|
84
|
+
def columns_comments_sql(table_name)
|
85
|
+
<<-SQL.squish
|
28
86
|
SELECT
|
29
87
|
cols.column_name,
|
30
|
-
pg_catalog.col_description(
|
31
|
-
FROM pg_catalog.pg_class
|
88
|
+
pg_catalog.col_description(pgc.oid, cols.ordinal_position::int)
|
89
|
+
FROM pg_catalog.pg_class pgc, information_schema.columns cols
|
32
90
|
WHERE
|
33
91
|
cols.table_catalog = '#{Rails.configuration.database_configuration[Rails.env]["database"]}' AND
|
34
92
|
cols.table_schema = 'public' AND
|
35
93
|
cols.table_name = '#{table_name}' AND
|
36
|
-
cols.table_name =
|
94
|
+
cols.table_name = pgc.relname
|
37
95
|
SQL
|
38
|
-
column_data = execute(sql).to_a.find { |column| column['column_name'].to_sym == column_name }
|
39
|
-
column_data.presence ? column_data['col_description'] : nil
|
40
96
|
end
|
41
97
|
|
42
|
-
private
|
43
|
-
|
44
98
|
def execute(sql)
|
45
99
|
::ActiveRecord::Base.connection.execute(sql)
|
46
100
|
end
|
101
|
+
|
102
|
+
def configuration
|
103
|
+
Commento.configuration
|
104
|
+
end
|
47
105
|
end
|
48
106
|
end
|
49
107
|
end
|
@@ -2,10 +2,14 @@
|
|
2
2
|
|
3
3
|
module Commento
|
4
4
|
class Configuration
|
5
|
-
attr_accessor :adapter
|
5
|
+
attr_accessor :adapter, :include_folders, :exclude_folders, :skip_table_names, :skip_column_names
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
@adapter = nil
|
9
|
+
@include_folders = %w[app lib]
|
10
|
+
@exclude_folders = ['app/assets']
|
11
|
+
@skip_table_names = %w[ar_internal_metadata schema_migrations]
|
12
|
+
@skip_column_names = %w[id uuid created_at updated_at]
|
9
13
|
end
|
10
14
|
end
|
11
15
|
end
|
data/lib/commento/dsl.rb
CHANGED
@@ -11,14 +11,29 @@ module Commento
|
|
11
11
|
@adapter = adapter
|
12
12
|
end
|
13
13
|
|
14
|
+
# Public: Sets comment for table.
|
15
|
+
def set_table_comment(table_name, value)
|
16
|
+
adapter.set_table_comment(table_name, value)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Public: Returns comment for table.
|
20
|
+
def table_comment(table_name)
|
21
|
+
adapter.table_comment(table_name)
|
22
|
+
end
|
23
|
+
|
14
24
|
# Public: Sets comment for table's column.
|
15
25
|
def set_column_comment(table_name, column_name, value)
|
16
26
|
adapter.set_column_comment(table_name, column_name, value)
|
17
27
|
end
|
18
28
|
|
19
29
|
# Public: Returns comment for table's column.
|
20
|
-
def
|
21
|
-
adapter.
|
30
|
+
def column_comment(table_name, column_name)
|
31
|
+
adapter.column_comment(table_name, column_name)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Public: Returns comments for tables and columns.
|
35
|
+
def comments_for_database
|
36
|
+
adapter.comments_for_database
|
22
37
|
end
|
23
38
|
end
|
24
39
|
end
|
data/lib/commento/helpers.rb
CHANGED
@@ -9,12 +9,20 @@ module Commento
|
|
9
9
|
end
|
10
10
|
|
11
11
|
module ClassMethods
|
12
|
+
def set_table_comment(value=nil)
|
13
|
+
instance.set_table_comment(table_name, value)
|
14
|
+
end
|
15
|
+
|
16
|
+
def table_comment
|
17
|
+
instance.table_comment(table_name)
|
18
|
+
end
|
19
|
+
|
12
20
|
def set_column_comment(column_name, value=nil)
|
13
21
|
instance.set_column_comment(table_name, column_name, value)
|
14
22
|
end
|
15
23
|
|
16
|
-
def
|
17
|
-
instance.
|
24
|
+
def column_comment(column_name)
|
25
|
+
instance.column_comment(table_name, column_name)
|
18
26
|
end
|
19
27
|
|
20
28
|
def instance
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Commento
|
4
|
+
class Report
|
5
|
+
COMMENTO_FOLDER_NAME = 'commento'
|
6
|
+
|
7
|
+
def initialize(data_collect_service: Commento::Services::DataCollect)
|
8
|
+
@data_collect_service = data_collect_service.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_report
|
12
|
+
@commento_data = @data_collect_service.call
|
13
|
+
FileUtils.mkdir_p(COMMENTO_FOLDER_NAME)
|
14
|
+
File.write(
|
15
|
+
"#{COMMENTO_FOLDER_NAME}/#{file_name}",
|
16
|
+
main_template.gsub('%tables_placeholder%', tables_placeholder)
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def tables_placeholder
|
23
|
+
database_comments.map do |table_data|
|
24
|
+
table_template
|
25
|
+
.gsub('%table_name%', table_data[:table_name])
|
26
|
+
.gsub('%table_comment%', table_data[:table_comment].presence || '')
|
27
|
+
.gsub('%columns_placeholder%', columns_placeholder(table_data[:table_name], table_data[:columns]))
|
28
|
+
end.join
|
29
|
+
end
|
30
|
+
|
31
|
+
def columns_placeholder(table_name, columns)
|
32
|
+
columns.map do |column_data|
|
33
|
+
full_column_name = "#{table_name}.#{column_data[:column_name]}"
|
34
|
+
column_template
|
35
|
+
.gsub('%column_name%', full_column_name)
|
36
|
+
.gsub('%column_comment%', column_data[:column_comment].presence || '')
|
37
|
+
.gsub('%data_placeholder%', data_placeholder(full_column_name))
|
38
|
+
end.join
|
39
|
+
end
|
40
|
+
|
41
|
+
def data_placeholder(full_column_name)
|
42
|
+
return '' if @commento_data[full_column_name].blank?
|
43
|
+
|
44
|
+
@commento_data[full_column_name].map do |filename|
|
45
|
+
data_template.gsub('%commento_data%', filename)
|
46
|
+
end.join
|
47
|
+
end
|
48
|
+
|
49
|
+
def database_comments
|
50
|
+
adapter.comments_for_database
|
51
|
+
end
|
52
|
+
|
53
|
+
def main_template
|
54
|
+
raise NotImplementedError
|
55
|
+
end
|
56
|
+
|
57
|
+
def table_template
|
58
|
+
raise NotImplementedError
|
59
|
+
end
|
60
|
+
|
61
|
+
def column_template
|
62
|
+
raise NotImplementedError
|
63
|
+
end
|
64
|
+
|
65
|
+
def data_template
|
66
|
+
raise NotImplementedError
|
67
|
+
end
|
68
|
+
|
69
|
+
def file_name
|
70
|
+
raise NotImplementedError
|
71
|
+
end
|
72
|
+
|
73
|
+
def adapter
|
74
|
+
Commento.adapter
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Commento
|
4
|
+
module Reports
|
5
|
+
class Html < Commento::Report
|
6
|
+
private
|
7
|
+
|
8
|
+
def main_template
|
9
|
+
[
|
10
|
+
'<!DOCTYPE html>',
|
11
|
+
'<html>',
|
12
|
+
' <head>',
|
13
|
+
" #{styles}",
|
14
|
+
' <meta charset="utf-8" />',
|
15
|
+
' </head>',
|
16
|
+
' <body>',
|
17
|
+
'%tables_placeholder%',
|
18
|
+
' </body>',
|
19
|
+
'</html>'
|
20
|
+
].join("\n")
|
21
|
+
end
|
22
|
+
|
23
|
+
def table_template
|
24
|
+
[
|
25
|
+
" <div class='table'>",
|
26
|
+
" <div class='table-header'>",
|
27
|
+
' <h3>%table_name%</h3>',
|
28
|
+
' <p>%table_comment%</p>',
|
29
|
+
' </div>',
|
30
|
+
" <div class='table-body'>",
|
31
|
+
'%columns_placeholder%',
|
32
|
+
' </div>',
|
33
|
+
" </div>\n"
|
34
|
+
].join("\n")
|
35
|
+
end
|
36
|
+
|
37
|
+
def column_template
|
38
|
+
[
|
39
|
+
" <div class='column-body'>",
|
40
|
+
' <p>%column_name%: %column_comment%</p>',
|
41
|
+
" <div class='column-data'>",
|
42
|
+
'%data_placeholder%',
|
43
|
+
' </div>',
|
44
|
+
" </div>\n"
|
45
|
+
].join("\n")
|
46
|
+
end
|
47
|
+
|
48
|
+
def data_template
|
49
|
+
' <span>%commento_data%</span>'
|
50
|
+
end
|
51
|
+
|
52
|
+
def file_name
|
53
|
+
'index.html'
|
54
|
+
end
|
55
|
+
|
56
|
+
def styles
|
57
|
+
[
|
58
|
+
'<style>',
|
59
|
+
'h3 { margin: 0 0 .25rem }',
|
60
|
+
'p { margin: 0 0 .5rem }',
|
61
|
+
'.table { padding: 0 .5rem; margin-bottom: 1rem }',
|
62
|
+
'.table-header { border-bottom: 1px solid #ddd; margin-bottom: .5rem }',
|
63
|
+
'.table-header h3 { padding: .25rem; background: #bbb }',
|
64
|
+
'.table-header p { padding: .25rem; margin: 0 }',
|
65
|
+
'.table-body { padding: 0 .25rem }',
|
66
|
+
'.column-body { margin-bottom: .5rem; }',
|
67
|
+
'.column-body p { margin: 0 }',
|
68
|
+
'.column-data { display: flex; flex-direction: column; margin: .5rem 0 }',
|
69
|
+
'.column-data span { font-style: italic; padding-left: 1rem }',
|
70
|
+
'</style>'
|
71
|
+
].join
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Commento
|
4
|
+
module Services
|
5
|
+
class DataCollect
|
6
|
+
COMMENTO_MATCH_REGEXP = /^[ \t]*# commento:.+$/.freeze
|
7
|
+
|
8
|
+
# @data contains data with next format
|
9
|
+
# {
|
10
|
+
# 'fantasy_sports.points' => [
|
11
|
+
# 'app/services/some_service.rb:11'
|
12
|
+
# ]
|
13
|
+
# }
|
14
|
+
# key - table_name.column_name
|
15
|
+
# values - lines of files where these columns are changed in the code
|
16
|
+
def initialize
|
17
|
+
@data = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def call
|
21
|
+
configuration.include_folders.each { |include_folder| iterate_folder(include_folder) }
|
22
|
+
@data
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def iterate_folder(include_folder)
|
28
|
+
Dir.glob("#{include_folder}/**/*.rb").each do |filename|
|
29
|
+
next if exclude_folders.include?(filename.split('/')[0..-2].join('/'))
|
30
|
+
|
31
|
+
File.open(filename) { |lines| iterate_filelines(lines, filename) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def iterate_filelines(lines, filename)
|
36
|
+
lines.each.with_index(1) do |line, index|
|
37
|
+
next unless COMMENTO_MATCH_REGEXP.match?(line)
|
38
|
+
|
39
|
+
field = line.strip.split('# commento: ')[-1]
|
40
|
+
@data[field] ||= []
|
41
|
+
@data[field] << "#{filename}:#{index}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def exclude_folders
|
46
|
+
@exclude_folders ||= configuration.exclude_folders
|
47
|
+
end
|
48
|
+
|
49
|
+
def configuration
|
50
|
+
Commento.configuration
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/commento/version.rb
CHANGED
data/lib/commento.rb
CHANGED
@@ -6,17 +6,20 @@ require 'commento/version'
|
|
6
6
|
require 'commento/configuration'
|
7
7
|
require 'commento/dsl'
|
8
8
|
require 'commento/helpers'
|
9
|
+
require 'commento/report'
|
10
|
+
require 'commento/reports/html'
|
11
|
+
require 'commento/services/data_collect'
|
9
12
|
|
10
13
|
module Commento
|
11
14
|
extend self
|
12
15
|
extend Forwardable
|
13
16
|
|
14
|
-
# Public: Given an adapter returns a handy DSL to all the
|
17
|
+
# Public: Given an adapter returns a handy DSL to all the commento goodness.
|
15
18
|
def new(adapter)
|
16
19
|
DSL.new(adapter)
|
17
20
|
end
|
18
21
|
|
19
|
-
# Public: Configure
|
22
|
+
# Public: Configure commento.
|
20
23
|
#
|
21
24
|
# Commento.configure do |config|
|
22
25
|
# config.adapter = Commento::Adapters::ActiveRecord.new
|
@@ -31,7 +34,7 @@ module Commento
|
|
31
34
|
@configuration ||= Configuration.new
|
32
35
|
end
|
33
36
|
|
34
|
-
# Public: Default per thread
|
37
|
+
# Public: Default per thread commento instance if configured.
|
35
38
|
# Returns Commento::DSL instance.
|
36
39
|
def instance
|
37
40
|
Thread.current[:commento_instance] ||= new(configuration.adapter)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: commento
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bogdanov Anton
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-08-
|
11
|
+
date: 2023-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -80,6 +80,9 @@ files:
|
|
80
80
|
- lib/commento/configuration.rb
|
81
81
|
- lib/commento/dsl.rb
|
82
82
|
- lib/commento/helpers.rb
|
83
|
+
- lib/commento/report.rb
|
84
|
+
- lib/commento/reports/html.rb
|
85
|
+
- lib/commento/services/data_collect.rb
|
83
86
|
- lib/commento/version.rb
|
84
87
|
homepage: https://github.com/kortirso/commento
|
85
88
|
licenses:
|