ChatGPT解决这个技术问题 Extra ChatGPT

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

我错误地将列命名为 hased_password 而不是 hashed_password

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


t
the Tin Man
rename_column :table, :old_column, :new_column

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

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

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

# 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

对于 Rails 3.1 使用:

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

有关详细信息,请参阅“Active Record Migrations”。

rails g migration FixColumnName

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

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

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

您可以使用 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

然后只需像往常一样db:migrate或您开展业务的方式。

对于 Rails 4:

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

$ > rails g migration ChangeColumnName

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

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

self.down 应该始终与 self.up 相反,所以“如果你需要或做其他事情或什么都不做”并不是真正推荐的。只需这样做: rename_column :table_name, :new_column, :old_column
虽然恢复您在 self.up 中所做的操作是正常做法,但我不会说 self.down“应该总是相反”。取决于您的迁移环境。仅仅把“对立面”放在“对面”可能不是“正确”的向下迁移。
在 Rails 3.1 中,您可以将 def self.updef self.down 替换为 def change,它会知道如何回滚。
Turadg - *它大部分时间都知道如何回滚。我发现 change 方法不是完全证明,因此倾向于使用 updown 方法进行复杂迁移。
重命名会删除索引吗?
t
the Tin Man

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

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


即使在“一个团队”中,如果您有多个应用程序实例正在运行,例如在不同的环境或多台计算机上等,管理编辑的迁移是一个主要的痛苦。如果我刚刚创建迁移并意识到它是错误的,并且还没有在其他任何地方运行它,我只会编辑它。
之后我不得不重新启动服务器。
此技术只应在您的更改尚未与生产分支合并且其他不依赖于数据持久性的情况下使用。在大多数生产环境中,这不是首选方法。
从来没有做过这种事情。
我喜欢对我的团队说:“迁移是免费的” 编辑已发布到野外的迁移的成本很高:我曾经花了几个小时弄清楚为什么我的代码无法正常工作,然后我才意识到另一个团队成员已经返回并编辑了我已经运行的迁移。因此,不要编辑现有迁移,使用新迁移来更改架构,因为... ...“迁移是免费的!” (严格来说,这不是真的,但它说明了这一点)
P
Paul Pettengill

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

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

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

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

git commit -m 'adding columns with correct name'

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

Production $ bundle exec rake db:migrate

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

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

然后我会将该承诺投入生产。

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

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

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

我意识到这涉及到一个过程,但我宁愿这样做,也不愿在生产迁移方面遇到问题。


我喜欢这背后的想法,我会为您的回复 +1,但数据更新需要很长时间才能执行,因为它要经过轨道并且一次只做一行。使用原始 sql 语句更新正确命名的列,迁移将执行得更快。例如,在第一个 db 迁移脚本中,添加重复的列名后,execute "Update table_name set correct_name_column_one = old_name_column_one"
@mr.ruh.roh ^ 完全同意,一开始就应该这样写。我已经编辑以反映一个有效的 sql 语句。感谢您的健全性检查。
在移动到新表和更新代码以使用新表之间的条目会发生什么情况?您不能留下潜在未迁移的数据吗?
虽然这是一个“安全”的答案,但我觉得它不完整。这里很多人说不要这样做-为什么?数据的持久性。这是有效的。可能实现目标最不痛苦的方法是创建新字段,用旧列中的数据填充它们,调整控制器。如果您想删除旧列,您当然必须编辑视图。保留它们的成本是额外的数据库空间和控制器中的一些重复工作。因此,权衡是显而易见的。
t
the Tin Man

请参阅“Active Record Migrations”文档中的“可用转换”部分。

rename_column(table_name, column_name, new_column_name):

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


t
the Tin Man

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

rails g migration ChangeHasedPasswordToHashedPassword

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

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

t
the Tin Man

从 API:

rename_column(table_name, column_name, new_column_name)

这会重命名列,但类型和内容保持不变。


s
sunil

如果您的代码未与其他人共享,那么最好的选择是仅执行 rake db:rollback,然后在迁移和 rake db:migrate 中编辑您的列名。而已

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

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

而已。


rake db:rollback 是一个很好的建议。但是就像你说的那样,只有在迁移还没有被推送的情况下。
t
the Tin Man

某些版本的 Ruby on Rails 支持用于迁移的 up/down 方法,如果您的迁移中有 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

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

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

有关详细信息,请参阅:Ruby on Rails - MigrationsActive Record Migrations


h
halfer

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

这是我修复它的方法:

在我的例子中,table_name 是“Products”,old_column 是“SKU”,new_column 是“ProductNumber”。

创建一个包含重命名列的命令的迁移文件: rails generate migration RenameSKUToProductNumberInProducts 打开 db/migrate 目录中的迁移文件: db/migrate/20201028082344_rename_sku_to_product_number_in_products.rb 添加重命名列的命令: class RenameSkuToProductNumberInProducts < ActiveRecord:: Migration[6.0] def change # rename_column :table_name, :old_column, :new_column rename_column :products, :sku, :product_number end end 保存,然后运行迁移命令: rails db:migrate

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

    db/schema.rb

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

    rails db:rollback

注意:努力在所有调用它的地方将列名修改为新名称。


t
the Tin Man

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

请参阅https://github.com/DAddYE/mini_record

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

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


P
Peter Mortensen

对于 Ruby on Rails 4:

def change
    rename_column :table_name, :column_name_old, :column_name_new
end

如果它节省了查找它的人,table_name 是复数。例如:学生
t
the Tin Man

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

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

P
Peter Mortensen

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

rake db:migrate:down VERSION='YOUR MIGRATION FILE VERSION HERE'

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

rake db:migrate

P
Peter Mortensen

只需创建一个新的迁移,然后在一个块中使用 rename_column,如下所示。

rename_column :your_table_name, :hased_password, :hashed_password

t
the Tin Man

生成迁移文件:

rails g migration FixName

创建 db/migrate/xxxxxxxxxx.rb

根据您的意愿编辑迁移:

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

P
Peter Mortensen

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

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

打开 app/db/migrate/xxxxxxxxx_migration_file.rb

将 hased_password 更新为 hashed_password

运行以下命令 $> rake db:migrate:down VERSION=xxxxxxxxx

然后它将删除您的迁移:

$> rake db:migrate:up VERSION=xxxxxxxxx

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


它不安全,因为您可能会丢失数据 - 如果该列已经存在。但可以为新列和/或表做。
M
Maddie

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

打开刚刚生成的迁移文件,在方法中添加这一行(在 def changeend 之间):

rename_column :table_name, :the_name_you_want_to_change, :the_new_name

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

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

希望这可以帮助 :)


A
Apoorv
 def change
    rename_column :table_name, :old_column_name, :new_column_name
  end

如果您提供解释为什么这是首选解决方案并解释它是如何工作的,它会更有帮助。我们想要教育,而不仅仅是提供代码。
B
BenKoshy

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

1.创建迁移

rails g 迁移 RenameNameToFullNameInStudents

rails g RenameOldFieldToNewFieldInTableName - 这样以后代码库的维护人员就很清楚了。 (使用复数作为表名)。

2. 编辑迁移

# I prefer to explicitly write theandmethods.

# ./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

3. 运行你的迁移

rake db:migrate

你要去参加比赛了!


P
Peter Mortensen

生成 Ruby on Rails 迁移:

$:> rails g migration Fixcolumnname

在迁移文件(XXXXfixcolumnname.rb)中插入代码:

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

P
Prabhakar Undurthi
$:  rails g migration RenameHashedPasswordColumn
invoke  active_record
      create    db/migrate/20160323054656_rename_hashed_password_column.rb

打开该迁移文件并按如下方式修改该文件(请输入您原来的 table_name

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

A
Ashish Darji

在控制台中:

rails generate migration newMigration

在新迁移文件中:

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

您的答案可以通过额外的支持信息得到改进。请edit添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。您可以找到有关如何写出好答案的更多信息in the help center
P
Peter Mortensen

打开 Ruby on Rails 控制台并输入:

ActiveRecord::Migration.rename_column :tablename, :old_column, :new_column

S
Sarwan Kumar

你有两种方法可以做到这一点:

在这种类型中,它会在回滚时自动运行它的反向代码。 def change rename_column :table_name, :old_column_name, :new_column_name end 对于这种类型,rake db:migrate 时运行 up 方法,rake db:rollback 时运行 down 方法: def self.up rename_column :table_name, :old_column_name, :new_column_name end def self.down rename_column :table_name,:new_column_name,:old_column_name end


t
tomb

我在 Rails 5.2 上,并试图重命名设计用户上的列。

rename_column 位对我有用,但单数 :table_name 抛出“未找到用户表”错误。复数为我工作。

rails g RenameAgentinUser

然后将迁移文件更改为:

rename_column :users, :agent?, :agent

哪里:代理?是旧的列名。


S
Sachin Singh

您可以编写迁移运行以下命令来更新列名:

rename_column :your_table_name, :hased_password, :hashed_password

此外,请确保使用新列名更新代码中旧列名的任何用法。


t
the Tin Man

create_table 的近亲是 change_table,用于更改现有表。它的使用方式与 create_table 类似,但让给块的对象知道更多技巧。例如:

class ChangeBadColumnNames < ActiveRecord::Migration
  def change
    change_table :your_table_name do |t|
      t.rename :old_column_name, :new_column_name
    end
  end
end

如果我们将它与其他更改方法一起使用,例如:删除/添加索引/删除索引/添加列,这种方式会更有效。我们可以这样做:

改名

t.rename :old_column_name, :new_column_name

添加列

t.string :new_column

删除列

t.remove :removing_column

索引栏

t.index :indexing_column

请不要使用“已编辑”或“更新”类型的标签。相反,将更改融入其中,就好像它一直都存在一样。如果我们需要知道发生了什么变化,我们可以查看编辑日志。
S
Sara Lins

rails g migration migrationName

因此,您转到生成的迁移并添加:

rename_column :table, :old_column, :new_column

对方法


S
Saman

首先你需要运行

rails g migration create_new_column_in_tablename new_column:datatype
rails g migration remove_column_in_tablename old_column:datatype

然后您需要检查 db/migration 您可以检查 nem 迁移中的详细信息,如果所有详细信息都正确,则需要运行:

rails db:migrate

您是否需要将现有数据从 old_column 迁移到 new_column ?
不,如果您只想重命名它,则不需要。
t
the Tin Man

只需使用以下命令生成迁移:

rails g migration rename_hased_password

之后编辑迁移并在 change 方法中添加以下行:

rename_column :table, :hased_password, :hashed_password

这应该可以解决问题。