【问题标题】:Rails migration change time to datetime preserving dataRails 迁移将时间更改为保留数据的日期时间
【发布时间】:2021-09-17 00:55:17
【问题描述】:

我需要将我的列“start_time”从 time 更改为 datetime (我认为日期时间和时间戳是一回事吗?注意:我在 postgres 上)

class ChangeStartTimeToBeDatetimeInAssignments < ActiveRecord::Migration[5.0]
  def up
    change_column :assignments, :start_time, :datetime
  end
  def down
    change_column :assignments, :start_time, :time
  end
end

列中的数据很重要,不能删除...

注意:这里是 json 输出的 sn-p,仅显示“start_time”部分(如果重要)

"start_time":"2000-01-01T12:00:00"

迁移时出现此错误:

PG::DatatypeMismatch: ERROR:  column "start_time" cannot be cast automatically to type timestamp without time zone
HINT:  You might need to specify "USING start_time::timestamp without time zone".

正在运行此迁移...

class ChangeStartTimeToBeDatetimeInAssignments < ActiveRecord::Migration[5.0]
  def up
    change_column :assignments, :start_time, :datetime, 'USING start_time::timestamp without time zone'
  end
  def down
    change_column :assignments, :start_time, :time
  end
end

给出这个错误...

== 20210916230930 ChangeStartTimeToBeDatetimeInAssignments: migrating =========
-- change_column(:assignments, :start_time, :datetime, "USING start_time::timestamp without time zone")
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

no implicit conversion of Symbol into Integer

我做错了什么?

如何将“时间”迁移到“日期时间”?

如何修改我的迁移并按照建议添加“USING start_time::timestamp without time zone”?

(我认为日期时间和时间戳是一回事吗?)

感谢您的宝贵时间。

【问题讨论】:

  • ActiveRecords :datetime 类型对应于 Postgres 上的 timestamp 类型。例如,它的驱动程序依赖于 MySQL DATETIME。您应该可以使用 change_column :assignments, :start_time, :datetime, "USING start_time::timestamp without time zone" 之类的东西。
  • @max 确切的咒语是我正在寻找的。 change_column :assignments, :start_time, :datetime, "USING start_time::timestamp without time zone" 给出一个错误。更新了我的问题以显示我在运行迁移时得到的结果。

标签: ruby-on-rails rails-migrations


【解决方案1】:

为了可读性,一步一步做。这也将有助于定义正确的 down 方法以确保回滚不会出错。

class ChangeStartTimeToBeDatetimeInAssignments < ActiveRecord::Migration[5.0]
  def up
    # add a temporary column
    add_column :assignments, :start_time_datetime, :datetime
    
    # add the the current start_time as datetime to the temporary column for each entry
    Assignment.all.each do |assignment|
      assignment.update(start_time_datetime: assignment.start_time.to_datetime)
    end

    # drop the old time column
    remove_column :assignments, :start_time
    
    # rename the temporary column to start_time   
    rename_column :assignments, :start_time_datetime, :start_time
  end

  def down
    add_column :assignments, :start_time_time, :time
    
    Assignment.all.each do |assignment|
      assignment.update(start_time_time: assignment.start_time.to_time
    end

    remove_column :assignments, :start_time
    rename_column :assignments, :start_time_time, :start_time
  end
end

为确保更新循环不会因为数据不一致而出错并让您得到一半混乱的数据,您可以将更新部分包装到 https://api.rubyonrails.org/v6.1.4/classes/ActiveRecord/Transactions/ClassMethods.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-16
    • 1970-01-01
    • 2019-12-26
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多