Rails 迁移变更列

发布于 2024-08-31 12:16:25 字数 195 浏览 4 评论 0原文

我们使用脚本/生成迁移 add_fieldname_to_tablename fieldname:datatype 语法来向模型添加新列。

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

我想将列从 datetime 更改为 date

We have script/generate migration add_fieldname_to_tablename fieldname:datatype syntax for adding new columns to a model.

On the same line, do we have a script/generate for changing the datatype of a column? Or should I write SQL directly into my vanilla migration?

I want to change a column from datetime to date.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

客…行舟 2024-09-07 12:16:25

使用#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)

Use #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)

NOTE: the same result can be achieved even outside of db migrations, this might be handy for testing/debugging but this method needs to be used very cautiously:

ActiveRecord::Base.connection.change_column(:table_name, :column_name, :date)
撧情箌佬 2024-09-07 12:16:25

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

示例:

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

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

You can also use a block if you have multiple columns to change within a table.

Example:

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

See the API documentation on the Table class for more details.

爱人如己 2024-09-07 12:16:25

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

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

I'm not aware if you can create a migration from the command line to do all this, but you can create a new migration, then edit the migration to perform this taks.

If tablename is the name of your table, fieldname is the name of your field and you want to change from a datetime to date, you can write a migration to do this.

You can create a new migration with:

rails g migration change_data_type_for_fieldname

Then edit the migration to use 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

Then run the migration:

rake db:migrate
守望孤独 2024-09-07 12:16:25

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

步骤 1:

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

rails g migration sample_name_change_column_type

步骤 2:

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

  1. 定义更改
        更改列(:表名,:列名,:新类型)
    结尾
    

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 测试了此解决方案,效果良好。

As I found by the previous answers, three steps are needed to change the type of a column:

Step 1:

Generate a new migration file using this code:

rails g migration sample_name_change_column_type

Step 2:

Go to /db/migrate folder and edit the migration file you made. There are two different solutions.

  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

Step 3:

Don't forget to do this command:

rake db:migrate

I have tested this solution for Rails 4 and it works well.

茶花眉 2024-09-07 12:16:25

对于 Rails 5,

来自 Rails 指南

如果您希望迁移执行 Active Record 不知道如何反转的操作,您可以使用 可逆

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

With Rails 5

From Rails Guides:

If you wish for a migration to do something that Active Record doesn’t know how to reverse, you can use 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
能怎样 2024-09-07 12:16:25

只需生成迁移:

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

Just generate migration:

rails g migration change_column_to_new_from_table_name

Update migration like this:

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

and finally

rake db:migrate
凤舞天涯 2024-09-07 12:16:25

这一切都假设列的数据类型对任何现有数据都有隐式转换。我遇到过几种情况,现有数据(比如说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

This is all assuming that the datatype of the column has an implicit conversion for any existing data. I've run into several situations where the existing data, let's say a String can be implicitly converted into the new datatype, let's say Date.

In this situation, it's helpful to know you can create migrations with data conversions. Personally, I like putting these in my model file, and then removing them after all database schemas have been migrated and are stable.

/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
冰葑 2024-09-07 12:16:25

您可以使用 change_column 为此:

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

You can use change_column for this:

def change
  change_column :table_name, :column_name, :new_data_type
end
风启觞 2024-09-07 12:16:25

要在编辑默认值时完成答案:

在 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

To complete answers in case of editing default value :

In your rails console :

rails g migration MigrationName

In the migration :

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

Will look like :

  def change
    change_column :members, :approved, :boolean, default: true
  end
但可醉心 2024-09-07 12:16:25

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

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

ex:

rails g migration RemoveFieldNameFromTableName field_name:data_type

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

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

ex:

rails g migration AddFieldNameToTableName field_name:data_type

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

Another way to change data type using migration

step1:
You need to remove the faulted data type field name using migration

ex:

rails g migration RemoveFieldNameFromTableName field_name:data_type

Here don't forget to specify data type for your field

Step 2:
Now you can add field with correct data type

ex:

rails g migration AddFieldNameToTableName field_name:data_type

That's it, now your table will added with correct data type field, Happy ruby coding!!

森末i 2024-09-07 12:16:25

使用 Postgresql,您可能会收到错误,因为 Postgresql 需要有关如何将值转换为另一种类型的特定说明。这可以通过 CAST 来实现。您可能需要编写单独的“向上”和“向下”迁移,因为 Rails 无法反转 CAST 语句。例如,将字符串字段转换为文本:

def up
  change_column :mytable, :myfield, 'text USING CAST(myfield AS text)'
end
def down
  change_column :mytable, :myfield, 'string USING CAST(myfield AS string)'
end

有关 CAST 的更多信息,请参见 https:// /www.postgresql.org/docs/8.3/sql-expressions.html

With Postgresql you might get an error because Postgresql needs specific instructions on how to cast values into another type. This can be achieved with CAST. You probably need to write separate "up" and "down" migrations because Rails cannot reverse the CAST statement. For example to cast a string field into text:

def up
  change_column :mytable, :myfield, 'text USING CAST(myfield AS text)'
end
def down
  change_column :mytable, :myfield, 'string USING CAST(myfield AS string)'
end

More info on CAST in https://www.postgresql.org/docs/8.3/sql-expressions.html.

鸠书 2024-09-07 12:16:25

这种格式可以帮助我:

change_column(:table, :column, :datatype, using: 'INFO_FROM_HINT')

That format helps me:

change_column(:table, :column, :datatype, using: 'INFO_FROM_HINT')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文