Rails generated names
Status: Evidence-backed direction. The Analyzer checks these rules against frozen profile data.
Generated Rails source must not collide with Rails, Ruby, Core, selected gems, or other generated names. The target
profile freezes the names that each pinned runtime already occupies: dangerous model members, record-protocol
methods, Object-table constants, named scopes, routes, and Core tables. Pure Analyzers derive every generated model
member, constant, route, helper, and table name through a checksummed inflection snapshot, then compare those claims
with the frozen occupants and with one another. Allocators move only compiler-private bindings and helpers; public
Rails names stay conventional. A collision should omit its participants and dependents and list exact gaps,
although some current analyzers still block instead. The
profile data notes (repository-only) record the frozen
registries and how they are reproduced.
On this page
- Model member namespace
- Top-level constants
- Model method families
- Ruby bindings
- Routes and navigation names
- Model helper allocation
- Target-owned tables
- Admission and collisions
Model member namespace
The target freezes Rails 8.1.3.1's 477 dangerous attribute methods from Core
9181b05043977f95fb1ead1012a2b1478363eb67, under Ruby 4.0.5. It follows Rails' own boundary rather than reserving
every inherited Ruby method. Ordinary format and display attributes are therefore available. The target also
protects 18 record-protocol methods needed by assignment, callbacks, Association type checks, presence checks, route
identity, and AASM dispatch. Rails' unsafe list excludes methods also defined on Object, including Rails' own
present? and blank? overrides. Allowing an enum predicate to replace those methods changes Policy and
required-Reference behavior; a Field reader named send or public_send breaks callbacks or assignment.
TARGET_RECORD_PROTOCOL_METHOD_NAMES in the profile (repository-only) holds the bounded list. Rails' list subtracts
Object's names even where Active Record overrides them. Pinned
attribute assignment calls public_send; callbacks call send and
instance_exec; autosave uses instance_eval and equal?; and
AASM's literal invoker uses method, __send__, and respond_to?. This supplements Rails'
rules without reserving all Ruby inheritance.
The profile also records and expands all 21 ordinary Active Record attribute-method patterns and the four ordinary
Association method families without consulting the Designer's loaded Active Record classes or inflections. A
checksummed English inflection snapshot supplies pure singularization, pluralization, local-key camelization, and
unqualified-constant underscoring under the target's Active Support rules. One immutable Policy-naming projection
derives each Policy and test constant and path through that snapshot. Policy record and Policy-gate lowerings carry
those facts to their renderers, so Designer acronym registrations cannot change the output. has_many expansion
derives its singular method stem from that snapshot, including Rails' empty-stem _ids edge case for the valid key
s; exact Core extraction verifies that derived name is unoccupied.
A separate immutable named-scope registry records the exact 707 lower-snake names rejected by Rails 8.1.3.1 when
defining a scope under the maximal supported Account, Policy, and State Machine dependency union. Exact Ruby 4.0.5
historical boots combine the pinned Core source with the checksummed three-contributor overlay, enumerate every
inherited visibility of the ActiveRecord::Base singleton and ActiveRecord::Relation instance namespaces plus
Rails' RESTRICTED_CLASS_METHODS, then apply Rails' two live scope predicates over that complete union. The
checked-in decision combines 483 dangerous model class-method names and 338 occupied Relation names with 114 overlaps;
the reproducibility report retains both source sets and all three environment boots independently. Frozen extraction
provenance remains bound to its original Core/overlay tuple. Current-pin compatibility instead verifies the active
Core revision, maximal dependency universe, and exact vendored Bundler projector package as one Compiler-owned tuple;
it neither follows an active overlay nor falls back to an ambient Bundler.
The current maximal universe also loads StripAttributes 2.0.1. Its raw namespace census is verified before reconciling
the single strip_attributes contribution with the unchanged base registries. The optional contribution remains
separately qualified; it is not a global rejection in applications without trim. Action Policy 0.7.6 contributes
policy_cache_key, policy_class, and policy_name to the Relation namespace, so a Core-only or current Designer
boot is an incomplete oracle. Predicate and Ordering lowering consult the frozen profile namespace, then the Entity's
selected-dependency availability check. Neither reads the Designer's loaded Active Record classes. These target
occupancy checks are separate from collisions among scopes generated for the same Entity; host-runtime changes cannot
alter Compilation.
Top-level constants
A separate immutable registry records 292 direct Object-table occupants whose names match the
/\A[A-Z][A-Za-z0-9]*\z/ shape emitted from current Plan keys, across the supported generated-app boot, application
test/support, migration-definition, job-CLI prelude, server, successful root-request, Rake/asset-precompile, console,
runner, and generator processes. Constants inherited from Object's ancestors and names the profile cannot emit are
outside this direct-namespace registry. Fresh filesystem-isolated processes reproduce the exact union and per-process
counts on both arm64-darwin and x86_64-linux whenever census inputs change; the replaceable Core application
module is excluded so the Project's actual module remains a dynamic claim. Core-only qualification directories omitted
by the Compiler are also removed from the disposable census source. Those fixtures cannot reserve Domain names;
ordinary Core CI continues to run them against its complete registry. This Core-process census includes both classes
and modules, but does not load the optional normalization gem. Its StripAttributes module is qualified separately
when selecting trim, as Text normalization describes.
A fixed two-query immutable input graph retains the Application key and every Entity's naming identity, canonical source pointer, target/profile provenance, and Project generation. Its pure builder produces the same value from the sealed Compiler Project graph without SQL. The Application remains a UUID-less document root. A pure Analyzer derives 108 Application, Entity, and create-table migration claims from those 57 authored identities through the pinned inflector and compares them with the 292 direct target occupants and one another. An Entity constant is camelized from its canonical model-file stem so the admitted constant is exactly the one Zeitwerk expects from the emitted path. Reserved target occupancy takes precedence over a Project-local collision on the same constant; each diagnostic retains every source location and an Entity subject UUID when one is available. All six design-and-parity Plans have no top-level constant collisions. The current Analyzer still reports a generated-name collision as a blocking Rails target diagnostic. The product direction instead treats it as a target-support gap whenever all collision participants and their dependents can be omitted deterministically; no participant wins arbitrarily. This blocking behavior is an implementation exception, not structural invalidity in the submitted JSON or a target policy to extend.
Model method families
The dangerous-method set follows Rails' dangerous_attribute_method? policy. Rails-target Association-family
resolution consumes the four ordinary method families. Their secondary methods occupy the model namespace even
though Rails checks only the bare Association name. Polymorphic as: declarations use the plain has_one and
has_many families because they change no method names; only polymorphic belongs_to needs its own family,
because Rails omits its constructors. The Plan cannot request Association validate: or autosave: options, so
only the default families are admitted. Supporting such an option must first select an option-qualified family,
or the Analyzer would underclaim the generated validation or autosave helpers.
A fixed nine-query immutable input graph combines every Association with every Field, preserving each Field's kind
and, for an aggregate derivation, its operation and exact Association and Field sources.
It also marks the Account Entity. Those facts let later analysis remain incomplete instead of pretending every Field
generates the ordinary 21-method attribute family. A pure profile selector returns complete 21-method signatures only
for 11 ordinary stored scalar kinds. Counter, enum, position, and State Machine Fields retain those 21 known attribute
methods with partial coverage. Attachment, image, money, rich-text, secure-token, and aggregate-derived Fields retain
only their semantic reader with partial coverage. A target-unknown Field kind or derivation operation remains
explicitly unsupported with no claimed method.
The same pure graph builder consumes the sealed Compiler Project graph without further SQL. A pure whole-Project Analyzer now combines those signatures with Association-family resolution, exact Reference storage, and the Account marker. It compares those claims within each Entity against one another and the frozen target occupants, and reports source-addressed reserved or generated collisions. Plans that use specialized-Field, aggregate, exclusive-arc, or general Account method families remain explicitly unresolved rather than admitted, because those families are incomplete. The isolated Account qualifier separately checks its fixed Rodauth runtime members without making those broader Plans publicly admissible. This describes complete collision-proof coverage in the current Analyzer; incomplete method-family knowledge does not by itself bar a bootable partial.
A pure Reference storage resolver derives each Reference's physical columns: ordinary <key>_id, polymorphic
<key>_id and <key>_type, or one exclusive-arc <target-entity-key>_id per closed target. Those columns
contribute their known Active Record attribute methods.
Resolution is query-free, ignores authored aliases, propagates upstream blocking without duplicate diagnostics, and
rejects overlaps within one exclusive arc before method provenance can be collapsed. Arc columns intentionally use
only target Entity keys; conflicts across different References wait for the whole-Project union.
The Analyzer merges the resulting attribute methods into their existing Reference claims, propagates stage-local
blocking without another diagnostic, and catches conflicts between every unblocked claim and the other Project
claims or target occupants in its Entity.
Exclusive-arc diagnostics retain the target Entity keys that named contributing columns. Account members outside the
public Field-only or private qualification paths, derived-Field support columns, complete specialized Field method
families, and generalized PostgreSQL identifier-length admission remain open; see its source and
provenance (repository-only).
Ruby bindings
Public Rails names remain conventional. Public index record scopes and one-hop Reference-option maps allocate their
compiler-private bindings. The mutation index declares its unparenthesized link_to helper; its remaining helpers are
parenthesized or use _path-suffixed names that cannot equal the unsuffixed record binding. Scoped creation allocates
its private parent record, collection path, and optional form URL with the child's instance-variable name already
occupied. The existing target-profile allocator moves only a conflicting helper: @parent_record becomes
@the_parent_record when the child is Parent Record; Collection Path and Form URL receive the same treatment. Their
public model and parameter names stay unchanged. Other generated Scaffold scopes use fixed compiler-private locals.
Generalized Scaffold output fixes the reserved case binding as case_record, so it emits @cases.each do |case_record| while preserving public Case, CasesController, /cases, @case, :case, case_path,
params.expect(case: ...), scope: :case, and the cases table unchanged. The retained legacy public-index and
private Policy-gate allocator claims candidates in order, prefixing the_ while a name is one of this profile's 35
frozen lower-snake Ruby keywords or is already claimed. There, movie remains movie, Case uses the_case, and a
helper already named the_case becomes the_the_case. An Entity named Descriptor still claims descriptor; a
same-scope helper becomes the_descriptor. The mutation index reserves its unparenthesized link_to helper, so
Entity LinkTo uses the_link_to only for that record binding. This does not weaken separate top-level constant or
model-member analysis: target-occupied constants such as Class, Module, and Thread remain Rails target gaps and
cannot be emitted under those constants. They are not invalid Foundation Plan Entity names; omit or partially generate
affected output unless no bootable residual exists. The target-pinned keyword set is runtime authority; Rails'
ActiveSupport::Delegation::RUBY_RESERVED_KEYWORDS is only a pinned-version test oracle. Controller-owned Redirects
and Cancel links no longer allocate shared return_to or cancel_to instance variables.
Routes and navigation names
The profile carries 44 immutable normalized route claims reproduced from the Compiler's route defaults and active Core
runtime: all 44 development routes and the same 36-route subset in test and production. A direct cross-platform census
and the active-package compatibility wrapper both verify this committed active-pin snapshot; they are complementary
code paths over one archive, not an independent historical baseline. Each claim retains nullable helper and
controller/action names, sorted request methods, the Journey path specification and regexp, environment membership,
and whether it precedes the application declarations. This includes internal Action Cable, development Rails and
Action Mailer routes, the target defaults, and the later Turbo Native, Action Mailbox, Active Storage, and development
welcome routes without retaining live Rails route objects.
The cross-platform profile workflow reproduces the canonical registry and its logical SHA-256 from fresh archive
extractions; TARGET_ROUTE_CLAIMS_LOGICAL_SHA256 in the profile (repository-only) pins that digest.
Pure profile transforms derive an Entity's resource helper, member helper, literal collection and member paths,
controller key, and controller class through the same pinned pluralization (person becomes people, /people, and
PeopleController). Rails' uncountable-resource convention is retained: series produces the series_index
collection helper, /series path, and SeriesController. The pinned English rules also pluralize authored display
names for shared web and native navigation labels, including Movies, People, HOAs, and Cafés.
Pure whole-Project Analyzers consume the public-index surface, bounded mutation route claims, and same-generation
top-level constant analysis. The base mutation shape expands index, new, create, edit, and update to their
exact helpers, request methods, sample paths, and shared controller. Its only show-bearing extension inserts the
member GET claim immediately after index. Every generated helper is checked against target helpers and generated peers
regardless of verb. Generated paths are checked against target routes with an overlapping method that precede the
application declarations. Generated controllers are checked against target occupants, all Project constant claims, and
generated peers. Results carry exact Project-generation and target provenance, retain every derived claim, and report
collisions at each claim's actual authored resource-route pointer with other authored claim locations attached.
term, page, person, series, and the person plus people pair pin the singular, plural, irregular,
uncountable, target, and generated boundaries. A separate new_movie Entity pins the cross-Entity collision between
its member helper and Movie's new_movie collection action. Controller collisions use the established top-level
constant collision codes because controllers and models occupy the same Ruby namespace; the resource-route pointer
distinguishes the controller claim. Analysis does not itself activate routes.
Model helper allocation
A Compiler-owned registry separates instance and class names. It includes emitted attribute and Association families,
Account members, AASM's selected methods, authored scopes, and enum mapping methods. No registry or runtime
interception machinery enters the generated application. A single enum normally keeps Rails' plain predicates, bang
methods, and positive and negative scopes. Two enums sharing draft both receive prefix: true; a valid enum value
is prefixed to preserve Rails' valid?. present and blank preserve record presence semantics, and id follows
Rails' enum-specific scope prohibition. Class scopes preserve the same required Object protocols: an enum value send
needs a prefix because Rails' enum macro itself calls Model.send while defining the remaining helpers. The class
footprint also protects class, clone, extend, freeze, hash, and singleton_class for class identity, query
cloning, extension, caching, and scope declaration; pinned scope construction uses
singleton_class and clones the current Relation, so a delegated enum scope named clone recurses. It also protects
const_set, define_method, instance_method, module_eval, and ruby2_keywords, which AASM 6.0.0's declaration
code uses, and to_s, by which its machine store keys models. Native bypass helpers
remain available, so their former removal no longer reserves undef_method. If the Field prefix also collides, the
Compiler tries suffix: true, then a numbered Field prefix. Each choice checks the complete method family. Allocation
uses sorted Field keys, so it does not depend on render order. AASM retains its existing ordinary-or-Field-namespace
choice; enums allocate around its final API. Private Validation methods allocate last, using readable paths such as
validate_not_self and title_present_when_released_condition?. A numeric suffix resolves an actual collision with
an emitted member. These are library-native declarations and ordinary private methods; no LLM participates in
Compilation. Rails' enum
implementation detects dangerous
and sibling-enum names, but does not inventory every authored attribute or other library's API. The Compiler supplies
that cross-feature knowledge. Ruby redefinition warnings and syntax linters do not reliably detect overriding a method
from an included module, so generated runtime tests remain the verification boundary. Rails enum prefixes cannot
rename the plural mapping method. An unresolvable mapping collision retains the existing Field gap, preserving
authored query names instead of replacing the enum with a different feature. AASM's fixed-API or unresolved dynamic
collisions likewise retain storage and a behavior gap.
Target-owned tables
The first bounded Domain renderer currently rejects exact collisions with Active Record 8.1.3.1's schema_migrations
and ar_internal_metadata tables and with the 13 tables in the pinned Core schema. These are exact target facts, not
reserved prefixes. That whole-Project rejection is an implementation exception; the intended outcome omits the
affected Entity and dependents and lists exact gaps. Future target-owned migrations must extend the audited registry.
Admission and collisions
Before task enumeration, this slice builds the existing top-level-constant and model-instance-member analysis inputs from the sealed Project and applies their pinned target results. Top-level admission covers the Application module, Entity class, and generated create-table migration class. Current analyzers block emission for reserved Ruby, Rails, and Core constants, generated-constant collisions, reserved Active Record members, generated-member collisions, overlong table or Field-column identifiers, and target-owned table names. Those whole-Project outcomes are implementation exceptions: the intended result omits every affected subject and dependent and lists exact gaps whenever a deterministic residual remains. Reference columns follow that omission rule already. Index names use the pinned Active Record 8.1 deterministic SHA-256 fallback when their descriptive name exceeds 62 bytes. No transform truncates or silently rewrites authored keys.
Current naming analyzers still block on generated Entity identifiers over the PostgreSQL limit, target-owned table collisions, and reserved Rails member names. These are the implementation exceptions described above, not structural Plan failures. Like an overlong Reference foreign key, the intended result omits each affected subject and dependent and lists the exact target gaps.