rails-ai-context 5.31.0 → 5.32.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 +695 -0
- data/CONTEXT.md +7 -3
- data/README.md +1 -1
- data/docs/ARCHITECTURE.md +3 -3
- data/docs/CLI.md +1 -1
- data/docs/COMPATIBILITY.md +29 -7
- data/docs/CONFIGURATION.md +1 -1
- data/docs/FAQ.md +1 -1
- data/docs/GUIDE.md +7 -7
- data/docs/INTROSPECTORS.md +46 -24
- data/docs/SECURITY.md +33 -0
- data/docs/TOOLS.md +47 -10
- data/lib/generators/rails_ai_context/install/install_generator.rb +1 -0
- data/lib/rails_ai_context/action_filters.rb +119 -45
- data/lib/rails_ai_context/app_commands.rb +2 -2
- data/lib/rails_ai_context/app_kind.rb +65 -8
- data/lib/rails_ai_context/ast_cache.rb +53 -18
- data/lib/rails_ai_context/base_mixins.rb +6 -4
- data/lib/rails_ai_context/boot_manager.rb +5 -1
- data/lib/rails_ai_context/cli/entry_boot.rb +17 -2
- data/lib/rails_ai_context/cli/tool_runner.rb +15 -1
- data/lib/rails_ai_context/concern_macros.rb +127 -53
- data/lib/rails_ai_context/concern_membership.rb +21 -3
- data/lib/rails_ai_context/concern_paths.rb +35 -15
- data/lib/rails_ai_context/config_yaml.rb +40 -0
- data/lib/rails_ai_context/configuration.rb +1 -1
- data/lib/rails_ai_context/data/docs/index.json +324 -0
- data/lib/rails_ai_context/database_yml.rb +136 -0
- data/lib/rails_ai_context/doctor.rb +30 -37
- data/lib/rails_ai_context/erb_source.rb +40 -0
- data/lib/rails_ai_context/fingerprinter.rb +48 -22
- data/lib/rails_ai_context/fixture_keys.rb +42 -1
- data/lib/rails_ai_context/gem_lock.rb +275 -47
- data/lib/rails_ai_context/hydrators/hydration_formatter.rb +8 -2
- data/lib/rails_ai_context/hydrators/schema_hint_builder.rb +10 -5
- data/lib/rails_ai_context/introspector.rb +10 -1
- data/lib/rails_ai_context/introspectors/action_mailbox_introspector.rb +27 -19
- data/lib/rails_ai_context/introspectors/action_presence.rb +6 -5
- data/lib/rails_ai_context/introspectors/action_resolver.rb +36 -25
- data/lib/rails_ai_context/introspectors/action_text_introspector.rb +2 -2
- data/lib/rails_ai_context/introspectors/active_record_settings.rb +56 -0
- data/lib/rails_ai_context/introspectors/active_storage_introspector.rb +1 -1
- data/lib/rails_ai_context/introspectors/active_support_introspector.rb +98 -22
- data/lib/rails_ai_context/introspectors/admin_resources.rb +101 -0
- data/lib/rails_ai_context/introspectors/anyway_configs.rb +64 -0
- data/lib/rails_ai_context/introspectors/apartment_config.rb +47 -0
- data/lib/rails_ai_context/introspectors/api_introspector.rb +125 -26
- data/lib/rails_ai_context/introspectors/asset_pipeline_introspector.rb +24 -19
- data/lib/rails_ai_context/introspectors/ast_walk.rb +18 -0
- data/lib/rails_ai_context/introspectors/auth_introspector.rb +71 -18
- data/lib/rails_ai_context/introspectors/autoload_introspector.rb +62 -15
- data/lib/rails_ai_context/introspectors/base.rb +38 -0
- data/lib/rails_ai_context/introspectors/call_site_expansion.rb +167 -37
- data/lib/rails_ai_context/introspectors/component_introspector.rb +26 -14
- data/lib/rails_ai_context/introspectors/config_introspector.rb +22 -9
- data/lib/rails_ai_context/introspectors/connection_pool_introspector.rb +1 -4
- data/lib/rails_ai_context/introspectors/controller_filters.rb +335 -31
- data/lib/rails_ai_context/introspectors/controller_introspector.rb +312 -126
- data/lib/rails_ai_context/introspectors/controller_settings.rb +182 -0
- data/lib/rails_ai_context/introspectors/convention_introspector.rb +18 -15
- data/lib/rails_ai_context/introspectors/database_stats_introspector.rb +1 -1
- data/lib/rails_ai_context/introspectors/declared_constant.rb +93 -17
- data/lib/rails_ai_context/introspectors/eager_load.rb +12 -7
- data/lib/rails_ai_context/introspectors/engine_introspector.rb +13 -5
- data/lib/rails_ai_context/introspectors/env_config_introspector.rb +62 -17
- data/lib/rails_ai_context/introspectors/env_introspector.rb +8 -6
- data/lib/rails_ai_context/introspectors/env_references.rb +21 -4
- data/lib/rails_ai_context/introspectors/frontend_framework_introspector.rb +37 -22
- data/lib/rails_ai_context/introspectors/gem_introspector.rb +3 -1
- data/lib/rails_ai_context/introspectors/gemfile_gems.rb +53 -5
- data/lib/rails_ai_context/introspectors/grape_endpoints.rb +109 -0
- data/lib/rails_ai_context/introspectors/helper_names.rb +12 -1
- data/lib/rails_ai_context/introspectors/i18n_introspector.rb +101 -46
- data/lib/rails_ai_context/introspectors/includers.rb +6 -1
- data/lib/rails_ai_context/introspectors/initializer_introspector.rb +2 -5
- data/lib/rails_ai_context/introspectors/job_introspector.rb +498 -98
- data/lib/rails_ai_context/introspectors/listener_registration.rb +11 -1
- data/lib/rails_ai_context/introspectors/listeners/associations_listener.rb +51 -4
- data/lib/rails_ai_context/introspectors/listeners/autoload_ignore_listener.rb +31 -0
- data/lib/rails_ai_context/introspectors/listeners/autoload_paths_listener.rb +4 -47
- data/lib/rails_ai_context/introspectors/listeners/base_listener.rb +77 -11
- data/lib/rails_ai_context/introspectors/listeners/branch_conditions.rb +156 -0
- data/lib/rails_ai_context/introspectors/listeners/callbacks_listener.rb +59 -24
- data/lib/rails_ai_context/introspectors/listeners/class_definition_listener.rb +35 -6
- data/lib/rails_ai_context/introspectors/listeners/component_structure_listener.rb +30 -2
- data/lib/rails_ai_context/introspectors/listeners/conditional_macro_listener.rb +19 -0
- data/lib/rails_ai_context/introspectors/listeners/config_assignment_listener.rb +255 -10
- data/lib/rails_ai_context/introspectors/listeners/constant_reference_listener.rb +34 -0
- data/lib/rails_ai_context/introspectors/listeners/constructor_macro_listener.rb +123 -0
- data/lib/rails_ai_context/introspectors/listeners/definition_file_paths_listener.rb +66 -0
- data/lib/rails_ai_context/introspectors/listeners/enums_listener.rb +2 -2
- data/lib/rails_ai_context/introspectors/listeners/env_access_listener.rb +31 -0
- data/lib/rails_ai_context/introspectors/listeners/filter_macro_listener.rb +54 -0
- data/lib/rails_ai_context/introspectors/listeners/fixture_paths_listener.rb +62 -0
- data/lib/rails_ai_context/introspectors/listeners/gemfile_dsl_listener.rb +42 -1
- data/lib/rails_ai_context/introspectors/listeners/generic_macro_listener.rb +26 -2
- data/lib/rails_ai_context/introspectors/listeners/grape_api_listener.rb +137 -0
- data/lib/rails_ai_context/introspectors/listeners/http_client_call_listener.rb +50 -0
- data/lib/rails_ai_context/introspectors/listeners/i18n_load_path_listener.rb +54 -0
- data/lib/rails_ai_context/introspectors/listeners/literal_paths.rb +123 -0
- data/lib/rails_ai_context/introspectors/listeners/macros_listener.rb +248 -4
- data/lib/rails_ai_context/introspectors/listeners/mailbox_routing_listener.rb +2 -1
- data/lib/rails_ai_context/introspectors/listeners/method_call_listener.rb +7 -1
- data/lib/rails_ai_context/introspectors/listeners/methods_listener.rb +352 -69
- data/lib/rails_ai_context/introspectors/listeners/migration_dsl_listener.rb +1 -1
- data/lib/rails_ai_context/introspectors/listeners/migration_replay_listener.rb +35 -26
- data/lib/rails_ai_context/introspectors/listeners/mixins_listener.rb +41 -1
- data/lib/rails_ai_context/introspectors/listeners/mount_listener.rb +8 -0
- data/lib/rails_ai_context/introspectors/listeners/namespaced_roots_listener.rb +35 -0
- data/lib/rails_ai_context/introspectors/listeners/nested_constants_listener.rb +32 -0
- data/lib/rails_ai_context/introspectors/listeners/owner_scope.rb +1 -1
- data/lib/rails_ai_context/introspectors/listeners/preview_paths_listener.rb +16 -7
- data/lib/rails_ai_context/introspectors/listeners/queue_assignment_listener.rb +54 -0
- data/lib/rails_ai_context/introspectors/listeners/rake_task_dsl_listener.rb +21 -8
- data/lib/rails_ai_context/introspectors/listeners/route_files_listener.rb +4 -11
- data/lib/rails_ai_context/introspectors/listeners/routes_dsl_listener.rb +461 -65
- data/lib/rails_ai_context/introspectors/listeners/schema_dsl_listener.rb +76 -14
- data/lib/rails_ai_context/introspectors/listeners/scopes_listener.rb +40 -1
- data/lib/rails_ai_context/introspectors/listeners/validations_listener.rb +10 -1
- data/lib/rails_ai_context/introspectors/listeners/view_paths_listener.rb +37 -0
- data/lib/rails_ai_context/introspectors/middleware_introspector.rb +47 -3
- data/lib/rails_ai_context/introspectors/migration_introspector.rb +3 -3
- data/lib/rails_ai_context/introspectors/migration_replay/helpers.rb +4 -3
- data/lib/rails_ai_context/introspectors/migration_replay/statements.rb +72 -12
- data/lib/rails_ai_context/introspectors/migration_replay.rb +110 -14
- data/lib/rails_ai_context/introspectors/model_introspector.rb +463 -128
- data/lib/rails_ai_context/introspectors/module_aliases.rb +11 -3
- data/lib/rails_ai_context/introspectors/multi_database_introspector.rb +9 -57
- data/lib/rails_ai_context/introspectors/observability_introspector.rb +5 -8
- data/lib/rails_ai_context/introspectors/performance_introspector.rb +28 -8
- data/lib/rails_ai_context/introspectors/rake_task_introspector.rb +118 -51
- data/lib/rails_ai_context/introspectors/recurring_schedules.rb +150 -0
- data/lib/rails_ai_context/introspectors/rendered_record.rb +87 -0
- data/lib/rails_ai_context/introspectors/retry_policy.rb +8 -5
- data/lib/rails_ai_context/introspectors/route_introspector.rb +153 -42
- data/lib/rails_ai_context/introspectors/schema_conventions.rb +127 -40
- data/lib/rails_ai_context/introspectors/schema_dump_path.rb +80 -0
- data/lib/rails_ai_context/introspectors/schema_introspector.rb +346 -112
- data/lib/rails_ai_context/introspectors/schema_reader.rb +69 -29
- data/lib/rails_ai_context/introspectors/service_classes.rb +21 -15
- data/lib/rails_ai_context/introspectors/source_calls.rb +1 -1
- data/lib/rails_ai_context/introspectors/source_introspector.rb +17 -2
- data/lib/rails_ai_context/introspectors/source_scan.rb +171 -25
- data/lib/rails_ai_context/introspectors/sqlite_virtual_tables.rb +28 -0
- data/lib/rails_ai_context/introspectors/stimulus_introspector.rb +3 -1
- data/lib/rails_ai_context/introspectors/structure_sql_reader.rb +281 -90
- data/lib/rails_ai_context/introspectors/superclass_chain.rb +14 -15
- data/lib/rails_ai_context/introspectors/table_name.rb +46 -45
- data/lib/rails_ai_context/introspectors/test_introspector.rb +289 -78
- data/lib/rails_ai_context/introspectors/turbo_introspector.rb +10 -5
- data/lib/rails_ai_context/introspectors/view_introspector.rb +5 -40
- data/lib/rails_ai_context/introspectors/view_template_introspector.rb +12 -10
- data/lib/rails_ai_context/migration_status.rb +5 -5
- data/lib/rails_ai_context/package_json.rb +96 -5
- data/lib/rails_ai_context/path_resolver.rb +170 -15
- data/lib/rails_ai_context/payload.rb +48 -0
- data/lib/rails_ai_context/pending_migrations.rb +15 -18
- data/lib/rails_ai_context/portable_path.rb +76 -4
- data/lib/rails_ai_context/route_coverage.rb +5 -1
- data/lib/rails_ai_context/safe_path.rb +44 -6
- data/lib/rails_ai_context/schema_hint.rb +8 -2
- data/lib/rails_ai_context/schema_version.rb +7 -9
- data/lib/rails_ai_context/serializers/claude_rules_serializer.rb +1 -1
- data/lib/rails_ai_context/serializers/markdown_serializer.rb +13 -4
- data/lib/rails_ai_context/serializers/section_facts.rb +5 -1
- data/lib/rails_ai_context/serializers/stack_overview_helper.rb +2 -2
- data/lib/rails_ai_context/serializers/tool_guide_helper.rb +7 -4
- data/lib/rails_ai_context/test_framework.rb +32 -5
- data/lib/rails_ai_context/tools/analyze_feature.rb +22 -10
- data/lib/rails_ai_context/tools/base_tool.rb +59 -29
- data/lib/rails_ai_context/tools/diagnose.rb +1 -1
- data/lib/rails_ai_context/tools/generate_test.rb +8 -9
- data/lib/rails_ai_context/tools/get_active_support.rb +19 -4
- data/lib/rails_ai_context/tools/get_api.rb +17 -11
- data/lib/rails_ai_context/tools/get_autoload.rb +10 -5
- data/lib/rails_ai_context/tools/get_callbacks.rb +51 -8
- data/lib/rails_ai_context/tools/get_component_catalog.rb +7 -4
- data/lib/rails_ai_context/tools/get_concern.rb +30 -17
- data/lib/rails_ai_context/tools/get_config.rb +52 -18
- data/lib/rails_ai_context/tools/get_controllers.rb +57 -13
- data/lib/rails_ai_context/tools/get_conventions.rb +39 -15
- data/lib/rails_ai_context/tools/get_engines.rb +2 -0
- data/lib/rails_ai_context/tools/get_env.rb +209 -52
- data/lib/rails_ai_context/tools/get_env_config.rb +38 -7
- data/lib/rails_ai_context/tools/get_frontend_stack.rb +56 -7
- data/lib/rails_ai_context/tools/get_helper_methods.rb +136 -26
- data/lib/rails_ai_context/tools/get_job_pattern.rb +136 -86
- data/lib/rails_ai_context/tools/get_mailers.rb +59 -2
- data/lib/rails_ai_context/tools/get_model_details.rb +174 -25
- data/lib/rails_ai_context/tools/get_partial_interface.rb +101 -62
- data/lib/rails_ai_context/tools/get_routes.rb +35 -9
- data/lib/rails_ai_context/tools/get_schema.rb +156 -61
- data/lib/rails_ai_context/tools/get_service_pattern.rb +121 -25
- data/lib/rails_ai_context/tools/get_stimulus.rb +1 -1
- data/lib/rails_ai_context/tools/get_test_info.rb +152 -82
- data/lib/rails_ai_context/tools/get_view.rb +37 -20
- data/lib/rails_ai_context/tools/migration_advisor.rb +64 -24
- data/lib/rails_ai_context/tools/onboard.rb +174 -88
- data/lib/rails_ai_context/tools/read_logs.rb +45 -17
- data/lib/rails_ai_context/tools/runtime_info.rb +1 -1
- data/lib/rails_ai_context/tools/safe_call.rb +20 -15
- data/lib/rails_ai_context/tools/search_code.rb +60 -28
- data/lib/rails_ai_context/tools/search_docs.rb +18 -6
- data/lib/rails_ai_context/tools/security_scan.rb +48 -3
- data/lib/rails_ai_context/tools/validate.rb +21 -4
- data/lib/rails_ai_context/tools/validate_semantics.rb +18 -6
- data/lib/rails_ai_context/version.rb +1 -1
- data/lib/rails_ai_context/vfs.rb +2 -2
- data/lib/rails_ai_context/view_file.rb +53 -3
- data/lib/rails_ai_context.rb +9 -1
- data/server.json +1 -1
- metadata +31 -3
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,701 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [5.32.0] - 2026-10-06
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`model_details` lists more of what a model declares.** Under Macros:
|
|
13
|
+
`attribute` (with its type and default), `alias_attribute`, `has_rich_text`,
|
|
14
|
+
`strict_loading_by_default`, `implicit_order_column`, `locking_column`,
|
|
15
|
+
`store_full_sti_class`, `attr_readonly` and `query_constraints`, in both
|
|
16
|
+
tiers; a setting assigned inside a method or a nested class is not listed as
|
|
17
|
+
the model's. An STI model names its parent (or a base its subclasses) and its
|
|
18
|
+
type column, honoring `inheritance_column`, and only where the table has that
|
|
19
|
+
column (the static tier reads the schema dump). A model whose base class calls
|
|
20
|
+
`connects_to` gets a Database line with the call as written and the class it
|
|
21
|
+
comes from, in `model_details` and `get_context`; a call under a condition
|
|
22
|
+
says `(only if ...)`, and otherwise the model's columns come from the schema
|
|
23
|
+
of the database it writes to. (#294, #390, #395)
|
|
24
|
+
- **`model_details` lists a model's `default_scope`** at the top of Scopes,
|
|
25
|
+
declared as the macro or as `def self.default_scope` in the model's own class
|
|
26
|
+
(not a class or module nested in its file), with `all_queries: true` when
|
|
27
|
+
declared. A base's default scope comes first, in the order Rails stacks them.
|
|
28
|
+
(#295)
|
|
29
|
+
- **`model_details` reads common model gems.** An `aasm` machine shows its
|
|
30
|
+
states, initial state, events and transitions, and `has_paper_trail`,
|
|
31
|
+
`friendly_id`, `mount_uploader`, `monetize` (with the attribute it adds),
|
|
32
|
+
`pg_search_scope`, `acts_as_list` and other gem macros get a line each, as
|
|
33
|
+
written. The static tier lists the `belongs_to` that `acts_as_tenant`
|
|
34
|
+
declares. A macro written inside a method body or a nested class is not
|
|
35
|
+
credited to the model, and `aasm.current_state` in a method opens no second
|
|
36
|
+
machine. (#389)
|
|
37
|
+
- **`model_details` lists each index a Mongoid document declares**, as written,
|
|
38
|
+
and the fields and indexes its included concerns declare. (#412)
|
|
39
|
+
- **In an Apartment app, `model_details` says where a model's table lives**: in
|
|
40
|
+
the shared schema (`excluded_models`) or in each tenant's schema, whatever the
|
|
41
|
+
`Apartment.configure` block calls its parameter. A list built with `+=` or
|
|
42
|
+
`<<` is named as computed. (#415)
|
|
43
|
+
- **The schema lists views, materialized views and SQLite virtual tables** in
|
|
44
|
+
both tiers (scenic's schema.rb, structure.sql, the connection), labelled in
|
|
45
|
+
the listings. The table view shows a view's SQL or a virtual table's module,
|
|
46
|
+
with its columns by name alone, and the indexes declared on a materialized
|
|
47
|
+
view. Views and virtual tables are not counted as tables with no model file,
|
|
48
|
+
and a table the dumper could not write is listed with its reason. Known limit:
|
|
49
|
+
booted on Rails 7.x with SQLite older than 3.37, a virtual table's shadow
|
|
50
|
+
tables still list as tables. (#354)
|
|
51
|
+
- **`job_pattern` shows more of how a job runs.** A job's page shows its
|
|
52
|
+
`queue_with_priority`, `enqueue_after_transaction_commit`, Solid Queue
|
|
53
|
+
`limits_concurrency` and its enqueue, perform and `after_discard` callbacks;
|
|
54
|
+
`retry_on` keeps its `queue:`, `priority:` and `jitter:`, and a Sidekiq
|
|
55
|
+
worker's `sidekiq_retry_in` and `sidekiq_retries_exhausted` blocks are listed
|
|
56
|
+
under its retries (the worker listing names such a block by its macro only). A
|
|
57
|
+
priority given as a lambda reads as computed. A job that includes
|
|
58
|
+
`ActiveJob::Continuable`, itself or through a base, is marked so, with the
|
|
59
|
+
steps its `perform` runs in order. (#392, #409)
|
|
60
|
+
- **`job_pattern` names the queues Solid Queue's workers poll** in
|
|
61
|
+
`config/queue.yml` and flags every job queue no worker polls, in the listing
|
|
62
|
+
and on the job's own page, when the app runs Solid Queue (its config sets
|
|
63
|
+
`active_job.queue_adapter = :solid_queue`, or sets no adapter and the Gemfile
|
|
64
|
+
has `solid_queue`). (#396)
|
|
65
|
+
- **delayed_job's `handle_asynchronously` methods are listed** with their
|
|
66
|
+
options, in `job_pattern` and `model_details`, where `job_pattern` used to say
|
|
67
|
+
No jobs found. A method a concern wraps is listed under each model that
|
|
68
|
+
includes the concern, directly or through another concern. (#410)
|
|
69
|
+
- **`mailers` lists Action Mailbox and more mailer settings.** The mailboxes,
|
|
70
|
+
the routing rules in the order Rails tries them with the mailbox each sends
|
|
71
|
+
to, and each mailbox's processing callbacks. Each mailer shows its own
|
|
72
|
+
`default`, `layout`, helpers and callbacks, the template formats of each
|
|
73
|
+
action and its preview class; the full listing names the queue `deliver_later`
|
|
74
|
+
uses, the interceptors and observers the config registers, and the mailer
|
|
75
|
+
preview paths. (#386, #393)
|
|
76
|
+
- **`env` lists environment variables from more places**: the env Kamal's
|
|
77
|
+
`config/deploy.yml` sets at the top level, for each role
|
|
78
|
+
(`servers.<role>.env`) and for each `env.tags` tag (secret names, never
|
|
79
|
+
values, and clear values, except one holding a URL or a key-like token, or
|
|
80
|
+
under a secret-named variable, which shows as hidden, and one an ERB tag sets,
|
|
81
|
+
which says so; a `config/deploy.<destination>.yml` is named as not read), the
|
|
82
|
+
setting keys in the config gem's `config/settings.yml` and
|
|
83
|
+
`config/settings/<env>.yml` when the bundle has the config gem, each
|
|
84
|
+
`Anyway::Config` class's attributes with the env names they read (values left
|
|
85
|
+
out), the ENV names `Rails.app.creds` and `Rails.app.envs` read on Rails 8.2
|
|
86
|
+
(`require(:stripe_api_key)` is `STRIPE_API_KEY`, nested keys joined by `__`),
|
|
87
|
+
and the ENV names read in `config.ru`, `db/seeds.rb`, `db/seeds/` and the Ruby
|
|
88
|
+
scripts in `bin/`. (#397, #398, #404, #417)
|
|
89
|
+
- **`config` lists what runs in front of Rails and what CurrentAttributes
|
|
90
|
+
holds**: the middleware `config.ru` adds (with the `if` it runs under, and the
|
|
91
|
+
`map` it sits inside when that map runs the app itself) and the `map` mounts
|
|
92
|
+
that run their own Rack app, in the static tier too, and each
|
|
93
|
+
CurrentAttributes class's attributes, their defaults and its reset hooks.
|
|
94
|
+
(#398, #399)
|
|
95
|
+
- **`env_config` lists the config keys `config/application.rb` sets for every
|
|
96
|
+
environment** (`config.x` included) and, for each `config_for` call (a name,
|
|
97
|
+
or `Rails.root.join` of literal parts), the keys its YAML file gives the
|
|
98
|
+
running environment, or the environment a literal `env:` names. A file on
|
|
99
|
+
`sensitive_patterns`, outside the app, or over `max_file_size` is named with
|
|
100
|
+
that reason and its keys are not read. (#394)
|
|
101
|
+
- **`active_support` lists the ActiveSupport::Notifications events the app
|
|
102
|
+
subscribes to** (`subscribe`, `monotonic_subscribe`, and a Subscriber's
|
|
103
|
+
`attach_to`, inside the class with or without `self.`, or called on it
|
|
104
|
+
afterwards) with the file and line of each, in both tiers. An `attach_to`
|
|
105
|
+
lists one `<method>.<namespace>` event per public method the subscriber
|
|
106
|
+
defines in that file, and says so in words when it defines none. (#387)
|
|
107
|
+
- **`onboard` lists the app's own tooling**: its custom rake tasks (Rakefile,
|
|
108
|
+
`lib/tasks`, `rakelib`) with their arguments, the description `rake -T` prints
|
|
109
|
+
and the file, one entry for a task defined in several places (the first 15 at
|
|
110
|
+
standard detail, every one at full), its own generators (`bin/rails generate
|
|
111
|
+
service`), the `lib/templates` files that replace a built-in generator's
|
|
112
|
+
template, and the Railties under `lib/` with their initializers. (#385, #400)
|
|
113
|
+
- **`onboard` and the gems resource read more Ruby version sources.** A Ruby
|
|
114
|
+
engine other than CRuby is named from `.ruby-version`, `.tool-versions`, the
|
|
115
|
+
Gemfile `ruby` line or the lockfile ("declaring JRuby 9.4.8.0 (Ruby
|
|
116
|
+
3.1.4p0)"), where a `jruby-` `.ruby-version`, or a bare `jruby` one, gave no
|
|
117
|
+
Ruby at all. A version pinned in mise (`mise.toml`, `mise.local.toml`,
|
|
118
|
+
`.mise.toml`, `mise/config.toml`, `.mise/config.toml`, `.config/mise.toml` or
|
|
119
|
+
`.config/mise/config.toml`) is read when no other file names one. (#420, #421)
|
|
120
|
+
- **`controllers` and `view` say which layout a controller renders in**
|
|
121
|
+
(declared, inherited, set by an app concern it includes, or found by name),
|
|
122
|
+
and `controllers` lists the `allow_browser`, `protect_from_forgery`,
|
|
123
|
+
`add_flash_types`, `default_form_builder` and `wrap_parameters` settings it,
|
|
124
|
+
its ancestors and their app concerns declare. (#337)
|
|
125
|
+
- **`controllers` lists the filters authorization gems add**: cancancan's
|
|
126
|
+
`load_and_authorize_resource`, `load_resource`, `authorize_resource`,
|
|
127
|
+
`check_authorization` and `skip_authorization_check`, and acts_as_tenant's
|
|
128
|
+
`find_tenant_by_subdomain`, in both tiers; one passed `prepend: true` is
|
|
129
|
+
listed first, where cancancan adds it. Each is read only when the lockfile
|
|
130
|
+
resolves that gem and no class on the chain defines a class method of the same
|
|
131
|
+
name. A responders class-level `respond_to :json` shows its formats in both
|
|
132
|
+
tiers, and a subclass shows the formats its ancestors declare, as responders
|
|
133
|
+
copies them. (#406, #407)
|
|
134
|
+
- **`view` marks template and partial variants and locales**:
|
|
135
|
+
`show.html+mobile.erb` is the `mobile` variant of `show`, and
|
|
136
|
+
`show.fr.html.erb` its `fr` locale. (#408)
|
|
137
|
+
- **`routes` lists the endpoints of a mounted Grape API** under its mount: verb,
|
|
138
|
+
full path with prefix and version, and declared params, with a `route_param`'s
|
|
139
|
+
param and a params block before a namespace given to every endpoint inside it.
|
|
140
|
+
Read from `app/api` and `lib/api` in both tiers; an edit there refreshes the
|
|
141
|
+
MCP server's cached answer. (#411)
|
|
142
|
+
- **`service_pattern` reads more service shapes.** It reads `app/interactions`
|
|
143
|
+
and `app/interactors` as well as `app/services` (so does the generated files'
|
|
144
|
+
Services line), lists an interactor organizer's steps in order, and shows an
|
|
145
|
+
Initialize line and an Inputs section for a service whose constructor comes
|
|
146
|
+
from T::Struct `const`/`prop`, Dry::Struct `attribute`, dry-initializer
|
|
147
|
+
`param`/`option` or the attr_extras initializers. Dry::Struct attributes and
|
|
148
|
+
dry-initializer params and options an app superclass declares are included,
|
|
149
|
+
marked with the class they come from. (#402, #403)
|
|
150
|
+
- **`conventions` and `analyze_feature` list the models an admin gem exposes**:
|
|
151
|
+
ActiveAdmin (with the params it permits), Administrate, Avo (2 and 3 resource
|
|
152
|
+
naming), Madmin and Trestle. (#405)
|
|
153
|
+
- **`conventions` lists `.standard.yml`, `.erb_lint.yml` (or the older
|
|
154
|
+
`.erb-lint.yml`), `sorbet/config` and `Steepfile`** under Notable config
|
|
155
|
+
files, beside `.rubocop.yml`. (#422)
|
|
156
|
+
- **The package manager is found at the JS workspace root.** `frontend_stack`
|
|
157
|
+
and `conventions` name it when the lockfile sits in a workspace root above the
|
|
158
|
+
app (never above the git root), and `frontend_stack` says which directory that
|
|
159
|
+
is. (#401)
|
|
160
|
+
|
|
161
|
+
### Changed
|
|
162
|
+
|
|
163
|
+
- **A configured frontend directory outside the app root is read for its
|
|
164
|
+
manifests.** A `frontend_paths` entry such as `../web-client`, and the JS
|
|
165
|
+
workspace root above the app, are read for `package.json`, lockfiles and the
|
|
166
|
+
presence of a bundler config only, plus a configured entry's `tsconfig.json`
|
|
167
|
+
and the configs it extends inside that directory. `frontend_stack` reports the
|
|
168
|
+
framework, build tool, package manager and TypeScript settings and names the
|
|
169
|
+
directory instead of calling the app API-only; an entry inside the app root
|
|
170
|
+
gets the same build tool and package manager answer. docs/SECURITY.md lists
|
|
171
|
+
this read under "Frontend roots outside the app". (#377, #401)
|
|
172
|
+
- **An app with no lockfile of its own reads the bundle `config/boot.rb` points
|
|
173
|
+
at.** In an engine's `test/dummy`, static `onboard`, `gems`, `env` and the
|
|
174
|
+
Rails version read the Gemfile and lockfile its `BUNDLE_GEMFILE` names when
|
|
175
|
+
they sit inside the app's git repository; outside one, they say that bundle is
|
|
176
|
+
not read and name it. docs/SECURITY.md lists this read, and the engine source
|
|
177
|
+
a booted `test/dummy` reads, under "The bundle config/boot.rb declares" and
|
|
178
|
+
"The engine an app's test/dummy runs in". (#381, #423)
|
|
179
|
+
- **The controllers payload carries `rate_limits`**, one entry per `rate_limit`
|
|
180
|
+
call, in place of `rate_limit` and `rate_limit_parsed`. `controllers` prints
|
|
181
|
+
every limit a controller declares, whole when the call spans lines, and in a
|
|
182
|
+
controller's own detail each limit an ancestor declares, named by the class
|
|
183
|
+
that declares it. (#332)
|
|
184
|
+
- **A booted filter an outside module defines carries that module as
|
|
185
|
+
`from_concern`.** With `include ActiveStorage::SetBlob`, `set_blob` reads
|
|
186
|
+
`(from ActiveStorage::SetBlob)` and is never labelled as not declared in the
|
|
187
|
+
controller chain; an `on_load` filter beside it still is. (#293)
|
|
188
|
+
- **A strong params entry's `nested` list keeps a doubly-wrapped list as an
|
|
189
|
+
inner array.** `params.expect(thing: [items: [[:sku, :qty]]])` carries
|
|
190
|
+
`"items" => [["sku", "qty"]]`, where it was flattened to the single-hash
|
|
191
|
+
`["sku", "qty"]`, and the `controllers` summary prints it as
|
|
192
|
+
`items: [[:sku, :qty]]`. (#333)
|
|
193
|
+
- **The views payload no longer carries `conditional_layouts`.** Each controller
|
|
194
|
+
entry carries `layout` and `settings` instead. (#337)
|
|
195
|
+
- **The mailboxes payload drops each mailbox's `routing` list** (`{pattern,
|
|
196
|
+
action}`). A mailbox carries `routed_from`, the patterns that send to it, the
|
|
197
|
+
section gains a top-level `routes` list (`{pattern, mailbox, file}`) in the
|
|
198
|
+
order Rails tries them, and a mailbox's `file` is relative to the app root
|
|
199
|
+
(`app/mailboxes/replies_mailbox.rb`), not to `app/mailboxes`. (#386)
|
|
200
|
+
- **A job's `callbacks` in the jobs payload holds the declarations as written**
|
|
201
|
+
(`before_perform :log_start`) in place of the bare macro names
|
|
202
|
+
(`before_perform`). (#392)
|
|
203
|
+
- **A Mongoid model's payload always carries `collection:`**, the `store_in`
|
|
204
|
+
name or the one Mongoid derives (`admin_shelves`), where it was set only for
|
|
205
|
+
`store_in`. An embedded document carries `embedded_in:` (its parent class)
|
|
206
|
+
in its place, and a subclass of a document (`class Ebook < Book`) is a
|
|
207
|
+
Mongoid model with its root's collection and fields and `parent_model:`,
|
|
208
|
+
where it was read as an ActiveRecord model with an `ebooks` table. (#382)
|
|
209
|
+
- **`schema --table` JSON for a name that holds different tables in two
|
|
210
|
+
databases is `{table:, databases: {<name> => table}}`** instead of one table's
|
|
211
|
+
keys at the top level. (#356)
|
|
212
|
+
- **Views are counted apart from tables.** Schema entries carry `kind:` (`view`,
|
|
213
|
+
`materialized_view`, `virtual_table`) in JSON, `total_tables` leaves views
|
|
214
|
+
out, and the schema headers read `116 tables and 2 views`. `onboard` counts
|
|
215
|
+
tables only. (#354)
|
|
216
|
+
- **`encryption_details` options are the source text.** Each `encrypts` entry
|
|
217
|
+
carries every option as the file writes it (`"true"`, not `true`), a
|
|
218
|
+
`normalizes` entry carries its `with:` lambda and other options as written,
|
|
219
|
+
and `generates_token_for` its `expires_in` as written. (#391)
|
|
220
|
+
- **`concern` lists only what an includer gains under Class Methods**:
|
|
221
|
+
`class_methods do`, `module ClassMethods`, and a `def self.x` written in
|
|
222
|
+
`included do`. The module's own `def self.x` and `class << self` methods move
|
|
223
|
+
to a new Module Methods section, and its `def self.included(base)` (or
|
|
224
|
+
`extended`, `prepended`) hook is listed under neither. A `def self.x` or
|
|
225
|
+
`class << self` written inside `class_methods do` belongs to ClassMethods
|
|
226
|
+
alone, so neither section lists it. (#312)
|
|
227
|
+
- **The tests payload's `factories` carries `unread: true`** when a test helper
|
|
228
|
+
loads factories from a path built at run time. Its `count` is then the files
|
|
229
|
+
of the paths that were read, and nil when none was; `test_info` and `onboard`
|
|
230
|
+
print no file count in that case. (#373)
|
|
231
|
+
- **`search_docs` no longer accepts `source: "api"`**, which never had entries.
|
|
232
|
+
The valid sources are all, guides, stimulus, turbo and hotwire. (#322)
|
|
233
|
+
- **The auth payload's `has_secure_password` lists only models with the
|
|
234
|
+
default password.** A named one (`has_secure_password :six_digit_code`) goes
|
|
235
|
+
under a new `secure_password_digests` key, model => attributes. A class
|
|
236
|
+
written across several files keeps its password, and a nested class's
|
|
237
|
+
digest is not credited to the outer model. (#369)
|
|
238
|
+
- **`model_details` Structure sections no longer share a line.** Each section
|
|
239
|
+
ends on the line before the next one starts, so a 3-line model reads
|
|
240
|
+
`class definition(1-1) → associations(2-3)` where 5.31.0 printed `(1-2)`.
|
|
241
|
+
- **The schema payload's `declared_tables` includes db/schema.rb's
|
|
242
|
+
`create_virtual_table` names and the tables it records as "Could not dump
|
|
243
|
+
table".** The booted `schema` line that compares
|
|
244
|
+
declared and connected tables counts a virtual table as a table and a view
|
|
245
|
+
as neither, as the header above it does, so the two numbers match.
|
|
246
|
+
|
|
247
|
+
### Fixed
|
|
248
|
+
|
|
249
|
+
- **Three crashes on older or unusual setups are gone.** After a boot that fails
|
|
250
|
+
inside a Rails 7.0 app's activesupport (Logger not loaded), the static tier
|
|
251
|
+
answers instead of every tool crashing. Booted tools no longer fail with
|
|
252
|
+
"wrong number of arguments" on a Rails 7.0 app whose bundle locks zeitwerk
|
|
253
|
+
2.5; the gem now accepts zeitwerk 2.5. CLI tools no longer crash with
|
|
254
|
+
Encoding::CompatibilityError on a non-ASCII argument under a C or other
|
|
255
|
+
non-UTF-8 locale. (#272, #273, #275)
|
|
256
|
+
- **A Sinatra app with `config/environment.rb` and `app/` is not read as a Rails
|
|
257
|
+
app**; both tiers answer "No Rails app found". With no lockfile, a Gemfile
|
|
258
|
+
that names neither rails nor railties decides the same before anything boots,
|
|
259
|
+
so the tree's own `bundler/setup` never runs and never writes a lockfile into
|
|
260
|
+
it. A tree whose `config/environment.rb` loads but defines no Rails
|
|
261
|
+
application, with no lockfile to decide, reports a failed boot and answers
|
|
262
|
+
from the static tier. (#274)
|
|
263
|
+
- **An app without Active Record says so.** `schema` says introspection does not
|
|
264
|
+
apply, `onboard` no longer says "on unknown", and `model_details` says there
|
|
265
|
+
is no Active Record model by that name. A sequel-rails app gets "this app uses
|
|
266
|
+
Sequel; ActiveRecord schema introspection does not apply" instead of id-only
|
|
267
|
+
tables replayed from Sequel migrations, and a replay behind an empty schema.rb
|
|
268
|
+
says the dump declares no tables. (#364, #383)
|
|
269
|
+
- **Gems are read from `gems.rb` and `eval_gemfile` files.** An app on `gems.rb`
|
|
270
|
+
and `gems.locked` reads its gems, Rails version and Ruby version in `gems`,
|
|
271
|
+
`onboard` and `doctor` as one on `Gemfile` does, and gems declared in a file
|
|
272
|
+
named by `eval_gemfile` are read, so `env`, `gems`, `helper_methods` and the
|
|
273
|
+
app-kind checks see them. (#418, #419)
|
|
274
|
+
- **A new Rails 8 app reads right.** `onboard` names the adapter database.yml
|
|
275
|
+
declares when there are no tables yet, where it said "on unknown"; `schema`
|
|
276
|
+
lists the solid_queue, solid_cache and solid_cable tables from their own dump
|
|
277
|
+
files and says the primary database has no tables yet. `onboard --detail full`
|
|
278
|
+
says "Dockerfile: present." and "Deployment: kamal.", names a `Procfile.dev`
|
|
279
|
+
on its own line instead of reporting a Procfile, and no longer prints an empty
|
|
280
|
+
"File Storage & Rich Text" heading. The migrations list names a migration
|
|
281
|
+
`active_storage:install` or `action_text:install` copied by its class, without
|
|
282
|
+
the scope suffix. (#276, #280, #281, #284)
|
|
283
|
+
- **`config` reports the Action Cable adapter of the current environment**
|
|
284
|
+
(solid_cable in a default Rails 8 production, not the development block's
|
|
285
|
+
async) and keeps the Database line when the environment lists several
|
|
286
|
+
databases. `observability` reports Rails 8.1's event reporter (`Rails.event`)
|
|
287
|
+
as available, with its subscriber count. (#285, #286)
|
|
288
|
+
- **`test_info` reads Rails 8.1 test setups.** It and `onboard` name
|
|
289
|
+
`config/ci.rb` (`rails_ci`), Buildkite, Jenkins and Bitbucket Pipelines as CI,
|
|
290
|
+
and `test_info` lists the steps `bin/ci` runs. It lists `test/test_helpers`
|
|
291
|
+
(where the authentication generator puts `SessionTestHelper`) as test helpers,
|
|
292
|
+
no longer lists `test/helpers` helper tests as helpers, and shows the
|
|
293
|
+
`parallelize`, `fixtures` and `driven_by` calls. (#277, #287)
|
|
294
|
+
- **Rails 8 generated authentication reads right.** `controllers` no longer
|
|
295
|
+
drops the authentication filter from every controller: a `skip_before_action`
|
|
296
|
+
inside a class method (`allow_unauthenticated_access`) applies only where a
|
|
297
|
+
controller calls that method, with the options the call passes, also through a
|
|
298
|
+
class method of its base, or of a concern either one includes, that calls it.
|
|
299
|
+
`conventions` builds the controller test's sign-in from the call the app's
|
|
300
|
+
tests make (`sign_in_as`), and signs in the app's own users fixture where the
|
|
301
|
+
tests sign in a variable set elsewhere. (#288, #289)
|
|
302
|
+
- **`read_logs` reads the level a formatter writes**, never a word in the
|
|
303
|
+
message, and reads Sidekiq's 6/7, 8 (colored) and JSON formats and
|
|
304
|
+
rails_semantic_logger's one-letter level. It filters by level only when most
|
|
305
|
+
lines carry a severity; otherwise (Rails' default dev and 8.0+ production
|
|
306
|
+
formatter) it shows every line and says it cannot filter by level. It reads a
|
|
307
|
+
rotated log (`file: "development.log.0"`) and lists rotated logs under the
|
|
308
|
+
available files. (#278, #343)
|
|
309
|
+
- **Static `routes` draws more of what Rails draws.** Shallow nesting,
|
|
310
|
+
`path_names`, a `new do` block, every path of a multi-path route (Rails 8.1
|
|
311
|
+
refuses that form, so on 8.1 it counts as not expanded), routes inside
|
|
312
|
+
`controller :x do`, `options` routes, and the routes of a method defined in a
|
|
313
|
+
route file, where it is called. A resource whose options are a variable, and a
|
|
314
|
+
call it cannot expand (`load`, `use_doorkeeper`, `ActiveAdmin.routes(self)`,
|
|
315
|
+
also inside a `constraints` or `authenticate` block), count as not expanded
|
|
316
|
+
instead of listing seven actions or vanishing; `direct` and `resolve` are no
|
|
317
|
+
longer counted, and a lambda mount counts as the booted tier counts it. Routes
|
|
318
|
+
an initializer adds with `Rails.application.routes.prepend` or `.append` are
|
|
319
|
+
listed first and last, as Rails draws them, including one registered inside
|
|
320
|
+
`after_initialize`, which Rails runs before it draws the routes; one
|
|
321
|
+
registered inside another `on_load` hook counts as not expanded, since that
|
|
322
|
+
hook may run after the draw. The framework count says it covers only the app's
|
|
323
|
+
route files, and that routes Rails' own engines and gems draw are read only
|
|
324
|
+
with the app booted; `onboard`, the rake summary and the generated context
|
|
325
|
+
files say so beside their route count too. (#283, #325, #326, #328)
|
|
326
|
+
- **A route, mount or filter under a condition carries it.** Static `routes`
|
|
327
|
+
marks a route under `if`/`unless`, a `case` branch or an `&&`/`||` guard
|
|
328
|
+
(`case Rails.env`, `Rails.env.development?`, `ENV[...]`) with that condition.
|
|
329
|
+
A mounted app in the `routes`, `engines` and `onboard` lists and the generated
|
|
330
|
+
context files, and a controller filter or skip declared under one
|
|
331
|
+
(`before_action :x if Rails.env.test?`), carry it too, on both tiers; a skip
|
|
332
|
+
under one leaves the filter in the chain, and the generated files no longer
|
|
333
|
+
count such a filter as global. (#327)
|
|
334
|
+
- **`routes --detail full` prints each route's constraints and defaults** beside
|
|
335
|
+
its path, as `bin/rails routes` does, on both tiers, and escapes the `|` in a
|
|
336
|
+
merged `PATCH|PUT` or `via:` verb so each route stays one table row. (#279,
|
|
337
|
+
#329)
|
|
338
|
+
- **Engine routes are counted.** Run from a mountable engine's root, `routes`
|
|
339
|
+
and `onboard` list and count the engine's own routes instead of 0, including
|
|
340
|
+
an engine whose namespace does not match its path (`PgHero::Engine` in
|
|
341
|
+
`lib/pghero/engine.rb`). `engines` counts a loaded engine's routes the way
|
|
342
|
+
`routes` does, PATCH and PUT as one, and counts its redirects and lambdas
|
|
343
|
+
beside them (`23 routes, 2 redirect or lambda routes`). (#379, #380)
|
|
344
|
+
- **Booted from a mountable engine's `test/dummy`, the engine's own code is
|
|
345
|
+
read.** `model_details`, `controllers` and the other class listings include
|
|
346
|
+
the engine's own models and controllers, name their files relative to the app
|
|
347
|
+
root (`../../app/models/...`), and list and render the views and layouts in
|
|
348
|
+
the engine's `app/views`; `test_info`, `analyze_feature` and `generate_test`
|
|
349
|
+
read the engine's test suite. With `--no-boot` the test tools read it too when
|
|
350
|
+
the engine's bundle is inside the app's git repository. When it is not, the
|
|
351
|
+
test framework reads "not read" in `test_info`, `onboard` and the generated
|
|
352
|
+
context, where it said "no tests yet", and a `test_info` model or controller
|
|
353
|
+
search says the engine's suite was not searched. `controllers` with
|
|
354
|
+
`--no-boot` from a `test/dummy` says the engine above it is not read, where it
|
|
355
|
+
listed no controllers and said nothing, and `view` and `partial_interface` say
|
|
356
|
+
the engine's views are read only with the app booted. (#381)
|
|
357
|
+
- **`view` lists more templates.** Templates with no handler extension
|
|
358
|
+
(`pwa/service-worker.js`, `pages/about.text`), which Rails renders with its
|
|
359
|
+
raw handler, are listed and shown, each fenced by what renders it. View paths
|
|
360
|
+
`config/application.rb` adds to `config.paths["app/views"]` are read, so a
|
|
361
|
+
template under `app/views/custom` is listed as `posts/show` and an overlay
|
|
362
|
+
such as `enterprise/app/views` is listed at all; `helper_methods` and
|
|
363
|
+
`stimulus` read those paths too. On an API-only app that keeps the two mailer
|
|
364
|
+
layouts `rails new --api` creates, `view` lists them instead of saying
|
|
365
|
+
`app/views` does not exist. (#282, #338, #346)
|
|
366
|
+
- **`partial_interface` reads strict locals and implicit renders right.** A
|
|
367
|
+
strict locals comment that ends in `-%>`, has a default with parentheses, or
|
|
368
|
+
is the empty `locals: ()` (now said to accept no locals) is read. `render
|
|
369
|
+
@posts` is credited to the partial Rails renders: under the view's controller
|
|
370
|
+
namespace unless `prefix_partial_path_with_controller_namespace` is off
|
|
371
|
+
(booted, as ActionView::Base holds it; unbooted, as `config.action_view`,
|
|
372
|
+
ActionView::Base or an `on_load(:action_view)` block sets it in
|
|
373
|
+
config/application.rb, the environment file or any initializer), or at the
|
|
374
|
+
path a model's `to_partial_path` returns when it returns a string literal.
|
|
375
|
+
`render @post.comments` goes to the partial of the records the association
|
|
376
|
+
the model declares holds (its `class_name:` when it has one), a chain on a
|
|
377
|
+
receiver that is no model (`current_user.posts`) goes to the partial of the
|
|
378
|
+
records it names, a trailing call on a collection (`@posts.first`,
|
|
379
|
+
`@posts.recent`) keeps that collection's records, and a chain the app's
|
|
380
|
+
models cannot resolve, or a `through:` association that names its
|
|
381
|
+
`source:`, is credited to no partial. The `view` tool's `renders:` list
|
|
382
|
+
reads the call the same way. (#323, #324)
|
|
383
|
+
- **`schema` shows more of each column and table**, in both tiers: precision,
|
|
384
|
+
scale, limit, the unsigned flag and collation, the table comment, unique
|
|
385
|
+
constraints, a MySQL text or blob column's size (`size: medium`), index
|
|
386
|
+
options (using, include, order), foreign key actions with the deferrable mode
|
|
387
|
+
and `validate: false`, the enabled extensions, the primary key (a composite
|
|
388
|
+
one as its columns, in `model_details` too, which also names a key the model
|
|
389
|
+
sets with `self.primary_key =`, and the table's beside it when they differ),
|
|
390
|
+
and with `--table` the check constraints (a MySQL one without the parentheses
|
|
391
|
+
MySQL adds), the enum types its columns use with their values, and generated
|
|
392
|
+
columns with their expressions. A `t.virtual` column is typed by its `type:`
|
|
393
|
+
in every static source, migration replays included. (#290, #291, #292, #352)
|
|
394
|
+
- **`db/structure.sql` reads like schema.rb.** A structure.sql app gets the
|
|
395
|
+
column types schema.rb gives the same table (hstore, citext, enum with its
|
|
396
|
+
type, jsonb, timestamptz, binary, time, integer with its limit, unsigned),
|
|
397
|
+
plus table and column comments, and its extensions; an index shows its method,
|
|
398
|
+
order, operator class, prefix lengths and INCLUDE list, and a table its unique
|
|
399
|
+
constraints. On SQLite, a table with a multi-line foreign key or a dump with
|
|
400
|
+
no semicolons is read whole, and `sqlite_sequence` is not listed as a table.
|
|
401
|
+
On MySQL, a `FULLTEXT KEY` or `SPATIAL KEY` line is an index with its type,
|
|
402
|
+
not a column. (#348, #349, #350)
|
|
403
|
+
- **MySQL column types read as the dumper writes them.** A schema.rb column
|
|
404
|
+
written as `t.column "kind", "enum('a','b')"` is listed with that type instead
|
|
405
|
+
of dropped, and the booted tier names MySQL enum, set and timestamp columns
|
|
406
|
+
the same way. (#351)
|
|
407
|
+
- **A schema.rb dumped with more than one schema names a public table by its
|
|
408
|
+
bare name** (`users`, not `public.users`), so `--table users` and the `User`
|
|
409
|
+
model find it; foreign keys, indexes and enum types follow. (#353)
|
|
410
|
+
- **The static tier reads the database the app configures.** The adapter comes
|
|
411
|
+
from `DATABASE_URL` or `<NAME>_DATABASE_URL` when set, and from a `url:` in
|
|
412
|
+
database.yml, as Rails merges them, and the replayed schema types its implicit
|
|
413
|
+
primary keys by that adapter. The schema comes from the dump the app
|
|
414
|
+
configures: database.yml's `schema_dump` name and `schema_format = :sql`
|
|
415
|
+
(database.yml on Rails 8.0.3 and later, else
|
|
416
|
+
`config.active_record.schema_format`, which Rails applies after every
|
|
417
|
+
initializer, and only then `ActiveRecord.schema_format`); the doctor, schema
|
|
418
|
+
version, tool guide, onboarding setup command and missing-table messages name
|
|
419
|
+
the same file, a configured dump over `max_schema_file_size` is reported as
|
|
420
|
+
too large, and a change to any `.sql` dump under `db/` refreshes the MCP
|
|
421
|
+
cache. (#355, #357)
|
|
422
|
+
- **The MCP cache, live reload and `watch` cover all of `app/`, `test/` and
|
|
423
|
+
`spec/`.** An edit to a mailer preview, a fixture, a factory, a spec or any
|
|
424
|
+
file under `app/` that a tool reads refreshes the cached answer. A bundler's
|
|
425
|
+
output in `app/assets/builds` does not, and a re-recorded VCR cassette does
|
|
426
|
+
not either.
|
|
427
|
+
- **A table in a secondary database is found** by `schema --table`,
|
|
428
|
+
`model_details`, `analyze_feature`, `diagnose`, `migration_advisor`, the
|
|
429
|
+
controllers schema hint and the model resource. The table view names every
|
|
430
|
+
database that holds it, and where one name holds different tables in two
|
|
431
|
+
databases it shows each database's columns and models. `migration_advisor`
|
|
432
|
+
passes `--database <name>` so the migration lands in that database's
|
|
433
|
+
migrations_paths. For a database only another environment configures (Rails
|
|
434
|
+
8's queue, cache and cable outside production), the Run line sets that
|
|
435
|
+
`RAILS_ENV` and names its migrations_paths; when no environment configures
|
|
436
|
+
it, no Run line is given. It also leaves out `foreign_key: true` on a reference between
|
|
437
|
+
tables in different databases. A replica or a `database_tasks: false` entry is
|
|
438
|
+
not listed as a database of its own. (#356)
|
|
439
|
+
- **Migration replay follows what Rails runs.** It reads migrations in
|
|
440
|
+
subdirectories of `db/migrate` and in the migrations_paths database.yml sets
|
|
441
|
+
(for the primary and for a secondary with no dump yet), and the migrations
|
|
442
|
+
listing, the pending check and `doctor` read the same directories; a migration
|
|
443
|
+
file symlinked from outside the app is not read, and a secondary database's
|
|
444
|
+
line in `schema` names its pending migrations. A `revert` block is undone (a
|
|
445
|
+
nested one runs forward), and `revert SomeMigration` counts as a statement it
|
|
446
|
+
could not follow. One column is kept when both branches of an `if` declare it,
|
|
447
|
+
temporary and `if_not_exists` tables are skipped, `as:` and `execute "CREATE
|
|
448
|
+
TABLE"` tables are read (a heredoc over several lines too), check constraints
|
|
449
|
+
are replayed, `rename_index` is followed, and `Migration[5.0]` tables get
|
|
450
|
+
integer keys. An `execute` whose CREATE TABLE is built at run time counts as
|
|
451
|
+
not replayed. (#360, #361, #362, #363)
|
|
452
|
+
- **Static primary keys and table names read as Rails reads them.** A primary
|
|
453
|
+
key written as `id: { type: :string, limit: 36 }` is typed `string, limit:
|
|
454
|
+
36`, and a model whose class, base class or app sets `pluralize_table_names =
|
|
455
|
+
false` reads its singular table with its columns. (#358, #359)
|
|
456
|
+
- **`model_details` prints every association option** (`as:`, `counter_cache:`,
|
|
457
|
+
`touch:`, `inverse_of:`, `extend:`, `before_add:`, the foreign key a
|
|
458
|
+
`has_many` or `has_one` declares and the rest) and an extension block's
|
|
459
|
+
methods; `callbacks` lists association callbacks; and `--no-boot` reads
|
|
460
|
+
`required: false` as optional and `query_constraints:` as the foreign key (a
|
|
461
|
+
`has_many` prints the option). (#296)
|
|
462
|
+
- **`model_details` reads more model declarations.** A `validate do ... end`
|
|
463
|
+
block is a custom validation with its `on:`/`if:`/`unless:` and first line. An
|
|
464
|
+
enum shows its `default:` and, with a prefix or suffix, the methods Rails
|
|
465
|
+
defines (`kind_lead?`). A prefixed delegate names the methods it defines
|
|
466
|
+
(`owner_name`) and `private: true` is marked. Each store column is listed once
|
|
467
|
+
with its accessors, including the names `prefix:` and `suffix:` give. Columns
|
|
468
|
+
dropped with `self.ignored_columns` are left out and listed on an "Ignored
|
|
469
|
+
columns" line. `encrypts`, `normalizes`, `serialize` and `generates_token_for`
|
|
470
|
+
show every option (`expires_in: 2.days`, or `never`), and a named
|
|
471
|
+
`has_secure_password :recovery_password` keeps its name. A Mongoid document's
|
|
472
|
+
schema hint in `controllers` names its collection and `_id` key instead of an
|
|
473
|
+
empty table, and a field shows its default. An array constant wrapped in
|
|
474
|
+
`Ractor.make_shareable` is listed under Constants. A validation, association,
|
|
475
|
+
scope or enum written in a method nothing calls is not listed. (#302, #305,
|
|
476
|
+
#306, #307, #309, #382, #391, #414)
|
|
477
|
+
- **`delegated_type`, `has_secure_token` and `accepts_nested_attributes_for` are
|
|
478
|
+
read.** The static tier lists the polymorphic `belongs_to` that
|
|
479
|
+
`delegated_type` declares, both tiers name its types (booted asks the model's
|
|
480
|
+
`<role>_types` when the source names them through a constant, and the static
|
|
481
|
+
tier names that constant as not read), and `model_details` lists
|
|
482
|
+
`has_secure_token` and `accepts_nested_attributes_for` under Macros. (#365)
|
|
483
|
+
- **`callbacks` and `model_details` read callbacks as Rails registers them.** A
|
|
484
|
+
callback the model removes with `skip_callback`, by name or by callback
|
|
485
|
+
object, is not listed (a conditional skip shows as the negated condition). A
|
|
486
|
+
callback object (`after_commit AuditTrail`, `before_validation
|
|
487
|
+
PostNormalizer.new`) prints as the class or expression the model passes. A
|
|
488
|
+
concern's `prepended do` block applies only to a class that prepends it, and
|
|
489
|
+
its `included do` block only to one that includes it. (#303, #304, #310)
|
|
490
|
+
- **Models outside `app/models` are found**, in both tiers: in another `app/*`
|
|
491
|
+
directory such as `app/domain`, or under a path `config/application.rb` adds
|
|
492
|
+
to `eager_load_paths` or `autoload_paths`, when its superclass is a model. A
|
|
493
|
+
class there that is not a model is left out even when it does not load, and
|
|
494
|
+
the lib subdirectories `autoload_lib(ignore:)` names are not read. The static
|
|
495
|
+
tier also finds models under a symlinked directory or file in `app/models`
|
|
496
|
+
that points inside the app, a model assigned `Class.new(ApplicationRecord)`
|
|
497
|
+
with what its block declares (the `self.table_name` it sets included), and
|
|
498
|
+
reads a job assigned `Class.new(ApplicationJob)`, or a class whose parent is
|
|
499
|
+
such a base, the same way. An assignment counts only when the file's path
|
|
500
|
+
names it, so an error constant such as `PaymentError = Class.new(StandardError)`
|
|
501
|
+
is never listed as a service, serializer or model. The static tier also
|
|
502
|
+
merges a module prepended after the class body (`Note.prepend(EE::Note)`,
|
|
503
|
+
GitLab's `prepend_mod_with("Note")`). (#344, #347, #413, #416)
|
|
504
|
+
- **Booted `model_details` no longer credits every model with a gem's base
|
|
505
|
+
mixins**, such as Kaminari's two modules and `page` and `default_per_page` on
|
|
506
|
+
the app's abstract base, or on a model that subclasses ActiveRecord::Base
|
|
507
|
+
itself, which Kaminari reaches the same way. (#371)
|
|
508
|
+
- **Method listings read more of how Ruby defines methods**, in `model_details`,
|
|
509
|
+
`concern`, `service_pattern` and every tool that reads a file's methods. A
|
|
510
|
+
`private` inside `class << self` or a `concerning` block no longer hides the
|
|
511
|
+
public methods and actions after it. `def Widget.x` is a class method,
|
|
512
|
+
`private_class_method` methods are private, a `def self.x` after `private`
|
|
513
|
+
stays public, and a `module_function` method is a module method
|
|
514
|
+
(`self.total(items)`). Methods defined with `alias`, `alias_method`, `attr_*`,
|
|
515
|
+
`define_method`, `class_attribute` and `cattr_*`/`mattr_*` are listed, an
|
|
516
|
+
inline `private attr_reader :x` or `protected attr_writer :y` keeping its
|
|
517
|
+
visibility, and `service_pattern` writes the class-side reader, writer and
|
|
518
|
+
predicate a `class_attribute` defines with `self.`. A method in a scope or
|
|
519
|
+
association extension block, a `concern :Name do` block, or a `Struct.new`,
|
|
520
|
+
`Data.define`, `Class.new` or `Module.new` block is not the enclosing class's;
|
|
521
|
+
one assigned to a constant is that constant's, and a `Module.new` held in a
|
|
522
|
+
local is the enclosing class's, where it is included. In `model_details` the
|
|
523
|
+
methods written with `def` come first, so a long run of delegations no longer
|
|
524
|
+
pushes them past the 25-row cap. (#297, #298, #308, #388)
|
|
525
|
+
- **A one-line or endless method is cut at its own line.** `callbacks` and
|
|
526
|
+
`concern --detail full` show `def strip_name; end` or `def wrap_save = yield`
|
|
527
|
+
under `(line N)` instead of running to the end of the class, and `search_code`
|
|
528
|
+
trace cuts such a body the same way. (#301)
|
|
529
|
+
- **`search_code` finds more definitions.** Definition and trace modes find
|
|
530
|
+
`private def x`, `def Widget.x`, `ruby2_keywords def x` and other modifier
|
|
531
|
+
forms; trace counts a call inside an endless def body as a call site; class
|
|
532
|
+
mode finds `class Billing::Ledger`, `class ::Top` and a constant assigned
|
|
533
|
+
`Data.define`, `Struct.new`, `Class.new` or `Module.new`. (#300)
|
|
534
|
+
- **A compact class name resolves its superclass as Ruby does.** `class
|
|
535
|
+
Api::UsersController < BaseController` gets the top-level `BaseController` as
|
|
536
|
+
its parent and its filters, on both tiers. The static model list, job chains,
|
|
537
|
+
service and component base detection, mailer chains and `generate_test` read a
|
|
538
|
+
compact class the same way, so `class Admin::Thing < Base` is not a model when
|
|
539
|
+
`Base` is a plain class. (#299)
|
|
540
|
+
- **`concern` lists a class that prepends the concern** under Included By.
|
|
541
|
+
(#311)
|
|
542
|
+
- **`controllers` lists block, lambda and object filters, in the order Rails
|
|
543
|
+
adds them to the chain** (after filters run last-declared first). A block or
|
|
544
|
+
proc filter (`proc {}`, `Proc.new {}`) reads `block (line N)` and a lambda
|
|
545
|
+
(`-> {}`, `lambda {}`) `lambda (line N)`, or `(line N of <file>)` when
|
|
546
|
+
written outside the controller's own file (a concern's class method, an
|
|
547
|
+
ancestor), each with its own `only:`/`except:`, in both tiers; every name a
|
|
548
|
+
`before_action :a, :b` call gives is listed in the order Rails runs them (a
|
|
549
|
+
lambda where it stands, the block last); the static tier reads
|
|
550
|
+
`prepend_after_action`, `prepend_around_action` and `append_around_action`,
|
|
551
|
+
each prepended filter at the front of the chain; `skip_forgery_protection`
|
|
552
|
+
shows as the `verify_authenticity_token` skip it is. An object filter
|
|
553
|
+
(`around_action TimingFilter.new`) reads `TimingFilter (object)` in both
|
|
554
|
+
tiers, where the booted tier printed a memory address. The booted tier leaves
|
|
555
|
+
out a block filter Rails or a gem adds (`allow_browser`, `rate_limit`), even
|
|
556
|
+
when the bundle is installed under the app root. The static tier names a gem
|
|
557
|
+
module the controller or one of its app bases includes
|
|
558
|
+
(`include ActiveStorage::SetBlob`) as an included module not read, where a
|
|
559
|
+
filter it adds would be missing, and leaves out a Rails module whose include
|
|
560
|
+
adds no filter (`ActionController::Live`). `http_basic_authenticate_with` is a
|
|
561
|
+
before filter with its `only:`/`except:`, never its credentials. (#293, #332,
|
|
562
|
+
#335)
|
|
563
|
+
- **`controllers` reads strong params and delegated actions.**
|
|
564
|
+
`params.expect(user: [tags: []])` reads as an array of scalars, and the
|
|
565
|
+
summary lists nested keys, arrays and `key: {}` hashes beside the flat
|
|
566
|
+
permits, a hash that names its keys with only those keys. An action defined
|
|
567
|
+
with `def_delegators`, `def_delegator` or `delegate` is counted, so
|
|
568
|
+
`controllers` and `validate` no longer report a route to one as missing.
|
|
569
|
+
(#333, #334)
|
|
570
|
+
- **`helper_methods` lists the view helpers declared with `helper_method`** in a
|
|
571
|
+
controller, a controller concern or a lib module the controller includes, each
|
|
572
|
+
with the class or module that declares it. (#336)
|
|
573
|
+
- **`test_info` reads fixtures and factories where Rails and factory_bot load
|
|
574
|
+
them.** Fixture files that open with an ERB line or use the `DEFAULTS` alias
|
|
575
|
+
are read, subfolder sets such as `admin/posts` stay apart, `_fixture` and the
|
|
576
|
+
labels its `ignore:` names are dropped, and directories a helper adds to
|
|
577
|
+
`fixture_paths` are read (inside `RSpec.configure do |config|` too, on
|
|
578
|
+
`ActiveSupport::TestCase` by name, and as a path built from `__dir__` or
|
|
579
|
+
`__FILE__`); an RSpec `spec/fixtures` no helper loads gives no sets, and a
|
|
580
|
+
file it cannot parse lists its labels. A fixture file that links out of the
|
|
581
|
+
app or to a sensitive file is not read, here or by `generate_test` and
|
|
582
|
+
`conventions`, and a file over `max_test_file_size` is named as too large. A
|
|
583
|
+
label or value ERB computes (`row_<%= i %>`) is shown as ERB, and such a label
|
|
584
|
+
is never written as a fixture key. Factories are found in `factories.rb`,
|
|
585
|
+
`factories/`, `test/factories.rb`, `spec/factories.rb` and each pack's
|
|
586
|
+
`spec/factories` and `test/factories` (both suites' when both exist). A helper
|
|
587
|
+
that sets or appends to `FactoryBot.definition_file_paths` is followed when it
|
|
588
|
+
then calls `FactoryBot.find_definitions` (added to the defaults
|
|
589
|
+
factory_bot_rails already loaded) or `FactoryBot.reload` (in place of them);
|
|
590
|
+
`config.factory_bot.definition_file_paths` is not read. Fabrication's
|
|
591
|
+
fabricators are listed, `onboard` names Fabrication as the data setup of a
|
|
592
|
+
fabricators-only suite, the generated context lists the fabricators directory,
|
|
593
|
+
and a Cucumber `features/` tree is counted. (#313, #373)
|
|
594
|
+
- **`i18n` reads the locale files Rails loads.** `.rb` locales are read for
|
|
595
|
+
their keys (the plural rule and transliteration settings under `i18n.plural`
|
|
596
|
+
and `i18n.transliterate` are not counted as keys), `.yaml` files Rails ignores
|
|
597
|
+
are not counted, files `config.i18n.load_path` adds or replaces (`+=`, `<<`,
|
|
598
|
+
`=`) are listed and counted in both tiers, a sensitive file a `load_path` glob
|
|
599
|
+
reaches is never read, and the Fallbacks section shows on a booted app whose
|
|
600
|
+
`config.i18n.fallbacks` sets only default locales. (#314, #315)
|
|
601
|
+
- **Initializers in subdirectories of `config/initializers` are read** for the
|
|
602
|
+
default locale, middleware, tagged logging, OmniAuth providers, component
|
|
603
|
+
preview paths, CORS, Rack::Attack, inflections and the shard selector, and
|
|
604
|
+
`config` lists them by their path, as Rails loads them at any depth. (#316)
|
|
605
|
+
- **`env` and `env_config` list what the app reads.** The environment variable
|
|
606
|
+
catalog drops `RAILS_EAGER_LOAD` and `RAILS_EVENT_REPORTER`, which Rails never
|
|
607
|
+
reads, and adds `SECRET_KEY_BASE_DUMMY`, `RAILS_DEVELOPMENT_HOSTS`,
|
|
608
|
+
`RAILS_GROUPS`, `RAILS_CACHE_ID`, `RAILS_APP_VERSION` and
|
|
609
|
+
`SOLID_QUEUE_IN_PUMA`. Credentials that decrypt to nothing are said to hold no
|
|
610
|
+
keys. External services called as `Net::HTTP.get(URI("..."))`,
|
|
611
|
+
`Net::HTTP.start("host")`, `Faraday.get("...")`, `RestClient`, `HTTP`
|
|
612
|
+
(http.rb), `Excon`, `Typhoeus` or `URI.open`, and HTTP clients in `lib/` or
|
|
613
|
+
`config/`, are listed; a loopback, private or unspecified (`0.0.0.0`) IP, a
|
|
614
|
+
file name handed to a client, and a call in a comment or a string are not.
|
|
615
|
+
`env_config` lists keys set with `<<`, `+=`/`||=`/`&&=`, an index write
|
|
616
|
+
(`config.action_dispatch.default_headers["X-Frame-Options"] = "DENY"`), a
|
|
617
|
+
write through an index read (`config.paths["app/views"] << "x"`), a method
|
|
618
|
+
call or a block, and not a call whose value is used (`x =
|
|
619
|
+
config.root.join("tmp")`), a method argument named `config`, or another
|
|
620
|
+
library's config (`OmniAuth.config.test_mode`). (#317, #318, #319, #320)
|
|
621
|
+
- **`active_support` lists files that sign with
|
|
622
|
+
`Rails.application.message_verifier`**, `message_verifiers` or
|
|
623
|
+
`ActiveStorage.verifier`, and not a file that only rescues
|
|
624
|
+
`MessageVerifier::InvalidSignature` or names one in a comment or a string.
|
|
625
|
+
(#321)
|
|
626
|
+
- **`search_docs` finds the 21 Rails guides the index lacked** (upgrading,
|
|
627
|
+
engines, autoloading, error reporting, generators, core extensions and more).
|
|
628
|
+
A guide newer than the app's Rails links to main and says so, since the app's
|
|
629
|
+
stable branch has no file for it. (#322)
|
|
630
|
+
- **`frontend_stack` names the asset pipeline and CSS and build tools.** A
|
|
631
|
+
Propshaft or Sprockets pipeline is named (with Sprockets' `manifest.js` link
|
|
632
|
+
lines), an app with no JavaScript build is said so, and an app is called
|
|
633
|
+
API-only only when `config.api_only` is set. webpack, rollup or bun is named
|
|
634
|
+
as a jsbundling-rails app's build tool, and `conventions` names Rollup and
|
|
635
|
+
reads bun from the text `bun.lock`. `conventions` and `frontend_stack` name
|
|
636
|
+
Tailwind CSS or Bootstrap on a `rails new --css` app. (#339, #340, #341)
|
|
637
|
+
- **`validate` checks Ruby syntax with the app's own Ruby grammar** (the running
|
|
638
|
+
Ruby when booted, the declared one with `--no-boot`, or the running Ruby when
|
|
639
|
+
the app declares none), so a file valid on Ruby 3.3 is not failed for a rule
|
|
640
|
+
3.4 added. Ruby 3.1 and 3.2 are checked as 3.3, the oldest grammar prism has.
|
|
641
|
+
An app that declares JRuby or TruffleRuby and no Ruby version is checked with
|
|
642
|
+
the running Ruby's grammar, and a syntax error says so. (#342)
|
|
643
|
+
- **`autoload` lists every root Rails autoloads from**: app/models, app/lib,
|
|
644
|
+
app/services and the rest, other engines' app/* directories, a directory an
|
|
645
|
+
initializer adds with `push_dir` (with the namespace it loads under),
|
|
646
|
+
autoload-once paths added through `config.paths`, and directories a loader
|
|
647
|
+
keeps out of eager loading. (#345)
|
|
648
|
+
- **`job_pattern` reads more queues and schedules.** Channels show their
|
|
649
|
+
streams, timers and actions without booting, a `periodically` timer with a
|
|
650
|
+
block is listed in both tiers, and the connection says what it is
|
|
651
|
+
`identified_by`. A job's schedule comes from the task that runs it (Solid
|
|
652
|
+
Queue `config/recurring.yml` with its environment, sidekiq-cron,
|
|
653
|
+
sidekiq-scheduler, GoodJob `config.good_job.cron` including `merge!`,
|
|
654
|
+
whenever's `config/schedule.rb`); a job named only in a comment is not
|
|
655
|
+
scheduled, and `--detail full` lists every recurring task, on an app with no
|
|
656
|
+
job classes too. A schedule an ERB tag builds reads as computed. Without
|
|
657
|
+
booting, queues are named as ActiveJob names them, with `queue_name_prefix`,
|
|
658
|
+
`queue_name_delimiter` and `default_queue_name` applied, and a job with no
|
|
659
|
+
`queue_as` is on the default queue in both tiers. A Resque job's `@queue` (or
|
|
660
|
+
`def self.queue` when it sets none) and a Que job's `self.queue =` are read,
|
|
661
|
+
Que::Job subclasses are listed with their `run` signature, and `run` is the
|
|
662
|
+
entry point of a Que job only. (#330, #331, #366, #374)
|
|
663
|
+
- **`api` names the serialization layer and OpenAPI specs right.** Blueprinter
|
|
664
|
+
blueprints, Alba resources and RABL templates are named; an Active Job
|
|
665
|
+
argument serializer and a mixin module the serializers include are not counted
|
|
666
|
+
as response serializers. A file is an OpenAPI spec only when its top-level
|
|
667
|
+
`openapi` or `swagger` key holds a version number, found in `public/`, `doc/`,
|
|
668
|
+
`app/` and `config/` as well; a docs site's `_config.yml` and locale files are
|
|
669
|
+
not listed. A spec over the per-file read limit is still listed: the check
|
|
670
|
+
reads only the first 64KB of each candidate. `gems` says rswag-api serves
|
|
671
|
+
specs from its configured `openapi_root`, and names
|
|
672
|
+
`config/initializers/rswag_api.rb` when the app has it. (#367, #368, #375)
|
|
673
|
+
- **`onboard` names auth and serialization like the other tools.** An
|
|
674
|
+
"Authentication & Authorization" section covers Rodauth, Action Policy and
|
|
675
|
+
Rails 8 generated authentication; the Devise model is named with its modules,
|
|
676
|
+
those a concern's `included` block adds too; the authentication gem is still
|
|
677
|
+
named when the only auth finding is policy classes. A named
|
|
678
|
+
`has_secure_password :six_digit_code` is listed as a digest, not as login,
|
|
679
|
+
there and in the generated context. The API section names the
|
|
680
|
+
serialization as `api` does and is left out when there is none. `gems` lists
|
|
681
|
+
`action_policy` and `rolify` under auth. (#369)
|
|
682
|
+
- **`conventions` names more model patterns**: full-text search, tree structures
|
|
683
|
+
and soft deletes from `pg_search_scope`, `multisearchable`, `has_ancestry`,
|
|
684
|
+
`has_closure_tree` and `include Discard::Model`, multi-tenancy from
|
|
685
|
+
activerecord-multi-tenant, and a `discarded_at` column as soft delete. (#370)
|
|
686
|
+
- **`component_catalog` reads more components.** The usage example for a
|
|
687
|
+
`renders_many` slot calls the singular setter (`c.with_item do`), and the
|
|
688
|
+
one for a polymorphic slot calls each setter its `types:` define. A component
|
|
689
|
+
in the layout
|
|
690
|
+
`phlex:install` generates types as Phlex, read from its root even outside
|
|
691
|
+
`app/components` (`app/views/components`), and is named by the constant that
|
|
692
|
+
renders it (`Components::Badge`). (#372, #378)
|
|
693
|
+
- **`performance_check` no longer suggests `counter_cache: true`** on a
|
|
694
|
+
`belongs_to` whose count column `counter_culture` already keeps. (#376)
|
|
695
|
+
- **Rake tasks are read whole.** Tasks after a brace-form `namespace(:x) { }`
|
|
696
|
+
are not put inside it, `task "a:b"` names and `multitask` are listed, and the
|
|
697
|
+
Rakefile and `rakelib/*.rake` are read; a rake file symlinked out of the app
|
|
698
|
+
is not. (#384)
|
|
699
|
+
- **A tool failure's `At:` line names a frame outside the app and every gem by
|
|
700
|
+
its file name and line**, never an absolute path from the answering machine.
|
|
701
|
+
A frame inside an `eval` names the evaluated file the same way.
|
|
702
|
+
|
|
8
703
|
## [5.31.0] - 2026-10-05
|
|
9
704
|
|
|
10
705
|
### Changed
|