如何在 Ruby on Rails 迁移中重命名数据库列?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1992019/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 22:05:58  来源:igfitidea点击:

How can I rename a database column in a Ruby on Rails migration?

ruby-on-railsruby-on-rails-3migrationrenamealter-table

提问by user1994764

I wrongly named a column hased_passwordinstead of hashed_password.

我错误地命名了一个列hased_password而不是hashed_password.

How do I update the database schema, using migration to rename this column?

如何更新数据库架构,使用迁移重命名此列?

回答by nowk

rename_column :table, :old_column, :new_column

You'll probably want to create a separate migration to do this. (Rename FixColumnNameas you will.):

您可能需要创建一个单独的迁移来执行此操作。(随意重命名FixColumnName。):

script/generate migration FixColumnName
# creates  db/migrate/xxxxxxxxxx_fix_column_name.rb

Then edit the migration to do your will:

然后编辑迁移以执行您的意愿:

# db/migrate/xxxxxxxxxx_fix_column_name.rb
class FixColumnName < ActiveRecord::Migration
  def self.up
    rename_column :table_name, :old_column, :new_column
  end

  def self.down
    # rename back if you need or do something else or do nothing
  end
end


For Rails 3.1 use:

对于 Rails 3.1 使用:

While, the upand downmethods still apply, Rails 3.1 receives a changemethod that "knows how to migrate your database and reverse it when the migration is rolled back without the need to write a separate down method".

虽然updown方法仍然适用,但Rails 3.1 收到了一种change方法,该方法“知道如何迁移数据库并在回滚迁移时将其反转,而无需编写单独的向下方法”。

See "Active Record Migrations" for more information.

有关更多信息,请参阅“活动记录迁移”。

rails g migration FixColumnName

class FixColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

If you happen to have a whole bunch of columns to rename, or something that would have required repeating the table name over and over again:

如果您碰巧有一大堆要重命名的列,或者需要一遍又一遍地重复表名的内容:

rename_column :table_name, :old_column1, :new_column1
rename_column :table_name, :old_column2, :new_column2
...

You could use change_tableto keep things a little neater:

你可以change_table用来让事情更整洁一点:

class FixColumnNames < ActiveRecord::Migration
  def change
    change_table :table_name do |t|
      t.rename :old_column1, :new_column1
      t.rename :old_column2, :new_column2
      ...
    end
  end
end

Then just db:migrateas usual or however you go about your business.

然后就像db:migrate往常一样,或者不管你怎么做你的生意。



For Rails 4:

对于 Rails 4:

While creating a Migrationfor renaming a column, Rails 4 generates a changemethod instead of upand downas mentioned in the above section. The generated changemethod is:

在创建Migration用于重命名列的 a 时,Rails 4 生成了一个change方法,而不是上面部分中提到的updown。生成的change方法是:

$ > rails g migration ChangeColumnName

which will create a migration file similar to:

这将创建一个类似于以下内容的迁移文件:

class ChangeColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

回答by elf.xf

In my opinion, in this case, it's better to use rake db:rollback, then edit your migration and again run rake db:migrate.

在我看来,在这种情况下,最好使用rake db:rollback,然后编辑您的迁移并再次运行rake db:migrate

However, if you have data in the column you don't want to lose, then use rename_column.

但是,如果您不想丢失列中的数据,请使用rename_column.

回答by Paul Pettengill

If the column is already populated with data and live in production, I'd recommend a step by step approach, so as to avoid downtime in production while waiting for the migrations.

如果该列已经填充了数据并在生产中使用,我建议采用分步方法,以避免在等待迁移时生产停机。

First I'd create a db migration to add columns with the new name(s) and populate them with the values from the old column name.

首先,我会创建一个数据库迁移来添加具有新名称的列,并使用旧列名称中的值填充它们。

class AddCorrectColumnNames < ActiveRecord::Migration
  def up
    add_column :table, :correct_name_column_one, :string
    add_column :table, :correct_name_column_two, :string

    puts 'Updating correctly named columns'
    execute "UPDATE table_name SET correct_name_column_one = old_name_column_one, correct_name_column_two = old_name_column_two"
    end
  end

  def down
    remove_column :table, :correct_name_column_one
    remove_column :table, :correct_name_column_two
  end
end

Then I'd commit just that change, and push the change into production.

然后我会提交那个更改,并将更改推送到生产中。

git commit -m 'adding columns with correct name'

Then once the commit has been pushed into production, I'd run.

然后一旦提交被推入生产,我就会运行。

Production $ bundle exec rake db:migrate

Then I'd update all of the views/controllers that referenced the old column name to the new column name. Run through my test suite, and commit just those changes. (After making sure it was working locally and passing all tests first!)

然后我会将所有引用旧列名的视图/控制器更新为新列名。运行我的测试套件,并仅提交这些更改。(在确保它在本地工作并首先通过所有测试之后!)

git commit -m 'using correct column name instead of old stinky bad column name'

Then I'd push that commit to production.

然后我会将该承诺推向生产。

At this point you can remove the original column without worrying about any sort of downtime associated with the migration itself.

此时,您可以删除原始列,而不必担心与迁移本身相关的任何类型的停机时间。

class RemoveBadColumnNames < ActiveRecord::Migration
  def up
    remove_column :table, :old_name_column_one
    remove_column :table, :old_name_column_two
  end

  def down
    add_column :table, :old_name_column_one, :string
    add_column :table, :old_name_column_two, :string
  end
end

Then push this latest migration to production and run bundle exec rake db:migratein the background.

然后将此最新迁移推送到生产并bundle exec rake db:migrate在后台运行。

I realize this is a bit more involved of a process, but I'd rather do this than have issues with my production migration.

我意识到这涉及更多的过程,但我宁愿这样做也不愿在我的生产迁移中遇到问题。

回答by James Manning

http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

Under Available Transformations

在下面 Available Transformations

rename_column(table_name, column_name, new_column_name):

rename_column(table_name, column_name, new_column_name):

Renames a column but keeps the type and content.

重命名列但保留类型和内容。

回答by Shoaib Malik

Run the below command to create a migration file:

运行以下命令以创建迁移文件:

rails g migration ChangeHasedPasswordToHashedPassword

Then in the file generated in the db/migratefolder, write rename_columnas below:

然后在文件db/migrate夹中生成的文件中,写入rename_column如下:

class ChangeOldCoulmnToNewColumn < ActiveRecord::Migration
  def change
     rename_column :table_name, :hased_password, :hashed_password
  end
end

回答by super_p

From API:

来自API:

rename_column(table_name, column_name, new_column_name)

It renames a column but keeps the type and content remains same.

它重命名列但保持类型和内容保持不变。

回答by uma

Some versions of Ruby on Rails support to up/down method to migration and if you have up/down method in your migration, then:

某些版本的 Ruby on Rails 支持向上/向下迁移方法,如果您在迁移中有向上/向下方法,则:

def up
    rename_column :table_name, :column_old_name, :column_new_name
end

def down
    rename_column :table_name, :column_new_name, :column_old_name
end

If you have the changemethod in your migration, then:

如果您change的迁移中有该方法,则:

def change
    rename_column :table_name, :column_old_name, :column_new_name
end

For more information you can move: Ruby on Rails - Migrationsor Active Record Migrations.

有关更多信息,您可以移动:Ruby on Rails - MigrationsActive Record Migrations

回答by sunil

If your code is not shared with other one, then best option is to do just rake db:rollbackthen edit your column name in migration and rake db:migrate. Thats it

如果您的代码不与其他人共享,那么最好的选择是rake db:rollback在迁移和rake db:migrate. 就是这样

And you can write another migration to rename the column

您可以编写另一个迁移来重命名列

 def change
    rename_column :table_name, :old_name, :new_name
  end

Thats it.

就是这样。

回答by Steven Garcia

As an alternative option, if you are not married to the idea of migrations, there is a compelling gem for ActiveRecord which will handle the name changes automatically for you, Datamapper style. All you do is change the column name in your model (and make sure you put Model.auto_upgrade!at the bottom of your model.rb) and viola! Database is updated on the fly.

作为另一种选择,如果您不接受迁移的想法,那么 ActiveRecord 有一个引人注目的 gem,它将自动为您处理名称更改,Datamapper 风格。您所做的就是更改模型中的列名称(并确保将Model.auto_upgrade!放在model.rb的底部)和中提琴!数据库是动态更新的。

https://github.com/DAddYE/mini_record

https://github.com/DAddYE/mini_record

Note: You will need to nuke db/schema.rbto prevent conflicts

注意:您需要核对db/schema.rb以防止冲突

Still in beta phases and obviously not for everyone but still a compelling choice (I am currently using it in two non-trivial production apps with no issues)

仍处于测试阶段,显然不适合所有人,但仍然是一个引人注目的选择(我目前在两个非平凡的生产应用程序中使用它,没有任何问题)

回答by Abram

If you need to switch column names you will need to create a placeholder to avoid a duplicate column name error. Here's an example:

如果您需要切换列名,您将需要创建一个占位符以避免出现重复的列名错误。下面是一个例子:

class SwitchColumns < ActiveRecord::Migration
  def change
    rename_column :column_name, :x, :holder
    rename_column :column_name, :y, :x
    rename_column :column_name, :holder, :y
  end
end