Repository navigation
Generate model-aware fixtures - #116
Conversation
3cb10a2 to
e0e3f4e
Compare
52af7ba to
2de7c3f
Compare
2de7c3f to
d53a416
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Non-isolated fixture loading currently fails, and custom-primary-key models lose explicit fixture labels.
2 open findings
What changed in this PR
Adds model-aware fixture generation while preserving raw SQL fallback for ineligible tables.
Changes:
- Resolves eligible Active Record models by table name, pool, and primary key.
- Emits Rails
_fixture.model_classmetadata and detects ambiguous models. - Reorganizes and expands isolated fixture-generation tests.
| File | Description |
|---|---|
lib/fixture_builder/model_resolver.rb |
Implements model resolution. |
lib/fixture_builder/ambiguous_model_error.rb |
Adds deterministic ambiguity errors. |
lib/fixture_builder/builder.rb |
Generates model-aware fixtures and metadata. |
lib/fixture_builder.rb |
Loads the new error type. |
fixture_builder.gemspec |
Adds with_model for tests. |
README.md |
Documents model-aware fixtures. |
CHANGELOG.md |
Records the new behavior. |
doc/plans/2026-08-29-maintainer-backlog-triage.md |
Updates implementation plans. |
test/test_helper.rb |
Adds isolated fixture filesystem support. |
test/support/test_database.rb |
Reuses and resets the shared database. |
test/support/model_resolver_ambiguity_behavior.rb |
Shares ambiguity assertions. |
test/fixture_builder_test.rb |
Retains public API integration coverage. |
test/fixtures_path_test.rb |
Extracts fixture-path tests. |
test/configuration_test.rb |
Extracts configuration tests. |
test/configuration/manifest_test.rb |
Isolates manifest coverage. |
test/configuration/generated_file_marker_test.rb |
Reuses the shared connection. |
test/configuration/fixture_output_digest_test.rb |
Uses an ephemeral model. |
test/configuration/factories_test.rb |
Avoids dumping unrelated tables. |
test/builder/table_name_test.rb |
Covers configured table names. |
test/builder/serialization_test.rb |
Covers model serialization. |
test/builder/raw_sql_test.rb |
Covers raw SQL fallback. |
test/builder/metadata_test.rb |
Covers Rails fixture metadata. |
test/builder/generated_fixture_ownership_test.rb |
Preserves the connection pool. |
test/builder/generated_columns_test.rb |
Covers generated model columns. |
test/model_resolver/table_name_test.rb |
Tests model-backed versus raw extraction. |
test/model_resolver/sti_test.rb |
Tests STI root resolution. |
test/model_resolver/selection_test.rb |
Tests resolver eligibility rules. |
test/model_resolver/ambiguous_model_error_test.rb |
Tests error attributes and ordering. |
test/model_resolver/ambiguity/alphabetical_definition_order_test.rb |
Tests ambiguity ordering. |
test/model_resolver/ambiguity/reverse_alphabetical_definition_order_test.rb |
Tests reverse definition ordering. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| fixture_set.create_fixtures(fixture_directory, table_names, {}, &block) | ||
| end | ||
| else | ||
| fixture_set.create_fixtures(test_path("fixtures"), table_names, {}, &block) | ||
| fixture_set.create_fixtures(fixture_directory, table_names, {}, &block) |
There was a problem hiding this comment.
Not applicable: NamerTest loads its fixtures with ActiveRecord::FixtureSet.create_fixtures directly, not through this helper. Every caller of the create_fixtures helper (the generated-columns, metadata, raw SQL, and resolver selection tests) prepends IsolatedFixtureFilesystem, so fixture_directory is always defined.
| primary_keys = Array(model.primary_key).compact | ||
| primary_keys.any? && primary_keys.all? { |key| model.columns_hash.key?(key) } |
There was a problem hiding this comment.
Fixed in ce787cd. The namer now builds its keys from each table's primary key: name uses model_object.id, record_name takes the primary key column(s) from the builder (falling back to id for raw SQL tables), and populate_custom_names uses the fixture model's primary key. Values compare as strings, so typecast and raw values match and composite keys compare element by element. test/builder/primary_key_naming_test.rb covers a string primary key and a composite key; both lost their explicit names before the change.
d53a416 to
4059339
Compare
4059339 to
66189f1
Compare
add2531 to
ce787cd
Compare
ce787cd to
3b345fe
Compare


Fixture generation currently treats every configured table as raw SQL. That leaves Rails without enough model information to reload generated fixtures for models whose constants do not follow the conventional table-name inference.
This foundation resolves eligible Active Record models by their configured table names and writes Rails-native
_fixture.model_classmetadata for model-backed output. It preserves raw-SQL behavior when no eligible model is available, including tables without usable primary keys and models on another connection pool.It also organizes tests into one concrete case per file, with path-matching namespaces under
test/builder/,test/configuration/, andtest/model_resolver/. The top-leveltest/fixture_builder_test.rbretains integration coverage through the public API, and recursive discovery includes the nested suites. Isolated model-backed tests own their ephemeral schemas withwith_model. The development dependency requireswith_model2.5, whosetable(false)lets abstract models and models that map to an existing table skip creating an unused table of their own.This replaces the earlier draft stack in #112, #113, and #115, which are now closed. The dependent follow-up migrates the remaining ordinary fixture tests to the same ownership model.
The configuration tests added in #122 and #125 now use the same pattern: the fixture-output digest test declares its model with
with_model, and neither file opens its own in-memory connection. Opening one left laterwith_modeltests creating tables on a different connection than the one they queried.Models defined inside a migration class are ignored during resolution, so the throwaway models that data migrations define for the tables they backfill no longer tie with the application model and raise
AmbiguousModelError.Explicit fixture names now follow each model's primary key, including custom and composite keys. This also fixes an existing bug: records with UUID or other string
idvalues silently lost their explicit names, because the namer stored the name under the string id but looked it up withid.to_i.test/builder/primary_key_naming_test.rbcovers string, composite, and UUID keys.Closes #109
Closes #72
Closes #49
Closes #124
Closes #129