annotaterb 4.23.0 → 4.25.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.md +100 -3
- data/README.md +129 -9
- data/VERSION +1 -1
- data/lib/annotate_rb/model_annotator/annotation/annotation_builder.rb +8 -1
- data/lib/annotate_rb/model_annotator/column_annotation/default_value_builder.rb +1 -0
- data/lib/annotate_rb/model_annotator/column_annotation/enum_default.rb +11 -0
- data/lib/annotate_rb/model_annotator/column_annotation.rb +1 -0
- data/lib/annotate_rb/model_annotator/exclusion_constraint_annotation/annotation.rb +40 -0
- data/lib/annotate_rb/model_annotator/exclusion_constraint_annotation/annotation_builder.rb +38 -0
- data/lib/annotate_rb/model_annotator/exclusion_constraint_annotation/exclusion_constraint_component.rb +27 -0
- data/lib/annotate_rb/model_annotator/exclusion_constraint_annotation.rb +11 -0
- data/lib/annotate_rb/model_annotator/file_parser/annotation_finder.rb +38 -2
- data/lib/annotate_rb/model_annotator/file_parser/yml_parser.rb +44 -5
- data/lib/annotate_rb/model_annotator/foreign_key_annotation/foreign_key_component_builder.rb +7 -1
- data/lib/annotate_rb/model_annotator/index_annotation/annotation_builder.rb +29 -0
- data/lib/annotate_rb/model_annotator/index_annotation/index_component.rb +15 -5
- data/lib/annotate_rb/model_annotator/model_wrapper.rb +63 -1
- data/lib/annotate_rb/model_annotator/project_annotation_remover.rb +3 -1
- data/lib/annotate_rb/model_annotator/related_files_list_builder.rb +27 -2
- data/lib/annotate_rb/model_annotator/single_file_annotation_remover.rb +1 -1
- data/lib/annotate_rb/model_annotator/single_file_annotator.rb +1 -1
- data/lib/annotate_rb/model_annotator/unique_constraint_annotation/annotation.rb +40 -0
- data/lib/annotate_rb/model_annotator/unique_constraint_annotation/annotation_builder.rb +37 -0
- data/lib/annotate_rb/model_annotator/unique_constraint_annotation/unique_constraint_component.rb +27 -0
- data/lib/annotate_rb/model_annotator/unique_constraint_annotation.rb +11 -0
- data/lib/annotate_rb/model_annotator.rb +2 -0
- data/lib/annotate_rb/options.rb +11 -4
- data/lib/annotate_rb/parser.rb +21 -1
- data/lib/annotate_rb/runner.rb +0 -2
- metadata +10 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e76c98c2c18b7021f7844189a076f4d5cb52b61777c5200bff9888497d3924d2
|
|
4
|
+
data.tar.gz: ddf7481ef3fdb08071855c9131a7dfca2426d29ad0c7dfdeff9f891d510a867b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 38dd0ae99e1a1e21dd68963b5e6f85bb72d620955ab001df8136dc4d40122196d4bb88dd107bfe95fdd93bcb17befe907f4ebe001ad05f364067b17d40c839e3
|
|
7
|
+
data.tar.gz: be47e90cad90aefdd1ea96d494783731270b26c5a8f24843912eea6f418a1375bbbc7bdc3550181f763eef47eb46eb595d1e54fc2bc06ede1eb26abfbfeb917b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,108 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v4.24.0](https://github.com/drwl/annotaterb/tree/v4.24.0) (2026-07-24)
|
|
4
|
+
|
|
5
|
+
[Full Changelog](https://github.com/drwl/annotaterb/compare/v4.23.0...v4.24.0)
|
|
6
|
+
|
|
7
|
+
**Implemented enhancements:**
|
|
8
|
+
|
|
9
|
+
- Annotate postgres enums [\#309](https://github.com/drwl/annotaterb/issues/309)
|
|
10
|
+
- `--frozen` option returns a non-zero error code when database is inaccessible [\#240](https://github.com/drwl/annotaterb/issues/240)
|
|
11
|
+
- Add support for printing enum types [\#176](https://github.com/drwl/annotaterb/issues/176)
|
|
12
|
+
|
|
13
|
+
**Fixed bugs:**
|
|
14
|
+
|
|
15
|
+
- Annotation placement for namespaced models is inconsistent — anchor shifts with file shape \(doc comment presence\) [\#366](https://github.com/drwl/annotaterb/issues/366)
|
|
16
|
+
- Fixture files that start with \<% \(erb\) insert doc inside the erb block [\#345](https://github.com/drwl/annotaterb/issues/345)
|
|
17
|
+
- Schema information inserted every run into some fixture files. [\#344](https://github.com/drwl/annotaterb/issues/344)
|
|
18
|
+
|
|
19
|
+
**Closed issues:**
|
|
20
|
+
|
|
21
|
+
- Routes are not annotated after migration tasks [\#251](https://github.com/drwl/annotaterb/issues/251)
|
|
22
|
+
|
|
23
|
+
**Merged pull requests:**
|
|
24
|
+
|
|
25
|
+
- Bump version to v4.24.0 [\#371](https://github.com/drwl/annotaterb/pull/371) ([drwl](https://github.com/drwl))
|
|
26
|
+
- Revert "Release v4.24.0" [\#370](https://github.com/drwl/annotaterb/pull/370) ([drwl](https://github.com/drwl))
|
|
27
|
+
- Show DEFERRABLE INITIALLY on foreign keys [\#365](https://github.com/drwl/annotaterb/pull/365) ([kamipo](https://github.com/kamipo))
|
|
28
|
+
- Annotate PostgreSQL unique and exclusion constraints [\#364](https://github.com/drwl/annotaterb/pull/364) ([kamipo](https://github.com/kamipo))
|
|
29
|
+
- Fix `--without-comment` help text to say exclude [\#363](https://github.com/drwl/annotaterb/pull/363) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
30
|
+
- Fix NoMethodError when handling malformed annotations [\#362](https://github.com/drwl/annotaterb/pull/362) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
31
|
+
- Remove empty TODO comment from Runner [\#361](https://github.com/drwl/annotaterb/pull/361) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
32
|
+
- Move ignore\_database\_name check into AnnotationBuilder [\#360](https://github.com/drwl/annotaterb/pull/360) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
33
|
+
- Add YAML configuration option reference to the README. [\#359](https://github.com/drwl/annotaterb/pull/359) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
34
|
+
- Respect DB column defaults over `attribute :foo, default: X` overrides [\#358](https://github.com/drwl/annotaterb/pull/358) ([kamipo](https://github.com/kamipo))
|
|
35
|
+
- added :ignore\_database\_name option [\#357](https://github.com/drwl/annotaterb/pull/357) ([HoneyryderChuck](https://github.com/HoneyryderChuck))
|
|
36
|
+
- Add Markdown annotation idempotency test [\#356](https://github.com/drwl/annotaterb/pull/356) ([aouxwoux](https://github.com/aouxwoux))
|
|
37
|
+
- Fix schema\_like? to recognize markdown-formatted annotation rows [\#354](https://github.com/drwl/annotaterb/pull/354) ([nashirox](https://github.com/nashirox))
|
|
38
|
+
- Keep fixture annotations out of ERB blocks \(\#345\) [\#353](https://github.com/drwl/annotaterb/pull/353) ([Halvanhelv](https://github.com/Halvanhelv))
|
|
39
|
+
- Stop tracking generated secondary DB artifacts in dummyapp [\#352](https://github.com/drwl/annotaterb/pull/352) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
40
|
+
- Add Rails version matrix to CI [\#351](https://github.com/drwl/annotaterb/pull/351) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
41
|
+
- Create release script [\#349](https://github.com/drwl/annotaterb/pull/349) ([drwl](https://github.com/drwl))
|
|
42
|
+
- Generate changelog for v4.23.0 [\#348](https://github.com/drwl/annotaterb/pull/348) ([drwl](https://github.com/drwl))
|
|
43
|
+
|
|
44
|
+
## [v4.23.0](https://github.com/drwl/annotaterb/tree/v4.23.0) (2026-06-25)
|
|
45
|
+
|
|
46
|
+
[Full Changelog](https://github.com/drwl/annotaterb/compare/v4.22.0...v4.23.0)
|
|
47
|
+
|
|
48
|
+
**Implemented enhancements:**
|
|
49
|
+
|
|
50
|
+
- \[Request\] Support for multiple serializers for one model [\#329](https://github.com/drwl/annotaterb/issues/329)
|
|
51
|
+
- Support COMMENT on an INDEX [\#258](https://github.com/drwl/annotaterb/issues/258)
|
|
52
|
+
|
|
53
|
+
**Fixed bugs:**
|
|
54
|
+
|
|
55
|
+
- Re-running annotaterb strips indentation from nested \(indented\) schema annotations [\#332](https://github.com/drwl/annotaterb/issues/332)
|
|
56
|
+
- Setting all sort options to `false` sometimes doesn't respect migration/DB order [\#237](https://github.com/drwl/annotaterb/issues/237)
|
|
57
|
+
|
|
58
|
+
**Closed issues:**
|
|
59
|
+
|
|
60
|
+
- mistake post please delete this [\#314](https://github.com/drwl/annotaterb/issues/314)
|
|
61
|
+
- Removal of final empty comment line after foreign keys results in duplicate `fk_rails_...` line [\#297](https://github.com/drwl/annotaterb/issues/297)
|
|
62
|
+
- Default settings does not indent correctly inside a module [\#271](https://github.com/drwl/annotaterb/issues/271)
|
|
63
|
+
- Top does not do what I think it should? And annotator fails to indent. [\#202](https://github.com/drwl/annotaterb/issues/202)
|
|
64
|
+
- annotaterb is moving my class doc [\#201](https://github.com/drwl/annotaterb/issues/201)
|
|
65
|
+
|
|
66
|
+
**Merged pull requests:**
|
|
67
|
+
|
|
68
|
+
- Bump version to v4.23.0 [\#347](https://github.com/drwl/annotaterb/pull/347) ([drwl](https://github.com/drwl))
|
|
69
|
+
- Bump actions/checkout from 6 to 7 [\#346](https://github.com/drwl/annotaterb/pull/346) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
70
|
+
- Fix duplicate annotations when a file ends with a trailing blank line [\#342](https://github.com/drwl/annotaterb/pull/342) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
71
|
+
- Fix update\_config for non-default config locations [\#341](https://github.com/drwl/annotaterb/pull/341) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
72
|
+
- Fix NameError in ZeitwerkClassGetter for collapsed Zeitwerk paths [\#339](https://github.com/drwl/annotaterb/pull/339) ([KaiyuanMa](https://github.com/KaiyuanMa))
|
|
73
|
+
- Fix annotation inserted inside module when doc comment is present [\#338](https://github.com/drwl/annotaterb/pull/338) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
74
|
+
- Add `position_in_class: after_doc` to keep class doc adjacent to class [\#337](https://github.com/drwl/annotaterb/pull/337) ([yamat47](https://github.com/yamat47))
|
|
75
|
+
- Fix annotation placement above inner class declarations under `nested_position` [\#336](https://github.com/drwl/annotaterb/pull/336) ([yamat47](https://github.com/yamat47))
|
|
76
|
+
- Drop Ruby \< 3.3 from CI matrix [\#335](https://github.com/drwl/annotaterb/pull/335) ([drwl](https://github.com/drwl))
|
|
77
|
+
- Fix annotation placement in nested files and around trailing user comments [\#334](https://github.com/drwl/annotaterb/pull/334) ([yamat47](https://github.com/yamat47))
|
|
78
|
+
- Preserve indentation when re-running annotaterb on nested-position annotations. [\#333](https://github.com/drwl/annotaterb/pull/333) ([yamat47](https://github.com/yamat47))
|
|
79
|
+
- Respect `--config-path` during config loading [\#331](https://github.com/drwl/annotaterb/pull/331) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
80
|
+
- Fall back to current task when no top-level task is set [\#328](https://github.com/drwl/annotaterb/pull/328) ([jordan-brough](https://github.com/jordan-brough))
|
|
81
|
+
- Fix --show-migration option not working on Rails 7.2+. [\#327](https://github.com/drwl/annotaterb/pull/327) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
82
|
+
- Exit with non-zero code when database is not accessible [\#326](https://github.com/drwl/annotaterb/pull/326) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
83
|
+
- fix potential ReDoS in route annotator regex [\#325](https://github.com/drwl/annotaterb/pull/325) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
84
|
+
- Support opt-in display of PostgreSQL enum types in annotations [\#324](https://github.com/drwl/annotaterb/pull/324) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
85
|
+
- Fix error when column comments contain `%` [\#322](https://github.com/drwl/annotaterb/pull/322) ([willnet](https://github.com/willnet))
|
|
86
|
+
- Add unit tests for AnnotateRb::Helper [\#321](https://github.com/drwl/annotaterb/pull/321) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
87
|
+
- Migrate issue templates to folder-based format [\#320](https://github.com/drwl/annotaterb/pull/320) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
88
|
+
- Add opt-in show\_indexes\_comments option to display index comments [\#319](https://github.com/drwl/annotaterb/pull/319) ([olleolleolle](https://github.com/olleolleolle))
|
|
89
|
+
- Only connect SecondaryRecord to secondary DB when MULTI\_DB\_TEST is set [\#318](https://github.com/drwl/annotaterb/pull/318) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
90
|
+
- Correct secondary database setup in dummy app [\#317](https://github.com/drwl/annotaterb/pull/317) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
91
|
+
- Remove duplicate ignore\_unknown\_models option definition [\#316](https://github.com/drwl/annotaterb/pull/316) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
92
|
+
- Fix column annotation alignment for CJK and fullwidth characters [\#315](https://github.com/drwl/annotaterb/pull/315) ([SergeyGildenshtern](https://github.com/SergeyGildenshtern))
|
|
93
|
+
- Added command example for applying annotations to README [\#313](https://github.com/drwl/annotaterb/pull/313) ([zackerms](https://github.com/zackerms))
|
|
94
|
+
- Generate changelog for v4.22.0 [\#311](https://github.com/drwl/annotaterb/pull/311) ([drwl](https://github.com/drwl))
|
|
95
|
+
- Add opt-in support for automatically annotating routes after migration tasks [\#293](https://github.com/drwl/annotaterb/pull/293) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
96
|
+
|
|
3
97
|
## [v4.22.0](https://github.com/drwl/annotaterb/tree/v4.22.0) (2026-02-12)
|
|
4
98
|
|
|
5
99
|
[Full Changelog](https://github.com/drwl/annotaterb/compare/v4.21.0...v4.22.0)
|
|
6
100
|
|
|
101
|
+
**Implemented enhancements:**
|
|
102
|
+
|
|
103
|
+
- Feature: ruby-lsp addon [\#175](https://github.com/drwl/annotaterb/issues/175)
|
|
104
|
+
- Mounting ActionCable leads to weird annotation [\#161](https://github.com/drwl/annotaterb/issues/161)
|
|
105
|
+
|
|
7
106
|
**Fixed bugs:**
|
|
8
107
|
|
|
9
108
|
- Yardoc formatting for comments on database attributes [\#162](https://github.com/drwl/annotaterb/issues/162)
|
|
@@ -13,8 +112,6 @@
|
|
|
13
112
|
- New `ignore_multi_database_name` option seems to be non-functional [\#303](https://github.com/drwl/annotaterb/issues/303)
|
|
14
113
|
- Changing sort options does not change annotations [\#294](https://github.com/drwl/annotaterb/issues/294)
|
|
15
114
|
- CLI script for annotaterb not installed or runnable [\#290](https://github.com/drwl/annotaterb/issues/290)
|
|
16
|
-
- Feature: ruby-lsp addon [\#175](https://github.com/drwl/annotaterb/issues/175)
|
|
17
|
-
- Mounting ActionCable leads to weird annotation [\#161](https://github.com/drwl/annotaterb/issues/161)
|
|
18
115
|
|
|
19
116
|
**Merged pull requests:**
|
|
20
117
|
|
|
@@ -22,7 +119,7 @@
|
|
|
22
119
|
- Run CI on CRuby 4.0 [\#308](https://github.com/drwl/annotaterb/pull/308) ([viralpraxis](https://github.com/viralpraxis))
|
|
23
120
|
- Generate changelog for v4.21.0 [\#307](https://github.com/drwl/annotaterb/pull/307) ([drwl](https://github.com/drwl))
|
|
24
121
|
- fix NoMethodError when using nested\_position with fixture files [\#298](https://github.com/drwl/annotaterb/pull/298) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
25
|
-
- fix: Respect configured sort [\#295](https://github.com/drwl/annotaterb/pull/295) ([patrickarnett](https://github.com/patrickarnett))
|
|
122
|
+
- fix: Respect configured sort [\#295](https://github.com/drwl/annotaterb/pull/295) ([patrickarnett](https://github.com/patrickarnett))
|
|
26
123
|
- Use `#lease_connection` if available [\#292](https://github.com/drwl/annotaterb/pull/292) ([viralpraxis](https://github.com/viralpraxis))
|
|
27
124
|
- refactor: simplify primary key check logic \(no functional changes\) [\#285](https://github.com/drwl/annotaterb/pull/285) ([OdenTakashi](https://github.com/OdenTakashi))
|
|
28
125
|
- Honor skip\_on\_db\_migrate config option when runnig migrate tasks [\#274](https://github.com/drwl/annotaterb/pull/274) ([martinechtner](https://github.com/martinechtner))
|
data/README.md
CHANGED
|
@@ -22,16 +22,17 @@ The schema comment looks like this:
|
|
|
22
22
|
```ruby
|
|
23
23
|
# == Schema Information
|
|
24
24
|
#
|
|
25
|
-
# Table name:
|
|
25
|
+
# Table name: users
|
|
26
26
|
#
|
|
27
|
-
# id
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
27
|
+
# id :integer not null, primary key
|
|
28
|
+
# name :string
|
|
29
|
+
# email :string
|
|
30
|
+
# sign_in_count :integer default(0), not null
|
|
31
|
+
# admin :boolean default(FALSE), not null
|
|
32
|
+
# created_at :datetime not null
|
|
33
|
+
# updated_at :datetime not null
|
|
33
34
|
#
|
|
34
|
-
class
|
|
35
|
+
class User < ApplicationRecord
|
|
35
36
|
...
|
|
36
37
|
```
|
|
37
38
|
|
|
@@ -68,7 +69,7 @@ This will copy a rake task into your Rails project's `lib/tasks` directory that
|
|
|
68
69
|
$ bin/rails db:migrate
|
|
69
70
|
# ...
|
|
70
71
|
# Annotating models
|
|
71
|
-
# Annotated (1): app/models/
|
|
72
|
+
# Annotated (1): app/models/user.rb
|
|
72
73
|
```
|
|
73
74
|
|
|
74
75
|
To skip the automatic annotation that happens after a db task, pass the environment variable `ANNOTATERB_SKIP_ON_DB_TASKS=1` before your command.
|
|
@@ -158,6 +159,8 @@ Annotate model options:
|
|
|
158
159
|
--without-column-comments exclude column comments in model annotations
|
|
159
160
|
--position-of-column-comment [with_name|rightmost_column]
|
|
160
161
|
set the position, in the annotation block, of the column comment
|
|
162
|
+
--enum-default-format [label|raw|both]
|
|
163
|
+
set how defaults of enum backed columns are shown
|
|
161
164
|
--with-table-comments include table comments in model annotations
|
|
162
165
|
--without-table-comments exclude table comments in model annotations
|
|
163
166
|
--classes-default-to-s class Custom classes to be represented with `to_s`, may be used multiple times
|
|
@@ -237,6 +240,123 @@ Annotaterb reads first the configuration file, if it exists, passes its content
|
|
|
237
240
|
|
|
238
241
|
For further details visit the [section in the migration guide](MIGRATION_GUIDE.md#automatic-annotations-after-running-database-migration-commands).
|
|
239
242
|
|
|
243
|
+
### Configuration options
|
|
244
|
+
|
|
245
|
+
Keys use snake_case and match the gem defaults in `AnnotateRb::Options`. CLI flags override values from the config file.
|
|
246
|
+
|
|
247
|
+
#### Position
|
|
248
|
+
|
|
249
|
+
| Option | Default | Description |
|
|
250
|
+
| --- | --- | --- |
|
|
251
|
+
| `position` | `before` | Fallback position for all `position_in_*` options. One of `before`, `top`, `after`, `bottom`, `before_doc`. |
|
|
252
|
+
| `position_in_class` | `before` | Position in model files. `before_doc` keeps class documentation adjacent to the class. |
|
|
253
|
+
| `position_in_factory` | `before` | Position in FactoryBot factory files. |
|
|
254
|
+
| `position_in_fixture` | `before` | Position in fixture files. |
|
|
255
|
+
| `position_in_test` | `before` | Position in test/spec files. |
|
|
256
|
+
| `position_in_routes` | `before` | Position in `config/routes.rb`. |
|
|
257
|
+
| `position_in_serializer` | `before` | Position in serializer files. |
|
|
258
|
+
| `position_in_additional_file_patterns` | `before` | Position in files matched by `additional_file_patterns`. |
|
|
259
|
+
| `nested_position` | `false` | Place annotations directly above nested classes/modules instead of at the top of the file. |
|
|
260
|
+
|
|
261
|
+
#### Schema annotation content
|
|
262
|
+
|
|
263
|
+
| Option | Default | Description |
|
|
264
|
+
| --- | --- | --- |
|
|
265
|
+
| `show_foreign_keys` | `true` | List foreign key constraints. |
|
|
266
|
+
| `show_complete_foreign_keys` | `false` | Use complete foreign key names. |
|
|
267
|
+
| `show_indexes` | `true` | List table indexes. |
|
|
268
|
+
| `show_indexes_comments` | `false` | Include index comments. |
|
|
269
|
+
| `show_indexes_include` | `false` | Include `INCLUDE` columns on indexes. |
|
|
270
|
+
| `simple_indexes` | `false` | Concat related indexes onto each column line. |
|
|
271
|
+
| `show_check_constraints` | `false` | List check constraints. |
|
|
272
|
+
| `show_enums` | `false` | Show PostgreSQL enum types. |
|
|
273
|
+
| `enum_default_format` | `label` | Default shown for enum backed columns: `label` (`default("idnow")`), `raw` (`default(0)`) or `both` (`default(0: "idnow")`). |
|
|
274
|
+
| `show_virtual_columns` | `false` | Show virtual/generated columns. |
|
|
275
|
+
| `include_version` | `false` | Include the migration version number. |
|
|
276
|
+
| `with_comment` | `true` | Include database comments (fallback for column/table comment flags). |
|
|
277
|
+
| `with_column_comments` | `true` | Include column comments. |
|
|
278
|
+
| `with_table_comments` | `true` | Include table comments. |
|
|
279
|
+
| `position_of_column_comment` | `with_name` | Column comment placement: `with_name` or `rightmost_column`. |
|
|
280
|
+
| `hide_default_column_types` | `""` | Comma-separated column types that omit defaults (e.g. `json,jsonb,hstore`). |
|
|
281
|
+
| `hide_limit_column_types` | `""` | Comma-separated column types that omit limits (e.g. `integer,boolean,text`). |
|
|
282
|
+
| `ignore_columns` | `null` | Regex of column names to skip. |
|
|
283
|
+
| `ignore_database_name` | `false` | Omit the database name from annotations. |
|
|
284
|
+
| `ignore_multi_database_name` | `false` | Omit the database name in multi-database setups. |
|
|
285
|
+
| `timestamp_columns` | `[created_at, updated_at]` | Column names treated as timestamps for classified sorting. |
|
|
286
|
+
| `classes_default_to_s` | `[]` | Class names whose default values are rendered with `to_s`. |
|
|
287
|
+
|
|
288
|
+
#### Sorting and format
|
|
289
|
+
|
|
290
|
+
| Option | Default | Description |
|
|
291
|
+
| --- | --- | --- |
|
|
292
|
+
| `sort` | `false` | Sort columns alphabetically. |
|
|
293
|
+
| `classified_sort` | `true` | Sort as id → other columns → timestamps → associations. |
|
|
294
|
+
| `grouped_polymorphic` | `false` | Group polymorphic associations when using `classified_sort`. |
|
|
295
|
+
| `format_markdown` | `false` | Render annotations as Markdown. |
|
|
296
|
+
| `format_rdoc` | `false` | Render annotations as RDoc. |
|
|
297
|
+
| `format_yard` | `false` | Render annotations as YARD. |
|
|
298
|
+
|
|
299
|
+
#### What to annotate / exclude
|
|
300
|
+
|
|
301
|
+
| Option | Default | Description |
|
|
302
|
+
| --- | --- | --- |
|
|
303
|
+
| `active_admin` | `false` | Annotate ActiveAdmin models. |
|
|
304
|
+
| `exclude_controllers` | `true` | Skip controller files. |
|
|
305
|
+
| `exclude_factories` | `false` | Skip factory files. |
|
|
306
|
+
| `exclude_fixtures` | `false` | Skip fixture files. |
|
|
307
|
+
| `exclude_helpers` | `true` | Skip helper files. |
|
|
308
|
+
| `exclude_scaffolds` | `true` | Skip scaffold files. |
|
|
309
|
+
| `exclude_serializers` | `false` | Skip serializer files. |
|
|
310
|
+
| `exclude_sti_subclasses` | `false` | Skip STI subclasses. |
|
|
311
|
+
| `exclude_tests` | `false` | Skip test/spec files. Can also be an array of symbols. |
|
|
312
|
+
| `ignore_model_sub_dir` | `false` | Ignore subdirectories under `model_dir`. |
|
|
313
|
+
| `ignore_unknown_models` | `false` | Suppress warnings for bad model files. |
|
|
314
|
+
|
|
315
|
+
#### Paths
|
|
316
|
+
|
|
317
|
+
| Option | Default | Description |
|
|
318
|
+
| --- | --- | --- |
|
|
319
|
+
| `model_dir` | `[app/models]` | Directories containing models. |
|
|
320
|
+
| `root_dir` | `[""]` | Root directories for multi-project layouts. |
|
|
321
|
+
| `additional_file_patterns` | `[]` | Extra paths/globs to annotate (supports `%MODEL_NAME%`). |
|
|
322
|
+
| `require` | `[]` | Extra files to require before loading models. |
|
|
323
|
+
|
|
324
|
+
#### Routes
|
|
325
|
+
|
|
326
|
+
| Option | Default | Description |
|
|
327
|
+
| --- | --- | --- |
|
|
328
|
+
| `ignore_routes` | `null` | Regex of routes to skip. |
|
|
329
|
+
| `timestamp` | `false` | Include a timestamp in route annotations. |
|
|
330
|
+
| `auto_annotate_routes_after_migrate` | `false` | Also annotate routes after DB migrate tasks. |
|
|
331
|
+
|
|
332
|
+
#### Wrappers and behavior
|
|
333
|
+
|
|
334
|
+
| Option | Default | Description |
|
|
335
|
+
| --- | --- | --- |
|
|
336
|
+
| `wrapper` | `null` | Text used for both opening and closing wrappers. |
|
|
337
|
+
| `wrapper_open` | `null` | Opening wrapper text (falls back to `wrapper`). |
|
|
338
|
+
| `wrapper_close` | `null` | Closing wrapper text (falls back to `wrapper`). |
|
|
339
|
+
| `force` | `false` | Rewrite annotations even when unchanged. |
|
|
340
|
+
| `frozen` | `false` | Exit non-zero if annotations would change. |
|
|
341
|
+
| `skip_on_db_migrate` | `false` | Skip automatic annotation after DB migrate tasks. |
|
|
342
|
+
| `debug` | `false` | Print resolved options for debugging. |
|
|
343
|
+
| `trace` | `false` | Print full stack traces when annotation fails. |
|
|
344
|
+
|
|
345
|
+
Example:
|
|
346
|
+
|
|
347
|
+
```yml
|
|
348
|
+
# .annotaterb.yml
|
|
349
|
+
position: after
|
|
350
|
+
show_foreign_keys: true
|
|
351
|
+
show_indexes: true
|
|
352
|
+
show_enums: true
|
|
353
|
+
classified_sort: true
|
|
354
|
+
model_dir:
|
|
355
|
+
- app/models
|
|
356
|
+
- app/models/concerns
|
|
357
|
+
skip_on_db_migrate: false
|
|
358
|
+
```
|
|
359
|
+
|
|
240
360
|
### Preserving class documentation comments
|
|
241
361
|
|
|
242
362
|
By default, when `position_in_class` is `before` (or `top`), AnnotateRb places the schema annotation immediately before the class declaration line. Any human-written documentation comment that was directly above the class is therefore pushed above the annotation.
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
1
|
+
4.25.0
|
|
@@ -27,6 +27,8 @@ module AnnotateRb
|
|
|
27
27
|
IndexAnnotation::AnnotationBuilder.new(@model, @options).build,
|
|
28
28
|
ForeignKeyAnnotation::AnnotationBuilder.new(@model, @options).build,
|
|
29
29
|
CheckConstraintAnnotation::AnnotationBuilder.new(@model, @options).build,
|
|
30
|
+
UniqueConstraintAnnotation::AnnotationBuilder.new(@model, @options).build,
|
|
31
|
+
ExclusionConstraintAnnotation::AnnotationBuilder.new(@model, @options).build,
|
|
30
32
|
EnumAnnotation::AnnotationBuilder.new(@model, @options).build,
|
|
31
33
|
SchemaFooter.new
|
|
32
34
|
]
|
|
@@ -65,7 +67,7 @@ module AnnotateRb
|
|
|
65
67
|
table_name = @model.table_name
|
|
66
68
|
table_comment = @model.connection.try(:table_comment, @model.table_name)
|
|
67
69
|
max_size = @model.max_schema_info_width
|
|
68
|
-
database_name = @model.database_name if
|
|
70
|
+
database_name = @model.database_name if show_database_name?
|
|
69
71
|
|
|
70
72
|
_annotation = Annotation.new(@options,
|
|
71
73
|
version: version, table_name: table_name, table_comment: table_comment,
|
|
@@ -74,6 +76,11 @@ module AnnotateRb
|
|
|
74
76
|
|
|
75
77
|
private
|
|
76
78
|
|
|
79
|
+
# TODO: Consolidate ignore_database_name and ignore_multi_database_name; they serve the same purpose
|
|
80
|
+
def show_database_name?
|
|
81
|
+
!@options[:ignore_database_name] && multi_db_environment?
|
|
82
|
+
end
|
|
83
|
+
|
|
77
84
|
def multi_db_environment?
|
|
78
85
|
return false if @options[:ignore_multi_database_name]
|
|
79
86
|
|
|
@@ -37,6 +37,7 @@ module AnnotateRb
|
|
|
37
37
|
when Float, Integer then value.to_s
|
|
38
38
|
# BigDecimals need to be output in a non-normalized form and quoted.
|
|
39
39
|
when BigDecimal then value.to_s("F")
|
|
40
|
+
when EnumDefault then "#{quote(value.raw)}: #{quote(value.label)}"
|
|
40
41
|
when String then value.inspect
|
|
41
42
|
else
|
|
42
43
|
value.inspect
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AnnotateRb
|
|
4
|
+
module ModelAnnotator
|
|
5
|
+
module ColumnAnnotation
|
|
6
|
+
# Pairs the raw DB default of an enum backed column with its label, so
|
|
7
|
+
# that annotations can show both.
|
|
8
|
+
EnumDefault = Struct.new(:raw, :label)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -8,6 +8,7 @@ module AnnotateRb
|
|
|
8
8
|
autoload :ColumnWrapper, "annotate_rb/model_annotator/column_annotation/column_wrapper"
|
|
9
9
|
autoload :AnnotationBuilder, "annotate_rb/model_annotator/column_annotation/annotation_builder"
|
|
10
10
|
autoload :DefaultValueBuilder, "annotate_rb/model_annotator/column_annotation/default_value_builder"
|
|
11
|
+
autoload :EnumDefault, "annotate_rb/model_annotator/column_annotation/enum_default"
|
|
11
12
|
autoload :ColumnComponent, "annotate_rb/model_annotator/column_annotation/column_component"
|
|
12
13
|
end
|
|
13
14
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AnnotateRb
|
|
4
|
+
module ModelAnnotator
|
|
5
|
+
module ExclusionConstraintAnnotation
|
|
6
|
+
class Annotation
|
|
7
|
+
HEADER_TEXT = "Exclusion Constraints"
|
|
8
|
+
|
|
9
|
+
def initialize(constraints)
|
|
10
|
+
@constraints = constraints
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def body
|
|
14
|
+
[
|
|
15
|
+
Components::BlankCommentLine.new,
|
|
16
|
+
Components::Header.new(HEADER_TEXT),
|
|
17
|
+
Components::BlankCommentLine.new,
|
|
18
|
+
*@constraints
|
|
19
|
+
]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_markdown
|
|
23
|
+
body.map(&:to_markdown).join("\n")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_rdoc
|
|
27
|
+
body.map(&:to_rdoc).join("\n")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_yard
|
|
31
|
+
body.map(&:to_yard).join("\n")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_default
|
|
35
|
+
body.map(&:to_default).join("\n")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AnnotateRb
|
|
4
|
+
module ModelAnnotator
|
|
5
|
+
module ExclusionConstraintAnnotation
|
|
6
|
+
class AnnotationBuilder
|
|
7
|
+
def initialize(model, options)
|
|
8
|
+
@model = model
|
|
9
|
+
@options = options
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def build
|
|
13
|
+
return Components::NilComponent.new if !@options[:show_exclusion_constraints]
|
|
14
|
+
return Components::NilComponent.new unless @model.connection.respond_to?(:supports_exclusion_constraints?) &&
|
|
15
|
+
@model.connection.supports_exclusion_constraints? && @model.connection.respond_to?(:exclusion_constraints)
|
|
16
|
+
|
|
17
|
+
exclusion_constraints = @model.connection.exclusion_constraints(@model.table_name)
|
|
18
|
+
return Components::NilComponent.new if exclusion_constraints.empty?
|
|
19
|
+
|
|
20
|
+
max_size = exclusion_constraints.map { |exclusion_constraint| exclusion_constraint.name.size }.max + 1
|
|
21
|
+
|
|
22
|
+
constraints = exclusion_constraints.sort_by(&:name).map do |exclusion_constraint|
|
|
23
|
+
details = "(#{exclusion_constraint.expression})"
|
|
24
|
+
details += " USING #{exclusion_constraint.using}" if exclusion_constraint.using
|
|
25
|
+
details += " WHERE (#{exclusion_constraint.where})" if exclusion_constraint.where
|
|
26
|
+
if exclusion_constraint.deferrable
|
|
27
|
+
details += " DEFERRABLE INITIALLY #{exclusion_constraint.deferrable.to_s.upcase}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
ExclusionConstraintComponent.new(exclusion_constraint.name, details, max_size)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
_annotation = Annotation.new(constraints)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AnnotateRb
|
|
4
|
+
module ModelAnnotator
|
|
5
|
+
module ExclusionConstraintAnnotation
|
|
6
|
+
class ExclusionConstraintComponent < Components::Base
|
|
7
|
+
attr_reader :name, :details, :max_size
|
|
8
|
+
|
|
9
|
+
def initialize(name, details, max_size)
|
|
10
|
+
@name = name
|
|
11
|
+
@details = details
|
|
12
|
+
@max_size = max_size
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_default
|
|
16
|
+
# standard:disable Lint/FormatParameterMismatch
|
|
17
|
+
sprintf("# %-#{max_size}.#{max_size}s %s", name, details).rstrip
|
|
18
|
+
# standard:enable Lint/FormatParameterMismatch
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_markdown
|
|
22
|
+
sprintf("# * `%s`: `%s`", name, details)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AnnotateRb
|
|
4
|
+
module ModelAnnotator
|
|
5
|
+
module ExclusionConstraintAnnotation
|
|
6
|
+
autoload :AnnotationBuilder, "annotate_rb/model_annotator/exclusion_constraint_annotation/annotation_builder"
|
|
7
|
+
autoload :Annotation, "annotate_rb/model_annotator/exclusion_constraint_annotation/annotation"
|
|
8
|
+
autoload :ExclusionConstraintComponent, "annotate_rb/model_annotator/exclusion_constraint_annotation/exclusion_constraint_component"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -19,9 +19,19 @@ module AnnotateRb
|
|
|
19
19
|
SCHEMA_HEADER_EXACT = [
|
|
20
20
|
IndexAnnotation::Annotation::HEADER_TEXT,
|
|
21
21
|
ForeignKeyAnnotation::Annotation::HEADER_TEXT,
|
|
22
|
-
CheckConstraintAnnotation::Annotation::HEADER_TEXT
|
|
22
|
+
CheckConstraintAnnotation::Annotation::HEADER_TEXT,
|
|
23
|
+
UniqueConstraintAnnotation::Annotation::HEADER_TEXT,
|
|
24
|
+
ExclusionConstraintAnnotation::Annotation::HEADER_TEXT,
|
|
25
|
+
EnumAnnotation::Annotation::HEADER_TEXT
|
|
23
26
|
].freeze
|
|
24
27
|
|
|
28
|
+
# `format_markdown: true` renders each of the section headers above as
|
|
29
|
+
# "### <name>" instead of "<name>", so SCHEMA_HEADER_EXACT can't match it directly.
|
|
30
|
+
# There's no HEADER_TEXT constant for the columns table itself,
|
|
31
|
+
# so "Columns" is listed explicitly here.
|
|
32
|
+
MARKDOWN_HEADER_PREFIX = "### "
|
|
33
|
+
MARKDOWN_SECTION_HEADERS = (SCHEMA_HEADER_EXACT + ["Columns"]).freeze
|
|
34
|
+
|
|
25
35
|
class MalformedAnnotation < StandardError; end
|
|
26
36
|
|
|
27
37
|
class NoAnnotationFound < StandardError; end
|
|
@@ -118,7 +128,18 @@ module AnnotateRb
|
|
|
118
128
|
ending
|
|
119
129
|
end
|
|
120
130
|
|
|
121
|
-
#
|
|
131
|
+
# A line is part of the schema block if it matches one of the known
|
|
132
|
+
# header prefixes/exact texts, or if it looks like a tabular/list row
|
|
133
|
+
# of the annotation body:
|
|
134
|
+
#
|
|
135
|
+
# - Default/plain format: rows have >= 2 leading spaces after `#`
|
|
136
|
+
# (e.g. "# id :integer not null"); prose has at most one.
|
|
137
|
+
# - Markdown format (`format_markdown: true`) instead uses a single
|
|
138
|
+
# leading space after `#` for everything, so it needs its own
|
|
139
|
+
# detection: "### <name>" section headers (matched against
|
|
140
|
+
# MARKDOWN_SECTION_HEADERS with the prefix stripped), "|"-delimited
|
|
141
|
+
# table rows (header/divider/data), and "* `...`" bulleted list
|
|
142
|
+
# items for indexes/foreign keys/enums.
|
|
122
143
|
def schema_like?(comment)
|
|
123
144
|
return true if comment == DEFAULT_ANNOTATION_ENDING
|
|
124
145
|
|
|
@@ -128,6 +149,21 @@ module AnnotateRb
|
|
|
128
149
|
return true if SCHEMA_HEADER_PREFIXES.any? { |p| text.start_with?(p) }
|
|
129
150
|
return true if SCHEMA_HEADER_EXACT.include?(text)
|
|
130
151
|
|
|
152
|
+
# Markdown section headers, e.g. "### Columns", "### Indexes".
|
|
153
|
+
if text.start_with?(MARKDOWN_HEADER_PREFIX)
|
|
154
|
+
return MARKDOWN_SECTION_HEADERS.include?(text.delete_prefix(MARKDOWN_HEADER_PREFIX))
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Requires at least two | separators to identify Markdown tables.
|
|
158
|
+
# This prevents normal user comments containing a single | from being mistaken for a table.
|
|
159
|
+
return true if text.count("|") >= 2
|
|
160
|
+
|
|
161
|
+
# Markdown bulleted list items used for foreign keys/indexes/enums,
|
|
162
|
+
# e.g. "* `index_name`:" or the nested " * **`column`**". The
|
|
163
|
+
# backtick right after the bullet marker distinguishes these from
|
|
164
|
+
# an unrelated user comment that starts with a plain "* ".
|
|
165
|
+
return true if text.match?(/\A\s*\*\s+\*{0,2}`/)
|
|
166
|
+
|
|
131
167
|
comment.match?(/\A#\s{2,}\S/)
|
|
132
168
|
end
|
|
133
169
|
end
|
|
@@ -31,7 +31,7 @@ module AnnotateRb
|
|
|
31
31
|
def parse_comments
|
|
32
32
|
# Adds 0-indexed line numbers
|
|
33
33
|
@input.split($/).each_with_index do |line, line_no|
|
|
34
|
-
if line.strip.
|
|
34
|
+
if line.strip.start_with?("#")
|
|
35
35
|
@comments << [line, line_no]
|
|
36
36
|
end
|
|
37
37
|
end
|
|
@@ -43,10 +43,20 @@ module AnnotateRb
|
|
|
43
43
|
begin
|
|
44
44
|
parser.parse(@input)
|
|
45
45
|
rescue Psych::SyntaxError => _e
|
|
46
|
-
# "Dynamic fixtures with ERB" exist in Rails
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
# "Dynamic fixtures with ERB" exist in Rails and cause Psych.parser to error.
|
|
47
|
+
#
|
|
48
|
+
# We deliberately do not evaluate the ERB and read line numbers off the
|
|
49
|
+
# result: evaluating runs arbitrary code, and the line numbers from the
|
|
50
|
+
# evaluated output do not map back to the original file (ERB tags spanning
|
|
51
|
+
# multiple lines shift the offsets), which would place annotations inside
|
|
52
|
+
# an ERB tag. Instead we derive the content bounds straight from the
|
|
53
|
+
# original lines so annotations land around the ERB body.
|
|
54
|
+
#
|
|
55
|
+
# Only fall back for actual ERB fixtures. Genuinely malformed YAML
|
|
56
|
+
# (no ERB tags) should keep surfacing the parse error rather than
|
|
57
|
+
# being silently annotated.
|
|
58
|
+
raise unless erb_fixture?
|
|
59
|
+
return record_erb_positions
|
|
50
60
|
end
|
|
51
61
|
|
|
52
62
|
stream = parser.handler.root
|
|
@@ -68,6 +78,35 @@ module AnnotateRb
|
|
|
68
78
|
@ends << [nil, stream.end_line]
|
|
69
79
|
end
|
|
70
80
|
end
|
|
81
|
+
|
|
82
|
+
# Locates the content bounds of an ERB fixture directly from the original
|
|
83
|
+
# lines, treating the ERB/YAML body as the doc. The start is the first
|
|
84
|
+
# non-blank, non-comment line so annotations are written above the ERB
|
|
85
|
+
# block (and after any leading comments), never inside a tag.
|
|
86
|
+
def record_erb_positions
|
|
87
|
+
lines = @input.split($/)
|
|
88
|
+
content_start = lines.index { |line| content_line?(line) }
|
|
89
|
+
|
|
90
|
+
if content_start.nil?
|
|
91
|
+
@starts << [nil, 0]
|
|
92
|
+
@ends << [nil, 0]
|
|
93
|
+
else
|
|
94
|
+
content_end = lines.rindex { |line| content_line?(line) }
|
|
95
|
+
@starts << [nil, content_start]
|
|
96
|
+
@ends << [nil, content_end + 1]
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def content_line?(line)
|
|
101
|
+
stripped = line.strip
|
|
102
|
+
!stripped.empty? && !stripped.start_with?("#")
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# True when the input contains an ERB tag, i.e. it is a dynamic fixture
|
|
106
|
+
# rather than plain (possibly malformed) YAML.
|
|
107
|
+
def erb_fixture?
|
|
108
|
+
@input.match?(/<%.*?%>/m)
|
|
109
|
+
end
|
|
71
110
|
end
|
|
72
111
|
end
|
|
73
112
|
end
|
data/lib/annotate_rb/model_annotator/foreign_key_annotation/foreign_key_component_builder.rb
CHANGED
|
@@ -13,7 +13,7 @@ module AnnotateRb
|
|
|
13
13
|
|
|
14
14
|
def formatted_name
|
|
15
15
|
@formatted_name ||= if foreign_key.name.blank?
|
|
16
|
-
|
|
16
|
+
stringified_columns
|
|
17
17
|
else
|
|
18
18
|
@options[:show_complete_foreign_keys] ? foreign_key.name : foreign_key.name.gsub(/(?<=^fk_rails_)[0-9a-f]{10}$/, "...")
|
|
19
19
|
end
|
|
@@ -32,6 +32,12 @@ module AnnotateRb
|
|
|
32
32
|
constraints_info = ""
|
|
33
33
|
constraints_info += "ON DELETE => #{foreign_key.on_delete} " if foreign_key.on_delete
|
|
34
34
|
constraints_info += "ON UPDATE => #{foreign_key.on_update} " if foreign_key.on_update
|
|
35
|
+
if foreign_key.respond_to?(:deferrable) && foreign_key.deferrable
|
|
36
|
+
# Rails 7.0's extract_foreign_key_deferrable returns `true` for the initially-immediate case;
|
|
37
|
+
# 7.1+ normalized this to `:immediate`. Map `true` back to IMMEDIATE so we don't emit "INITIALLY TRUE".
|
|
38
|
+
initially = (foreign_key.deferrable == true) ? "IMMEDIATE" : foreign_key.deferrable.to_s.upcase
|
|
39
|
+
constraints_info += "DEFERRABLE INITIALLY #{initially} "
|
|
40
|
+
end
|
|
35
41
|
constraints_info.strip
|
|
36
42
|
end
|
|
37
43
|
end
|
|
@@ -15,6 +15,9 @@ module AnnotateRb
|
|
|
15
15
|
indexes = @model.retrieve_indexes_from_table
|
|
16
16
|
return Components::NilComponent.new if indexes.empty?
|
|
17
17
|
|
|
18
|
+
indexes = reject_constraint_backed_indexes(indexes)
|
|
19
|
+
return Components::NilComponent.new if indexes.empty?
|
|
20
|
+
|
|
18
21
|
max_size = indexes.map { |index| index.name.size }.max + 1
|
|
19
22
|
|
|
20
23
|
indexes = indexes.sort_by(&:name).map do |index|
|
|
@@ -23,6 +26,32 @@ module AnnotateRb
|
|
|
23
26
|
|
|
24
27
|
_annotation = Annotation.new(indexes)
|
|
25
28
|
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
# Mirrors ActiveRecord's schema_dumper#indexes_in_create: PostgreSQL's
|
|
33
|
+
# unique and exclusion constraints are backed by indexes with the same
|
|
34
|
+
# name, so those show up in `connection.indexes` too. Drop them here so
|
|
35
|
+
# they only appear under their dedicated sections.
|
|
36
|
+
def reject_constraint_backed_indexes(indexes)
|
|
37
|
+
connection = @model.connection
|
|
38
|
+
|
|
39
|
+
if connection.respond_to?(:supports_exclusion_constraints?) &&
|
|
40
|
+
connection.supports_exclusion_constraints? &&
|
|
41
|
+
connection.respond_to?(:exclusion_constraints)
|
|
42
|
+
excl_names = connection.exclusion_constraints(@model.table_name).map(&:name)
|
|
43
|
+
indexes = indexes.reject { |index| excl_names.include?(index.name) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
if connection.respond_to?(:supports_unique_constraints?) &&
|
|
47
|
+
connection.supports_unique_constraints? &&
|
|
48
|
+
connection.respond_to?(:unique_constraints)
|
|
49
|
+
unique_names = connection.unique_constraints(@model.table_name).map(&:name)
|
|
50
|
+
indexes = indexes.reject { |index| unique_names.include?(index.name) }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
indexes
|
|
54
|
+
end
|
|
26
55
|
end
|
|
27
56
|
end
|
|
28
57
|
end
|
|
@@ -136,13 +136,23 @@ module AnnotateRb
|
|
|
136
136
|
|
|
137
137
|
def columns_info
|
|
138
138
|
Array(index.columns).map do |col|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
139
|
+
column = col.to_s.gsub("\r", '\r').gsub("\n", '\n')
|
|
140
|
+
opclass = column_option(:opclasses, col)
|
|
141
|
+
order = column_option(:orders, col)
|
|
142
|
+
|
|
143
|
+
[column, opclass, order&.upcase].compact.join(" ")
|
|
144
144
|
end
|
|
145
145
|
end
|
|
146
|
+
|
|
147
|
+
# ActiveRecord condenses per column index options (`opclasses`, `orders`)
|
|
148
|
+
# into a single value when every column shares the same one, so the
|
|
149
|
+
# option can either be a Hash keyed by column or a bare value.
|
|
150
|
+
def column_option(option, col)
|
|
151
|
+
value = index.try(option)
|
|
152
|
+
value = value[col.to_s] if value.is_a?(Hash)
|
|
153
|
+
|
|
154
|
+
value.presence&.to_s
|
|
155
|
+
end
|
|
146
156
|
end
|
|
147
157
|
end
|
|
148
158
|
end
|
|
@@ -68,8 +68,23 @@ module AnnotateRb
|
|
|
68
68
|
connection.table_comment(@klass.table_name).present?
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
+
# Returns column defaults for annotations.
|
|
72
|
+
#
|
|
73
|
+
# `Model#column_defaults` reflects `attribute :foo, default: X` overrides,
|
|
74
|
+
# which would incorrectly show the Ruby-side default in annotations
|
|
75
|
+
# instead of the DB schema default. To preserve model-level decorations
|
|
76
|
+
# such as enum labels or `TimeZoneConverter` on datetime columns, we start
|
|
77
|
+
# from `column_defaults` and only substitute the DB schema value for
|
|
78
|
+
# attributes whose raw default was replaced.
|
|
71
79
|
def column_defaults
|
|
72
|
-
@klass.column_defaults
|
|
80
|
+
@column_defaults ||= @klass.column_defaults.each_with_object({}) do |(name, value), result|
|
|
81
|
+
column = @klass.columns_hash[name]
|
|
82
|
+
result[name] = if attribute_default_overridden?(name, column)
|
|
83
|
+
schema_default_for(column)
|
|
84
|
+
else
|
|
85
|
+
enum_default(name, column, value)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
73
88
|
end
|
|
74
89
|
|
|
75
90
|
# Add columns managed by the globalize gem if this gem is being used.
|
|
@@ -263,6 +278,53 @@ module AnnotateRb
|
|
|
263
278
|
|
|
264
279
|
@options.get_state(cache_key)
|
|
265
280
|
end
|
|
281
|
+
|
|
282
|
+
private
|
|
283
|
+
|
|
284
|
+
# `attribute :foo, default: X` replaces the raw default Rails read from
|
|
285
|
+
# the DB column, so comparing the two raw values detects the override.
|
|
286
|
+
# Comparing cast values instead would misreport decorated attribute types
|
|
287
|
+
# (an enum casts the DB default `0` into its label) as overrides.
|
|
288
|
+
def attribute_default_overridden?(name, column)
|
|
289
|
+
return false if column.nil?
|
|
290
|
+
|
|
291
|
+
@klass._default_attributes[name].value_before_type_cast != column.default
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# An enum attribute type casts the raw DB default into its label, which is
|
|
295
|
+
# what `column_defaults` reports and what annotations have historically
|
|
296
|
+
# shown. `enum_default_format` picks between that label, the raw value,
|
|
297
|
+
# and both.
|
|
298
|
+
def enum_default(name, column, label)
|
|
299
|
+
return label unless @klass.defined_enums.key?(name)
|
|
300
|
+
|
|
301
|
+
raw = schema_default_for(column)
|
|
302
|
+
return label if raw == label
|
|
303
|
+
|
|
304
|
+
case @options[:enum_default_format]
|
|
305
|
+
when :raw then raw
|
|
306
|
+
when :both then ColumnAnnotation::EnumDefault.new(raw, label)
|
|
307
|
+
else label
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def schema_default_for(column)
|
|
312
|
+
return nil if column.nil? || column.default.nil? || column.default_function
|
|
313
|
+
cast_type_for(column).deserialize(column.default)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# Rails post-8.1 exposes `Column#cast_type` directly; Rails 8.1 introduced
|
|
317
|
+
# the transitional `Column#fetch_cast_type(connection)`; older versions
|
|
318
|
+
# required `connection.lookup_cast_type_from_column(column)`.
|
|
319
|
+
def cast_type_for(column)
|
|
320
|
+
if column.respond_to?(:cast_type)
|
|
321
|
+
column.cast_type
|
|
322
|
+
elsif column.respond_to?(:fetch_cast_type)
|
|
323
|
+
column.fetch_cast_type(connection)
|
|
324
|
+
else
|
|
325
|
+
connection.lookup_cast_type_from_column(column)
|
|
326
|
+
end
|
|
327
|
+
end
|
|
266
328
|
end
|
|
267
329
|
end
|
|
268
330
|
end
|
|
@@ -43,7 +43,9 @@ module AnnotateRb
|
|
|
43
43
|
|
|
44
44
|
klass.reset_column_information
|
|
45
45
|
model_name = klass.name.underscore
|
|
46
|
-
|
|
46
|
+
# Match annotation behavior so a secondary model with a duplicate table
|
|
47
|
+
# name cannot remove annotations from the primary database's fixture.
|
|
48
|
+
table_name = klass.table_name if klass.connection_specification_name == ActiveRecord::Base.name
|
|
47
49
|
|
|
48
50
|
model_instruction = SingleFileRemoveAnnotationInstruction.new(file, @options)
|
|
49
51
|
instructions << model_instruction
|
|
@@ -88,8 +88,33 @@ module AnnotateRb
|
|
|
88
88
|
|
|
89
89
|
patterns
|
|
90
90
|
.map { |f| FileNameResolver.call(f, @model_name, @table_name) }
|
|
91
|
-
.
|
|
92
|
-
.
|
|
91
|
+
.flat_map { |f| Dir.glob(f) }
|
|
92
|
+
.select { |f| owning_root_dir(f) == model_root_dir }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def model_root_dir
|
|
96
|
+
return @model_root_dir if defined?(@model_root_dir)
|
|
97
|
+
|
|
98
|
+
@model_root_dir = owning_root_dir(@file)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Patterns are expanded for every `root_dir` and resolved by model name alone, so models sharing a
|
|
102
|
+
# file basename across root directories (e.g. packwerk packs) glob the same related files. Root
|
|
103
|
+
# directories can be nested, so a file belongs to the most specific one containing it, and only
|
|
104
|
+
# models from that same root directory may annotate it. Returns nil for the project root.
|
|
105
|
+
def owning_root_dir(file)
|
|
106
|
+
expanded_file = File.expand_path(file)
|
|
107
|
+
|
|
108
|
+
expanded_root_dirs
|
|
109
|
+
.select { |dir| expanded_file.start_with?("#{dir}/") }
|
|
110
|
+
.max_by(&:length)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def expanded_root_dirs
|
|
114
|
+
@expanded_root_dirs ||= Array(@options[:root_dir])
|
|
115
|
+
.reject { |root_dir| root_dir.to_s.empty? }
|
|
116
|
+
.flat_map { |root_dir| Dir.glob(root_dir) }
|
|
117
|
+
.map { |root_dir| File.expand_path(root_dir) }
|
|
93
118
|
end
|
|
94
119
|
|
|
95
120
|
def add_related_test_files
|
|
@@ -18,7 +18,7 @@ module AnnotateRb
|
|
|
18
18
|
parsed_file = FileParser::ParsedFile.new(old_content, "", parser_klass, options).parse
|
|
19
19
|
rescue FileParser::AnnotationFinder::MalformedAnnotation => e
|
|
20
20
|
warn "Unable to process #{file_name}: #{e.message}"
|
|
21
|
-
warn "\t" + e.backtrace.join("\n\t") if
|
|
21
|
+
warn "\t" + e.backtrace.join("\n\t") if options[:trace]
|
|
22
22
|
return false
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -31,7 +31,7 @@ module AnnotateRb
|
|
|
31
31
|
parsed_file = FileParser::ParsedFile.new(old_content, annotation, parser_klass, options, model_class_name: model_class_name).parse
|
|
32
32
|
rescue FileParser::AnnotationFinder::MalformedAnnotation => e
|
|
33
33
|
warn "Unable to process #{file_name}: #{e.message}"
|
|
34
|
-
warn "\t" + e.backtrace.join("\n\t") if
|
|
34
|
+
warn "\t" + e.backtrace.join("\n\t") if options[:trace]
|
|
35
35
|
return false
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AnnotateRb
|
|
4
|
+
module ModelAnnotator
|
|
5
|
+
module UniqueConstraintAnnotation
|
|
6
|
+
class Annotation
|
|
7
|
+
HEADER_TEXT = "Unique Constraints"
|
|
8
|
+
|
|
9
|
+
def initialize(constraints)
|
|
10
|
+
@constraints = constraints
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def body
|
|
14
|
+
[
|
|
15
|
+
Components::BlankCommentLine.new,
|
|
16
|
+
Components::Header.new(HEADER_TEXT),
|
|
17
|
+
Components::BlankCommentLine.new,
|
|
18
|
+
*@constraints
|
|
19
|
+
]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_markdown
|
|
23
|
+
body.map(&:to_markdown).join("\n")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_rdoc
|
|
27
|
+
body.map(&:to_rdoc).join("\n")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_yard
|
|
31
|
+
body.map(&:to_yard).join("\n")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_default
|
|
35
|
+
body.map(&:to_default).join("\n")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AnnotateRb
|
|
4
|
+
module ModelAnnotator
|
|
5
|
+
module UniqueConstraintAnnotation
|
|
6
|
+
class AnnotationBuilder
|
|
7
|
+
def initialize(model, options)
|
|
8
|
+
@model = model
|
|
9
|
+
@options = options
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def build
|
|
13
|
+
return Components::NilComponent.new if !@options[:show_unique_constraints]
|
|
14
|
+
return Components::NilComponent.new unless @model.connection.respond_to?(:supports_unique_constraints?) &&
|
|
15
|
+
@model.connection.supports_unique_constraints? && @model.connection.respond_to?(:unique_constraints)
|
|
16
|
+
|
|
17
|
+
unique_constraints = @model.connection.unique_constraints(@model.table_name)
|
|
18
|
+
return Components::NilComponent.new if unique_constraints.empty?
|
|
19
|
+
|
|
20
|
+
max_size = unique_constraints.map { |unique_constraint| unique_constraint.name.size }.max + 1
|
|
21
|
+
|
|
22
|
+
constraints = unique_constraints.sort_by(&:name).map do |unique_constraint|
|
|
23
|
+
columns = Array(unique_constraint.column)
|
|
24
|
+
details = "(#{columns.join(", ")})"
|
|
25
|
+
if unique_constraint.deferrable
|
|
26
|
+
details += " DEFERRABLE INITIALLY #{unique_constraint.deferrable.to_s.upcase}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
UniqueConstraintComponent.new(unique_constraint.name, details, max_size)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
_annotation = Annotation.new(constraints)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/annotate_rb/model_annotator/unique_constraint_annotation/unique_constraint_component.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AnnotateRb
|
|
4
|
+
module ModelAnnotator
|
|
5
|
+
module UniqueConstraintAnnotation
|
|
6
|
+
class UniqueConstraintComponent < Components::Base
|
|
7
|
+
attr_reader :name, :details, :max_size
|
|
8
|
+
|
|
9
|
+
def initialize(name, details, max_size)
|
|
10
|
+
@name = name
|
|
11
|
+
@details = details
|
|
12
|
+
@max_size = max_size
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_default
|
|
16
|
+
# standard:disable Lint/FormatParameterMismatch
|
|
17
|
+
sprintf("# %-#{max_size}.#{max_size}s %s", name, details).rstrip
|
|
18
|
+
# standard:enable Lint/FormatParameterMismatch
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_markdown
|
|
22
|
+
sprintf("# * `%s`: `%s`", name, details)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AnnotateRb
|
|
4
|
+
module ModelAnnotator
|
|
5
|
+
module UniqueConstraintAnnotation
|
|
6
|
+
autoload :AnnotationBuilder, "annotate_rb/model_annotator/unique_constraint_annotation/annotation_builder"
|
|
7
|
+
autoload :Annotation, "annotate_rb/model_annotator/unique_constraint_annotation/annotation"
|
|
8
|
+
autoload :UniqueConstraintComponent, "annotate_rb/model_annotator/unique_constraint_annotation/unique_constraint_component"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -27,6 +27,8 @@ module AnnotateRb
|
|
|
27
27
|
autoload :FileParser, "annotate_rb/model_annotator/file_parser"
|
|
28
28
|
autoload :ZeitwerkClassGetter, "annotate_rb/model_annotator/zeitwerk_class_getter"
|
|
29
29
|
autoload :CheckConstraintAnnotation, "annotate_rb/model_annotator/check_constraint_annotation"
|
|
30
|
+
autoload :UniqueConstraintAnnotation, "annotate_rb/model_annotator/unique_constraint_annotation"
|
|
31
|
+
autoload :ExclusionConstraintAnnotation, "annotate_rb/model_annotator/exclusion_constraint_annotation"
|
|
30
32
|
autoload :EnumAnnotation, "annotate_rb/model_annotator/enum_annotation"
|
|
31
33
|
autoload :FileToParserMapper, "annotate_rb/model_annotator/file_to_parser_mapper"
|
|
32
34
|
autoload :Components, "annotate_rb/model_annotator/components"
|
data/lib/annotate_rb/options.rb
CHANGED
|
@@ -42,11 +42,14 @@ module AnnotateRb
|
|
|
42
42
|
format_yard: false, # ModelAnnotator
|
|
43
43
|
frozen: false, # ModelAnnotator, but should be used by both
|
|
44
44
|
grouped_polymorphic: false, # ModelAnnotator
|
|
45
|
+
ignore_database_name: false, # ModelAnnotator
|
|
45
46
|
ignore_model_sub_dir: false, # ModelAnnotator
|
|
46
47
|
ignore_unknown_models: false, # ModelAnnotator
|
|
47
48
|
include_version: false, # ModelAnnotator
|
|
48
49
|
show_complete_foreign_keys: false, # ModelAnnotator
|
|
49
50
|
show_check_constraints: false, # ModelAnnotator
|
|
51
|
+
show_unique_constraints: false, # ModelAnnotator
|
|
52
|
+
show_exclusion_constraints: false, # ModelAnnotator
|
|
50
53
|
show_enums: false, # ModelAnnotator
|
|
51
54
|
show_foreign_keys: true, # ModelAnnotator
|
|
52
55
|
show_indexes: true, # ModelAnnotator
|
|
@@ -60,7 +63,8 @@ module AnnotateRb
|
|
|
60
63
|
with_comment: true, # ModelAnnotator
|
|
61
64
|
with_column_comments: nil, # ModelAnnotator
|
|
62
65
|
with_table_comments: nil, # ModelAnnotator
|
|
63
|
-
position_of_column_comment: :with_name # ModelAnnotator
|
|
66
|
+
position_of_column_comment: :with_name, # ModelAnnotator
|
|
67
|
+
enum_default_format: :label # ModelAnnotator
|
|
64
68
|
}.freeze
|
|
65
69
|
|
|
66
70
|
OTHER_OPTIONS = {
|
|
@@ -81,7 +85,6 @@ module AnnotateRb
|
|
|
81
85
|
ignore_multi_database_name: false, # ModelAnnotator
|
|
82
86
|
ignore_routes: nil, # RouteAnnotator
|
|
83
87
|
models: true, # Core
|
|
84
|
-
routes: false, # Core
|
|
85
88
|
skip_on_db_migrate: false, # Core
|
|
86
89
|
auto_annotate_routes_after_migrate: false, # Core
|
|
87
90
|
target_action: :do_annotations, # Core; Possible values: :do_annotations, :remove_annotations
|
|
@@ -118,10 +121,13 @@ module AnnotateRb
|
|
|
118
121
|
:format_yard,
|
|
119
122
|
:frozen,
|
|
120
123
|
:grouped_polymorphic,
|
|
124
|
+
:ignore_database_name,
|
|
121
125
|
:ignore_model_sub_dir,
|
|
122
126
|
:ignore_unknown_models,
|
|
123
127
|
:include_version,
|
|
124
128
|
:show_check_constraints,
|
|
129
|
+
:show_unique_constraints,
|
|
130
|
+
:show_exclusion_constraints,
|
|
125
131
|
:show_enums,
|
|
126
132
|
:show_complete_foreign_keys,
|
|
127
133
|
:show_foreign_keys,
|
|
@@ -135,7 +141,8 @@ module AnnotateRb
|
|
|
135
141
|
:with_comment,
|
|
136
142
|
:with_column_comments,
|
|
137
143
|
:with_table_comments,
|
|
138
|
-
:position_of_column_comment
|
|
144
|
+
:position_of_column_comment,
|
|
145
|
+
:enum_default_format
|
|
139
146
|
].freeze
|
|
140
147
|
|
|
141
148
|
OTHER_OPTION_KEYS = [
|
|
@@ -149,7 +156,6 @@ module AnnotateRb
|
|
|
149
156
|
:ignore_routes,
|
|
150
157
|
:ignore_multi_database_name,
|
|
151
158
|
:models,
|
|
152
|
-
:routes,
|
|
153
159
|
:skip_on_db_migrate,
|
|
154
160
|
:auto_annotate_routes_after_migrate,
|
|
155
161
|
:target_action,
|
|
@@ -218,6 +224,7 @@ module AnnotateRb
|
|
|
218
224
|
@options[:with_column_comments] = @options[:with_comment] if @options[:with_column_comments].nil?
|
|
219
225
|
@options[:with_table_comments] = @options[:with_comment] if @options[:with_table_comments].nil?
|
|
220
226
|
@options[:position_of_column_comment] = @options[:position_of_column_comment].to_sym
|
|
227
|
+
@options[:enum_default_format] = @options[:enum_default_format].to_sym
|
|
221
228
|
|
|
222
229
|
self
|
|
223
230
|
end
|
data/lib/annotate_rb/parser.rb
CHANGED
|
@@ -207,6 +207,16 @@ module AnnotateRb
|
|
|
207
207
|
@options[:show_check_constraints] = true
|
|
208
208
|
end
|
|
209
209
|
|
|
210
|
+
option_parser.on("--show-unique-constraints",
|
|
211
|
+
"List the table's unique constraints in the annotation") do
|
|
212
|
+
@options[:show_unique_constraints] = true
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
option_parser.on("--show-exclusion-constraints",
|
|
216
|
+
"List the table's exclusion constraints in the annotation") do
|
|
217
|
+
@options[:show_exclusion_constraints] = true
|
|
218
|
+
end
|
|
219
|
+
|
|
210
220
|
option_parser.on("--hide-limit-column-types VALUES",
|
|
211
221
|
"don't show limit for given column types, separated by commas (i.e., `integer,boolean,text`)") do |values|
|
|
212
222
|
@options[:hide_limit_column_types] = values.to_s
|
|
@@ -222,6 +232,11 @@ module AnnotateRb
|
|
|
222
232
|
@options[:ignore_unknown_models] = true
|
|
223
233
|
end
|
|
224
234
|
|
|
235
|
+
option_parser.on("--ignore-database-name",
|
|
236
|
+
"don't include the database name in the annotation") do
|
|
237
|
+
@options[:ignore_database_name] = true
|
|
238
|
+
end
|
|
239
|
+
|
|
225
240
|
option_parser.on("-I",
|
|
226
241
|
"--ignore-columns REGEX",
|
|
227
242
|
"don't annotate columns that match a given REGEX (i.e., `annotate -I '^(id|updated_at|created_at)'`") do |regex|
|
|
@@ -234,7 +249,7 @@ module AnnotateRb
|
|
|
234
249
|
end
|
|
235
250
|
|
|
236
251
|
option_parser.on("--without-comment",
|
|
237
|
-
"
|
|
252
|
+
"exclude database comments in model annotations") do
|
|
238
253
|
@options[:with_comment] = false
|
|
239
254
|
end
|
|
240
255
|
|
|
@@ -253,6 +268,11 @@ module AnnotateRb
|
|
|
253
268
|
@options[:position_of_column_comment] = value.to_sym
|
|
254
269
|
end
|
|
255
270
|
|
|
271
|
+
option_parser.on("--enum-default-format [label|raw|both]",
|
|
272
|
+
"set how defaults of enum backed columns are shown") do |value|
|
|
273
|
+
@options[:enum_default_format] = value.to_sym
|
|
274
|
+
end
|
|
275
|
+
|
|
256
276
|
option_parser.on("--with-table-comments",
|
|
257
277
|
"include table comments in model annotations") do
|
|
258
278
|
@options[:with_table_comments] = true
|
data/lib/annotate_rb/runner.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: annotaterb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.25.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew W. Lee
|
|
@@ -88,12 +88,17 @@ files:
|
|
|
88
88
|
- lib/annotate_rb/model_annotator/column_annotation/column_component.rb
|
|
89
89
|
- lib/annotate_rb/model_annotator/column_annotation/column_wrapper.rb
|
|
90
90
|
- lib/annotate_rb/model_annotator/column_annotation/default_value_builder.rb
|
|
91
|
+
- lib/annotate_rb/model_annotator/column_annotation/enum_default.rb
|
|
91
92
|
- lib/annotate_rb/model_annotator/column_annotation/type_builder.rb
|
|
92
93
|
- lib/annotate_rb/model_annotator/components.rb
|
|
93
94
|
- lib/annotate_rb/model_annotator/enum_annotation.rb
|
|
94
95
|
- lib/annotate_rb/model_annotator/enum_annotation/annotation.rb
|
|
95
96
|
- lib/annotate_rb/model_annotator/enum_annotation/annotation_builder.rb
|
|
96
97
|
- lib/annotate_rb/model_annotator/enum_annotation/enum_component.rb
|
|
98
|
+
- lib/annotate_rb/model_annotator/exclusion_constraint_annotation.rb
|
|
99
|
+
- lib/annotate_rb/model_annotator/exclusion_constraint_annotation/annotation.rb
|
|
100
|
+
- lib/annotate_rb/model_annotator/exclusion_constraint_annotation/annotation_builder.rb
|
|
101
|
+
- lib/annotate_rb/model_annotator/exclusion_constraint_annotation/exclusion_constraint_component.rb
|
|
97
102
|
- lib/annotate_rb/model_annotator/file_name_resolver.rb
|
|
98
103
|
- lib/annotate_rb/model_annotator/file_parser.rb
|
|
99
104
|
- lib/annotate_rb/model_annotator/file_parser/annotation_finder.rb
|
|
@@ -124,6 +129,10 @@ files:
|
|
|
124
129
|
- lib/annotate_rb/model_annotator/single_file_annotator.rb
|
|
125
130
|
- lib/annotate_rb/model_annotator/single_file_annotator_instruction.rb
|
|
126
131
|
- lib/annotate_rb/model_annotator/single_file_remove_annotation_instruction.rb
|
|
132
|
+
- lib/annotate_rb/model_annotator/unique_constraint_annotation.rb
|
|
133
|
+
- lib/annotate_rb/model_annotator/unique_constraint_annotation/annotation.rb
|
|
134
|
+
- lib/annotate_rb/model_annotator/unique_constraint_annotation/annotation_builder.rb
|
|
135
|
+
- lib/annotate_rb/model_annotator/unique_constraint_annotation/unique_constraint_component.rb
|
|
127
136
|
- lib/annotate_rb/model_annotator/zeitwerk_class_getter.rb
|
|
128
137
|
- lib/annotate_rb/options.rb
|
|
129
138
|
- lib/annotate_rb/parser.rb
|