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

use*_*764 1419 migration ruby-on-rails ruby-on-rails-3

我错误地将列命名hased_passwordhashed_password.

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

now*_*owk 2256

rename_column :table, :old_column, :new_column
Run Code Online (Sandbox Code Playgroud)

更新:

您可能希望创建单独的迁移来执行此操作.(按照您的意愿重命名FixColumnName)

script/generate migration FixColumnName
# creates  db/migrate/xxxxxxxxxx_fix_column_name.rb
Run Code Online (Sandbox Code Playgroud)

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

# 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
Run Code Online (Sandbox Code Playgroud)

Rails 3.1的更新

虽然,这些updown方法仍然适用.Rails 3.1接收一种change方法"知道如何迁移数据库并在回滚迁移时将其反转,而无需编写单独的down方法"

rails g migration FixColumnName

class FixColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end
Run Code Online (Sandbox Code Playgroud)

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

rename_column :table_name, :old_column1, :new_column1
rename_column :table_name, :old_column2, :new_column2
...
Run Code Online (Sandbox Code Playgroud)

你可以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
Run Code Online (Sandbox Code Playgroud)

谢谢你,Luke&& Turadg,提出这个主题.

然后db:migrate像往常一样,或者你开始做生意.


Rails 4的更新

在创建Migration作为用于重命名的列,轨道4生成change方法,而不是updown如在以上提到的答案.生成的change方法如下:

$ > rails g migration ChangeColumnName
Run Code Online (Sandbox Code Playgroud)

这将创建一个类似于此的迁移文件:

class ChangeColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end
Run Code Online (Sandbox Code Playgroud)

  • self.down应该*总是*与self.up相反,所以"如果你需要或做其他事情或什么都不做"并不是真的推荐.只需执行:rename_column:table_name,:new_column,:old_column (24认同)
  • 在Rails 3.1中,你可以用`def change`替换`def self.up`和`def self.down`,它会知道如何回滚. (23认同)
  • 重命名删除索引吗? (6认同)
  • 虽然恢复你在`self.up`中做的事情是正常的做法,但我不会说'self.down`"应该*总是*相反".取决于您的迁移环境.只是把"对立"可能不是"正确"的向下迁移. (3认同)
  • 图拉格 - *它知道如何在大部分时间回滚.我发现`change`方法不是完全证明,因此倾向于使用`up`和`down`方法进行复杂的迁移. (2认同)
  • @MikeC它没有 - 索引被适当修改 (2认同)

小智 67

在这种情况下,IMO可以更好地使用rake db:rollback.然后编辑您的迁移并再次输入rake db:migrate.但是,如果列中有数据,则不想丢失,请使用rename_column.

  • 即使是在"一个团队",如果你有你的应用程序运行多个实例,说,在不同的环境中或在多台计算机等,管理编辑迁移是一个重大的痛苦.我只编辑了一个迁移,如果我*只是*创建它并意识到它是错误的,并且还没有在其他任何地方运行它. (29认同)
  • 此技术仅应用于尚未与生产分支合并更改的情况,而其他更改不依赖于数据持久性.在大多数生产环境中,这不是首选方法. (6认同)
  • 从来没有做过这种事情. (3认同)
  • 我想对我的团队说:'迁移是免费的'编辑已经发布的迁移的成本很高:我曾经花了几个小时来解决为什么我的代码在我意识到另一个团队成员之前没有工作的原因我已经回去编辑了一个我已经运行过的迁移.因此,不要编辑现有的迁移,使用新的迁移来更改模式,因为......"迁移是免费的!" (这不是严格意义上的,但它确实如此) (3认同)

Pau*_*ill 29

如果该列已经填充了数据并且正在生产中,我建议采用一步一步的方法,以避免在等待迁移时停止生产.

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

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
Run Code Online (Sandbox Code Playgroud)

然后,我将承诺改变,并将改变推向生产.

git commit -m 'adding columns with correct name'
Run Code Online (Sandbox Code Playgroud)

然后,一旦提交已投入生产,我就会运行.

Production $ bundle exec rake db:migrate
Run Code Online (Sandbox Code Playgroud)

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

git commit -m 'using correct column name instead of old stinky bad column name'
Run Code Online (Sandbox Code Playgroud)

然后我将这个提交推向生产.

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

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
Run Code Online (Sandbox Code Playgroud)

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

我意识到这一过程涉及到一个过程,但我宁愿这样做而不是生产迁移的问题.

  • 我喜欢这种想法,我会为您的回复+1,但是数据更新将花费很长的时间,因为它要经过轨道并一次执行一行。迁移将使用原始sql语句执行得更快,以更新正确命名的列。例如,在第一个数据库迁移脚本中,添加重复的列名后,“执行“更新表名设置正确的名称_列_ =旧的名称_列”” (2认同)
  • 移动到新表和更新代码以使用新表之间的条目会发生什么?你能否留下潜在的未迁移数据? (2认同)

Jam*_*ing 26

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

Available Transformations

rename_column(table_name, column_name, new_column_name):

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


小智 17

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

rails g migration ChangeHasedPasswordToHashedPassword
Run Code Online (Sandbox Code Playgroud)

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

class ChangeOldCoulmnToNewColumn < ActiveRecord::Migration
  def change
     rename_column :table_name, :hased_password, :hashed_password
  end
end
Run Code Online (Sandbox Code Playgroud)


sup*_*r_p 14

来自API:

rename_column(table_name, column_name, new_column_name)
Run Code Online (Sandbox Code Playgroud)

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


Pro*_*ton 14

我在使用 PostgreSQL 数据库开发 Rails 6 应用程序时遇到了这个挑战。

这是我修复它的方法:

就我而言,table_name是“产品”,old_column是“SKU”,是new_column“产品编号”。

  1. 创建一个迁移文件,其中将包含用于重命名列的命令:

     rails generate migration RenameSKUToProductNumberInProducts
    
    Run Code Online (Sandbox Code Playgroud)
  2. 打开以下位置的迁移文件db/migrate directory

     db/migrate/20201028082344_rename_sku_to_product_number_in_products.rb
    
    Run Code Online (Sandbox Code Playgroud)
  3. 添加重命名列的命令:

     class RenameSkuToProductNumberInProducts < ActiveRecord::Migration[6.0]
       def change
         # rename_column :table_name, :old_column, :new_column
         rename_column :products, :sku, :product_number
       end
     end
    
    Run Code Online (Sandbox Code Playgroud)
  4. 保存,然后运行迁移命令:

     rails db:migrate
    
    Run Code Online (Sandbox Code Playgroud)

您现在可以通过查看架构文件来确认列的重命名:

    db/schema.rb
Run Code Online (Sandbox Code Playgroud)

如果您对列的重命名不满意,可以随时回滚:

    rails db:rollback
Run Code Online (Sandbox Code Playgroud)

注意:尽量将所有调用的地方的列名修改为新名称。


uma*_*uma 12

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

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
Run Code Online (Sandbox Code Playgroud)

如果您change在迁移中使用了该方法,那么:

def change
    rename_column :table_name, :column_old_name, :column_new_name
end
Run Code Online (Sandbox Code Playgroud)

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


sun*_*nil 11

如果您的代码未与其他代码共享,那么最好的选择就是rake db:rollback 在迁移时编辑您的列名称rake db:migrate.而已

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

 def change
    rename_column :table_name, :old_name, :new_name
  end
Run Code Online (Sandbox Code Playgroud)

而已.


Ste*_*cia 8

作为一种替代选择,如果您没有与迁移的想法结合,那么ActiveRecord有一个引人注目的宝石,它将自动为您处理名称更改,Datamapper样式.您所做的只是更改模型中的列名称(并确保将Model.auto_upgrade!放在model.rb的底部)和中提琴!数据库即时更新.

https://github.com/DAddYE/mini_record

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

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


Abr*_*ram 8

如果需要切换列名,则需要创建占位符以避免重复的列名错误.这是一个例子:

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
Run Code Online (Sandbox Code Playgroud)


dir*_*ter 7

如果当前数据对您不重要,您可以使用以下方法删除原始迁移:

rake db:migrate:down VERSION='YOUR MIGRATION FILE VERSION HERE'
Run Code Online (Sandbox Code Playgroud)

如果没有引号,则在原始迁移中进行更改,然后通过以下方式再次运行向上迁移:

rake db:migrate
Run Code Online (Sandbox Code Playgroud)


jon*_*now 6

只需创建一个新的迁移,并在一个块中,使用rename_column如下.

rename_column :your_table_name, :hased_password, :hashed_password
Run Code Online (Sandbox Code Playgroud)


Har*_*iya 6

对于Ruby on Rails 4:

def change
    rename_column :table_name, :column_name_old, :column_name_new
end
Run Code Online (Sandbox Code Playgroud)


Sum*_*not 5

我们可以手动使用以下方法:

我们可以手动编辑迁移,如:

然后它将删除您的迁移:

$> rake db:migrate:up VERSION=xxxxxxxxx
Run Code Online (Sandbox Code Playgroud)

它将使用更新的更改添加您的迁移.


vip*_*pin 5

生成迁移文件:

rails g migration FixName
Run Code Online (Sandbox Code Playgroud)

#创建db / migrate / xxxxxxxxxx.rb

编辑迁移以按照您的意愿进行。

class FixName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end
Run Code Online (Sandbox Code Playgroud)


Mad*_*die 5

运行rails g migration ChangesNameInUsers(或任何您想命名的名称)

打开刚刚生成的迁移文件,然后在方法(在def change和之间end)中添加以下行:

rename_column :table_name, :the_name_you_want_to_change, :the_new_name

保存文件,然后rake db:migrate在控制台中运行

请检查您schema.db的名称,以查看数据库中的名称实际上是否已更改!

希望这可以帮助 :)


Apo*_*orv 5

 def change
    rename_column :table_name, :old_column_name, :new_column_name
  end
Run Code Online (Sandbox Code Playgroud)


BKS*_*eon 5

让我们亲吻吧。只需要三个简单的步骤。以下适用于Rails 5.2

1 . 创建迁移

  • rails g migration RenameNameToFullNameInStudents

  • rails g RenameOldFieldToNewFieldInTableName- 这样以后代码库的维护者就很清楚了。(表名使用复数形式)。

2. 编辑迁移

# I prefer to explicitly write the向上and向下methods.

# ./db/migrate/20190114045137_rename_name_to_full_name_in_students.rb

class RenameNameToFullNameInStudents < ActiveRecord::Migration[5.2]
  def up
    # rename_column :table_name, :old_column, :new_column
    rename_column :students, :name, :full_name
  end

  def down
            # Note that the columns are reversed
    rename_column :students, :full_name, :name
  end
end
Run Code Online (Sandbox Code Playgroud)

3. 运行您的迁移

rake db:migrate

然后你就可以参加比赛了!