Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 609
max pleaner Avatar asked Mar 11 '16 00:03

max pleaner


2 Answers

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.

like image 170
rafaelfranca Avatar answered Oct 08 '22 06:10

rafaelfranca


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
like image 38
Ctpelnar1988 Avatar answered Oct 08 '22 05:10

Ctpelnar1988