更改列的 Rails 迁移
Posted
技术标签:
【中文标题】更改列的 Rails 迁移【英文标题】:Rails migration for change column 【发布时间】:2011-02-17 11:47:35 【问题描述】:我们有script/generate migration add_fieldname_to_tablename fieldname:datatype
语法用于向模型添加新列。
在同一行,我们是否有一个脚本/生成来更改列的数据类型?还是应该将 SQL 直接写入我的 vanilla 迁移?
我想将一列从datetime
更改为date
。
【问题讨论】:
【参考方案1】:我认为这应该可行。
change_column :table_name, :column_name, :date
【讨论】:
@b_ayan:据我所知,迁移名称中唯一神奇的词是“add”和“remove”。 这里的轨道菜鸟排序,但是......我理解答案,但不是这个答案的 cmets。澄清赞赏:) 当你创建一个迁移时,你给它一个名字(例如上面问题中的 add_fieldname_to_tablename )。如果它以“add”或“remove”开头,那么迁移将自动填充添加或删除列的代码,这样您就不用自己编写代码了。 还值得记住的是,您应该用单独的up
和 down
操作替换通常的 change
操作,因为 change_column
是不可逆的迁移,如果您需要会引发错误回滚。
@QPaysTaxes up 应该包含您想要更改列的内容,down 应该包含如何撤消该更改。【参考方案2】:
如果表中有多个列要更改,也可以使用块。
例子:
change_table :table_name do |t|
t.change :column_name, :column_type, options
end
有关详细信息,请参阅API documentation on the Table class。
【讨论】:
【参考方案3】:我不知道您是否可以从命令行创建迁移来执行所有这些操作,但您可以创建新迁移,然后编辑迁移以执行此任务。
如果 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
【讨论】:
【参考方案4】:我从前面的答案中发现,更改列的类型需要三个步骤:
第 1 步:
使用此代码生成新的迁移文件:
rails g migration sample_name_change_column_type
第二步:
转到/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【参考方案5】:另一种使用迁移更改数据类型的方法
第一步: 您需要使用迁移删除错误的数据类型字段名称
例如:
rails g migration RemoveFieldNameFromTableName field_name:data_type
这里不要忘记为您的字段指定数据类型
第 2 步: 现在您可以添加具有正确数据类型的字段
例如:
rails g migration AddFieldNameToTableName field_name:data_type
就是这样,现在您的表格将添加正确的数据类型字段,快乐 ruby 编码!
【讨论】:
这里值得注意的是,该列中的所有数据都将使用此方法丢失。 是的,当然,如果您在该列中有数据,请先添加该列,然后从现有列中提取数据 并非每个人的编码水平都相同。所以这对每个人来说都不是很明显,尤其是初学者。由于这个 SO 问题是关于更改列类型而不是重新创建它,我认为这是一个有效的警告。【参考方案6】:只需生成迁移:
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
【讨论】:
【参考方案7】:使用 Rails 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
【讨论】:
【参考方案8】:在编辑默认值时完成答案:
在您的 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
【讨论】:
【参考方案9】:这都是假设列的数据类型对任何现有数据都有隐式转换。我遇到过几种情况,其中现有数据,比如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
【讨论】:
【参考方案10】:您可以为此使用change_column
:
def change
change_column :table_name, :column_name, :new_data_type
end
【讨论】:
这里唯一的问题是它不可逆转。改用def up
并实现def down
。【参考方案11】:
您可以像这样编写迁移并更改列名
def change
change_column :table_name, :column_name, :new_data_type
end
【讨论】:
您的代码与几个月前发布的this answer 中的代码完全相同相同。以上是关于更改列的 Rails 迁移的主要内容,如果未能解决你的问题,请参考以下文章