【问题标题】:Sharing a mongoid model between 2 applications - using engine vs. plugin在 2 个应用程序之间共享一个 mongoid 模型 - 使用引擎与插件
【发布时间】:2015-07-09 16:16:50
【问题描述】:

我想在我的 Rails 应用程序的 2 个(将来可能更多)之间共享一个模型。我找不到任何明确的建议,但我收集了一些我读过的问题和答案,得出的结论是必须使用“gemmed”插件引擎来完成。 我决定使用插件,因为我读到该引擎只是一种“完整”插件。

所以我创建了一个插件,使用:rails plugin new my_models --skip-active-record --skip-test-unit --dummy-path=spec/dummy(选项是跳过 activerecord 作为 ORM 并使用 rspec 进行测试)。

创建插件后,我得到以下文件:

my_models.gemspec  Gemfile  Gemfile.lock  lib  MIT-LICENSE  Rakefile  README.rdoc  spec

我尝试使用以下方法包含模型:

  1. 只需创建一个app/models 目录并将我的模型放入其中
  2. 按照this tutorial 中的建议(我可以在devise's github 中看到),我创建了一个生成器来尝试生成模型。

他们都失败了,然后我决定采用引擎建议(只需将 --mountable 添加到“rails new”命令的选项列表中),我得到了完整的 rails 应用程序结构(带有 app、bin , db 和其他目录),将我的模型放在 app/models 目录中,它就像魔术一样工作!

因为我相信我是程序员而不是魔术师,所以我不会做这种魔术,所以你能告诉我我的两个瘦插件解决方案(使用生成器/创建模型)有什么问题吗?此外,使用这些生成器有什么好处?

我正在附上我的生成器的代码,也许我错过了什么:

require 'rails/generators/named_base'
require 'mongoid'

module Mongoid
  module AttackGenerator
    def generate_model
      invoke "mongoid:model", [name] unless model_exists? && behavior == :invoke
    end

    def inject_field_types
      inject_into_file model_path, migration_data, after: "include Mongoid::Document\n" if model_exists?
    end

    def migration_data
      field :link_url, type: String
      field :token, type: String
    end

    def model_exists?
      File.exists?(File.join(destination_root, model_path))
    end

    def model_path
      @model_path ||= File.join("app", "models", "#{file_path}.rb")
    end
  end
end

【问题讨论】:

  • 对于非完整引擎/插件,您可能需要 require 来自父应用程序的文件。如果它们已经在加载路径上,您可以执行require 'my_engine/whatever,否则为require MyEngine::Engine.root.join('app', 'models', 'whatever')
  • 我同意您关于成为程序员而不是魔术师的观点,但是当您使用 Rails 时,您已经完全投降于魔术领域。你必须学习咒语和咒语,如果你试图理解它们太过分,那就像盯着太阳一样。
  • 我可能错了,但插件的概念是“遗留”的东西,在 rails 2 中有效(不确定在 3 中是否仍然有效),也许生成器只是为了这个目的。目前,创建一个引擎就像在一个简单的 gem 中使用 Railtie 一样简单,该 gem 由 bundle gem gem_nameapp 目录和一些小东西构建。虽然我必须承认,在你的具体情况下,感觉你不需要引擎,你可以用一个简单的 gem
  • @Fire-Dragon-DoL 引擎和简单的 gem 有什么区别?如何创建既不是引擎也不是插件的 gem?
  • 其实我忘了迁移,你需要一个引擎。我添加了一个包含更多细节的答案。 gem 基本上是一个库,引擎仍然是一个 gem,但带有一个文件 engine.rb(加载在 gem 中),它通过自动加载应用程序目录和其他内容来增强 gem 功能。有关详细信息,请参阅我的答案。它很长,需要你学习各种各样的东西,但它们非常有趣,一旦你理解了它,你就会明白更多的“rails magic”;)

标签: ruby-on-rails ruby-on-rails-plugins rails-engines


【解决方案1】:

engine(非常好的指南)基本上是一个小型 Rails 应用程序:具有控制器,可以通过各种方式(共享类/控制器等)注入到您的 Rails 代码中,最重要的是,可以使用您的主要 Rails 应用程序代码透明的。

想了想,我相信你需要一个引擎,原因是,一个简单的模型仍然需要迁移。请注意,引擎基本上是一个 gem 加上 Rails 提供的一些附加功能。

虽然 miguiding(不再使用 rails 中的插件),但命令 rails plugin new blorgh --mountable 创建了一个 gem,它是一个 rails 引擎。

您如何理解 gem 是否是 rails 引擎?通过文件engine.rb(可以不同的命名,内容是重要的东西)。

module Blorgh
  class Engine < ::Rails::Engine
    isolate_namespace Blorgh
  end
end

您应该注意的另一件重要的事情是,当您将自定义 gem 添加到 gemfile 时,rails(实际上是 Bundler.require)自动 requires 一个文件:文件命名为 lib/yourgemname.rb,在本例中为 lib/blorgh.rb。那是你的切入点。 除此之外,所有其他东西(gemspec 和所有其他文件)都是为 ruby​​gems 创建的。重要的部分是您使用.gemspec 文件作为gemfile,只需使用add_dependency 而不是标准的Gemfile 语法添加gem。如果您想(并且应该)了解更多关于红宝石的信息,this article 非常棒

app 目录像 rails 一样自动加载,因此添加 app/models/yourmodel.rb 是让您的模型自动加载并与所有应用共享的好方法。 最后一个重要的事情是迁移。您必须记住在 Rails 应用程序中运行 your_engine_name:install:migrations 以将迁移从引擎复制到 Rails 应用程序并运行它们(否则您可以在 this article 上看到建议)

你准备好了。一注!要安装您的 gem,您有两个选择:使用远程 git 存储库(最佳选择)或本地开发,您可以使用 :path,这里有两个可以添加到 Rails 应用程序 gemfile 的示例:

# Use this only for development purposes
gem 'yourgem', '1.0.0', path: 'your/local/path/to/gem'

# Use this for deploy and such, you'll need access to that repository
gem 'yourgem', '1.0.0', git: 'yourgiturl'

应该够了

【讨论】:

    猜你喜欢
    • 2012-09-19
    • 2019-10-12
    • 2014-02-16
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    • 1970-01-01
    • 2014-09-30
    相关资源
    最近更新 更多