【问题标题】:What is the proper way of handling data migrations in Ruby on Rails?在 Ruby on Rails 中处理数据迁移的正确方法是什么?
【发布时间】:2020-05-23 23:03:36
【问题描述】:

我遇到了一个问题,我们的迁移文件(进行数据更改)依赖于尚未迁移的数据库。

我们正在使用支持多个数据库的 Rails 6:

production:
  primary:
    database: my_db_name
  other:
    database: other_db_name

以下是我们的模型示例:

class Product < ApplicationRecord
  belongs_to :other
end

class Other < ApplicationRecord
  establish_connection: :other
end

当主数据库的迁移尝试使用来自其他数据库的数据时,就会出现问题。

class AddInitialProducts < ActiveRecord::Migration[6.0]  
  def up
    obj = Other.find_by(name: "Special Object")
    Product.create(name: "Product", other: obj)
  end

  def down
    # Delete product created above.
  end
end

当我从空数据库开始运行rails db:migrate 时,它会首先尝试迁移primary 数据库,但由于other_db_name 尚不存在而失败。尚未迁移。

我知道rails db:schema:load 命令,但我们需要数据存在于我们的应用程序中。这也是所需数据的一个简单示例。应用程序的每个版本之间可能会有数据迁移,因此种子似乎不是一个好主意,因为该文件用于开发/测试。

处理版本之间数据迁移的正确方法是什么?

【问题讨论】:

    标签: ruby-on-rails database-migration


    【解决方案1】:

    这听起来超出了迁移实际应该用于转换数据库架构的范围。

    相反,您想要的是可能与服务对象结合的 rake 任务。您可以使用以下方式生成 rake 任务:

    rails g task products import
    

    生成器将生成:

    # lib\tasks\products.rake
    namespace :products do
      desc "TODO"
      task import: :environment do
      end
    end
    

    可以在您选择的任何时候使用bin/rake products:import 调用此任务。

    当然不会有任何输出,因为任务还没有做任何事情。实际实现在传递给task 的块中。测试 Rake 任务可能有点挑战性,所以我发现最好在服务对象中完成大部分实际实现:

    class ProductImporter
      def initialize(env, **kwargs)
        # set up
      end
    
      def call
        # do actual work 
        # ...
        teardown
      end
    
      def self.call(env, **kwargs)
        new(kwargs).call
      end
    
      private 
    
      def teardown
        # clean up
      end
    end
    

    这很容易测试,因为它们只是普通的旧 ruby​​ 对象,您不必担心命令行参数之类的东西。

    然后从任务中调用你的服务:

    # lib\tasks\products.rake
    namespace :products do
      desc "Import a list of products from..."
      task import: :environment do
        ProductImporter.call(Rails.env)
      end
    end
    

    这样您只需测试您的 rake 任务是否使用正确的参数调用服务。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-13
      • 1970-01-01
      • 2012-05-14
      • 2019-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多