【问题标题】:Rails Gem: Running All Generators for given NamespaceRails Gem:为给定的命名空间运行所有生成器
【发布时间】:2013-03-28 09:41:48
【问题描述】:

我正在开发一个包含多个子模块的 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 任务或生成器。

提前致谢!

【问题讨论】:

  • 一个 rake 任务来运行其他 rake 任务? This tutorial 解释了如何做到这一点。这有帮助吗?
  • 这些不是 rake 任务,它们是生成器。但我不想运行所有这些,只运行命名空间中可用的那些。因此,Admin namspace 中的任何生成器都将运行。

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


【解决方案1】:

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

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

类似这样的:

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

Here's the link to the gist with complete tested code

这样,运行rails g admin:all 将直接在Admin::Generators 下运行所有​​其他生成器。

【讨论】:

  • 在 AllGenerator 中遍历 Admin::Generators 只会返回 AllGenerator。但是,当我运行rails g 时,我可以看到列表中的所有生成器并输出到控制台。
  • 你能分享一下你用来迭代生成器的代码要点吗?
  • 另一个答案有问题 - 需要添加 const_get 才能获得实际课程。请参阅更新的答案。 (我还没有尝试过,希望它有效:))
  • 感谢您的帮助。看起来这在大多数情况下都有效,但 AllGenerator 似乎没有加载任何其他生成器。 AllGenerator 的Here's a gist。当我运行rails g 时,我看到了我所有的puts 语句,并且我看到了所有的生成器,但是当我运行 All 命令时却没有。有什么想法吗?
  • 最后我测试了这个,猜猜看,它没有用。我已经修好了,here's the gist。我已经在 Rails 应用程序中对此进行了测试,它按预期工作。希望对您有所帮助。
【解决方案2】:

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

Find classes available in a Module

所以你所要做的就是访问

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 多一点,但我认为应该这样做。

【讨论】:

  • 在尝试c &lt; Rails::Generators::Base之前需要添加c = Admin::Generators.const_get(c)
猜你喜欢
  • 1970-01-01
  • 2015-06-15
  • 1970-01-01
  • 2016-10-02
  • 2013-02-09
  • 1970-01-01
  • 2012-01-09
  • 2016-04-06
  • 2014-01-29
相关资源
最近更新 更多