diff --git a/app/models/project.rb b/app/models/project.rb index 8315c3700..8375d1203 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Project < ApplicationRecord + self.ignored_columns += [:instructions] + module Types PYTHON = 'python' HTML = 'html' @@ -83,12 +85,11 @@ def scratch_component=(value) end def instructions - self[:instruction_steps].nil? ? self[:instructions] : self[:instruction_steps] + instruction_steps end def instructions=(value) - self[:instructions] = value unless value.is_a?(Array) - self[:instruction_steps] = value + self.instruction_steps = value end def last_edited_at diff --git a/db/migrate/20260825144345_backfill_instruction_steps_from_instructions.rb b/db/migrate/20260825144345_backfill_instruction_steps_from_instructions.rb new file mode 100644 index 000000000..d188887dd --- /dev/null +++ b/db/migrate/20260825144345_backfill_instruction_steps_from_instructions.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class BackfillInstructionStepsFromInstructions < ActiveRecord::Migration[8.1] + def up + execute <<~SQL.squish + UPDATE projects + SET instruction_steps = to_jsonb(instructions) + WHERE instruction_steps IS NULL AND instructions IS NOT NULL + SQL + end + + def down + end +end diff --git a/db/schema.rb b/db/schema.rb index e21d13889..0b3d42f5f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.1].define(version: 2026_08_20_122510) do +ActiveRecord::Schema[8.1].define(version: 2026_08_25_144345) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" enable_extension "pgcrypto" diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index cbfe99353..0f27463f7 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -437,31 +437,12 @@ end describe '#instructions' do - let(:project) { create(:project, :with_instructions, school:, user_id: create(:teacher, school:).id) } + let(:project) { create(:project, school:, user_id: create(:teacher, school:).id) } - it 'falls back to the legacy text column for rows that predate instruction_steps' do - project.instruction_steps = nil - project.save! - expect(project.instructions).to eq(project[:instructions]) - end - - it 'returns instruction_steps once set, without touching the legacy column for arrays' do - legacy_value = project[:instructions] + it 'delegates to instruction_steps' do project.update!(instructions: [{ markdown_content: 'step 1' }]) expect(project.instructions).to eq([{ 'markdown_content' => 'step 1' }]) - expect(project[:instructions]).to eq(legacy_value) - end - - it 'does not fall back to stale legacy text once instruction_steps is set to an empty array' do - project.update!(instructions: []) - expect(project.instructions).to eq([]) - end - - it 'also clears the legacy column when instructions are set to nil' do - project.update!(instructions: [{ markdown_content: 'step 1' }]) - project.update!(instructions: nil) - expect(project.instructions).to be_nil - expect(project[:instructions]).to be_nil + expect(project.instruction_steps).to eq([{ 'markdown_content' => 'step 1' }]) end end