ChatGPT解决这个技术问题 Extra ChatGPT

更改列的 Rails 迁移

我们有用于向模型添加新列的 script/generate migration add_fieldname_to_tablename fieldname:datatype 语法。

在同一行,我们是否有一个脚本/生成来更改列的数据类型?或者我应该将 SQL 直接写入我的 vanilla 迁移中?

我想将一列从 datetime 更改为 date


N
Nikita Fedyashev

使用 #change_column

change_column(:table_name, :column_name, :date)

# a few more examples:
change_column(:suppliers, :name, :string, limit: 80)
change_column(:accounts, :description, :text)

注意:即使在数据库迁移之外也可以获得相同的结果,这对于测试/调试可能很方便,但需要非常谨慎地使用此方法:

ActiveRecord::Base.connection.change_column(:table_name, :column_name, :date)

@b_ayan:据我所知,迁移名称中唯一神奇的词是“添加”和“删除”。
这里有点菜鸟,但是……我理解答案,但不理解对这个答案的评论。澄清赞赏:)
当你创建一个迁移时,你给它一个名字(例如上面问题中的 add_fieldname_to_tablename )。如果它以“add”或“remove”开头,那么迁移将自动填充代码以添加或删除列,这样您就不用自己编写代码了。
还值得牢记的是,您应该用单独的 updown 操作替换通常的 change 操作,因为 change_column 是不可逆的迁移,如果您需要回滚会引发错误。
@QPaysTaxes up 应该包含您想要更改列的内容,而 down 应该包含如何撤消该更改。
s
shilovk

如果表中有多个列要更改,也可以使用块。

例子:

change_table :table_name do |t|
  t.change :column_name, :column_type, {options}
end

有关详细信息,请参阅 API documentation on the Table class


R
Ryan

我不知道您是否可以从命令行创建迁移来执行所有这些操作,但您可以创建一个新的迁移,然后编辑迁移以执行此任务。

如果 tablename 是您的表的名称,fieldname 是您的字段的名称,并且您想从日期时间更改为日期,则可以编写迁移来执行此操作。

您可以使用以下命令创建新迁移:

rails g migration change_data_type_for_fieldname

然后编辑迁移以使用 change_table:

class ChangeDataTypeForFieldname < ActiveRecord::Migration
  def self.up
    change_table :tablename do |t|
      t.change :fieldname, :date
    end
  end
  def self.down
    change_table :tablename do |t|
      t.change :fieldname, :datetime
    end
  end
end

然后运行迁移:

rake db:migrate

A
Aboozar Rajabi

正如我在前面的答案中发现的,更改列的类型需要三个步骤:

步骤1:

使用以下代码生成新的迁移文件:

rails g migration sample_name_change_column_type

第2步:

转到 /db/migrate 文件夹并编辑您制作的迁移文件。有两种不同的解决方案。

def change change_column(:table_name, :column_name, :new_type) end

2.

    def up
        change_column :table_name, :column_name, :new_type
    end

    def down
        change_column :table_name, :column_name, :old_type
    end

第 3 步:

不要忘记执行此命令:

rake db:migrate

我已经为 Rails 4 测试了这个解决方案,它运行良好。


在第 2 步中,第一个在运行 rake db:rollback 后会失败,我建议您检查第二个
是否有一个 Rails 约定,允许在生成迁移文件时或多或少地完成所有事情而不去它,然后编辑它?
@BKSpureon 是的,请在此处查看文档:edgeguides.rubyonrails.org/active_record_migrations.html
M
Mr. Tao

使用导轨 5

Rails Guides

如果你希望迁移做一些 Active Record 不知道如何逆转的事情,你可以使用 reversible:

class ChangeTablenameFieldname < ActiveRecord::Migration[5.1]
  def change
    reversible do |dir|
      change_table :tablename do |t|
        dir.up   { t.change :fieldname, :date }
        dir.down { t.change :fieldname, :datetime }
      end
    end
  end
end

J
Joshua Pinter

只需生成迁移:

rails g migration change_column_to_new_from_table_name

像这样更新迁移:

class ClassName < ActiveRecord::Migration
  change_table :table_name do |table|
    table.change :column_name, :data_type
  end
end

最后

rake db:migrate

S
Sebastian Scholl

这一切都假设列的数据类型对任何现有数据都有隐式转换。我遇到过几种情况,其中现有数据(例如 String)可以隐式转换为新数据类型(例如 Date)。

在这种情况下,了解您可以使用数据转换创建迁移会很有帮助。就个人而言,我喜欢将它们放在我的模型文件中,然后在迁移所有数据库模式并且稳定后将它们删除。

/app/models/table.rb
  ...
  def string_to_date
    update(new_date_field: date_field.to_date)
  end

  def date_to_string
    update(old_date_field: date_field.to_s)
  end
  ...
    def up
        # Add column to store converted data
        add_column :table_name, :new_date_field, :date
        # Update the all resources
        Table.all.each(&:string_to_date)
        # Remove old column
        remove_column :table_name, :date_field
        # Rename new column
        rename_column :table_name, :new_date_field, :date_field
    end

    # Reversed steps does allow for migration rollback
    def down
        add_column :table_name, :old_date_field, :string
        Table.all.each(&:date_to_string)
        remove_column :table_name, :date_field
        rename_column :table_name, :old_date_field, :date_field
    end

S
Sachin Singh

您可以为此使用 change_column

def change
  change_column :table_name, :column_name, :new_data_type
end

这里唯一的问题是它不可逆转。请改用 def up 并实施 def down
P
Prasanth_Rubyist

使用迁移更改数据类型的另一种方法

step1:您需要使用migration移除故障数据类型字段名

前任:

rails g migration RemoveFieldNameFromTableName field_name:data_type

在这里不要忘记为您的字段指定数据类型

第 2 步:现在您可以添加具有正确数据类型的字段

前任:

rails g migration AddFieldNameToTableName field_name:data_type

就是这样,现在您的表格将添加正确的数据类型字段,快乐的红宝石编码!


值得注意的是,该列中的所有数据都将使用此方法丢失。
是的,当然,如果您在该列中有数据,请先添加该列,然后从现有列中提取数据
不是每个人的编码水平都相同。所以这对每个人来说都不是很明显,尤其是初学者。由于这个 SO 问题是关于更改列类型而不是重新创建它,我认为这是一个有效的警告。
G
Gregdebrick

在编辑默认值的情况下完成答案:

在您的 Rails 控制台中:

rails g migration MigrationName

在迁移中:

  def change
    change_column :tables, :field_name, :field_type, default: value
  end

看起来像:

  def change
    change_column :members, :approved, :boolean, default: true
  end