Rails迁移变更栏


327

我们具有script/generate migration add_fieldname_to_tablename fieldname:datatype将新列添加到模型的语法。

在同一行上,我们是否具有用于更改列的数据类型的脚本/生成器?还是应该将SQL直接写到我的原始迁移中?

我想将列从更改datetimedate

Answers:


548

我认为这应该有效。

change_column :table_name, :column_name, :date

13
@b_ayan:据我所知,迁移名称中唯一神奇的词是“添加”和“删除”。
亚历克斯·科本

1
排序滑轨新手,但是…我理解答案,但对这个答案的评论不了解。感谢澄清:)
Alan H.

7
创建迁移时,请为其命名(例如,上面问题中的add_fieldname_to_tablename)。如果它以“ add”或“ remove”开头,那么迁移将自动使用代码添加或删除列,从而省去了您自己编写代码的麻烦。
亚历克斯·科本

6
还应该记住,应该将常规change操作替换为单独操作updown操作,这change_column是不可逆转的迁移,如果需要回滚,则会引发错误。
DaveStephens 2015年

1
@QPaysTaxes向上应包含要在列之间更改的内容,向下应包含如何撤消更改的内容。
DaveStephens

98

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

例:

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

有关更多详细信息,请参见Table类上API文档


88

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

如果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

32

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

步骤1:

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

rails g migration sample_name_change_column_type

第2步:

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

  1. 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

第三步:

不要忘记执行以下命令:

rake db:migrate

我已经为Rails 4测试了该解决方案,并且效果很好。


1
在步骤2中,第一次将运行耙分贝失败后:回滚,我建议你检查第二个
Feuda

是否有Rails约定,允许在生成迁移文件时不做任何修改然后再编辑它,或多或少地完成所有工作?
BKSpurgeon '17

@BKSpurgeon是的,请在此处查看文档:edgeguides.rubyonrails.org/active_record_migrations.html
Aboozar Rajabi

12

带导轨5

Rails指南

如果您希望迁移执行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

8

只需生成迁移:

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

2

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

步骤1: 您需要使用迁移功能删除错误的数据类型字段名称

例如:

rails g migration RemoveFieldNameFromTableName field_name:data_type

在这里别忘了为您的字段指定数据类型

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

例如:

rails g migration AddFieldNameToTableName field_name:data_type

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


2

所有这些都假定该列的数据类型具有对任何现有数据的隐式转换。我遇到了几种情况,比如说现有数据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

0

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

在您的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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.