Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird Rails migration / schema.rb issue

A while back I ran the following migration:

class CreatePipelineSpecs < ActiveRecord::Migration
  def change
    create_table :pipeline_specs do |t|
      t.integer :id_no
      t.string :od
      t.string :wt
      t.string :material
      t.string :spec_type
      t.string :spec_grade
      t.string :mop
      t.string :stress_level
      t.string :joints
      t.text :notes
      t.string :ip
      t.references :pipeline, index: true, foreign_key: false

      t.timestamps null: false
    end
    add_index :pipeline_specs, :id_no
  end
end

I am not sure what has happened now but every time I run rake db:migrate the scheme.rb file gets updated with:

  create_table "pipeline_specs", force: :cascade do |t|
    t.integer  "id_no"
    t.string   "od"
    t.string   "wt"
    t.string   "material"
    t.string   "spec_type"
    t.string   "spec_grade"
    t.string   "mop"
    t.string   "stress_level"
    t.string   "joints"
    t.text     "notes"
    t.string   "ip"
    t.integer  "pipelines_id"
    t.datetime "created_at",   null: false
    t.datetime "updated_at",   null: false
  end

  add_index "pipeline_specs", ["id_no"], name: "index_pipeline_specs_on_id_no", using: :btree
  add_index "pipeline_specs", ["pipelines_id"], name: "index_pipeline_specs_on_pipelines_id", using: :btree

Note the plural pipelines_id. The actual database tables (dev, production etc.) are all pipeline_id which is correct as the reference table is Pipeline. So I add a new unrelated migration and the schema.rb gets updated and these get changed back to plural again after I change them back. If I forget to change them when I run tests everything breaks as the wrong schema gets loaded into the test environment.

I am at a loss here. I am I missing something obvious here or is there some hidden migration schema table etc.

The only think I can this of is when I made the original migration I used pipelines:references vs pipeline:references, then fixed my mistake, and then cleaned up the migrations before committing this and deploying it.

Any ideas here one why this is happening and how to fix it once and for all?

UPDATE

Here are my three related models:

irb(main):031:0> Pipeline
=> Pipeline(id: integer, licence: string, company: string, company_id: integer, ba_code: string, substance_code: string, substance: string, h2s: string, partial_pressure: string, notes: text, created_at: datetime, updated_at: datetime, slug: string)
irb(main):032:0> PipelineSpec
=> PipelineSpec(id: integer, id_no: integer, od: string, wt: string, material: string, spec_type: string, spec_grade: string, mop: string, stress_level: string, joints: string, notes: text, ip: string, pipeline_id: integer, created_at: datetime, updated_at: datetime, slug: string)
irb(main):033:0> PipelineSegment
=> PipelineSegment(id: integer, line: integer, lsd_from: integer, sec_from: integer, twp_from: integer, rge_from: integer, m_from: integer, fc_from: string, lsd_to: integer, sec_to: integer, twp_to: integer, rge_to: integer, m_to: integer, fc_to: string, length: string, aasm_state: string, state_comment: string, state_user_id: integer, aasm_date: datetime, env: string, volume: string, notes: text, pipeline_id: integer, pipeline_spec_id: integer, created_at: datetime, updated_at: datetime, slug: string)

Pipeline has_many PipelineSpec and PipelineSegment. PipelineSegment has_one PipelineSpec.

UPDATE 2

Checked my test environment schema - it's fine. Ran rake db:migrate and again the schema.rb gets updated. Run the tests again and get gobs of:

ActiveRecord::StatementInvalid:         ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column "pipeline_id" of relation "pipeline_specs" does not exist
        LINE 1: ..., "mop", "stress_level", "joints", "notes", "ip", "pipeline_...
                                                                     ^
        : INSERT INTO "pipeline_specs" ("id", "id_no", "od", "wt", "material", "spec_type", "spec_grade", "mop", "stress_level", "joints", "notes", "ip", "pipeline_id", "created_at", "updated_at") VALUES (1, 1, '88.9', '3.18', 'S', 'Z245.1', '359 2', '9930', '25', 'W', 'MyText', 'U', 1, '2017-04-24 03:47:26', '2017-04-24 03:47:26')

as the fixtures try to load into the incorrect test schema that was just loaded at test time.

like image 457
Dan Tappin Avatar asked Apr 23 '17 07:04

Dan Tappin


People also ask

What is schema RB?

The schema. rb serves mainly two purposes: It documents the final current state of the database schema. Often, especially when you have more than a couple of migrations, it's hard to deduce the schema just from the migrations alone. With a present schema.

Can I delete migration files rails?

【Ruby on Rails】 When you want to delete a migration file you made, you can choose version and delete it. You don't need to execute rails db:rollback many times!

Are rails migrations run in a transaction?

On databases that support transactions with statements that change the schema, migrations are wrapped in a transaction. If the database does not support this then when a migration fails the parts of it that succeeded will not be rolled back. You will have to rollback the changes that were made by hand.


1 Answers

The schema is recreated from the actual state of your database after each migrations run. So I guess the pipelines_id must indeed exist somewhere in your db or at least Rails must think it exists in the db. I would do the following to narrow the issue down:

  • Run rake db:schema:dump SCHEMA=myschema.rb - this will generate a differently-named schema file manually. This is the same rake task that is also run after the migrations. I expect that the new schema will contain the plural pipelines_id column, too.

  • Then I'd take a look in the log/development.log (or whatever environment you are experiencing the issue in). You should see SELECT schema_migrations.* FROM schema_migrations and a bunch of further queries for showing structure of each table in your database there. Find the query that deals with the pipeline_specs table and run it manually in the db console to see what you precisely get. My expectation is that you'll either:

    • see the plural pipelines_ids there too - that would prove the column indeed exists in the db
    • or not - in which case I would restart everything I could in rails just to be sure there is no caching involved anywhere - specifically I'd restart spring with spring stop. Also I'd check (don't know Postgres that well to tell for sure) whether there might be any caching involved on the Postgres side. Then I'd try again.
like image 65
Matouš Borák Avatar answered Oct 02 '22 10:10

Matouš Borák