sequel-annotate 1.3.1 → 1.4.0
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/CHANGELOG +6 -0
- data/README.rdoc +9 -0
- data/lib/sequel/annotate.rb +68 -39
- data/spec/sequel-annotate_spec.rb +43 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00ae8faeab78d5bf3db91c08be72e190c23c5937aff9a134b0f60d8a8a28fd46
|
4
|
+
data.tar.gz: 3324fec486219f6324ff300046ee1f80608c84621f3eb159e5192a0e7f42bdbf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 898b3c06f2728c69570071f04b14b506925d87e794b63fdbe0882bc710e03fc76c6c824f0c01384f96e19b1ee59894766722fa4bb12c668068794d632c3651c7
|
7
|
+
data.tar.gz: 0ac394e89f13a0d8f005b90ff7263fe882ce67aca63f9d19b7327d0561eb7666df04cb6e4031a01ad6f318c87372b7d59ae9aba39b38e0ffed870036ad1ff035
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
=== 1.4.0 (2018-11-15)
|
2
|
+
|
3
|
+
* Support adding borders to the beginning and end of comments via :border option (kreynolds) (#9)
|
4
|
+
|
5
|
+
* Support excluding indexes, constraints, and triggers from annotation via options (kreynolds) (#9)
|
6
|
+
|
1
7
|
=== 1.3.1 (2018-09-27)
|
2
8
|
|
3
9
|
* Make sure all annotation lines are commented by handling newlines inside annotations (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -83,6 +83,15 @@ Then you can use the +:namespace+ option to set the namespace to use:
|
|
83
83
|
|
84
84
|
Sequel::Annotate.annotate(Dir['models/*.rb'], namespace: 'ModelNamespace')
|
85
85
|
|
86
|
+
For PostgreSQL, you can optionally leave out indexes, foreign_keys, references,
|
87
|
+
triggers, and constraints by passing in false as a parameter as follows:
|
88
|
+
|
89
|
+
Sequel::Annotate.annotate(Dir['models/*.rb'], foreign_keys: false, :indexes: false, constraints: false)
|
90
|
+
|
91
|
+
The columns section can have a border on the top and bottom for easier visual distinction by setting the :border option to true
|
92
|
+
|
93
|
+
Sequel::Annotate.annotate(Dir['models/*.rb'], border: true)
|
94
|
+
|
86
95
|
=== Rake Task
|
87
96
|
|
88
97
|
Here's an example rake task for sequel-annotate:
|
data/lib/sequel/annotate.rb
CHANGED
@@ -41,7 +41,7 @@ module Sequel
|
|
41
41
|
|
42
42
|
if options[:position] == :before
|
43
43
|
current = current.gsub(/\A#\sTable[^\n\r]+\r?\n(?:#[^\n\r]*\r?\n)*/m, '').lstrip
|
44
|
-
current = "#{schema_comment}#{$/}#{$/}#{current}"
|
44
|
+
current = "#{schema_comment(options)}#{$/}#{$/}#{current}"
|
45
45
|
else
|
46
46
|
if m = current.reverse.match(/#{"#{$/}# Table: ".reverse}/m)
|
47
47
|
offset = current.length - m.end(0) + 1
|
@@ -52,7 +52,7 @@ module Sequel
|
|
52
52
|
current = current[0...offset].rstrip
|
53
53
|
end
|
54
54
|
end
|
55
|
-
current += "#{$/}#{$/}#{schema_comment}"
|
55
|
+
current += "#{$/}#{$/}#{schema_comment(options)}"
|
56
56
|
end
|
57
57
|
|
58
58
|
if orig != current
|
@@ -67,17 +67,36 @@ module Sequel
|
|
67
67
|
# key constraints in this table referencing other tables.
|
68
68
|
# On PostgreSQL, also includes check constraints, triggers,
|
69
69
|
# and foreign key constraints in other tables referencing this table.
|
70
|
-
|
70
|
+
#
|
71
|
+
# Options:
|
72
|
+
# :border :: Include a border above and below the comment.
|
73
|
+
# :indexes :: Do not include indexes in annotation if set to +false+.
|
74
|
+
# :foreign_keys :: Do not include foreign key constraints in annotation if set to +false+.
|
75
|
+
#
|
76
|
+
# PostgreSQL-specific options:
|
77
|
+
# :constraints :: Do not include check constraints if set to +false+.
|
78
|
+
# :references :: Do not include foreign key constraints in other tables referencing
|
79
|
+
# this table if set to +false+.
|
80
|
+
# :triggers :: Do not include triggers in annotation if set to +false+.
|
81
|
+
def schema_comment(options = {})
|
71
82
|
output = []
|
72
83
|
output << "# Table: #{model.table_name}"
|
73
84
|
|
74
85
|
meth = :"_schema_comment_#{model.db.database_type}"
|
75
86
|
if respond_to?(meth, true)
|
76
|
-
send(meth, output)
|
87
|
+
send(meth, output, options)
|
77
88
|
else
|
78
89
|
schema_comment_columns(output)
|
79
|
-
schema_comment_indexes(output)
|
80
|
-
schema_comment_foreign_keys(output)
|
90
|
+
schema_comment_indexes(output) unless options[:indexes] == false
|
91
|
+
schema_comment_foreign_keys(output) unless options[:foreign_keys] == false
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
# Add beginning and end to the table if specified
|
96
|
+
if options[:border]
|
97
|
+
border = "# #{'-' * (output.map(&:size).max - 2)}"
|
98
|
+
output.push(border)
|
99
|
+
output.insert(1, border)
|
81
100
|
end
|
82
101
|
|
83
102
|
output.join($/)
|
@@ -107,87 +126,97 @@ module Sequel
|
|
107
126
|
|
108
127
|
# Use the standard columns schema output, but use PostgreSQL specific
|
109
128
|
# code for additional schema information.
|
110
|
-
def _schema_comment_postgres(output)
|
111
|
-
schema_comment_columns(output)
|
129
|
+
def _schema_comment_postgres(output, options = {})
|
130
|
+
schema_comment_columns(output, options)
|
112
131
|
oid = model.db.send(:regclass_oid, model.table_name)
|
113
132
|
|
114
133
|
# These queries below are all based on the queries that psql
|
115
134
|
# uses, captured using the -E option to psql.
|
116
135
|
|
117
|
-
|
136
|
+
unless options[:indexes] == false
|
137
|
+
rows = model.db.fetch(<<SQL, :oid=>oid).all
|
118
138
|
SELECT c2.relname, i.indisprimary, i.indisunique, pg_catalog.pg_get_indexdef(i.indexrelid, 0, true)
|
119
139
|
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i
|
120
140
|
LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ('p','u','x'))
|
121
141
|
WHERE c.oid = :oid AND c.oid = i.indrelid AND i.indexrelid = c2.oid AND indisvalid
|
122
142
|
ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname;
|
123
143
|
SQL
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
144
|
+
unless rows.empty?
|
145
|
+
output << "# Indexes:"
|
146
|
+
rows = rows.map do |r|
|
147
|
+
[r[:relname], "#{"PRIMARY KEY " if r[:indisprimary]}#{"UNIQUE " if r[:indisunique] && !r[:indisprimary]}#{r[:pg_get_indexdef].match(/USING (.+)\z/m)[1]}"]
|
148
|
+
end
|
149
|
+
output.concat(align(rows))
|
128
150
|
end
|
129
|
-
output.concat(align(rows))
|
130
151
|
end
|
131
152
|
|
132
|
-
|
153
|
+
unless options[:constraints] == false
|
154
|
+
rows = model.db.fetch(<<SQL, :oid=>oid).all
|
133
155
|
SELECT r.conname, pg_catalog.pg_get_constraintdef(r.oid, true)
|
134
156
|
FROM pg_catalog.pg_constraint r
|
135
157
|
WHERE r.conrelid = :oid AND r.contype = 'c'
|
136
158
|
ORDER BY 1;
|
137
159
|
SQL
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
160
|
+
unless rows.empty?
|
161
|
+
output << "# Check constraints:"
|
162
|
+
rows = rows.map do |r|
|
163
|
+
[r[:conname], r[:pg_get_constraintdef].match(/CHECK (.+)\z/m)[1]]
|
164
|
+
end
|
165
|
+
output.concat(align(rows))
|
142
166
|
end
|
143
|
-
output.concat(align(rows))
|
144
167
|
end
|
145
168
|
|
146
|
-
|
169
|
+
unless options[:foreign_keys] == false
|
170
|
+
rows = model.db.fetch(<<SQL, :oid=>oid).all
|
147
171
|
SELECT conname,
|
148
172
|
pg_catalog.pg_get_constraintdef(r.oid, true) as condef
|
149
173
|
FROM pg_catalog.pg_constraint r
|
150
174
|
WHERE r.conrelid = :oid AND r.contype = 'f' ORDER BY 1;
|
151
175
|
SQL
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
176
|
+
unless rows.empty?
|
177
|
+
output << "# Foreign key constraints:"
|
178
|
+
rows = rows.map do |r|
|
179
|
+
[r[:conname], r[:condef].match(/FOREIGN KEY (.+)\z/m)[1]]
|
180
|
+
end
|
181
|
+
output.concat(align(rows))
|
156
182
|
end
|
157
|
-
output.concat(align(rows))
|
158
183
|
end
|
159
184
|
|
160
|
-
|
185
|
+
unless options[:references] == false
|
186
|
+
rows = model.db.fetch(<<SQL, :oid=>oid).all
|
161
187
|
SELECT conname, conrelid::pg_catalog.regclass,
|
162
188
|
pg_catalog.pg_get_constraintdef(c.oid, true) as condef
|
163
189
|
FROM pg_catalog.pg_constraint c
|
164
190
|
WHERE c.confrelid = :oid AND c.contype = 'f' ORDER BY 2, 1;
|
165
191
|
SQL
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
192
|
+
unless rows.empty?
|
193
|
+
output << "# Referenced By:"
|
194
|
+
rows = rows.map do |r|
|
195
|
+
[r[:conrelid], r[:conname], r[:condef].match(/FOREIGN KEY (.+)\z/m)[1]]
|
196
|
+
end
|
197
|
+
output.concat(align(rows))
|
170
198
|
end
|
171
|
-
output.concat(align(rows))
|
172
199
|
end
|
173
200
|
|
174
|
-
|
201
|
+
unless options[:triggers] == false
|
202
|
+
rows = model.db.fetch(<<SQL, :oid=>oid).all
|
175
203
|
SELECT t.tgname, pg_catalog.pg_get_triggerdef(t.oid, true), t.tgenabled, t.tgisinternal
|
176
204
|
FROM pg_catalog.pg_trigger t
|
177
205
|
WHERE t.tgrelid = :oid AND (NOT t.tgisinternal OR (t.tgisinternal AND t.tgenabled = 'D'))
|
178
206
|
ORDER BY 1;
|
179
207
|
SQL
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
208
|
+
unless rows.empty?
|
209
|
+
output << "# Triggers:"
|
210
|
+
rows = rows.map do |r|
|
211
|
+
[r[:tgname], r[:pg_get_triggerdef].match(/((?:BEFORE|AFTER) .+)\z/m)[1]]
|
212
|
+
end
|
213
|
+
output.concat(align(rows))
|
184
214
|
end
|
185
|
-
output.concat(align(rows))
|
186
215
|
end
|
187
216
|
end
|
188
217
|
|
189
218
|
# The standard column schema information to output.
|
190
|
-
def schema_comment_columns(output)
|
219
|
+
def schema_comment_columns(output, options = {})
|
191
220
|
if cpk = model.primary_key.is_a?(Array)
|
192
221
|
output << "# Primary Key: (#{model.primary_key.join(', ')})"
|
193
222
|
end
|
@@ -107,6 +107,46 @@ describe Sequel::Annotate do
|
|
107
107
|
Dir['spec/tmp/*.rb'].each{|f| File.delete(f)}
|
108
108
|
end
|
109
109
|
|
110
|
+
it "#schema_info should not return sections we set to false" do
|
111
|
+
Sequel::Annotate.new(Item).schema_comment(:indexes => false, :constraints => false, :foreign_keys => false, :triggers => false).must_equal(fix_pg_comment((<<OUTPUT).chomp))
|
112
|
+
# Table: items
|
113
|
+
# Columns:
|
114
|
+
# id | integer | PRIMARY KEY DEFAULT nextval('items_id_seq'::regclass)
|
115
|
+
# category_id | integer | NOT NULL
|
116
|
+
# manufacturer_name | character varying(50) |
|
117
|
+
# manufacturer_location | text |
|
118
|
+
# in_stock | boolean | DEFAULT false
|
119
|
+
# name | text | DEFAULT 'John'::text
|
120
|
+
# price | double precision | DEFAULT 0
|
121
|
+
OUTPUT
|
122
|
+
|
123
|
+
Sequel::Annotate.new(Category).schema_comment(:references => false).must_equal(fix_pg_comment((<<OUTPUT).chomp))
|
124
|
+
# Table: categories
|
125
|
+
# Columns:
|
126
|
+
# id | integer | PRIMARY KEY DEFAULT nextval('categories_id_seq'::regclass)
|
127
|
+
# name | text | NOT NULL
|
128
|
+
# Indexes:
|
129
|
+
# categories_pkey | PRIMARY KEY btree (id)
|
130
|
+
# categories_name_key | UNIQUE btree (name)
|
131
|
+
OUTPUT
|
132
|
+
end
|
133
|
+
|
134
|
+
it "#schema_info should return a border if we want one" do
|
135
|
+
Sequel::Annotate.new(Item).schema_comment(:border => true, :indexes => false, :constraints => false, :foreign_keys => false, :triggers => false).gsub(/----+/, '---').must_equal(fix_pg_comment((<<OUTPUT).chomp))
|
136
|
+
# Table: items
|
137
|
+
# ---
|
138
|
+
# Columns:
|
139
|
+
# id | integer | PRIMARY KEY DEFAULT nextval('items_id_seq'::regclass)
|
140
|
+
# category_id | integer | NOT NULL
|
141
|
+
# manufacturer_name | character varying(50) |
|
142
|
+
# manufacturer_location | text |
|
143
|
+
# in_stock | boolean | DEFAULT false
|
144
|
+
# name | text | DEFAULT 'John'::text
|
145
|
+
# price | double precision | DEFAULT 0
|
146
|
+
# ---
|
147
|
+
OUTPUT
|
148
|
+
end
|
149
|
+
|
110
150
|
it "#schema_info should return the model schema comment" do
|
111
151
|
Sequel::Annotate.new(Item).schema_comment.must_equal(fix_pg_comment((<<OUTPUT).chomp))
|
112
152
|
# Table: items
|
@@ -238,5 +278,8 @@ OUTPUT
|
|
238
278
|
FileUtils.cp('spec/namespaced/itm_unannotated.rb', 'spec/tmp/')
|
239
279
|
Sequel::Annotate.annotate(["spec/tmp/itm_unannotated.rb"], :namespace=>'ModelNamespace')
|
240
280
|
File.read("spec/tmp/itm_unannotated.rb").must_equal fix_pg_comment(File.read('spec/namespaced/itm_annotated.rb'))
|
281
|
+
Sequel::Annotate.annotate(["spec/tmp/itm_unannotated.rb"], :namespace=>'ModelNamespace', :border=>true)
|
282
|
+
Sequel::Annotate.annotate(["spec/tmp/itm_unannotated.rb"], :namespace=>'ModelNamespace')
|
283
|
+
File.read("spec/tmp/itm_unannotated.rb").must_equal fix_pg_comment(File.read('spec/namespaced/itm_annotated.rb'))
|
241
284
|
end
|
242
285
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel-annotate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|