在ROR迁移过程中将列类型从日期更改为日期时间

233

我需要将我的应用程序中的一列从日期类型更改为日期时间类型。由于该应用程序仍在开发中,因此我不关心数据。

我该如何做?

5个回答

513

首先在您的终端中执行以下命令:

rails g migration change_date_format_in_my_table

那么在你的迁移文件中:

对于 Rails >= 3.2:

class ChangeDateFormatInMyTable < ActiveRecord::Migration
  def up
    change_column :my_table, :my_column, :datetime
  end

  def down
    change_column :my_table, :my_column, :date
  end
end

27
没错,我只是默认初学者会选择最新的技术,但这当然是不确定的。 - apneadiving
12
问题标记为“ruby-on-rails-3”。 - Sucrenoir
2
@Sucrenoir 是的,这个标签是 apneadiving 回答后添加的。 - Jason
11
如果你想知道为什么不使用单个的 change 方法而是使用 updown 方法,那是因为 change 方法不支持 change_column 迁移定义 - Dennis
2
这个答案只有部分正确,即使在Rails 4中也不能在change内部使用change_column,否则向下迁移将无法工作。无论Rails的版本如何,您都应该使用up/down。 - Alan Peabody
显示剩余3条评论

80

此外,如果您正在使用Rails 3或更高版本,则不必使用updown方法。您只需使用change

class ChangeFormatInMyTable < ActiveRecord::Migration
  def change
    change_column :my_table, :my_column, :my_new_type
  end
end

79
更改方法仅适用于可逆迁移。上面的代码会引发ActiveRecord::IrreversibleMigration异常。只应在http://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html中使用change方法中的方法。 - davekaro
3
我正在使用Rails 4,并且以前进行过这种类型的迁移。更改不起作用!@davekaro的评论是正确的。 - harryt
3
对于Rails 5,这是正确且可行的解决方案。 - W.M.
3
当进行反向操作时,它如何知道应该将旧列类型更改回什么? - Andrew Grimm
@AndrewGrimm 你是正确的。当我尝试撤销我的迁移时,我看到的就是这个:This migration uses change_column, which is not automatically reversible. 要使迁移可逆,你可以选择: 1. 在 #change 方法的位置定义 #up 和 #down 方法。 2. 使用 #reversible 方法来定义可逆行为。 - Marklar

42
在Rails 3.2和Rails 4中,Benjamin的流行答案具有略微不同的语法。
首先在终端输入:
$ rails g migration change_date_format_in_my_table

然后在您的迁移文件中:

class ChangeDateFormatInMyTable < ActiveRecord::Migration
  def up
   change_column :my_table, :my_column, :datetime
  end

  def down
   change_column :my_table, :my_column, :date
  end
end

24

有一个change_column方法,只需要在迁移中执行它并将datetime作为新类型。

change_column(:my_table, :my_column, :my_new_type)

1
这是否保留了原始数据? - BenKoshy
1
是的,请保留原始数据。 - Mauro
从技术上讲,存在数据丢失的风险。日期时间字段的时间和时区数据将会丢失,并且仅仅通过运行 rake db:rollback 命令是无法恢复的。 - danielricecodes

1
据我所知,迁移是为了在进行模式更改时尝试重新塑造您关心的数据(即生产数据)。因此,除非这个说法是错误的,并且因为他确实说他不关心数据,为什么不只是在原始迁移中将列类型从日期修改为日期时间并重新运行迁移?(希望您已经进行了测试:))。

2
即使您不关心数据,如果您正在团队中工作并希望您的模式更改传播到团队中的所有其他开发人员,则在开发环境中使用迁移可能很重要。 - Jose B
我很难看出在这种情况下,额外迁移更改列会给您带来什么优势。更改创建列的原始迁移有什么问题吗?无论哪种情况,每个团队成员都必须重新运行所有迁移以获取新模式。 - fakeleft
如果您使用新的迁移,您只需撤销更改列类型的迁移即可。如果您要编辑原始文件,则必须回滚该编辑并在此之后重新运行迁移。 - jazzpi
考虑到目前还没有生产数据,这实际上是一个非常谨慎的答案。对于那些担心其他团队成员的人,可以使用 rake db:migrate:reset 命令来解决。 - Ryan McGeary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接