【问题标题】:"Regular" Ruby gem or Rails engine?“常规”Ruby gem 或 Rails 引擎?
【发布时间】:2016-04-13 19:30:55
【问题描述】:

我的 Rails 应用程序(Rails 3 和 4 的编译)都有自己的数据库(自然而然),但也访问第 3 方数据库。因此,他们有这个第 3 方数据库的模型。我想干燥这些模型以便可重复使用,而不是在每个应用程序中复制粘贴它们。没有需要考虑的控制器、助手或路由;只有模型。但由于它有 Rails “部件”,这似乎表明我需要一个引擎。但我希望在我的所有应用程序中使用这些模型这一事实似乎表明只需要一个“普通”兼容 rails 的 gem。

将其作为 gem 还是作为 Rails 引擎会更好吗?

如果引擎更好,我不太确定从哪里开始。从我读过的一些指南来看,好像你在一个新的 Rails 应用程序上创建了一个引擎。我对fullmountable 也有点不清楚,但我知道我希望这些模型在它们自己的命名空间中。

最后,我希望这些模型可以在我的所有应用程序中使用。引擎可以打包成 gem,对吗?如果是这样,那我就不能从 gem 开始,而不是从某个特定应用程序中的引擎开始,然后在事后导出 gem?

我很困惑,因此感谢任何反馈。我以前也从未构建过 gem 或引擎,所以请原谅这方面的任何愚蠢。

【问题讨论】:

  • 为什么除了模型之外没有其他任何东西表明您需要引擎?无论如何,哪个“更好”取决于,其余的非常广泛。从edgeguides.rubyonrails.org/engines.html 之类的内容开始并提出非常具体的问题是否有意义?
  • @DaveNewton:对不起,我的意思是因为它有任何 Rails“部件”,所以(在我看来)它应该是一个引擎。
  • 也许吧,虽然我不知道为什么会这样。如果它是一个 Gem,你也可以在 Rails 之外使用它(例如,命令行工具等),所以我倾向于这样做。
  • @DaveNewton:嗯,我看到的所有指南都提到“可重用 Rails 的东西 → 使用引擎”。这些是专门的 ActiveRecord 模型,因此(对我而言)在 Rails 之外使用它们没有意义。
  • 我想,但是有很多 ActiveXxx 的东西可以在 Rails 应用程序之外使用。

标签: ruby-on-rails model rubygems dry


【解决方案1】:

引擎实际上并没有那么神奇,尽管很容易获得这种印象。在最简单的情况下,“引擎”只是Rails::Engine 的子类。一旦它被您的 Rails 应用程序加载(例如require 'yourgem/engine),引擎中的方法就会执行并将您的引擎连接到 Rails 应用程序(包括神奇地将引擎内的一堆路径附加到应用程序的加载路径,这就是您的引擎模型和控制器如何加载到您的应用中的方式)。

现在,如果您尝试阅读Getting Started With Rails Engines,您可能会认为您无法创建引擎,除非您使用 Rails 生成器,并遵守 Rails 约定等等。但这一切都是可选的!我个人建议创建一个普通的 gem 并把它变成一个引擎,主要是通过阅读API docs,它更加脚踏实地。即使是推荐的在 gem 中使用 app 文件夹来保存模型和控制器等的模式,也可以被覆盖(请参阅 API 文档中的 Paths 部分)。

所以在你的情况下,你希望你的引擎只包含模型,我建议像这样的 gem 布局:

yourgem/
  app/
    models/
      yourgem/
        your_thing.rb
  db/
    migrate/
      20160413010101_create_models.rb
  lib/
    yourgem/
      engine.rb
      version.rb
    yourgem.rb
  yourgem.gemspec

你的 engine.rb 可以很简单:

# lib/yourgem/engine.rb
module YourGem
  class Engine < ::Rails::Engine
    isolate_namespace YourGem # this is generally recommended

    # no other special configuration needed. But maybe you want
    # an initializer to be added to the app? Easy!
    initializer 'yourgem.boot_stuff_up' do
      YourGem.boot_something_up!
    end
  end
end

并且您的迁移和模型看起来很正常(但请记住,您的模型必须在您的 gem 名称下限定范围,以避免与任何可能使用此引擎的应用发生冲突)。

希望有帮助!

【讨论】:

  • 好吧,您已经对引擎进行了更多解释,但我最初的问题仍未得到解答:哪种方法更好地完成我需要做的事情?另外(也许你错过了),我没有迁移;仅限模型。
  • @istrasci:无论哪种方式,您都需要创建一个 gem。现在,您的模型是 ActiveRecord::Base 的子类,还是只是普通的旧 Ruby 对象?如果是后者,忘记所有关于引擎的事情。如果是前者,我建议使用一个引擎来明确对 Rails 的依赖(并允许你挂钩,比如初始化器或生成器)。
  • 它们是 ActiveRecord::Base 的子类。因此,如果我在我现有的一个应用程序中创建一个引擎,那么我如何将这个引擎“编译”成我的其他应用程序可以使用的 gem?
  • 我建议手动提取它。我的意思是,创建你的 gem(bundler init 命令使这很容易;你应该在你的根工作区目录中,而不是在你的任何应用程序中),创建一个像我上面发布的文件夹结构(没有迁移文件夹,因为您不需要任何模型),然后将您的模型从您的应用程序中移出并移至该 gem 的 app/models/myengine 文件夹中。由于您正在为模型命名空间,请记住将它们全部从 MyModel 重命名为 MyEngine::MyModel。然后,将该 gem 添加到应用程序的 Gemfile 中,并更新对这些模型的引用以反映命名空间。
  • 如果您以前从未制作过 gem,那么在将引擎添加到组合中之前,创建一个简单的 gem 以了解 gemspecs 和 ruby​​gem 的工作原理可能是值得的。
猜你喜欢
  • 2010-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多