sequel-annotate 1.2.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +36 -0
  3. data/README.rdoc +39 -1
  4. data/Rakefile +2 -10
  5. data/lib/sequel/annotate.rb +134 -45
  6. data/spec/annotated_after/manufacturer.rb +1 -1
  7. data/spec/annotated_after/scomplexdataset.rb +7 -0
  8. data/spec/annotated_after/sitemwithcoding.rb +20 -0
  9. data/spec/annotated_after/sitemwithencoding.rb +20 -0
  10. data/spec/annotated_after/sitemwithfrozenliteral.rb +20 -0
  11. data/spec/annotated_after/sitemwithwarnindent.rb +20 -0
  12. data/spec/annotated_after/sitemwithwarnpastscope.rb +21 -0
  13. data/spec/annotated_before/manufacturer.rb +1 -1
  14. data/spec/annotated_before/scomplexdataset.rb +7 -0
  15. data/spec/annotated_before/sitemwithcoding.rb +20 -0
  16. data/spec/annotated_before/sitemwithencoding.rb +20 -0
  17. data/spec/annotated_before/sitemwithfrozenliteral.rb +20 -0
  18. data/spec/annotated_before/sitemwithwarnindent.rb +20 -0
  19. data/spec/annotated_before/sitemwithwarnpastscope.rb +21 -0
  20. data/spec/namespaced/itm_annotated.rb +24 -0
  21. data/spec/namespaced/itm_unannotated.rb +3 -0
  22. data/spec/sequel-annotate_spec.rb +170 -10
  23. data/spec/unannotated/manufacturer.rb +1 -1
  24. data/spec/unannotated/not_model.rb +4 -0
  25. data/spec/unannotated/scomplexdataset.rb +7 -0
  26. data/spec/unannotated/sitemwithcoding.rb +4 -0
  27. data/spec/unannotated/sitemwithencoding.rb +4 -0
  28. data/spec/unannotated/sitemwithfrozenliteral.rb +4 -0
  29. data/spec/unannotated/sitemwithmagiccomment.rb +4 -0
  30. data/spec/unannotated/sitemwithwarnindent.rb +4 -0
  31. data/spec/unannotated/sitemwithwarnpastscope.rb +5 -0
  32. metadata +44 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 112ffb3483f88eacd72945f7890fac2d21b8cfa8f4559b13210eb76d80e36e53
4
- data.tar.gz: b2a580e9ddc239a8d2fb948ac5c571733915d9badf2c84385f3d21aaede7ab71
3
+ metadata.gz: 42122bfc730bb5345c90160c5a17b0861c3a5a8308dfc6a008c1fccc0b73fe3e
4
+ data.tar.gz: 7bbb33c84261d97a66c17b942c19fc0b432d4029b8e384f148ec79ddf96c196e
5
5
  SHA512:
6
- metadata.gz: edcaf9424b611f0ec0b08fb511ef2f7f9d245756040e8adf829101264846c0768f24e4d52d143d64fed4e8a05d58aa820758023e6f1d49e83ed0b87e64c0aa70
7
- data.tar.gz: 267dbf8b5693e541abbe3d97154adddfd839d2ea0e3e88475146c0d4739b6f1b42cfd2d01959984d8d7a68851375875a0e11ec28fbf1d5ab8b5c942f2d9f9efd
6
+ metadata.gz: 4ee1e34b6317be4e57f113a33e47c83190157ee3cbbae9cfd209c8806895aacc5e44604bbf2f0cfcbee1114a8822ed0c36a9ccdad628cb66daab58873d9020b8
7
+ data.tar.gz: d27e5074fb1c7642993647185605d0d714482d1f9ce5bc9e7b58817872f69674d0e803fa68210d0d73b2c176a479a44224a3678c602b1681116acae8dbf16d8c
data/CHANGELOG CHANGED
@@ -1,3 +1,39 @@
1
+ === 1.6.0 (2020-10-05)
2
+
3
+ * Add support for :namespace=>true option to attempt to automatically determine namespace (adam12) (#20)
4
+
5
+ * Skip models that select from a subquery (adam12, jeremyevans) (#17)
6
+
7
+ * Allow files to be skipped with sequel-annotate: false magic comment (adam12) (#18)
8
+
9
+ * Ignore opening of singleton classes with class << when looking for models (adam12) (#16)
10
+
11
+ === 1.5.0 (2020-05-04)
12
+
13
+ * Add support for magic comments in model files when using the :position=>:before option (qortex, jeremyevans) (#15)
14
+
15
+ * Add support for PostgreSQL column comments (rgalanakis, jeremyevans) (#14)
16
+
17
+ * Respect domain types on PostgreSQL (chanks) (#13)
18
+
19
+ * Make schema comments handle table names that aren't just symbols (chanks) (#12)
20
+
21
+ === 1.4.0 (2018-11-15)
22
+
23
+ * Support adding borders to the beginning and end of comments via :border option (kreynolds) (#9)
24
+
25
+ * Support excluding indexes, constraints, and triggers from annotation via options (kreynolds) (#9)
26
+
27
+ === 1.3.1 (2018-09-27)
28
+
29
+ * Make sure all annotation lines are commented by handling newlines inside annotations (jeremyevans)
30
+
31
+ === 1.3.0 (2018-07-17)
32
+
33
+ * Support :namespace option to specify namespace to add for models nested in namespaces (jeremyevans)
34
+
35
+ * Make Sequel::Annotate.annotate support STI classes and custom abstract base classes (a0s) (#7)
36
+
1
37
  === 1.2.0 (2018-04-02)
2
38
 
3
39
  * Handle PostgreSQL 10+ identity columns when running on Sequel 5.7+ (jeremyevans)
@@ -5,7 +5,7 @@ default, it includes information on columns, indexes, and foreign key
5
5
  constraints for the current table.
6
6
 
7
7
  On PostgreSQL, this includes more advanced information, including
8
- check constraints, triggers, and foreign keys constraints for other
8
+ check constraints, triggers, comments, and foreign keys constraints for other
9
9
  tables that reference the current table.
10
10
 
11
11
  == Example
@@ -72,16 +72,54 @@ or
72
72
  sa = Sequel::Annotate.new(Item)
73
73
  sa.annotate('models/item.rb', position: :before)
74
74
 
75
+ If your models are nested in a namespace:
76
+
77
+ module ModelNamespace
78
+ class Item < Sequel::Model
79
+ end
80
+ end
81
+
82
+ Then you can use the +:namespace+ option to set the namespace to use:
83
+
84
+ Sequel::Annotate.annotate(Dir['models/*.rb'], namespace: 'ModelNamespace')
85
+
86
+ For PostgreSQL, you can optionally leave out indexes, foreign_keys, references,
87
+ triggers, comments, and constraints by passing in false as a parameter as follows:
88
+
89
+ Sequel::Annotate.annotate(Dir['models/*.rb'], foreign_keys: false,
90
+ :indexes: false, constraints: false, comments: false)
91
+
92
+ The columns section can have a border on the top and bottom for easier visual distinction by setting the :border option to true
93
+
94
+ Sequel::Annotate.annotate(Dir['models/*.rb'], border: true)
95
+
96
+ Models that use datasets that select from subqueries are automatically skipped,
97
+ as annotations don't really make sense for them since they are not backed by a
98
+ table. You can skip other models by using a <tt># sequel-annotate: false</tt>
99
+ magic comment somewhere in the file.
100
+
75
101
  === Rake Task
76
102
 
77
103
  Here's an example rake task for sequel-annotate:
78
104
 
79
105
  desc "Update model annotations"
80
106
  task :annotate do
107
+ # Load the models first
108
+ Dir['models/*.rb'].each{|f| require_relative f}
109
+
81
110
  require 'sequel/annotate'
82
111
  Sequel::Annotate.annotate(Dir['models/*.rb'])
83
112
  end
84
113
 
114
+ == Running Tests
115
+
116
+ Tests of sequel-annotate itself can be run with rake:
117
+
118
+ rake
119
+
120
+ Set the SEQUEL_ANNOTATE_SPEC_POSTGRES_URL environment variable or appropriate
121
+ libpq environment variables to specify which PostgreSQL database to connect to.
122
+
85
123
  == License
86
124
 
87
125
  MIT
data/Rakefile CHANGED
@@ -28,19 +28,11 @@ begin
28
28
  rescue Gem::LoadError
29
29
  end
30
30
 
31
- rdoc_task_class = begin
32
- require "rdoc/task"
33
- RDoc::Task
34
- rescue LoadError
35
- require "rake/rdoctask"
36
- Rake::RDocTask
37
- end
38
-
39
31
  RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
40
32
 
41
- rdoc_task_class.new do |rdoc|
33
+ require "rdoc/task"
34
+ RDoc::Task.new do |rdoc|
42
35
  rdoc.rdoc_dir = "rdoc"
43
36
  rdoc.options += RDOC_OPTS
44
37
  rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/**/*.rb"
45
38
  end
46
-
@@ -10,9 +10,29 @@ module Sequel
10
10
  # Sequel::Annotate.annotate(Dir['models/*.rb'])
11
11
  def self.annotate(paths, options = {})
12
12
  Sequel.extension :inflector
13
+ namespace = options[:namespace]
14
+
13
15
  paths.each do |path|
14
- if match = File.read(path).match(/class (\S+)\s*<\s*Sequel::Model/)
15
- new(match[1].constantize).annotate(path, options)
16
+ text = File.read(path)
17
+
18
+ next if text.match(/^#\s+sequel-annotate:\s+false$/i)
19
+
20
+ name = nil
21
+ if namespace == true
22
+ constants = text.scan(/\bmodule ([^\s]+)|class ([^\s<]+)\s*</).flatten.compact
23
+ name = constants.join("::") if constants.any?
24
+ elsif match = text.match(/class ([^\s<]+)\s*</)
25
+ name = match[1]
26
+ if namespace
27
+ name = "#{namespace}::#{name}"
28
+ end
29
+ end
30
+
31
+ if name
32
+ klass = name.constantize
33
+ if klass.ancestors.include?(Sequel::Model)
34
+ new(klass).annotate(path, options)
35
+ end
16
36
  end
17
37
  end
18
38
  end
@@ -28,11 +48,18 @@ module Sequel
28
48
  # Append the schema comment (or replace it if one already exists) to
29
49
  # the file at the given path.
30
50
  def annotate(path, options = {})
51
+ return if skip_model?
52
+
31
53
  orig = current = File.read(path).rstrip
32
54
 
33
55
  if options[:position] == :before
56
+ if current =~ /\A((?:^\s*$|^#\s*(?:frozen_string_literal|coding|encoding|warn_indent|warn_past_scope)[^\n]*\s*)*)/m
57
+ magic_comments = $1
58
+ current.slice!(0, magic_comments.length)
59
+ end
60
+
34
61
  current = current.gsub(/\A#\sTable[^\n\r]+\r?\n(?:#[^\n\r]*\r?\n)*/m, '').lstrip
35
- current = "#{schema_comment}#{$/}#{$/}#{current}"
62
+ current = "#{magic_comments}#{schema_comment(options)}#{$/}#{$/}#{current}"
36
63
  else
37
64
  if m = current.reverse.match(/#{"#{$/}# Table: ".reverse}/m)
38
65
  offset = current.length - m.end(0) + 1
@@ -43,7 +70,7 @@ module Sequel
43
70
  current = current[0...offset].rstrip
44
71
  end
45
72
  end
46
- current += "#{$/}#{$/}#{schema_comment}"
73
+ current += "#{$/}#{$/}#{schema_comment(options)}"
47
74
  end
48
75
 
49
76
  if orig != current
@@ -58,17 +85,38 @@ module Sequel
58
85
  # key constraints in this table referencing other tables.
59
86
  # On PostgreSQL, also includes check constraints, triggers,
60
87
  # and foreign key constraints in other tables referencing this table.
61
- def schema_comment
88
+ #
89
+ # Options:
90
+ # :border :: Include a border above and below the comment.
91
+ # :indexes :: Do not include indexes in annotation if set to +false+.
92
+ # :foreign_keys :: Do not include foreign key constraints in annotation if set to +false+.
93
+ #
94
+ # PostgreSQL-specific options:
95
+ # :constraints :: Do not include check constraints if set to +false+.
96
+ # :references :: Do not include foreign key constraints in other tables referencing
97
+ # this table if set to +false+.
98
+ # :triggers :: Do not include triggers in annotation if set to +false+.
99
+ def schema_comment(options = {})
100
+ return "" if skip_model?
101
+
62
102
  output = []
63
- output << "# Table: #{model.table_name}"
103
+ output << "# Table: #{model.dataset.with_quote_identifiers(false).literal(model.table_name)}"
64
104
 
65
105
  meth = :"_schema_comment_#{model.db.database_type}"
66
106
  if respond_to?(meth, true)
67
- send(meth, output)
107
+ send(meth, output, options)
68
108
  else
69
109
  schema_comment_columns(output)
70
- schema_comment_indexes(output)
71
- schema_comment_foreign_keys(output)
110
+ schema_comment_indexes(output) unless options[:indexes] == false
111
+ schema_comment_foreign_keys(output) unless options[:foreign_keys] == false
112
+ end
113
+
114
+
115
+ # Add beginning and end to the table if specified
116
+ if options[:border]
117
+ border = "# #{'-' * (output.map(&:size).max - 2)}"
118
+ output.push(border)
119
+ output.insert(1, border)
72
120
  end
73
121
 
74
122
  output.join($/)
@@ -87,105 +135,138 @@ module Sequel
87
135
 
88
136
  cols.times do |i|
89
137
  rows.each do |r|
90
- lengths[i] = r[i].length if r[i].length > lengths[i]
138
+ lengths[i] = r[i].length if r[i] && r[i].length > lengths[i]
91
139
  end
92
140
  end
93
141
 
94
142
  rows.map do |r|
95
- "# #{r.zip(lengths).map{|c, l| c.ljust(l)}.join(' | ')}".strip
143
+ "# #{r.zip(lengths).map{|c, l| c.to_s.ljust(l).gsub("\n", "\n# ")}.join(' | ')}".strip
96
144
  end
97
145
  end
98
146
 
99
147
  # Use the standard columns schema output, but use PostgreSQL specific
100
148
  # code for additional schema information.
101
- def _schema_comment_postgres(output)
102
- schema_comment_columns(output)
149
+ def _schema_comment_postgres(output, options = {})
150
+ schema_comment_columns(output, options)
103
151
  oid = model.db.send(:regclass_oid, model.table_name)
104
152
 
105
153
  # These queries below are all based on the queries that psql
106
154
  # uses, captured using the -E option to psql.
107
155
 
108
- rows = model.db.fetch(<<SQL, :oid=>oid).all
156
+ unless options[:indexes] == false
157
+ rows = model.db.fetch(<<SQL, :oid=>oid).all
109
158
  SELECT c2.relname, i.indisprimary, i.indisunique, pg_catalog.pg_get_indexdef(i.indexrelid, 0, true)
110
159
  FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i
111
160
  LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ('p','u','x'))
112
161
  WHERE c.oid = :oid AND c.oid = i.indrelid AND i.indexrelid = c2.oid AND indisvalid
113
162
  ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname;
114
163
  SQL
115
- unless rows.empty?
116
- output << "# Indexes:"
117
- rows = rows.map do |r|
118
- [r[:relname], "#{"PRIMARY KEY " if r[:indisprimary]}#{"UNIQUE " if r[:indisunique] && !r[:indisprimary]}#{r[:pg_get_indexdef].match(/USING (.+)\z/m)[1]}"]
164
+ unless rows.empty?
165
+ output << "# Indexes:"
166
+ rows = rows.map do |r|
167
+ [r[:relname], "#{"PRIMARY KEY " if r[:indisprimary]}#{"UNIQUE " if r[:indisunique] && !r[:indisprimary]}#{r[:pg_get_indexdef].match(/USING (.+)\z/m)[1]}"]
168
+ end
169
+ output.concat(align(rows))
119
170
  end
120
- output.concat(align(rows))
121
171
  end
122
172
 
123
- rows = model.db.fetch(<<SQL, :oid=>oid).all
173
+ unless options[:constraints] == false
174
+ rows = model.db.fetch(<<SQL, :oid=>oid).all
124
175
  SELECT r.conname, pg_catalog.pg_get_constraintdef(r.oid, true)
125
176
  FROM pg_catalog.pg_constraint r
126
177
  WHERE r.conrelid = :oid AND r.contype = 'c'
127
178
  ORDER BY 1;
128
179
  SQL
129
- unless rows.empty?
130
- output << "# Check constraints:"
131
- rows = rows.map do |r|
132
- [r[:conname], r[:pg_get_constraintdef].match(/CHECK (.+)\z/m)[1]]
180
+ unless rows.empty?
181
+ output << "# Check constraints:"
182
+ rows = rows.map do |r|
183
+ [r[:conname], r[:pg_get_constraintdef].match(/CHECK (.+)\z/m)[1]]
184
+ end
185
+ output.concat(align(rows))
133
186
  end
134
- output.concat(align(rows))
135
187
  end
136
188
 
137
- rows = model.db.fetch(<<SQL, :oid=>oid).all
189
+ unless options[:foreign_keys] == false
190
+ rows = model.db.fetch(<<SQL, :oid=>oid).all
138
191
  SELECT conname,
139
192
  pg_catalog.pg_get_constraintdef(r.oid, true) as condef
140
193
  FROM pg_catalog.pg_constraint r
141
194
  WHERE r.conrelid = :oid AND r.contype = 'f' ORDER BY 1;
142
195
  SQL
143
- unless rows.empty?
144
- output << "# Foreign key constraints:"
145
- rows = rows.map do |r|
146
- [r[:conname], r[:condef].match(/FOREIGN KEY (.+)\z/m)[1]]
196
+ unless rows.empty?
197
+ output << "# Foreign key constraints:"
198
+ rows = rows.map do |r|
199
+ [r[:conname], r[:condef].match(/FOREIGN KEY (.+)\z/m)[1]]
200
+ end
201
+ output.concat(align(rows))
147
202
  end
148
- output.concat(align(rows))
149
203
  end
150
204
 
151
- rows = model.db.fetch(<<SQL, :oid=>oid).all
205
+ unless options[:references] == false
206
+ rows = model.db.fetch(<<SQL, :oid=>oid).all
152
207
  SELECT conname, conrelid::pg_catalog.regclass,
153
208
  pg_catalog.pg_get_constraintdef(c.oid, true) as condef
154
209
  FROM pg_catalog.pg_constraint c
155
210
  WHERE c.confrelid = :oid AND c.contype = 'f' ORDER BY 2, 1;
156
211
  SQL
157
- unless rows.empty?
158
- output << "# Referenced By:"
159
- rows = rows.map do |r|
160
- [r[:conrelid], r[:conname], r[:condef].match(/FOREIGN KEY (.+)\z/m)[1]]
212
+ unless rows.empty?
213
+ output << "# Referenced By:"
214
+ rows = rows.map do |r|
215
+ [r[:conrelid], r[:conname], r[:condef].match(/FOREIGN KEY (.+)\z/m)[1]]
216
+ end
217
+ output.concat(align(rows))
161
218
  end
162
- output.concat(align(rows))
163
219
  end
164
220
 
165
- rows = model.db.fetch(<<SQL, :oid=>oid).all
221
+ unless options[:triggers] == false
222
+ rows = model.db.fetch(<<SQL, :oid=>oid).all
166
223
  SELECT t.tgname, pg_catalog.pg_get_triggerdef(t.oid, true), t.tgenabled, t.tgisinternal
167
224
  FROM pg_catalog.pg_trigger t
168
225
  WHERE t.tgrelid = :oid AND (NOT t.tgisinternal OR (t.tgisinternal AND t.tgenabled = 'D'))
169
226
  ORDER BY 1;
170
227
  SQL
171
- unless rows.empty?
172
- output << "# Triggers:"
173
- rows = rows.map do |r|
174
- [r[:tgname], r[:pg_get_triggerdef].match(/((?:BEFORE|AFTER) .+)\z/m)[1]]
228
+ unless rows.empty?
229
+ output << "# Triggers:"
230
+ rows = rows.map do |r|
231
+ [r[:tgname], r[:pg_get_triggerdef].match(/((?:BEFORE|AFTER) .+)\z/m)[1]]
232
+ end
233
+ output.concat(align(rows))
175
234
  end
176
- output.concat(align(rows))
177
235
  end
178
236
  end
179
237
 
238
+ def _column_comments_postgres
239
+ model.db.fetch(<<SQL, :oid=>model.db.send(:regclass_oid, model.table_name)).to_hash(:attname, :description)
240
+ SELECT a.attname, d.description
241
+ FROM pg_description d
242
+ JOIN pg_attribute a ON (d.objoid = a.attrelid AND d.objsubid = a.attnum)
243
+ WHERE d.objoid = :oid AND COALESCE(d.description, '') != '';
244
+ SQL
245
+ end
246
+
180
247
  # The standard column schema information to output.
181
- def schema_comment_columns(output)
248
+ def schema_comment_columns(output, options = {})
182
249
  if cpk = model.primary_key.is_a?(Array)
183
250
  output << "# Primary Key: (#{model.primary_key.join(', ')})"
184
251
  end
185
252
  output << "# Columns:"
253
+
254
+ meth = :"_column_comments_#{model.db.database_type}"
255
+ column_comments = if options[:comments] != false && respond_to?(meth, true)
256
+ send(meth)
257
+ else
258
+ {}
259
+ end
260
+
186
261
  rows = model.columns.map do |col|
187
262
  sch = model.db_schema[col]
188
- [col.to_s, sch[:db_type], "#{"PRIMARY KEY #{"AUTOINCREMENT " if sch[:auto_increment] && model.db.database_type != :postgres}" if sch[:primary_key] && !cpk}#{"NOT NULL " if sch[:allow_null] == false && !sch[:primary_key]}#{"DEFAULT #{sch[:default]}" if sch[:default]}#{"GENERATED BY DEFAULT AS IDENTITY" if sch[:auto_increment] && !sch[:default] && model.db.database_type == :postgres && model.db.server_version >= 100000}"]
263
+ parts = [
264
+ col.to_s,
265
+ sch[:db_domain_type] || sch[:db_type],
266
+ "#{"PRIMARY KEY #{"AUTOINCREMENT " if sch[:auto_increment] && model.db.database_type != :postgres}" if sch[:primary_key] && !cpk}#{"NOT NULL " if sch[:allow_null] == false && !sch[:primary_key]}#{"DEFAULT #{sch[:default]}" if sch[:default]}#{"GENERATED BY DEFAULT AS IDENTITY" if sch[:auto_increment] && !sch[:default] && model.db.database_type == :postgres && model.db.server_version >= 100000}",
267
+ ]
268
+ parts << (column_comments[col.to_s] || '') unless column_comments.empty?
269
+ parts
189
270
  end
190
271
  output.concat(align(rows))
191
272
  end
@@ -211,5 +292,13 @@ SQL
211
292
  output.concat(align(rows).sort)
212
293
  end
213
294
  end
295
+
296
+ # Whether we should skip annotations for the model.
297
+ # True if the model selects from a dataset.
298
+ def skip_model?
299
+ model.dataset.joined_dataset? || model.dataset.first_source_table.is_a?(Dataset)
300
+ rescue Sequel::Error
301
+ true
302
+ end
214
303
  end
215
304
  end
@@ -1,4 +1,4 @@
1
- class Manufacturer < Sequel::Model
1
+ class Manufacturer < ABC
2
2
  end
3
3
 
4
4
  # Table: manufacturers
@@ -0,0 +1,7 @@
1
+ dataset =
2
+ SDB[:items]
3
+ .left_join(:categories, { id: :category_id })
4
+ .select { Sequel[:items][:name] }
5
+
6
+ class SComplexDataset < Sequel::Model(dataset)
7
+ end
@@ -0,0 +1,20 @@
1
+ # coding: xyz
2
+
3
+ class SItemWithCoding < Sequel::Model(SDB[:items])
4
+ end
5
+
6
+ # Table: items
7
+ # Columns:
8
+ # id | integer | PRIMARY KEY AUTOINCREMENT
9
+ # category_id | integer | NOT NULL
10
+ # manufacturer_name | varchar(50) |
11
+ # manufacturer_location | varchar(255) |
12
+ # in_stock | boolean | DEFAULT 0
13
+ # name | varchar(255) | DEFAULT 'John'
14
+ # price | double precision | DEFAULT 0
15
+ # Indexes:
16
+ # manufacturer_name | (manufacturer_name)
17
+ # name | UNIQUE (manufacturer_name, manufacturer_location)
18
+ # Foreign key constraints:
19
+ # (category_id) REFERENCES categories
20
+ # (manufacturer_name, manufacturer_location) REFERENCES manufacturers
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ class SItemWithEncoding < Sequel::Model(SDB[:items])
4
+ end
5
+
6
+ # Table: items
7
+ # Columns:
8
+ # id | integer | PRIMARY KEY AUTOINCREMENT
9
+ # category_id | integer | NOT NULL
10
+ # manufacturer_name | varchar(50) |
11
+ # manufacturer_location | varchar(255) |
12
+ # in_stock | boolean | DEFAULT 0
13
+ # name | varchar(255) | DEFAULT 'John'
14
+ # price | double precision | DEFAULT 0
15
+ # Indexes:
16
+ # manufacturer_name | (manufacturer_name)
17
+ # name | UNIQUE (manufacturer_name, manufacturer_location)
18
+ # Foreign key constraints:
19
+ # (category_id) REFERENCES categories
20
+ # (manufacturer_name, manufacturer_location) REFERENCES manufacturers
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SItemWithFrozenLiteral < Sequel::Model(SDB[:items])
4
+ end
5
+
6
+ # Table: items
7
+ # Columns:
8
+ # id | integer | PRIMARY KEY AUTOINCREMENT
9
+ # category_id | integer | NOT NULL
10
+ # manufacturer_name | varchar(50) |
11
+ # manufacturer_location | varchar(255) |
12
+ # in_stock | boolean | DEFAULT 0
13
+ # name | varchar(255) | DEFAULT 'John'
14
+ # price | double precision | DEFAULT 0
15
+ # Indexes:
16
+ # manufacturer_name | (manufacturer_name)
17
+ # name | UNIQUE (manufacturer_name, manufacturer_location)
18
+ # Foreign key constraints:
19
+ # (category_id) REFERENCES categories
20
+ # (manufacturer_name, manufacturer_location) REFERENCES manufacturers
@@ -0,0 +1,20 @@
1
+ # warn_indent: true
2
+
3
+ class SItemWithWarnIndent < Sequel::Model(SDB[:items])
4
+ end
5
+
6
+ # Table: items
7
+ # Columns:
8
+ # id | integer | PRIMARY KEY AUTOINCREMENT
9
+ # category_id | integer | NOT NULL
10
+ # manufacturer_name | varchar(50) |
11
+ # manufacturer_location | varchar(255) |
12
+ # in_stock | boolean | DEFAULT 0
13
+ # name | varchar(255) | DEFAULT 'John'
14
+ # price | double precision | DEFAULT 0
15
+ # Indexes:
16
+ # manufacturer_name | (manufacturer_name)
17
+ # name | UNIQUE (manufacturer_name, manufacturer_location)
18
+ # Foreign key constraints:
19
+ # (category_id) REFERENCES categories
20
+ # (manufacturer_name, manufacturer_location) REFERENCES manufacturers
@@ -0,0 +1,21 @@
1
+ # warn_past_scope: true
2
+ # warn_indent: false
3
+ # Additional comment that should stay
4
+ class SItemWithWarnPastScope < Sequel::Model(SDB[:items])
5
+ end
6
+
7
+ # Table: items
8
+ # Columns:
9
+ # id | integer | PRIMARY KEY AUTOINCREMENT
10
+ # category_id | integer | NOT NULL
11
+ # manufacturer_name | varchar(50) |
12
+ # manufacturer_location | varchar(255) |
13
+ # in_stock | boolean | DEFAULT 0
14
+ # name | varchar(255) | DEFAULT 'John'
15
+ # price | double precision | DEFAULT 0
16
+ # Indexes:
17
+ # manufacturer_name | (manufacturer_name)
18
+ # name | UNIQUE (manufacturer_name, manufacturer_location)
19
+ # Foreign key constraints:
20
+ # (category_id) REFERENCES categories
21
+ # (manufacturer_name, manufacturer_location) REFERENCES manufacturers
@@ -8,5 +8,5 @@
8
8
  # Referenced By:
9
9
  # items | items_manufacturer_name_fkey | (manufacturer_name, manufacturer_location) REFERENCES manufacturers(name, location)
10
10
 
11
- class Manufacturer < Sequel::Model
11
+ class Manufacturer < ABC
12
12
  end
@@ -0,0 +1,7 @@
1
+ dataset =
2
+ SDB[:items]
3
+ .left_join(:categories, { id: :category_id })
4
+ .select { Sequel[:items][:name] }
5
+
6
+ class SComplexDataset < Sequel::Model(dataset)
7
+ end
@@ -0,0 +1,20 @@
1
+ # coding: xyz
2
+
3
+ # Table: items
4
+ # Columns:
5
+ # id | integer | PRIMARY KEY AUTOINCREMENT
6
+ # category_id | integer | NOT NULL
7
+ # manufacturer_name | varchar(50) |
8
+ # manufacturer_location | varchar(255) |
9
+ # in_stock | boolean | DEFAULT 0
10
+ # name | varchar(255) | DEFAULT 'John'
11
+ # price | double precision | DEFAULT 0
12
+ # Indexes:
13
+ # manufacturer_name | (manufacturer_name)
14
+ # name | UNIQUE (manufacturer_name, manufacturer_location)
15
+ # Foreign key constraints:
16
+ # (category_id) REFERENCES categories
17
+ # (manufacturer_name, manufacturer_location) REFERENCES manufacturers
18
+
19
+ class SItemWithCoding < Sequel::Model(SDB[:items])
20
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ # Table: items
4
+ # Columns:
5
+ # id | integer | PRIMARY KEY AUTOINCREMENT
6
+ # category_id | integer | NOT NULL
7
+ # manufacturer_name | varchar(50) |
8
+ # manufacturer_location | varchar(255) |
9
+ # in_stock | boolean | DEFAULT 0
10
+ # name | varchar(255) | DEFAULT 'John'
11
+ # price | double precision | DEFAULT 0
12
+ # Indexes:
13
+ # manufacturer_name | (manufacturer_name)
14
+ # name | UNIQUE (manufacturer_name, manufacturer_location)
15
+ # Foreign key constraints:
16
+ # (category_id) REFERENCES categories
17
+ # (manufacturer_name, manufacturer_location) REFERENCES manufacturers
18
+
19
+ class SItemWithEncoding < Sequel::Model(SDB[:items])
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Table: items
4
+ # Columns:
5
+ # id | integer | PRIMARY KEY AUTOINCREMENT
6
+ # category_id | integer | NOT NULL
7
+ # manufacturer_name | varchar(50) |
8
+ # manufacturer_location | varchar(255) |
9
+ # in_stock | boolean | DEFAULT 0
10
+ # name | varchar(255) | DEFAULT 'John'
11
+ # price | double precision | DEFAULT 0
12
+ # Indexes:
13
+ # manufacturer_name | (manufacturer_name)
14
+ # name | UNIQUE (manufacturer_name, manufacturer_location)
15
+ # Foreign key constraints:
16
+ # (category_id) REFERENCES categories
17
+ # (manufacturer_name, manufacturer_location) REFERENCES manufacturers
18
+
19
+ class SItemWithFrozenLiteral < Sequel::Model(SDB[:items])
20
+ end
@@ -0,0 +1,20 @@
1
+ # warn_indent: true
2
+
3
+ # Table: items
4
+ # Columns:
5
+ # id | integer | PRIMARY KEY AUTOINCREMENT
6
+ # category_id | integer | NOT NULL
7
+ # manufacturer_name | varchar(50) |
8
+ # manufacturer_location | varchar(255) |
9
+ # in_stock | boolean | DEFAULT 0
10
+ # name | varchar(255) | DEFAULT 'John'
11
+ # price | double precision | DEFAULT 0
12
+ # Indexes:
13
+ # manufacturer_name | (manufacturer_name)
14
+ # name | UNIQUE (manufacturer_name, manufacturer_location)
15
+ # Foreign key constraints:
16
+ # (category_id) REFERENCES categories
17
+ # (manufacturer_name, manufacturer_location) REFERENCES manufacturers
18
+
19
+ class SItemWithWarnIndent < Sequel::Model(SDB[:items])
20
+ end
@@ -0,0 +1,21 @@
1
+ # warn_past_scope: true
2
+ # warn_indent: false
3
+ # Table: items
4
+ # Columns:
5
+ # id | integer | PRIMARY KEY AUTOINCREMENT
6
+ # category_id | integer | NOT NULL
7
+ # manufacturer_name | varchar(50) |
8
+ # manufacturer_location | varchar(255) |
9
+ # in_stock | boolean | DEFAULT 0
10
+ # name | varchar(255) | DEFAULT 'John'
11
+ # price | double precision | DEFAULT 0
12
+ # Indexes:
13
+ # manufacturer_name | (manufacturer_name)
14
+ # name | UNIQUE (manufacturer_name, manufacturer_location)
15
+ # Foreign key constraints:
16
+ # (category_id) REFERENCES categories
17
+ # (manufacturer_name, manufacturer_location) REFERENCES manufacturers
18
+
19
+ # Additional comment that should stay
20
+ class SItemWithWarnPastScope < Sequel::Model(SDB[:items])
21
+ end
@@ -0,0 +1,24 @@
1
+ module ModelNamespace
2
+ class Itms < Model(:items); end
3
+ end
4
+
5
+ # Table: items
6
+ # Columns:
7
+ # id | integer | PRIMARY KEY DEFAULT nextval('items_id_seq'::regclass)
8
+ # category_id | integer | NOT NULL
9
+ # manufacturer_name | character varying(50) |
10
+ # manufacturer_location | text |
11
+ # in_stock | boolean | DEFAULT false
12
+ # name | text | DEFAULT 'John'::text
13
+ # price | double precision | DEFAULT 0
14
+ # Indexes:
15
+ # items_pkey | PRIMARY KEY btree (id)
16
+ # name | UNIQUE btree (manufacturer_name, manufacturer_location)
17
+ # manufacturer_name | btree (manufacturer_name)
18
+ # Check constraints:
19
+ # pos_id | (id > 0)
20
+ # Foreign key constraints:
21
+ # items_category_id_fkey | (category_id) REFERENCES categories(id)
22
+ # items_manufacturer_name_fkey | (manufacturer_name, manufacturer_location) REFERENCES manufacturers(name, location)
23
+ # Triggers:
24
+ # valid_price | BEFORE INSERT OR UPDATE ON items FOR EACH ROW EXECUTE PROCEDURE valid_price()
@@ -0,0 +1,3 @@
1
+ module ModelNamespace
2
+ class Itms < Model(:items); end
3
+ end
@@ -1,16 +1,23 @@
1
1
  require 'rubygems'
2
2
  require 'fileutils'
3
3
  require File.join(File.dirname(File.expand_path(__FILE__)), '../lib/sequel/annotate')
4
- require 'minitest/autorun'
5
4
 
6
- pg_user = ENV['PGUSER'] || 'postgres'
7
- db_name = ENV['SEQUEL_ANNOTATE_DB'] || 'sequel-annotate_spec'
8
- system("dropdb", "-U", pg_user, db_name)
9
- system("createdb", "-U", pg_user, db_name)
10
- DB = Sequel.postgres(db_name, :user=>pg_user)
11
- SDB = Sequel.sqlite
5
+ ENV['MT_NO_PLUGINS'] = '1' # Work around stupid autoloading of plugins
6
+ gem 'minitest'
7
+ require 'minitest/global_expectations/autorun'
12
8
 
9
+ DB = Sequel.connect(ENV['SEQUEL_ANNOTATE_SPEC_POSTGRES_URL'] || 'postgres:///sequel_annotate_test?user=sequel_annotate&password=sequel_annotate')
10
+ raise "test database name doesn't end with test" unless DB.get{current_database.function} =~ /test\z/
11
+ if defined?(JRUBY_VERSION)
12
+ SDB = Sequel.connect('jdbc:sqlite::memory:')
13
+ else
14
+ SDB = Sequel.sqlite
15
+ end
16
+
17
+ DB.drop_function(:valid_price) rescue nil
13
18
  [DB, SDB].each do |db|
19
+ db.drop_table?(:newline_tests, :items, :manufacturers, :categories, :comment_tests)
20
+
14
21
  db.create_table :categories do
15
22
  primary_key :id
16
23
  String :name, :index=>{:unique=>true, :name=>'categories_name_key'}, :null=>false
@@ -25,7 +32,7 @@ SDB = Sequel.sqlite
25
32
  db.create_table :items do
26
33
  primary_key :id
27
34
  foreign_key :category_id, :categories, :null => false
28
- foreign_key [:manufacturer_name, :manufacturer_location], :manufacturers
35
+ foreign_key [:manufacturer_name, :manufacturer_location], :manufacturers, :name=>:items_manufacturer_name_fkey
29
36
 
30
37
  String :manufacturer_name, :size => 50
31
38
  String :manufacturer_location
@@ -38,6 +45,12 @@ SDB = Sequel.sqlite
38
45
  index [:manufacturer_name, :manufacturer_location], :name=>:name, :unique=>true
39
46
  index [:manufacturer_name], :name=>:manufacturer_name
40
47
  end
48
+
49
+ db.create_table :newline_tests do
50
+ Integer :abcde_fghi_id
51
+ Integer :jkl_mnopqr_id
52
+ constraint(:valid_stuvw_xyz0, Sequel.case({{:abcde_fghi_id=>[5,6]}=>Sequel.~(:jkl_mnopqr_id=>nil)}, :jkl_mnopqr_id=>nil))
53
+ end
41
54
  end
42
55
 
43
56
  DB.run <<SQL
@@ -57,19 +70,61 @@ CREATE TRIGGER valid_price BEFORE INSERT OR UPDATE ON items
57
70
  FOR EACH ROW EXECUTE PROCEDURE valid_price();
58
71
  SQL
59
72
 
73
+ DB.run "CREATE DOMAIN test_domain AS text"
74
+
75
+ DB.create_table :domain_tests do
76
+ primary_key :id
77
+ test_domain :test_column
78
+ end
79
+
80
+ DB.create_table :comment_tests do
81
+ primary_key :id
82
+ String :name
83
+ end
84
+
85
+ DB.run "COMMENT ON COLUMN comment_tests.name IS 'name column comment'"
86
+
87
+ Minitest.after_run do
88
+ DB.drop_table(:items, :manufacturers, :categories, :domain_tests, :comment_tests)
89
+ DB.run "DROP DOMAIN test_domain"
90
+ DB.drop_function(:valid_price)
91
+ end
92
+
60
93
  class ::Item < Sequel::Model; end
61
94
  class ::Category < Sequel::Model; end
62
95
  class ::Manufacturer < Sequel::Model; end
96
+ class ::DomainTest < Sequel::Model; end
97
+ class ::CommentTest < Sequel::Model; end
63
98
  class ::SItem < Sequel::Model(SDB[:items]); end
99
+ class ::SItemWithFrozenLiteral < Sequel::Model(SDB[:items]); end
100
+ class ::SItemWithCoding < Sequel::Model(SDB[:items]); end
101
+ class ::SItemWithEncoding < Sequel::Model(SDB[:items]); end
102
+ class ::SItemWithWarnIndent < Sequel::Model(SDB[:items]); end
103
+ class ::SItemWithWarnPastScope < Sequel::Model(SDB[:items]); end
104
+ class ::SItemWithMagicComment < Sequel::Model(SDB[:items]); end
64
105
  class ::SCategory < Sequel::Model(SDB[:categories]); end
65
106
  class ::SManufacturer < Sequel::Model(SDB[:manufacturers]); end
107
+ class ::NewlineTest < Sequel::Model; end
108
+ class ::QualifiedTableNameTest < Sequel::Model(Sequel.qualify(:public, :categories)); end
109
+ class SComplexDataset < Sequel::Model(SDB[:items].left_join(:categories, :id => :category_id).select{items[:name]}); end
66
110
 
111
+ # Abstract Base Class
112
+ ABC = Class.new(Sequel::Model)
113
+
114
+ module ModelNamespace
115
+ Model = Class.new(Sequel::Model)
116
+ Model.def_Model(self)
117
+ class Itms < Model(:items); end
118
+ end
67
119
 
68
120
  describe Sequel::Annotate do
69
121
  def fix_pg_comment(comment)
70
122
  if DB.server_version >= 100002 && (Sequel::MAJOR > 5 || (Sequel::MAJOR == 5 && Sequel::MINOR >= 7))
71
123
  comment = comment.sub(/DEFAULT nextval\('[a-z]+_id_seq'::regclass\)/, 'GENERATED BY DEFAULT AS IDENTITY')
72
124
  end
125
+ if DB.server_version >= 120000
126
+ comment = comment.gsub(/FOR EACH ROW EXECUTE PROCEDURE/, 'FOR EACH ROW EXECUTE FUNCTION')
127
+ end
73
128
  comment
74
129
  end
75
130
 
@@ -80,6 +135,52 @@ describe Sequel::Annotate do
80
135
  Dir['spec/tmp/*.rb'].each{|f| File.delete(f)}
81
136
  end
82
137
 
138
+ it "skips files with the sequel-annotate magic comment set to false" do
139
+ FileUtils.cp('spec/unannotated/sitemwithmagiccomment.rb', 'spec/tmp/')
140
+ Sequel::Annotate.annotate(['spec/tmp/sitemwithmagiccomment.rb'])
141
+ File.read('spec/tmp/sitemwithmagiccomment.rb').must_equal File.read('spec/unannotated/sitemwithmagiccomment.rb')
142
+ end
143
+
144
+ it "#schema_info should not return sections we set to false" do
145
+ Sequel::Annotate.new(Item).schema_comment(:indexes => false, :constraints => false, :foreign_keys => false, :triggers => false).must_equal(fix_pg_comment((<<OUTPUT).chomp))
146
+ # Table: items
147
+ # Columns:
148
+ # id | integer | PRIMARY KEY DEFAULT nextval('items_id_seq'::regclass)
149
+ # category_id | integer | NOT NULL
150
+ # manufacturer_name | character varying(50) |
151
+ # manufacturer_location | text |
152
+ # in_stock | boolean | DEFAULT false
153
+ # name | text | DEFAULT 'John'::text
154
+ # price | double precision | DEFAULT 0
155
+ OUTPUT
156
+
157
+ Sequel::Annotate.new(Category).schema_comment(:references => false).must_equal(fix_pg_comment((<<OUTPUT).chomp))
158
+ # Table: categories
159
+ # Columns:
160
+ # id | integer | PRIMARY KEY DEFAULT nextval('categories_id_seq'::regclass)
161
+ # name | text | NOT NULL
162
+ # Indexes:
163
+ # categories_pkey | PRIMARY KEY btree (id)
164
+ # categories_name_key | UNIQUE btree (name)
165
+ OUTPUT
166
+ end
167
+
168
+ it "#schema_info should return a border if we want one" do
169
+ 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))
170
+ # Table: items
171
+ # ---
172
+ # Columns:
173
+ # id | integer | PRIMARY KEY DEFAULT nextval('items_id_seq'::regclass)
174
+ # category_id | integer | NOT NULL
175
+ # manufacturer_name | character varying(50) |
176
+ # manufacturer_location | text |
177
+ # in_stock | boolean | DEFAULT false
178
+ # name | text | DEFAULT 'John'::text
179
+ # price | double precision | DEFAULT 0
180
+ # ---
181
+ OUTPUT
182
+ end
183
+
83
184
  it "#schema_info should return the model schema comment" do
84
185
  Sequel::Annotate.new(Item).schema_comment.must_equal(fix_pg_comment((<<OUTPUT).chomp))
85
186
  # Table: items
@@ -104,6 +205,7 @@ describe Sequel::Annotate do
104
205
  # valid_price | BEFORE INSERT OR UPDATE ON items FOR EACH ROW EXECUTE PROCEDURE valid_price()
105
206
  OUTPUT
106
207
 
208
+ Sequel::Annotate.new(SComplexDataset).schema_comment.must_equal("")
107
209
  Sequel::Annotate.new(Category).schema_comment.must_equal(fix_pg_comment((<<OUTPUT).chomp))
108
210
  # Table: categories
109
211
  # Columns:
@@ -126,6 +228,19 @@ OUTPUT
126
228
  # manufacturers_pkey | PRIMARY KEY btree (name, location)
127
229
  # Referenced By:
128
230
  # items | items_manufacturer_name_fkey | (manufacturer_name, manufacturer_location) REFERENCES manufacturers(name, location)
231
+ OUTPUT
232
+
233
+ Sequel::Annotate.new(NewlineTest).schema_comment.must_equal((<<OUTPUT).chomp)
234
+ # Table: newline_tests
235
+ # Columns:
236
+ # abcde_fghi_id | integer |
237
+ # jkl_mnopqr_id | integer |
238
+ # Check constraints:
239
+ # valid_stuvw_xyz0 | (
240
+ # CASE
241
+ # WHEN abcde_fghi_id = ANY (ARRAY[5, 6]) THEN jkl_mnopqr_id IS NOT NULL
242
+ # ELSE jkl_mnopqr_id IS NULL
243
+ # END)
129
244
  OUTPUT
130
245
 
131
246
  Sequel::Annotate.new(SItem).schema_comment.must_equal((<<OUTPUT).chomp)
@@ -161,6 +276,36 @@ OUTPUT
161
276
  # Columns:
162
277
  # name | varchar(255) |
163
278
  # location | varchar(255) |
279
+ OUTPUT
280
+
281
+ Sequel::Annotate.new(QualifiedTableNameTest).schema_comment.must_equal(fix_pg_comment((<<OUTPUT).chomp))
282
+ # Table: public.categories
283
+ # Columns:
284
+ # id | integer | PRIMARY KEY DEFAULT nextval('categories_id_seq'::regclass)
285
+ # name | text | NOT NULL
286
+ # Indexes:
287
+ # categories_pkey | PRIMARY KEY btree (id)
288
+ # categories_name_key | UNIQUE btree (name)
289
+ # Referenced By:
290
+ # items | items_category_id_fkey | (category_id) REFERENCES categories(id)
291
+ OUTPUT
292
+
293
+ Sequel::Annotate.new(DomainTest).schema_comment.must_equal(fix_pg_comment((<<OUTPUT).chomp))
294
+ # Table: domain_tests
295
+ # Columns:
296
+ # id | integer | PRIMARY KEY DEFAULT nextval('categories_id_seq'::regclass)
297
+ # test_column | test_domain |
298
+ # Indexes:
299
+ # domain_tests_pkey | PRIMARY KEY btree (id)
300
+ OUTPUT
301
+
302
+ Sequel::Annotate.new(CommentTest).schema_comment.must_equal(fix_pg_comment((<<OUTPUT).chomp))
303
+ # Table: comment_tests
304
+ # Columns:
305
+ # id | integer | PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY |
306
+ # name | text | | name column comment
307
+ # Indexes:
308
+ # comment_tests_pkey | PRIMARY KEY btree (id)
164
309
  OUTPUT
165
310
  end
166
311
 
@@ -168,7 +313,7 @@ OUTPUT
168
313
  it "#annotate #{desc} should annotate the file comment" do
169
314
  FileUtils.cp(Dir['spec/unannotated/*.rb'], 'spec/tmp')
170
315
 
171
- [Item, Category, Manufacturer, SItem, SCategory, SManufacturer].each do |model|
316
+ [Item, Category, Manufacturer, SItem, SCategory, SManufacturer, SItemWithFrozenLiteral, SItemWithCoding, SItemWithEncoding, SItemWithWarnIndent, SItemWithWarnPastScope, SComplexDataset].each do |model|
172
317
  filename = model.name.downcase
173
318
  2.times do
174
319
  Sequel::Annotate.new(model).annotate("spec/tmp/#{filename}.rb", *args)
@@ -184,7 +329,7 @@ OUTPUT
184
329
 
185
330
  2.times do
186
331
  Sequel::Annotate.annotate(Dir["spec/tmp/*.rb"], *args)
187
- [Item, Category, Manufacturer, SItem, SCategory, SManufacturer].each do |model|
332
+ [Item, Category, Manufacturer, SItem, SCategory, SManufacturer, SItemWithFrozenLiteral, SItemWithCoding, SItemWithEncoding, SItemWithWarnIndent, SItemWithWarnPastScope, SComplexDataset].each do |model|
188
333
  filename = model.name.downcase
189
334
  expected = File.read("spec/annotated_#{pos}/#{filename}.rb")
190
335
  expected = fix_pg_comment(expected) if model.db == DB
@@ -193,4 +338,19 @@ OUTPUT
193
338
  end
194
339
  end
195
340
  end
341
+
342
+ it ".annotate #{desc} should handle :namespace option" do
343
+ FileUtils.cp('spec/namespaced/itm_unannotated.rb', 'spec/tmp/')
344
+ Sequel::Annotate.annotate(["spec/tmp/itm_unannotated.rb"], :namespace=>'ModelNamespace')
345
+ File.read("spec/tmp/itm_unannotated.rb").must_equal fix_pg_comment(File.read('spec/namespaced/itm_annotated.rb'))
346
+ Sequel::Annotate.annotate(["spec/tmp/itm_unannotated.rb"], :namespace=>'ModelNamespace', :border=>true)
347
+ Sequel::Annotate.annotate(["spec/tmp/itm_unannotated.rb"], :namespace=>'ModelNamespace')
348
+ File.read("spec/tmp/itm_unannotated.rb").must_equal fix_pg_comment(File.read('spec/namespaced/itm_annotated.rb'))
349
+ end
350
+
351
+ it ".annotate #{desc} should handle :namespace => true option" do
352
+ FileUtils.cp('spec/namespaced/itm_unannotated.rb', 'spec/tmp')
353
+ Sequel::Annotate.annotate(["spec/tmp/itm_unannotated.rb"], :namespace=>true)
354
+ File.read("spec/tmp/itm_unannotated.rb").must_equal fix_pg_comment(File.read('spec/namespaced/itm_annotated.rb'))
355
+ end
196
356
  end
@@ -1,2 +1,2 @@
1
- class Manufacturer < Sequel::Model
1
+ class Manufacturer < ABC
2
2
  end
@@ -0,0 +1,4 @@
1
+ class NotModel
2
+ class << self
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ dataset =
2
+ SDB[:items]
3
+ .left_join(:categories, { id: :category_id })
4
+ .select { Sequel[:items][:name] }
5
+
6
+ class SComplexDataset < Sequel::Model(dataset)
7
+ end
@@ -0,0 +1,4 @@
1
+ # coding: xyz
2
+
3
+ class SItemWithCoding < Sequel::Model(SDB[:items])
4
+ end
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+
3
+ class SItemWithEncoding < Sequel::Model(SDB[:items])
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SItemWithFrozenLiteral < Sequel::Model(SDB[:items])
4
+ end
@@ -0,0 +1,4 @@
1
+ # sequel-annotate: false
2
+
3
+ class SItemWithMagicComment < Sequel::Model(SDB[:items])
4
+ end
@@ -0,0 +1,4 @@
1
+ # warn_indent: true
2
+
3
+ class SItemWithWarnIndent < Sequel::Model(SDB[:items])
4
+ end
@@ -0,0 +1,5 @@
1
+ # warn_past_scope: true
2
+ # warn_indent: false
3
+ # Additional comment that should stay
4
+ class SItemWithWarnPastScope < Sequel::Model(SDB[:items])
5
+ 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.2.0
4
+ version: 1.6.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-04-02 00:00:00.000000000 Z
11
+ date: 2020-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest-global_expectations
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: pg
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -72,7 +86,7 @@ description: |
72
86
  constraints for the current table.
73
87
 
74
88
  On PostgreSQL, this includes more advanced information, including
75
- check constraints, triggers, and foreign keys constraints for other
89
+ check constraints, triggers, comments, and foreign keys constraints for other
76
90
  tables that reference the current table.
77
91
  email: code@jeremyevans.net
78
92
  executables: []
@@ -91,25 +105,50 @@ files:
91
105
  - spec/annotated_after/item.rb
92
106
  - spec/annotated_after/manufacturer.rb
93
107
  - spec/annotated_after/scategory.rb
108
+ - spec/annotated_after/scomplexdataset.rb
94
109
  - spec/annotated_after/sitem.rb
110
+ - spec/annotated_after/sitemwithcoding.rb
111
+ - spec/annotated_after/sitemwithencoding.rb
112
+ - spec/annotated_after/sitemwithfrozenliteral.rb
113
+ - spec/annotated_after/sitemwithwarnindent.rb
114
+ - spec/annotated_after/sitemwithwarnpastscope.rb
95
115
  - spec/annotated_after/smanufacturer.rb
96
116
  - spec/annotated_before/category.rb
97
117
  - spec/annotated_before/item.rb
98
118
  - spec/annotated_before/manufacturer.rb
99
119
  - spec/annotated_before/scategory.rb
120
+ - spec/annotated_before/scomplexdataset.rb
100
121
  - spec/annotated_before/sitem.rb
122
+ - spec/annotated_before/sitemwithcoding.rb
123
+ - spec/annotated_before/sitemwithencoding.rb
124
+ - spec/annotated_before/sitemwithfrozenliteral.rb
125
+ - spec/annotated_before/sitemwithwarnindent.rb
126
+ - spec/annotated_before/sitemwithwarnpastscope.rb
101
127
  - spec/annotated_before/smanufacturer.rb
128
+ - spec/namespaced/itm_annotated.rb
129
+ - spec/namespaced/itm_unannotated.rb
102
130
  - spec/sequel-annotate_spec.rb
103
131
  - spec/unannotated/category.rb
104
132
  - spec/unannotated/item.rb
105
133
  - spec/unannotated/manufacturer.rb
134
+ - spec/unannotated/not_model.rb
106
135
  - spec/unannotated/scategory.rb
136
+ - spec/unannotated/scomplexdataset.rb
107
137
  - spec/unannotated/sitem.rb
138
+ - spec/unannotated/sitemwithcoding.rb
139
+ - spec/unannotated/sitemwithencoding.rb
140
+ - spec/unannotated/sitemwithfrozenliteral.rb
141
+ - spec/unannotated/sitemwithmagiccomment.rb
142
+ - spec/unannotated/sitemwithwarnindent.rb
143
+ - spec/unannotated/sitemwithwarnpastscope.rb
108
144
  - spec/unannotated/smanufacturer.rb
109
145
  homepage: http://github.com/jeremyevans/sequel-annotate
110
146
  licenses:
111
147
  - MIT
112
- metadata: {}
148
+ metadata:
149
+ bug_tracker_uri: https://github.com/jeremyevans/sequel-annotate/issues
150
+ changelog_uri: https://github.com/jeremyevans/sequel-annotate/blob/master/CHANGELOG
151
+ source_code_uri: https://github.com/jeremyevans/sequel-annotate
113
152
  post_install_message:
114
153
  rdoc_options:
115
154
  - "--quiet"
@@ -132,8 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
171
  - !ruby/object:Gem::Version
133
172
  version: '0'
134
173
  requirements: []
135
- rubyforge_project:
136
- rubygems_version: 2.7.6
174
+ rubygems_version: 3.1.4
137
175
  signing_key:
138
176
  specification_version: 4
139
177
  summary: Annotate Sequel models with schema information