【问题标题】:How to configure an extra/different migrations folder如何配置额外/不同的迁移文件夹
【发布时间】:2011-04-22 18:15:15
【问题描述】:

我和一位同事在共享一些模型的不同项目中工作。因此,我们通过 git 子模块共享模型。

此外,我们还希望能够共享迁移:

这样,我同事的迁移将在我项目的文件夹db/migrate/other_db 中。

如何配置 rails 迁移以在这个额外的文件夹中运行迁移?

【问题讨论】:

    标签: ruby-on-rails ruby directory migration


    【解决方案1】:

    在您的配置文件中(config/application.rb 用于所有环境或 config/environments/$(environment).rb 仅用于特定环境)添加以下行:

    config.paths['db/migrate'] += 'db/migrate/other_db'
    

    如果你想改变默认的 'db/migrate' 路径(config.paths['db/migrate'] 是一个默认有一个字符串 'db/migrate' 的数组),这样做:

    config.paths['db/migrate'] = ['db/my_migrate']
    

    这是默认的 config.paths,我们也可以更改:

    "app" => ["app"],
    "app/assets" => ["app/assets"],
    "app/controllers" => ["app/controllers"],
    "app/helpers" => ["app/helpers"],
    "app/models" => ["app/models"],
    "app/mailers" => ["app/mailers"],
    "app/views" => ["app/views"],
    "lib" => ["lib"],
    "lib/assets" => ["lib/assets"],
    "lib/tasks" => ["lib/tasks"],
    "config" => ["config"],
    "config/environments" => ["config/environments"],
    "config/initializers" => ["config/initializers"],
    "config/locales" => ["config/locales"],
    "config/routes" => ["config/routes.rb"],
    "db" => ["db"],
    "db/migrate" => ["db/migrate"],
    "db/seeds" => ["db/seeds.rb"],
    "vendor" => ["vendor"],
    "vendor/assets" => ["vendor/assets"],
    "vendor/plugins" => ["vendor/plugins"],
    "config/database" => ["config/database.yml"],
    "config/environment" => ["config/environment.rb"],
    "lib/templates" => ["lib/templates"],
    "log" => ["log/development.log"],
    "public" => ["public"],
    "public/javascripts" => ["public/javascripts"],
    "public/stylesheets" => ["public/stylesheets"],
    "tmp" => ["tmp"],
    

    【讨论】:

    • 在 Rails 4 中:config.paths['db/migrate'] << 'db/migrate/other_db'
    • Rails 3 或 4 的正确答案是 config.paths['db/migrate'] << 'db/migrate/other_db'
    • config.paths['db/migrate'] += ['db/migrate/other_db'] 也可以。
    • @apocalyptiq 有没有办法单独更改资产中的图像和样式表目录???像 'app/assets/images' => 'apples/assets/images' ?
    • 请注意,至少在 Rails 4.2 之前,不可能(容易?)覆盖 migrations_path 因为它总是尝试设置默认值:github.com/rails/rails/blob/4-2-stable/activerecord/lib/…
    【解决方案2】:

    Rails 5/6 更新;

    Rails 5 建议在您的 config/database.yml 文件中设置额外的迁移路径。很简单,看这个例子;

    development:
      migrations_paths:
      - "db/migrate/other_db"
      - "db/migrate/something_else"
    

    ActiveRecord::Migrator.migrations_path= 将在 Rails 6 中被弃用。

    【讨论】:

      【解决方案3】:

      根据 Swanand 的回答,我们可以编写一个迁移以将迁移加载到外部目录中:

      class MigrateMetadata < ActiveRecord::Migration
        MIGRATIONS_PATH='db/migrate/metadata'
        def self.up
         Dir["#{MIGRATIONS_PATH}/[0-9]*_*.rb"].
         sort.map{|filename|require filename}.flatten.
         each{|class_name| const_get(class_name).up}
        end
      
        def self.down
          Dir["#{MIGRATIONS_PATH}/[0-9]*_*.rb"].sort.reverse.
          map{|filename|require filename}.flatten.
          each{|class_name| const_get(class_name).down}
        end
      end
      

      【讨论】:

        【解决方案4】:

        顺便说一句,如果你正在构建一个与 Rails 一起使用的 gem,你可以在你的 rail tie 中放置一个如下所示的块来添加 gem 自己的迁移。

          root = ... # the path to your gem
          initializer :append_migrations do |app|
            unless app.root.to_s.match root
              app.config.paths["db/migrate"] << File.join(root, 'db/migrate')
            end
          end
        

        如果您使用此技术,则无需使用生成器从 gem 中复制迁移。

        您可以使用类似这样的方法创建一个方法来生成 gem 的根目录...

        module MyGemName
          def root
            File.expand_path '../..', __FILE__
          end
        
          module_method :root
        end
        

        ... 在您的 gem 的文件 lib/my_gem_name.rb 中。

        【讨论】:

          【解决方案5】:

          我不知道一种非常干净的方法,但是运行迁移的代码看起来像:

          @migrations ||= begin                                                                                                                                            
                  files = Dir["#{@migrations_path}/[0-9]*_*.rb"]                                                                                                                 
          
                  migrations = files.inject([]) do |klasses, file|                                                                                                               
                    version, name = file.scan(/([0-9]+)_([_a-z0-9]*).rb/).first 
          

          在哪里,

          @migrations_path = 'db/migrate'
          

          因此,如果您将其更改为从配置文件中读取,它可能对您有利。但正如我所说,这绝对不是一种非常干净的方法。

          【讨论】:

            【解决方案6】:

            只需将此初始化程序添加到您的 lib/engine.rb:

            initializer 'your_engine_name.migrations' do |app|
              config.paths['db/migrate'].expanded.each do |expanded_path|
                app.config.paths['db/migrate'] << expanded_path
                ActiveRecord::Migrator.migrations_paths << expanded_path
            
                if Rake.application.top_level_tasks.empty?
                  ActiveRecord::Migration.check_pending! if ActiveRecord::Migrator.needs_migration?
                end
              end
            
            end
            

            【讨论】:

              猜你喜欢
              • 2011-11-26
              • 1970-01-01
              • 1970-01-01
              • 2022-02-05
              • 2020-02-13
              • 2017-01-20
              • 2013-07-26
              • 2020-01-07
              • 2021-05-26
              相关资源
              最近更新 更多