首页 > 解决方案 > 如何在 Rails Active Record 中实现“写入两列”(如 Strong 迁移所建议的那样)?

问题描述

我正在尝试更改 PostgreSQL (Rails 6) 中的列类型。

移民:

# frozen_string_literal: true

class ChangeUsersEmailToCitext < ActiveRecord::Migration[6.0]
  def up
    enable_extension('citext')

    change_column :users, :email, :citext
  end

  def down
    change_column :users, :email, :string
  end
end

但是 Strong Migrations 抛出错误并显示以下内容:

=== Dangerous operation detected #strong_migrations ===

Changing the type of an existing column blocks reads and writes
while the entire table is rewritten. A safer approach is to:

1. Create a new column
2. Write to both columns
3. Backfill data from the old column to the new column
4. Move reads from the old column to the new column
5. Stop writing to the old column
6. Drop the old column

我了解数据库锁定的意义和危险......但我的问题很愚蠢,我还没有找到答案。从字面上看,我如何才能获得第 2、第 4 和第 5 分?如何强制我的 ActiveRecord 模型同时写入两列并在回填后切换到正确的列?

标签: ruby-on-railspostgresqlrails-activerecordrails-migrations

解决方案


假设旧列是length,新列是length_advanced

2 - 写入两列

def length=(value)
  super(value)
  self[:length_advanced] = value
end

4 - 将读取从旧列移动到新列

def length
  if super.present?
    super
  else
    self[:length_advanced]
  end
end

5 - 停止写入旧列

def length=(value)
  # no write to old column
  self[:length_advanced] = value
end

有关所有这些的更多信息https://api.rubyonrails.org/classes/ActiveRecord/Base.html


推荐阅读