Migrate old instructions column - #981
Conversation
Previously, projects created before instruction_steps existed only had their instructions stored in the legacy text column, so Project#instructions had to fall back to it at read time. This change adds a data migration that copies the legacy instructions value into instruction_steps for any row where instruction_steps is still null, so every project can be read from instruction_steps alone. This is a step toward removing the instructions column entirely.
Previously, Project#instructions fell back to the legacy text column for rows written before instruction_steps existed, and the setter kept writing that column too. Now that instruction_steps has been backfilled for every project, that fallback is unnecessary and would break once the column is dropped. This change marks instructions as an ignored column and simplifies the instructions accessor and mutator to delegate directly to instruction_steps, removing the last runtime dependency on the legacy column so it can be safely dropped in a follow-up migration.
Test coverage93.43% line coverage reported by SimpleCov. |
There was a problem hiding this comment.
Pull request overview
This PR migrates legacy projects.instructions (text) into the newer projects.instruction_steps (jsonb) and updates the Project model to stop reading/writing the legacy column, preparing for dropping it in a later deploy.
Changes:
- Add a data migration to backfill
instruction_stepsfrom the legacyinstructionscolumn. - Update
Projectto ignore the legacyinstructionscolumn and makeinstructions/instructions=delegate toinstruction_steps. - Simplify the
Project#instructionsmodel spec to only validate delegation toinstruction_steps.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| app/models/project.rb | Ignores the legacy instructions column and delegates instructions accessors to instruction_steps. |
| db/migrate/20260825144345_backfill_instruction_steps_from_instructions.rb | Backfills instruction_steps from instructions for existing rows. |
| db/schema.rb | Updates schema version after adding the migration. |
| spec/models/project_spec.rb | Updates model tests to reflect the new delegation-only behavior. |
Suppressed comments (1)
db/migrate/20260825144345_backfill_instruction_steps_from_instructions.rb:13
downis currently a no-op, so rolling back this migration would report success while leaving data changed. If the backfill can’t be safely reversed, it should explicitly raiseActiveRecord::IrreversibleMigrationto avoid a misleading rollback.
def down
end
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| execute <<~SQL.squish | ||
| UPDATE projects | ||
| SET instruction_steps = to_jsonb(instructions) | ||
| WHERE instruction_steps IS NULL AND instructions IS NOT NULL | ||
| SQL |
There was a problem hiding this comment.
I'm going to be bold and try to run this as I expect the migration to run within a few seconds.
Status
What's changed?
This is tidy up after introducing instruction Steps to migrate all data into a single column.
By adding
instructionsto ignored columns tests will fail if anything is accessing it and we can later drop the old column in another deploy.Note that instruction steps is a JSONB column, that might contain an array of instruction objects, or a single string. Currently editor-ui handles these different formats. We could later do another migration to wrap the strings into an array which would allow us to simplify the frontend.