3

我正在开发一个包含多个子模块的 gem 核心,每个子模块都是自己的 gem。作为开发人员,您将能够安装核心和任何其他 gem。如何创建一个 rake 任务或生成器,以在主 gem 命名空间下使用生成器为所有已安装的 gem 运行生成器。

例如,如果我的 gem 被称为admin

module Admin
  module Generators
    class InstallGenerator < Rails::Generators::Base
    end
  end
end

我还有另一个用于其中一个子宝石的生成器:

module Admin
  module Generators
    class PostsGenerator < Rails::Generators::Base
    end
  end
end

还有一个:

module Admin
  module Generators
    class TagslGenerator < Rails::Generators::Base
    end
  end
end

最多可以安装 10 个 gem。而不是 rail g admin:... 安装每个,我想创建一个运行所有任务的 rake 任务或生成器。

提前致谢!

4

2 回答 2

1

首先查看以下问题和答案。

查找模块中可用的类

所以你所要做的就是访问

Admin::Generators.constants.each do |c| 
   c = Admin::Generators.const_get(c)
   if c < Rails::Generators::Base
     c.new.run(your_args)
   end
end

唯一的问题是我从未调用过这样的生成器,所以它可能比 c.new.run 多一点,但我认为应该这样做。

于 2013-04-05T21:16:59.120 回答
1

在 Admin 模块下保留一个“AllGenerator”类。生成器必须执行以下操作:

  1. 对于命名空间下作为生成器类的每个类,
  2. 从类名中获取命名空间。
  3. 使用命名空间调用invoke方法

像这样的东西:

module Admin
  module Generators
    class AllGenerator < Rails::Generators::Base
      def generator
        Rails::Generators.lookup!
        Admin::Generators.constants.each do |const|
          generator_class = Admin::Generators.const_get(const)
          next if self.class == generator_class
          if generator_class < Rails::Generators::Base
            namespace = generator_klass_to_namespace(generator_class)
            invoke(namespace)
          end
        end
      end
      private
        def generator_klass_to_namespace(klass)
          namespace = Thor::Util.namespace_from_thor_class(klass)
          return namespace.sub(/_generator$/, '').sub(/:generators:/, ':')
        end
    end

  end
end

这是带有完整测试代码的要点的链接

这样,runningrails g admin:all将直接在Admin::Generators.

于 2013-04-05T21:46:59.090 回答