Ruby on rails Rails 3.2:从可装载引擎添加种子任务

Ruby on rails Rails 3.2:从可装载引擎添加种子任务,ruby-on-rails,ruby-on-rails-3,rubygems,rake,Ruby On Rails,Ruby On Rails 3,Rubygems,Rake,我有一个rails应用程序,它使用了rakedb:seed来填充数据库中的一些基础知识以开始工作。这是通过一个小的基础设施和一个fixture来实现的。rb其他人编写了将YAML加载到DB中的命令。 我想做的是将这个基础设施转移到我自己的gem中,这样我就可以在其他地方再次使用它,这需要我通过gem的seed任务插入我自己的gem模型(我想通过调用db:seed或主应用程序中的类似任务来运行)主应用程序使用自己的种子推送一些gem的模型。第二部分我已经开始工作了,它是fixtures.rb文件中

我有一个rails应用程序,它使用了
rakedb:seed
来填充数据库中的一些基础知识以开始工作。这是通过一个小的基础设施和一个fixture来实现的。rb其他人编写了将YAML加载到DB中的命令。
我想做的是将这个基础设施转移到我自己的gem中,这样我就可以在其他地方再次使用它,这需要我通过gem的seed任务插入我自己的gem模型(我想通过调用
db:seed
或主应用程序中的类似任务来运行)主应用程序使用自己的种子推送一些gem的模型。第二部分我已经开始工作了,它是fixtures.rb文件中的一个简单修复。 我现在想做的事情是:

  • 将fixtures.rb移到gem中:我仍然没有任何源代码在gem中运行这个。现在要做到这一点,我可能需要
    [MyGem::Engine.root,'lib',…]中的文件。join
    然后在那里调用一个方法,该方法具有将YAML文件从加载到DB的路径,我不明白为什么它不应该工作
  • 获取
    rake db:seed
    以运行在我的gem中定义的任务。我在gem(它是一个引擎)的lib/tasks下添加了.rake文件,但我似乎无法从主应用程序rakefile调用它们。
    为了让自己明白,我想做的是通过gem(不是主应用程序-或者主应用程序中有一行代码)在主应用程序种子任务上添加一个依赖项,这样当有人在主应用程序中运行
    rake db:seed
    时,gem将运行额外的种子,而主应用程序开发人员甚至不必知道它们
我想要避免的肮脏解决方案是从主应用程序中的gem加载.rake文件,或者从主应用程序中的gem加载seeds.rb


因此,我要问的基本上是如何让rake db:seed任务只需在gemfile中包含所需的gem,就可以在gemfile中执行gem中定义的任务?

因此,在问了这个问题后,我很快就明白了。 第一步从这里开始:

然后在任务文件中

#lib/task/some_task.rake
Rake::Task['db:seed'].enhance ['my_seed_task']

#lib/tasks/my_seed_task.rake
task 'my_seed_task' do
  ...
end

现在,当我在主应用程序中运行rake db:seed时,它运行我的seed任务定义为额外条件的任何东西。

尝试扩展
Rails::Generators::Base

:

“生成器中的每个公共方法都是在调用生成器时执行的”

所以

classdbgenerator

这种方法将允许所有基于gem的seed数据复制到app dir中,以便运行
db:seed
run

由于依赖于
Rakefile
添加,因此很脆弱。Rails在Rails::generator中内置了一个反射器。为什么说它很脆弱?如果忘记将其添加到rakefile中,那么gem资产将被错误地放置。扩展的
Rails::Generators::Base
确保这些资产将被包括在内。如果您想要一个条件包含,那么这应该是包含gem本身的条件。我的第一个想法是,对于一个有一些你可能不想包括在内的资产的创业板来说,这是1。创业板中的资产太多,或2。资产创业板是错误的机制。关键是我使用的是增强。这样,就没有人将它添加到rakefile中,而是将gem安装到rails应用程序中会自动使我的rake任务成为
db:seed
的附加任务,无论如何都需要运行它。为了与gem合作,必须这样做。生成器也必须通过主机应用程序运行,然后db:seed也必须运行,不是吗?我必须考虑一下:Rails生成器组件和Rake take目标之间的责任差异。在以应用程序为中心的思维中,应用程序无法意识到额外的资产,即使它意识到了gem。
class DbGenerator < Rails::Generators::Base
  source_root File.expand_path('../../../../db', __FILE__)

  def copy_seeds_file
    copy_file 'seeds.rb', 'db/seeds.rb'
  end

  def copy_seeds_dir
    Dir.foreach seeds_dir do |file|
      copy_file "seeds/#{file}", "db/seeds/#{file}"  unless file.match /^\./
    end
  end

  def seeds_dir
    File.expand_path 'seeds', self.class.source_root
  end
end