如何覆盖gem中的rails生成器模板?

时间:2011-04-14 16:42:12

标签: ruby-on-rails-3 templates gem generator

如果要覆盖生成器模板(不替换生成器本身),在Rails 3中,您只需将文件放在lib / templates中相应命名的位置,Rails就会找到它们。

如果你想用宝石做这件事怎么办?我正在尝试采用我的团队的标准化脚手架格式并对其进行创建,以便我们可以在所有项目中共享它并轻松更新,而不是将文件复制到lib /中。这适用于我创建新生成器的情况;我用application.rb中的config.generators挂钩,然后Rails找到它。但是当我将模板文件放入 gem 中的lib / templates时,Rails首先找到它自己的默认模板,然后渲染它们而不是我的。我认为搜索顺序是RAILS_ROOT / lib / templates,RAILS_GEMS / lib / templates,OTHER_GEMS / lib / templates。

解决方案是什么?我在这方面找不到很多docco,并且通过Rails进行代码跳转没有提供明显的解决方案。谢谢!

6 个答案:

答案 0 :(得分:10)

我们想出来了。 generators config有一个'templates'变量,列出模板的搜索路径。问题确实是它按顺序搜索此数组,直到找到匹配项,因此您的应用程序或Rails中的模板将在gem中的模板之前找到。

解决方案是让你的gem的Railtie将模板路径放到模板路径数组的开头。看起来像这样。该文件位于[GEM] /lib/my_gem.rb中。模板在[GEM] / lib / templates /中与它平行。

module MyGem
  class Railtie < Rails::Railtie
    config.generators do |g|
      g.templates.unshift File::expand_path('../templates', __FILE__)
    end 
  end
end 

如果模板在[GEM] / lib / templates中有一条路径与您要覆盖的默认模板的路径相匹配,那么这应该有效。例如,如果您已完成此操作并创建[GEM] /lib/templates/active_record/model/model.rb,它将覆盖默认的AR模型模板。

不需要对生成器进行monkeypatching。

编辑:请注意,由于此答案最初发布,因此“配置生成器”已从Rails中删除。根据pixelearth的答案,使用config.app_generators代替。

答案 1 :(得分:10)

更新:IdahoEv有正确答案,但此代码自3.1起产生以下删除警告:

DEPRECATION WARNING: config.generators in Rails::Railtie is deprecated. Please use config.app_generators instead.

所以请改用:

module MyGem
  class Railtie < Rails::Railtie
    config.app_generators do |g|
      g.templates.unshift File::expand_path('../templates', __FILE__)
    end 
  end
end 

答案 2 :(得分:3)

使用rails 4.1.5时遇到同样的问题。这里是组装拼图解决方案。

首先在你的宝石like this中创建Railtie。 请记住,不推荐使用config.generators和thalespf`s answer

module SomeGem
  class Railtie < Rails::Railtie
    config.app_generators do |g|
      g.templates.unshift File::expand_path('../../templates', __FILE__)
    end
  end
end

像魅力一样!

UPD。我试图仅使用模板创建一个gem,并在Rails :: Engine中使用它。但它要求:

# lib/your_engine/engine.rb
require 'your_gem_with_generator_templates' # Loads Railtie

答案 3 :(得分:1)

对于导轨4和导轨引擎,我可以这样做:

module MyEngine
  class Engine < ::Rails::Engine
    isolate_namespace MyEngine

    config.generators do |g|
      g.templates.unshift File::expand_path("../templates", File.dirname(__FILE__))
    end
  end
end

答案 4 :(得分:1)

只有g.templates.unshift中的路径'../../templates'文件:: expand_path('../../ templates',_ FILE _)对我有用。我在轨道3.2

答案 5 :(得分:0)

如果有人在努力解决这个问题,我只需要使用其他答案就可以找到一个非常基本的宝石,你可以看一下这个例子:templates