Dan Tappin
Dan Tappin

Reputation: 3032

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.

Upvotes: 12

Views: 2217

Answers (3)

Matouš Bor&#225;k
Matouš Bor&#225;k

Reputation: 15934

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.

Upvotes: 3

nikolayp
nikolayp

Reputation: 17919

Try to specify a foregein_key in model PipelineSpec to pipelines_id

class PipelineSpec < ActiveRecord::Base
  belongs_to :pipeline, foreign_key: :pipelines_id
end

Upvotes: 0

lei liu
lei liu

Reputation: 2775

I think that because the migration you deleted did't run on test environment, try reset the test database by:

RAILS_ENV=test rake db:migrate:reset

Upvotes: 0

Related Questions