rigortype 0.2.8 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/data/core_overlay/csv.rbs +28 -0
- data/data/core_overlay/psych.rbs +22 -0
- data/docs/handbook/01-getting-started.md +9 -1
- data/docs/handbook/02-everyday-types.md +4 -1
- data/docs/handbook/08-understanding-errors.md +3 -3
- data/docs/manual/01-installation.md +1 -0
- data/docs/manual/02-cli-reference.md +16 -7
- data/docs/manual/07-plugins.md +1 -1
- data/docs/manual/14-rails-quickstart.md +4 -2
- data/docs/manual/15-type-protection-coverage.md +21 -0
- data/docs/manual/plugins/rigor-actionpack.md +1 -1
- data/docs/manual/plugins/rigor-activerecord.md +12 -5
- data/docs/manual/plugins/rigor-rails-routes.md +11 -0
- data/lib/rigor/cache/store.rb +174 -57
- data/lib/rigor/cli/coverage_command.rb +50 -29
- data/lib/rigor/cli/diagnostic_formats.rb +4 -1
- data/lib/rigor/cli/protection_fork_scan.rb +55 -0
- data/lib/rigor/cli/protection_report.rb +7 -1
- data/lib/rigor/environment/missing_gem_constant_index.rb +128 -0
- data/lib/rigor/environment.rb +54 -18
- data/lib/rigor/inference/expression_typer.rb +20 -2
- data/lib/rigor/inference/fork_map.rb +87 -0
- data/lib/rigor/inference/narrowing.rb +118 -0
- data/lib/rigor/inference/parameter_inference_collector.rb +55 -10
- data/lib/rigor/inference/scope_indexer.rb +9 -13
- data/lib/rigor/inference/statement_evaluator.rb +48 -3
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +23 -8
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +21 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +10 -1
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +61 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +20 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/structure_sql_parser.rb +172 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +22 -8
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +32 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +189 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +19 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +41 -10
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +42 -12
- data/sig/rigor/environment.rbs +1 -0
- metadata +8 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 565d25fe6c480013419e1e7f6d2bcb60512f7cf56c6a34b612e5951dad8b6c62
|
|
4
|
+
data.tar.gz: c48e0fcde278beb45ac4b8cb0c5acb272540d8bbc5c37111e983ffacee4c772d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8859749b0ee71c8dca814c164de8e47bd3004f52773299181f8aeca2bb30b5c96dc47bf46278a3378704f548a30ab68c3cb273b71a2c7346b6bba67bfbfb9365
|
|
7
|
+
data.tar.gz: 450f2f074e21d3a3fd7cff2e9f7f8971dd838bdfe1fadc0e80300e7c3dc9a98eb13b9890033436b77f5e82196238c91503f598fce78435f9ce9d598c64fd2e87
|
data/README.md
CHANGED
|
@@ -231,7 +231,7 @@ rigor docs --list # list every bundled page
|
|
|
231
231
|
|
|
232
232
|
## Status
|
|
233
233
|
|
|
234
|
-
Current release: **`v0.2.
|
|
234
|
+
Current release: **`v0.2.9`** (2026-07-11) — the latest cut on the
|
|
235
235
|
`0.2.x` evaluation line opened by `v0.2.0`, the first
|
|
236
236
|
publicly-announced (general / evaluation) release. The line publishes
|
|
237
237
|
an enumerated [compatibility surface](docs/compatibility.md) as a
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Rigor core overlay — supplemental core signatures.
|
|
2
|
+
#
|
|
3
|
+
# --- CSV::MalformedCSVError.new(message, line_number) ---
|
|
4
|
+
#
|
|
5
|
+
# The pinned `rbs` gem's `csv.rbs` never declares `MalformedCSVError`'s own
|
|
6
|
+
# constructor, so it falls back to the inherited `StandardError#initialize`
|
|
7
|
+
# (arity 0..1). But the `csv` gem's real, documented constructor takes two
|
|
8
|
+
# arguments — the message and the 1-based line number:
|
|
9
|
+
#
|
|
10
|
+
# raise CSV::MalformedCSVError.new("Unquoted fields...", line)
|
|
11
|
+
#
|
|
12
|
+
# Without the two-arg form a raise like GitLab's
|
|
13
|
+
# `import_csv/base_service.rb` false-fires `call.wrong-arity`
|
|
14
|
+
# ("expected 0..1, got 2"). The line number is optional here so the
|
|
15
|
+
# inherited single-arg form still type-checks.
|
|
16
|
+
|
|
17
|
+
# `CSV` is a CLASS in Ruby / RBS (a `module CSV` wrapper collides with upstream
|
|
18
|
+
# once the `csv` stdlib is in scope). It must be declared EXPLICITLY here — the
|
|
19
|
+
# overlay loads unconditionally, but `csv` is a stdlib library loaded only on
|
|
20
|
+
# demand, so a bare `class CSV::MalformedCSVError` would make RBS *synthesize*
|
|
21
|
+
# the `CSV` parent namespace (ADR-5) in every env that does not load `csv`,
|
|
22
|
+
# polluting `synthesized_namespaces`. Declaring `class CSV` reopens it cleanly
|
|
23
|
+
# when `csv` is loaded and declares it plainly when it is not.
|
|
24
|
+
class CSV
|
|
25
|
+
class MalformedCSVError
|
|
26
|
+
def initialize: (String message, ?Integer line_number) -> void
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Rigor core overlay — supplemental core signatures.
|
|
2
|
+
#
|
|
3
|
+
# --- Psych.parse / Psych.parse_stream ---
|
|
4
|
+
#
|
|
5
|
+
# The pinned `rbs` gem's `psych.rbs` declares `Psych.load` / `load_file` /
|
|
6
|
+
# `safe_load` / `unsafe_load*` but omits `Psych.parse` — a real, documented
|
|
7
|
+
# stdlib method (`YAML.parse` is the same method, `YAML` being an alias of
|
|
8
|
+
# `Psych`). It parses one YAML document into a `Psych::Nodes::Document` AST
|
|
9
|
+
# (used for structure-preserving inspection) and raises on a syntax error.
|
|
10
|
+
#
|
|
11
|
+
# YAML.parse(File.read("config.yml")) # => Psych::Nodes::Document
|
|
12
|
+
#
|
|
13
|
+
# Without the declaration a call like GitLab's
|
|
14
|
+
# `release_highlights/validator.rb` `YAML.parse(...)` false-fires
|
|
15
|
+
# `call.undefined-method`. The return is left `untyped` — the node AST is
|
|
16
|
+
# rarely consumed with per-method precision, and depending on
|
|
17
|
+
# `Psych::Nodes::Document` being present in the pinned RBS would be brittle.
|
|
18
|
+
|
|
19
|
+
module Psych
|
|
20
|
+
def self.parse: (String yaml, ?filename: untyped) -> untyped
|
|
21
|
+
def self.parse_stream: (String yaml, ?filename: untyped) -> untyped
|
|
22
|
+
end
|
|
@@ -87,6 +87,14 @@ silent everywhere it cannot prove a narrower type.
|
|
|
87
87
|
A diagnostic only fires when Rigor has enough static
|
|
88
88
|
information to be confident.
|
|
89
89
|
|
|
90
|
+
Where a *signature* does appear in this book — like
|
|
91
|
+
`def foo: (String) -> Integer` — that is **RBS**, Ruby's standard
|
|
92
|
+
signature language; read it as "takes a `String`, returns an
|
|
93
|
+
`Integer`." You write none of it to get started; Rigor consumes
|
|
94
|
+
whatever RBS your gems and the standard library already ship.
|
|
95
|
+
[Chapter 7](07-rbs-and-extended.md) covers RBS in full — if you
|
|
96
|
+
have never seen it, skim that chapter first.
|
|
97
|
+
|
|
90
98
|
## The smallest working session
|
|
91
99
|
|
|
92
100
|
Drop into your project root and run:
|
|
@@ -191,7 +199,7 @@ assert_type(":int | :str | nil", kind(7)) # union of all case branches
|
|
|
191
199
|
|
|
192
200
|
```ruby
|
|
193
201
|
greeting = "Hello, " # Constant<"Hello, ">
|
|
194
|
-
name = ARGV.first # String? (RBS-declared)
|
|
202
|
+
name = ARGV.first # String? (String or nil — RBS-declared)
|
|
195
203
|
hello = "#{greeting}#{name}!" # literal-string carrier:
|
|
196
204
|
# every interpolated part
|
|
197
205
|
# is itself literal-string-
|
|
@@ -42,7 +42,10 @@ this chapter is the carrier zoo.
|
|
|
42
42
|
One note on notation before the zoo: angle brackets hold a
|
|
43
43
|
concrete value or bound — `Constant<3>`, `int<0, max>` —
|
|
44
44
|
while square brackets hold type parameters, exactly as in RBS
|
|
45
|
-
— `Nominal[String]`, `Hash[K, V]`, `Dynamic[top]`.
|
|
45
|
+
— `Nominal[String]`, `Hash[K, V]`, `Dynamic[top]`. A type
|
|
46
|
+
parameter names the type of a *part*: `Hash[K, V]` is a Hash
|
|
47
|
+
whose keys are type `K` and values type `V`, just as
|
|
48
|
+
`Array[String]` is "an array of strings."
|
|
46
49
|
|
|
47
50
|
## Seeing carriers yourself — `rigor annotate`
|
|
48
51
|
|
|
@@ -142,9 +142,9 @@ shipped severities:
|
|
|
142
142
|
|
|
143
143
|
| Profile | Behaviour |
|
|
144
144
|
| --- | --- |
|
|
145
|
-
| `lenient` |
|
|
146
|
-
| `balanced` (default) | Most rules → `error`; `dump.type` → `info`. The shipped behaviour. |
|
|
147
|
-
| `strict` |
|
|
145
|
+
| `lenient` | Only proven rules stay `error` (`call.undefined-method`, `wrong-arity`, `assert.type-mismatch`); uncertain rules drop to `warning`, and several to `off`. For incremental adoption on legacy code. |
|
|
146
|
+
| `balanced` (default) | Most rules → `error`; uncertain rules → `warning`; `dump.type` → `info`. The shipped behaviour. |
|
|
147
|
+
| `strict` | Nearly every rule → `error`. The exceptions: `call.self-undefined-method` stays `off` (opt-in only), and `flow.unreachable-clause` is `warning` (pending its false-positive gate). Suitable for new projects with no legacy noise. |
|
|
148
148
|
|
|
149
149
|
Set in `.rigor.yml`:
|
|
150
150
|
|
|
@@ -279,6 +279,10 @@ inferring".
|
|
|
279
279
|
rigor coverage [paths]
|
|
280
280
|
```
|
|
281
281
|
|
|
282
|
+
`paths` are files or directories; when omitted, Rigor uses the
|
|
283
|
+
`paths:` list from the configuration file (default `lib`), the same
|
|
284
|
+
as [`rigor check`](#rigor-check).
|
|
285
|
+
|
|
282
286
|
`--format=text|json` selects the output format and
|
|
283
287
|
`--config=PATH` overrides config discovery. `--threshold=RATIO`
|
|
284
288
|
exits `1` when the precision ratio falls below `RATIO`
|
|
@@ -295,7 +299,13 @@ ranked "add a type here" list (the methods most often called on
|
|
|
295
299
|
an untyped receiver), then the least-protected files;
|
|
296
300
|
`--threshold` and `--format=json` work the same. It is a sound
|
|
297
301
|
upper bound on real protection — a concrete receiver is necessary
|
|
298
|
-
but not sufficient for a diagnostic to fire.
|
|
302
|
+
but not sufficient for a diagnostic to fire. `--workers=N`
|
|
303
|
+
fork-parallelizes the protection scan (both the parameter-inference
|
|
304
|
+
pre-pass and the per-file scan) with output byte-identical to a
|
|
305
|
+
sequential run; it resolves the worker count the same way `check`
|
|
306
|
+
does — `--workers` › `RIGOR_RACTOR_WORKERS` ›
|
|
307
|
+
[`parallel.workers:`](03-configuration.md) › `0` (sequential
|
|
308
|
+
default).
|
|
299
309
|
|
|
300
310
|
Adding `--mutation` (with `--protection`) switches to the
|
|
301
311
|
**effectiveness** tier: it measures whether Rigor *does* catch a
|
|
@@ -403,7 +413,7 @@ catalogue** ([ADR-37](../adr/37-plugin-interface-segregation.md)):
|
|
|
403
413
|
a focused, machine-readable map of what each loaded plugin
|
|
404
414
|
contributes — the AST node types its `node_rule`s match, the
|
|
405
415
|
receiver classes its `dynamic_return`s gate on, the methods its
|
|
406
|
-
`narrowing_facts`
|
|
416
|
+
`narrowing_facts` hooks narrow, and the facts it `produces` /
|
|
407
417
|
`consumes`. Combine with `--format=json` for tooling (an AI
|
|
408
418
|
agent can enumerate every plugin's behaviour without reading a
|
|
409
419
|
line of plugin source). The same narrow surfaces also appear in
|
|
@@ -557,8 +567,7 @@ rigor doctor [--config PATH] [--format text|json]
|
|
|
557
567
|
Runs a scoped analysis and audits:
|
|
558
568
|
|
|
559
569
|
- **Configuration audit** — unresolved `signature_paths:`, unknown
|
|
560
|
-
`libraries:`, inert `disable:` / `severity_overrides:` tokens
|
|
561
|
-
({ConfigAudit}).
|
|
570
|
+
`libraries:`, inert `disable:` / `severity_overrides:` tokens.
|
|
562
571
|
- **RBS environment health** — whether the RBS class universe built
|
|
563
572
|
successfully (`0` classes means a broken setup).
|
|
564
573
|
- **Plugin load errors** — whether every configured plugin loaded.
|
|
@@ -568,7 +577,7 @@ Runs a scoped analysis and audits:
|
|
|
568
577
|
but no Rails plugin is enabled.
|
|
569
578
|
|
|
570
579
|
Text output prints `[PASS]`, `[FAIL]`, or `[WARN]` per check plus a
|
|
571
|
-
routed hint (e.g. "Run `rigor baseline regenerate`").
|
|
580
|
+
routed hint (e.g. "Run `rigor baseline regenerate`"). JSON output
|
|
572
581
|
is a stable contract:
|
|
573
582
|
|
|
574
583
|
```json
|
|
@@ -585,7 +594,7 @@ Exits `1` when any check fails, `0` when all pass.
|
|
|
585
594
|
## `rigor upgrade`
|
|
586
595
|
|
|
587
596
|
Migration command skeleton ([ADR-50](../adr/50-release-engineering-and-stability-strategy.md)
|
|
588
|
-
WD7).
|
|
597
|
+
WD7). The real body lands when a concrete backwards-compatibility
|
|
589
598
|
break gives it a target (e.g. re-running `baseline regenerate`
|
|
590
599
|
against a strengthened default profile, surfacing renamed
|
|
591
600
|
suppression ids, reporting `bleeding_edge:` graduations).
|
|
@@ -595,7 +604,7 @@ rigor upgrade
|
|
|
595
604
|
```
|
|
596
605
|
|
|
597
606
|
Until then it prints the current version and notes that upgrade is
|
|
598
|
-
queued.
|
|
607
|
+
queued. Exits `0`.
|
|
599
608
|
|
|
600
609
|
## Environment variables
|
|
601
610
|
|
data/docs/manual/07-plugins.md
CHANGED
|
@@ -27,7 +27,7 @@ You need:
|
|
|
27
27
|
- **`mise` wired into your shell** — add
|
|
28
28
|
`eval "$(mise activate zsh)"` (or the equivalent for your
|
|
29
29
|
shell) to your shell rc so that `rigor` reaches your `PATH`.
|
|
30
|
-
See [Installing Rigor § Putting rigor on your PATH](01-installation.md)
|
|
30
|
+
See [Installing Rigor § Putting rigor on your PATH](01-installation.md#putting-rigor-on-your-path)
|
|
31
31
|
for detail.
|
|
32
32
|
- **An existing Rails project** at a known path.
|
|
33
33
|
|
|
@@ -156,7 +156,9 @@ source-of-truth copy is
|
|
|
156
156
|
|
|
157
157
|
If your first `rigor check` reports more than ~100 diagnostics,
|
|
158
158
|
acknowledge mode is the natural starting point. You can tighten
|
|
159
|
-
it later.
|
|
159
|
+
it later. In `.rigor.dist.yml` (Step 3) the mode maps to a
|
|
160
|
+
`severity_profile:` — acknowledge → `lenient`, strict → `strict`
|
|
161
|
+
(omit the key for the default `balanced`).
|
|
160
162
|
|
|
161
163
|
### Step 3 — Write .rigor.dist.yml
|
|
162
164
|
|
|
@@ -48,6 +48,14 @@ power. `--threshold=RATIO` turns it into a CI gate (exit `1`
|
|
|
48
48
|
below the ratio) and `--format=json` carries the structured
|
|
49
49
|
fields.
|
|
50
50
|
|
|
51
|
+
On a large project, `--workers=N` fork-parallelizes the scan
|
|
52
|
+
(both the parameter-inference pre-pass and the per-file scan),
|
|
53
|
+
with output byte-identical to a sequential run. The worker count
|
|
54
|
+
resolves the same way `rigor check` does — `--workers` ›
|
|
55
|
+
`RIGOR_RACTOR_WORKERS` › [`parallel.workers:`](03-configuration.md)
|
|
56
|
+
› `0` (sequential default) — so a project already configured for
|
|
57
|
+
parallel `check` gets parallel coverage for free.
|
|
58
|
+
|
|
51
59
|
This is the everyday number. When you want the truth behind it,
|
|
52
60
|
move to Tier 2.
|
|
53
61
|
|
|
@@ -200,6 +208,19 @@ the "Add a type here" header, and the JSON carries the same totals as
|
|
|
200
208
|
`tractability_summary`. Start with the `add_rbs` holes — they are the
|
|
201
209
|
ones a type actually catches.
|
|
202
210
|
|
|
211
|
+
> **`external_gem_without_rbs` needs your gems installed where Rigor
|
|
212
|
+
> can read them.** To tell whether an unresolved constant belongs to
|
|
213
|
+
> a gem, Rigor reads that gem's source — so it must find the gem on
|
|
214
|
+
> disk. It looks in the project's Bundler install tree (a
|
|
215
|
+
> `vendor/bundle`, or a path set with `bundler.bundle_path:`; see
|
|
216
|
+
> [Configuration](03-configuration.md)). A project whose gems live in
|
|
217
|
+
> the active Ruby's default gem home — the common `rbenv` / `mise`
|
|
218
|
+
> case with no `--path` set — is invisible to the isolated analyzer by
|
|
219
|
+
> design ([ADR-27](https://github.com/rigortype/rigor/blob/master/docs/adr/27-tool-distribution-model.md)):
|
|
220
|
+
> point Rigor at it with `bundler.bundle_path:`. Until you do, these
|
|
221
|
+
> holes keep the generic `engine_gap` cause instead of `add_rbs` —
|
|
222
|
+
> the label is missing, never wrong.
|
|
223
|
+
|
|
203
224
|
Provenance is precision-additive only: it never changes a type, fires
|
|
204
225
|
no diagnostic, and never affects severity or the protection ratio.
|
|
205
226
|
|
|
@@ -39,7 +39,7 @@ no-op rather than erroring.
|
|
|
39
39
|
| `plugin.actionpack.render-target` | info | an explicit `render :symbol` / `"string"` / `partial:` resolved to a view template |
|
|
40
40
|
| `plugin.actionpack.missing-template` | error | an explicit `render` resolved to a view path that doesn't exist under any `view_search_paths` |
|
|
41
41
|
| `plugin.actionpack.permit-call` | info | a `params.require(:m).permit(:key, …)` chain resolved to a known model; keys matched against its columns |
|
|
42
|
-
| `plugin.actionpack.unknown-permit-key` | error | a literal `permit(:key)`
|
|
42
|
+
| `plugin.actionpack.unknown-permit-key` | error | a literal `permit(:key)` is a near-miss (edit distance ≤ 2) of a real column but not one — a likely typo (with a did-you-mean). A key nothing like any column (a legitimate virtual attribute) does not fire |
|
|
43
43
|
|
|
44
44
|
Filter and render resolution honours nested-module controller
|
|
45
45
|
qualification (`module Admin; class WidgetsController` resolves
|
|
@@ -30,9 +30,9 @@ errors_demo.rb:25:1: error: `User.find` expects at least 1 argument, got 0 [plug
|
|
|
30
30
|
| Recognised `Model.find` / `Model.find_by` / `Model.where` call | `:info` | `plugin.activerecord.model-call` |
|
|
31
31
|
| `Model.find_by(unknown: ...)` / `Model.where(unknown: ...)` | `:error` | `plugin.activerecord.unknown-column` |
|
|
32
32
|
| `Model.find` with 0 args | `:error` | `plugin.activerecord.wrong-arity` |
|
|
33
|
-
| `db/schema.rb`
|
|
33
|
+
| No schema source (`db/schema.rb` or `db/structure.sql`) readable | `:warning` | `plugin.activerecord.load-error` |
|
|
34
34
|
|
|
35
|
-
Did-you-mean suggestions use
|
|
35
|
+
Did-you-mean suggestions use `DidYouMean` fuzzy matching against
|
|
36
36
|
the resolved table's column names.
|
|
37
37
|
|
|
38
38
|
## Configuration
|
|
@@ -42,13 +42,16 @@ plugins:
|
|
|
42
42
|
- gem: rigor-activerecord
|
|
43
43
|
config:
|
|
44
44
|
schema_file: "db/schema.rb" # default
|
|
45
|
+
structure_sql_file: "db/structure.sql" # default (fallback when schema_file is absent)
|
|
45
46
|
model_search_paths: ["app/models"] # default
|
|
46
47
|
model_base_classes: ["ApplicationRecord", "ActiveRecord::Base"] # default
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
All
|
|
50
|
+
All keys are optional. Tweak them when:
|
|
50
51
|
|
|
51
52
|
- the schema lives elsewhere (`schema_file: "shared/db/schema.rb"`);
|
|
53
|
+
- the project uses `schema_format = :sql` and its dump is not at the
|
|
54
|
+
default path (`structure_sql_file: "db/structure.sql"`);
|
|
52
55
|
- models are in a non-standard directory
|
|
53
56
|
(`model_search_paths: ["domain/models", "engines/billing/app/models"]`);
|
|
54
57
|
- the base class is custom
|
|
@@ -78,8 +81,12 @@ never surfaces a false `call.undefined-method`.
|
|
|
78
81
|
`User < ApplicationRecord` is not discovered. Either add `User`
|
|
79
82
|
to `model_base_classes`, or list every concrete model
|
|
80
83
|
explicitly.
|
|
81
|
-
-
|
|
82
|
-
|
|
84
|
+
- **PostgreSQL `db/structure.sql` fallback.** When `db/schema.rb` is
|
|
85
|
+
absent, the plugin parses `db/structure.sql` (the `schema_format =
|
|
86
|
+
:sql` dump) for the same column/type table. It reads PostgreSQL DDL
|
|
87
|
+
only; a column whose SQL type has no Ruby mapping (a custom enum,
|
|
88
|
+
`tsvector`, `ltree`) degrades to `Object` (never dropped), and
|
|
89
|
+
non-`public`-schema partition tables are skipped.
|
|
83
90
|
- **Column reads, not setters.** The plugin types instance-side
|
|
84
91
|
column *reads* (`user.name`, `user.admin?`) and singular
|
|
85
92
|
associations, but not the `name=` setter or the dirty-tracking
|
|
@@ -59,6 +59,8 @@ plugins:
|
|
|
59
59
|
routes_file: "config/routes.rb" # default
|
|
60
60
|
helper_paths: ["app"] # default; dirs scanned for
|
|
61
61
|
# project-defined *_path / *_url methods
|
|
62
|
+
grape_api_paths: ["lib/api", "app/api"]
|
|
63
|
+
# default; dirs scanned for Grape API classes
|
|
62
64
|
```
|
|
63
65
|
|
|
64
66
|
`helper_paths` lets the plugin also register URL builders you
|
|
@@ -66,6 +68,15 @@ define yourself (e.g. a private `def callback_url` under
|
|
|
66
68
|
`app/controllers` or `app/lib`), so calls to them are not flagged
|
|
67
69
|
as unknown helpers.
|
|
68
70
|
|
|
71
|
+
`grape_api_paths` is where the plugin looks for Grape API classes.
|
|
72
|
+
If you mount one, the `grape-path-helpers` gem generates helpers
|
|
73
|
+
named after each route's path (`api_v4_groups_badges_path`) from
|
|
74
|
+
grape's *runtime* route table, which no static parser can
|
|
75
|
+
enumerate. The plugin reads your API's `prefix` and `version`
|
|
76
|
+
declarations instead and treats the namespace they open as
|
|
77
|
+
unknowable-but-valid, so those calls are never flagged. The `_url`
|
|
78
|
+
form still is: `grape-path-helpers` defines only `_path` helpers.
|
|
79
|
+
|
|
69
80
|
## What it provides
|
|
70
81
|
|
|
71
82
|
The parsed helper table is published as the `:helper_table`
|