微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在迁移中使用重命名的列

如何解决在迁移中使用重命名的列

在 Rails 6.1 中,我想重命名列并在一次迁移中转换底层数据:

class RestructureExamples < ActiveRecord::Migration[6.1]
  
  def up
    rename_column :examples,:old_column_name,:new_column_name
    Example.reset_column_information
    Example.find_each do |example|
      unless example.new_column_name.nil?
        if example.new_column_name == 100
          example.new_column_name = 300
        else
          example.new_column_name = (example.new_column_name.to_f * 2.989).to_i
        end
      end
    end
  end

  def down
    # Do the reverse - left out for brevity
  end

end

即使添加reset_column_information(来自文档:“重置有关列的所有缓存信息,这将导致它们在下一个请求时重新加载。”),这会抛出 NoMethodError: undefined method `new_column_name'。>

记录 example 仍然有 old_cloumn_name。我期望在将 rename_column 一起调用 with reset_column_information 后,在数据库和模型中更新列信息。

我可以在 sources 中看到 rename_column 执行了一个 alter table sql 命令。在 rename_column 后通过 sql 检查列名称显示该列已正确重命名。所以,我假设只有模型包含过时的信息。

可能有几种解决方法(使用 sql 而不是模型,在转换数据后重命名,使用两个单独的迁移,...),但我更喜欢我的方法来提高可理解性。

解决方法

如果你想让它像你现在使用的那样工作,你必须在 change_table 中重命名它。

change_table :examples do |t|
  t.rename :old_name,:new_name
end

Example.reset_column_information
# ....
,

我想我找到了我自己问题的答案。正如 migrations guide 中所建议的,可以将本地模型与 reset_column_information 结合使用:

class RestructureExamples < ActiveRecord::Migration[6.1]
  
  class Example < ActiveRecord::Base
  end
  
  def up
    rename_column :examples,:old_column_name,:new_column_name
    Example.reset_column_information
    Example.find_each do |example|
      unless example.new_column_name.nil?
        if example.new_column_name == 100
          example.new_column_name = 300
        else
          example.new_column_name = (example.new_column_name.to_f * 2.989).to_i
        end
      end
    end
  end

  def down
    # Do the reverse - left out for brevity
  end

end

这种方法对我有用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。