不可逆转的移民,可以修复吗? - Rails 4

时间:2015-08-07 00:39:55

标签: ruby-on-rails ruby heroku

所以我做了这样的迁移

class AddDatetimeAttrToUsers < ActiveRecord::Migration
  def change
    change_column :users, :oauth_expires_at, :datetime
  end
end

在我的本地环境中它工作得很好但是当我尝试

heroku run rake db:migrate我收到错误

ERROR:  column "oauth_expires_at" cannot be cast automatically to type timestamp without time zone
HINT:  Specify a USING expression to perform the conversion.

当我搜索它时,我创建了一个新的迁移,这是使用更改更改属性的最佳做法。

class PutDatetimeFieldToUsersExpireAtColumn < ActiveRecord::Migration
  def change
    remove_column :users, :oauth_expires_at
    add_column :users, :oauth_expires_at, :datetime
  end
end

所以我尝试使用rake db:rollback来删除上次迁移并添加这个,告知我上次迁移是不可逆转的。

我的问题是,有没有办法实际回滚不可逆转的迁移,还是应该使用上面的新迁移进行迁移?

4 个答案:

答案 0 :(得分:1)

您可以在迁移中定义updown方法,而不是change。 这是一个例子:

def up
  connection.execute %(create or replace view name_of_the_db_view)
end

def down
  connection.execute %(drop view name_of_the_db_view)
end

有了它,您就可以migraterollback之前不可逆转的迁移,就像正常迁移一样。

答案 1 :(得分:0)

似乎你需要指定当前类型的oauth_expires_at列,因为在回滚时Rails应该知道它来创建列。我的意思是:

remove_column :users, :oauth_expires_at, :string

答案 2 :(得分:0)

在您的示例中,您具有以下迁移文件:

class AddDatetimeAttrToUsers < ActiveRecord::Migration
  def change
    change_column :users, :oauth_expires_at, :datetime
  end
end

您已经在开发环境中成功运行rake db:migrate。您正在本地运行sqlite3,并在heroku上运行了PG,因此,您的change_column在本地运行,但是在PG上失败,因为PG期望使用'using'语句。

此问题的解决方法,步骤1是编辑迁移文件,以按照上述Yohann的建议添加上下迁移。是的,即使您已经完成了此迁移,也应该这样做。

class AddDatetimeAttrToUsers < ActiveRecord::Migration
      def up
        change_column :users, :oauth_expires_at, :datetime
      end
      def down
        change_column :users, :oauth_expires_at, :time (or whatever type existed before datetime)
      end
    end

现在,您可以运行rake db:rollback并避免不可逆的迁移错误,但前提是您没有附加的迁移。如果添加了其他迁移,则需要使用rake db:down VERSION=2018xxxxxxxrake db:rollback STEP=X指定要返回的距离。

现在编辑迁移,使其与pg和sqlite3配合使用:

class AddDatetimeAttrToUsers < ActiveRecord::Migration
          def up
            change_column :users, :oauth_expires_at, :datetime, using: 'oauth_expires_at::datetime'
          end
          def down
            change_column :users, :oauth_expires_at, :time

        end

现在,您应该能够耙db:migrate,推送到heroku,并且heroku运行rake db:migrate并继续前进。

最后,您应该让pg在本地工作以匹配您的生产环境。

答案 3 :(得分:-1)

如果您敢于丢失本地数据库中的数据,那么您可以通过以下步骤从不可逆转的迁移中恢复(通过丢失数据库数据):

1-首先删除您的数据库(假设您在开发环境中并且可以在此环境中删除数据库 - 您的测试数据库也将消失)

export RAILS_ENV=development


rake db:drop

2-重新加载模式文件:

rake db:schema:load

3-查看当前的迁移文件:

rake db:migrate:status

4-删除您要删除的迁移:

rake db:migrate:down VERSION=xxxxxx


rails destroy migration migration_name

5-然后,您可以使db:migrate迁移迁移。

rake db:migrate