sequel-annotate 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|