The Rails guides to active record migrations says that you can do
change_column_default :products, :approved, from: true, to: false
I've got a change
method in Rails that's similar to the following:
change_column_default :people, :height, from: nil, to: 0
with the intention of going from not having any defaults, to having a default of zero.
However, when I try rolling it back, I get
ActiveRecord::IrreversibleMigration: ActiveRecord::IrreversibleMigration
Considering I give Rails a from
and to
, why isn't it accepting it?
I'm using Rails 4.2.0.
Just to add a few points. If you are stuck with the Rails version not supporting reversible change_column_default, one option to get past the problem is:
As of Oct 2016, This feature (using
to:
andfrom:
forchange_column_default
to be reversible) is now available on the 5.x branch. Unfortunately it's not available 4.2.x or lower. :(Verification:
git tag --contains f9c841927ac3d1daea2a9cebf08b18e844e5eec5
in the rails project.First of all as Jonathan Allard said the
from
andto
are not in the method source which means that thechange_column_default
doesn't accepts it. It is simply like this:Now if you try and pass two variables to it like
sum(a, b)
or anything it will not accept that right. This what you are trying to do above usingfrom
andto
.Now the correct syntax of this is:
The method doesn't accepts
from
andto
(as it is defined as such, even if they are hash keys, if the method doesn't uses that key value pair anywhere then it is of no use to it) and if it is a new column the obviously it will have default valuenil
(if not set before) and suppose if the columnheight
if of typeinteger
and you give it default valuea
it will store0
as the default value (not 100% sure but have tried doing this from rails console). It doesn't matters to rails what the default value currently is, it just needs the new default value. So if the current default value be0
and you set it tonil
rails will not complaint. It is your database and you wish what to do with it. Just if the database interrupts it if you are doing something wrong like assigningstring
toboolean
then it will obviously throw error.Now once this migration has ran then it will set the default value to
0
now rails doesn't know what the previous default value was. As it is gone and it has not store that anywhere. So that is whychange_column_default
is a irreversible migration. And if you try to roll it back it gives youActiveRecord::IrreversibleMigration: ActiveRecord::IrreversibleMigration
in case ofchange
method. Means when you have used:So that is why for this kind of migrations we use the method
up
anddown
:Hope this helps.
When you try to downgrade the data type , from
value
(0) tonil
in this case , rails will complain this error. Because it might lose dataAnother example would be going from
string
->integer
.this is a really good article explain the same
UPDATE
It seems like your reverse migration calls
change_column_default
incommand_recorder
(activerecord-4.2.0/lib/active_record/migration/command_recorder.rb#76)
please check if you set thenil
as the default value.UPDATE2
it turns out that, if you use
change
in migrations, those have to be able to reversiblebut change_column is not reversible through
change
method. So you will have to use the old rails migration method withup
anddown
read this article explain the scenario
if you are using mysql as adapter, then according to this link http://apidock.com/rails/ActiveRecord/ConnectionAdapters/AbstractMysqlAdapter/change_column_default, your
change_column_default
migration runs like thisso as you see it calls
change_column
within itself when you callchange_column_default
and according to this link http://edgeguides.rubyonrails.org/active_record_migrations.htmlchange_column
migration is irreversible.This shows why you get
ActiveRecord::IrreversibleMigration: ActiveRecord::IrreversibleMigration
So if you want to run migration using
change_column_default
you have to adddef up
anddef down
.I would suggest to use change_column as it is already been called within change_column_default.
Using
from
andto
was added in Rails 5+The guide linked to in the question is for Edge Rails, not for a released version of Rails.
Reversible syntax for
change_column_default
is the result of pull request 20018. The pull request also updated the Rails guides for Edge Rails.From
activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
:The pull request was made June 27, 2015, which is more recent than any version of Rails released as of August 1, 2015.
The documentation for migration for Rails 4.2.3 reflects the fact that reversible syntax is not yet available: