ActiveRecord::Migration deprecation warning - asks for Rails version, but I'm not using Rails
Asked Answered
A

2

13

This is a Ruby non-web project that uses ActiveRecord to talk to the database.

There is a single file which contains the db connection code, migration, and model. See here (but it's not necessary to read this to answer the question)

require 'sqlite3'
require 'active_record'
require 'yaml'
require 'active_support/all'
require 'securerandom'

BasePath = "#{File.dirname(__FILE__)}/.."
DATABASE_FILENAME = "database.sqlite"
DATABASE_PATH = "#{BasePath}/#{DATABASE_FILENAME}"
SQLite3::Database.new(DATABASE_PATH)
ActiveRecord::Base.establish_connection(
  adapter: 'sqlite3',
  database: DATABASE_PATH
)

class Migrations < ActiveRecord::Migration
  def up
    create_table :todos do |t|
      t.string :content
      t.boolean :completed
      t.timestamps null: false
    end
  end
  def down
    puts "backing up database".red_on_black if File.file?(DATABASE_PATH)
    loop { (`cp #{DATABASE_PATH} #{DATABASE_PATH}-#{SecureRandom.urlsafe_base64}.backup`; break) rescue next }
    sleep 0.5
    drop_table :todos
    puts "dropped todos table"
  end
end # Migrations

class Todo < ActiveRecord::Base
end

The question is about this line:

class Migrations < ActiveRecord::Migration

When I run the migration with Migrations.migrate(:up), I get a deprecation warning:

DEPRECATION WARNING: Directly inheriting from ActiveRecord::Migration is deprecated.
Please specify the Rails release the migration was written for:

  class Migrations < ActiveRecord::Migration[4.2]

Like it advises I change my class definition to

  class Migrations < ActiveRecord::Migration[4.2]

And then I no longer get the warning.

I'm wondering if anyone can explain the purpose of this.

My app doesn't depend on any version of Rails. Why would I need

to specify a Rails version?

Acetylide answered 11/3, 2016 at 0:11 Comment(0)
K
40

Because Active Record wants to know in which version the migrations were generated. Sometimes a default in a migration can change between Rails releases (when I say Rails releases I'm talking about the release of Rails the framework, not rails the gem).

So let's say you have a migration like:

create_table :todos do |t|
  t.string :content
end

And it was generated with Active Record 4.2 (and thus Rails 4.2 release). In Rails 4.2, strings columns have the default size of 4 bytes. In Rails 5.0, the Rails team decided to change the default size to 8 bytes. If you upgrade the gem to 5.0 rollback this migration and run again now your database will have a string column with 8 bytes of size.

If you specify the version in the migration, no matter which version of Active Record you are using the column will always be generated with the size that were the default in the version of Rails that it was generated. In my example, if you specify 4.2 as the version it will be always a 4 bytes string column.

Keek answered 11/3, 2016 at 2:0 Comment(3)
Wow! @rafaelfranca! thanks for explaining here.. ;) +1Potty
That makes sense though it is confusing for people who are using AR outside of rails.Babism
@Keek Any advice on how gem maintainers can update auto-generated migration scripts to support both rails 4.1 and older, and the new Rails migration version API? The solutions I've used for this are hacky. E.g.: if Rails::VERSION::STRING[0..2].to_f >= 5 active_record_migration_class = ActiveRecord::Migration[Rails::VERSION::STRING[0..2].to_f] else active_record_migration_class = ActiveRecord::Migration end Is there something more elegant?Eulau
W
3

If upgrading from rails 4 to rails 5, you can just add the version number to the migration like so after rollback or drop:

Rails 4.2.6

class CreateStudents < ActiveRecord::Migration
  def change
    create_table :students do |t|
      t.belongs_to :user, index: true
      t.string :first_name
      t.string :last_name
      t.string :phone
      t.timestamps null: false
    end
  end
end

Rails 5.1.3

class CreateStudents < ActiveRecord::Migration[5.1]
  def change
    create_table :students do |t|
      t.belongs_to :user, index: true
      t.string :first_name
      t.string :last_name
      t.string :phone
      t.timestamps null: false
    end
  end
end
Washko answered 10/8, 2017 at 14:26 Comment(1)
Thank you. I was running into this error, and just added the version at the end and it cleared the error. Though, in my case I had to add [4.2] at the end, even though I am running Rails 5.1.4.Gnathous

© 2022 - 2024 — McMap. All rights reserved.