41

我有多个 Rails 应用程序与同一个后端通信,我希望它们共享一些迁移。
我设置了一个 Rails 引擎(使用 enginex),我可以共享任何东西(控制器、视图、模型……)但不能迁移。我不能让它工作!

我试图创建一个文件 db/migrate/my_migration.rb 但如果我这样做,则在我的主应用程序中:

  rake db:migrate

它不会加载它们。

经过一番谷歌搜索后,似乎最近有一些关于此的工作并且似乎已合并到 rails master。我使用的是 rails 3.0.3,你有什么办法可以完成这项工作吗?

谢谢 !

4

6 回答 6

44

在 rails 3.1 中,您可以使用此命令执行此操作,假设您的引擎名称为example

# Note that you append _engine to the name
rake example_engine:install:migrations
于 2011-11-07T00:20:08.610 回答
34

我所做的是添加一个InstallGenerator将迁移添加到 Rails 站点本身的。它的行为与您提到的行为不完全相同,但就目前而言,对我而言,它已经足够好了。

一个小方法:

首先,创建文件夹lib\generators\<your-gem-name>\install并在该文件夹内创建一个文件install_generator.rb,使用以下代码调用:

require 'rails/generators/migration'

module YourGemName
  module Generators
    class InstallGenerator < ::Rails::Generators::Base
      include Rails::Generators::Migration
      source_root File.expand_path('../templates', __FILE__)
      desc "add the migrations"

      def self.next_migration_number(path)
        unless @prev_migration_nr
          @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
        else
          @prev_migration_nr += 1
        end
        @prev_migration_nr.to_s
      end

      def copy_migrations
        migration_template "create_something.rb", "db/migrate/create_something.rb"
        migration_template "create_something_else.rb", "db/migrate/create_something_else.rb"
      end
    end
  end
end

并在其中lib/generators/<your-gem-name>/install/templates添加包含迁移的两个文件,例如取一个名为create_something.rb

class CreateAbilities < ActiveRecord::Migration
  def self.up
    create_table :abilities do |t|
      t.string  :name
      t.string  :description
      t.boolean :needs_extent      
      t.timestamps
    end
  end

  def self.down
    drop_table :abilities
  end
end

然后,当您的 gem 添加到某个应用程序时,您可以这样做

rails g <your_gem_name>:install

这将添加迁移,然后你就可以做rake db:migrate.

希望这可以帮助。

于 2011-01-18T15:38:12.353 回答
23

在 3.1 下,您可以通过更改 config/application.rb 执行以下操作来共享迁移,而无需安装它们:

# Our migrations live exclusively w/in the Commons project
config.paths['db/migrate'] = Commons::Engine.paths['db/migrate'].existent
于 2011-12-03T00:37:47.037 回答
22

从 Rails 3.1 开始,解决方案看起来是:

bundle exec rake railties:install:migrations

如果您只想从特定的 railtie 复制,则:

bundle exec rake railties:install:migrations FROM=foo_engine

请注意,名称是您的 gem 名称加上 _engine。因此,如果 gem 是“foo”,那么名称就是 foo_engine。

于 2011-08-23T14:32:31.520 回答
18

对于导轨 4,请使用:

   initializer :append_migrations do |app|
      unless app.root.to_s.match root.to_s
        config.paths["db/migrate"].expanded.each do |expanded_path|
          app.config.paths["db/migrate"] << expanded_path
        end
      end
    end

https://content.pivotal.io/blog/leave-your-migrations-in-your-rails-engines

于 2014-02-12T16:51:40.327 回答
13

要摆脱 Levi 的回答,您也可以在实际引擎的引擎文件中执行类似的操作,而不是应用程序。

所以在 lib/commons/engine.rb

module Commons
  class Engine < Rails::Engine
    initializer "commons.load_app_instance_data" do |app|
      Commons.setup do |config|
        config.app_root = app.root
      end
      app.class.configure do 
        #Pull in all the migrations from Commons to the application
        config.paths['db/migrate'] += Commons::Engine.paths['db/migrate'].existent
      end
    end
    initializer "commons.load_static_assets" do |app|
      app.middleware.use ::ActionDispatch::Static, "#{root}/public"
    end
  end
end

编辑:尽管这样做之后不要弄乱人们的迁移历史,但要小心,如果需要更改,请确保添加新的迁移,否则您可能会迫使某人进行一些丑陋的回滚。

于 2012-06-26T18:05:57.933 回答