121

有人可以帮我理解 Rails 引擎和 Mountable 应用程序之间的区别吗?在 Rails 3.1 中,您可以使用“rails new plugin _ __ ”命令创建任何一个。

rails plugin new forum --full        # Engine
rails plugin new forum --mountable   # Mountable App

您想在什么时候使用一个与另一个?我知道您可以将 Engine 打包为一个 gem。可安装应用程序不是这种情况吗?还有哪些不同之处?

4

5 回答 5

145

我注意到以下几点:

全引擎

使用完整的引擎,父应用程序从引擎继承路由。没有必要在 中指定任何内容parent_app/config/routes.rb。在 Gemfile 中指定 gem 足以让父应用继承模型、路由等。引擎路由指定为:

# my_engine/config/routes.rb 
Rails.application.routes.draw do 
  # whatever 
end 

没有模型、控制器等的命名空间。父应用程序可以立即访问这些。

可挂载引擎

引擎的命名空间默认是隔离的:

# my_engine/lib/my_engine/engine.rb
module MyEngine 
  class Engine < Rails::Engine 
    isolate_namespace MyEngine 
  end 
end

使用可挂载引擎,路由是命名空间的,并且父应用程序可以将此功能捆绑在单个路由下:

# my_engine/config/routes.rb 
MyEngine::Engine.routes.draw do 
  #whatever 
end 

# parent_app/config/routes.rb 
ParentApp::Application.routes.draw do 
    mount MyEngine::Engine => "/engine", :as => "namespaced" 
end 

模型、控制器等与父应用程序隔离 - 尽管可以轻松共享帮助程序。

这些是我发现的主要区别。也许还有其他人?我在这里问过,但还没有收到回复。

我的印象是,由于完整的引擎不会将自己与父应用程序隔离,因此最好将其用作与父应用程序相邻的独立应用程序。我相信可能会发生名称冲突。

在您希望避免名称冲突并将引擎捆绑在父应用程序中的一个特定路径下的情况下,可以使用可安装引擎。例如,我正在构建我的第一个为客户服务设计的引擎。父应用程序可以将其功能捆绑在单个路由下,例如:

mount Cornerstone::Engine => "/cornerstone", :as => "help" 

如果我的假设与我的假设相去甚远,请有人告诉我,我会修正这个回复。我在这里写了一篇关于这个主题的小文章 干杯!

于 2011-07-26T16:22:15.447 回答
43

这两个选项都将生成一个引擎。不同之处在于--mountable它将在隔离的命名空间中--full创建引擎,而将创建一个共享主应用程序命名空间的引擎。

差异将体现在3个方面:

1)引擎类文件将调用isolate_namespace

lib/my_full_engine/engine.rb:

module MyFullEngine
  class Engine < Rails::Engine
  end
end

lib/my_mountable_engine/engine.rb:

module MyMountableEngine
  class Engine < Rails::Engine
    isolate_namespace MyMountableEngine # --mountable option inserted this line
  end
end

2)引擎的config/routes.rb文件将被命名空间:

全引擎:

Rails.application.routes.draw do
end

安装发动机:

MyMountableEngine::Engine.routes.draw do
end

3) 控制器、助手、视图和资产的文件结构将被命名为:

create app/controllers/ my_mountable_engine /application_controller.rb
create app/helpers/ my_mountable_engine /application_helper.rb
create app/mailers create app/models
create app/views/layouts/ my_mountable_engine /application.html.erb
create app/assets/images/ my_mountable_engine
create app/assets/stylesheets/ my_mountable_engine /application.css
create app/assets/javascripts/ my_mountable_engine /application.js
create config/routes.rb create lib/my_mountable_engine.rb
create lib/tasks/my_mountable_engine.rake
create lib/my_mountable_engine/version .rb
创建 lib/my_mountable_engine/engine.rb


解释

--full选项的用例似乎非常有限。就我个人而言,我想不出任何充分的理由为什么你想在不隔离命名空间的情况下将代码分离到一个引擎中——它本质上只会给你两个紧密耦合的应用程序共享相同的文件结构以及所有的冲突和代码泄漏这需要。

我看过的每一篇文档都展示了这个--mountable选项,而且当前的边缘指南确实强烈鼓励你包含isolate namespace——这与说 use --mountableover是一样的--full

最后是术语混乱:不幸的是rails plugin -h显示以下描述:

[--full] # 生成一个带有捆绑 Rails 应用程序的 Rails引擎
用于测试 [--mountable] # 生成可挂载的隔离应用程序

这给人的印象是您--full用来创建“引擎”并--mountable创建其他称为“可安装应用程序”的东西,而实际上它们都是引擎 - 一个是命名空间的,一个不是。这势必会导致混淆,因为希望创建引擎的用户可能会认为这--full是更相关的选项。

结论

  • rails plugin new something --full= 应用程序命名空间中的引擎。(你为什么会?)
  • rails plugin new something --mountable= 具有自己命名空间的引擎。(惊人的)

参考

于 2013-06-23T17:34:42.950 回答
17

我也想知道,因此,最终来到了这里。在我看来,早期的答案基本上涵盖了这个问题,但我认为以下内容也可能有所帮助:

# generate plugins (NOTE: using same name each time to minimize differences)
# -----------------------------------------------------------------------------

$ rails plugin new test-plugin -T
$ mv test-plugin{,.01}

$ rails plugin new test-plugin -T --mountable
$ mv test-plugin{,.02}

$ rails plugin new test-plugin -T --full
$ mv test-plugin{,.03}

$ rails plugin new test-plugin -T --full --mountable
$ mv test-plugin{,.04}




# compare "stock" (01) with "mountable" (02)
# -----------------------------------------------------------------------------

$ diff -r test-plugin.01 test-plugin.02

Only in test-plugin.02: app
Only in test-plugin.02: config
Only in test-plugin.02/lib/test-plugin: engine.rb
diff -r test-plugin.01/lib/test-plugin.rb test-plugin.02/lib/test-plugin.rb
0a1,2
> require "test-plugin/engine"
> 
Only in test-plugin.02: script
diff -r test-plugin.01/test-plugin.gemspec test-plugin.02/test-plugin.gemspec
18a19
>   # s.add_dependency "jquery-rails"




# compare "stock" (01) with "full" (03)
# -----------------------------------------------------------------------------

$ diff -r test-plugin.01 test-plugin.03
Only in test-plugin.03: app
Only in test-plugin.03: config
Only in test-plugin.03/lib/test-plugin: engine.rb
diff -r test-plugin.01/lib/test-plugin.rb test-plugin.03/lib/test-plugin.rb
0a1,2
> require "test-plugin/engine"
> 
Only in test-plugin.03: script
diff -r test-plugin.01/test-plugin.gemspec test-plugin.03/test-plugin.gemspec
18a19
>   # s.add_dependency "jquery-rails"




# compare "mountable" (02) with "full" (03)
# -----------------------------------------------------------------------------

$ diff -r test-plugin.02 test-plugin.03

Only in test-plugin.03/app/assets/javascripts/test-plugin: .gitkeep
Only in test-plugin.02/app/assets/javascripts/test-plugin: application.js
Only in test-plugin.03/app/assets/stylesheets/test-plugin: .gitkeep
Only in test-plugin.02/app/assets/stylesheets/test-plugin: application.css
Only in test-plugin.03/app/controllers: .gitkeep
Only in test-plugin.02/app/controllers: test-plugin
Only in test-plugin.03/app/helpers: .gitkeep
Only in test-plugin.02/app/helpers: test-plugin
Only in test-plugin.03/app/mailers: .gitkeep
Only in test-plugin.03/app/models: .gitkeep
Only in test-plugin.03/app/views: .gitkeep
Only in test-plugin.02/app/views: layouts
diff -r test-plugin.02/config/routes.rb test-plugin.03/config/routes.rb
1c1
< TestPlugin::Engine.routes.draw do
---
> Rails.application.routes.draw do
diff -r test-plugin.02/lib/test-plugin/engine.rb test-plugin.03/lib/test-plugin/engine.rb
3d2
<     isolate_namespace TestPlugin




# compare "mountable" (02) with "full & mountable" (04)
# -----------------------------------------------------------------------------

$ diff -r test-plugin.02 test-plugin.04

<no difference>




# compare "full" (03) with "full & mountable" (04)
# -----------------------------------------------------------------------------

$ diff -r test-plugin.03 test-plugin.04

Only in test-plugin.03/app/assets/javascripts/test-plugin: .gitkeep
Only in test-plugin.04/app/assets/javascripts/test-plugin: application.js
Only in test-plugin.03/app/assets/stylesheets/test-plugin: .gitkeep
Only in test-plugin.04/app/assets/stylesheets/test-plugin: application.css
Only in test-plugin.03/app/controllers: .gitkeep
Only in test-plugin.04/app/controllers: test-plugin
Only in test-plugin.03/app/helpers: .gitkeep
Only in test-plugin.04/app/helpers: test-plugin
Only in test-plugin.03/app/mailers: .gitkeep
Only in test-plugin.03/app/models: .gitkeep
Only in test-plugin.03/app/views: .gitkeep
Only in test-plugin.04/app/views: layouts
diff -r test-plugin.03/config/routes.rb test-plugin.04/config/routes.rb
1c1
< Rails.application.routes.draw do
---
> TestPlugin::Engine.routes.draw do
diff -r test-plugin.03/lib/test-plugin/engine.rb test-plugin.04/lib/test-plugin/engine.rb
2a3
>     isolate_namespace TestPlugin

(对我来说)特别感兴趣的是,两者之间没有区别

rails plugin new test-plugin -T --mountable

rails plugin new test-plugin -T --full --mountable
于 2012-09-25T07:57:20.657 回答
8

我对不同之处的理解是引擎就像插件,向现有应用程序添加功能。虽然可挂载应用程序本质上是一个应用程序,并且可以独立存在。

因此,如果您希望能够单独运行它或在另一个应用程序中运行它,您将制作一个可挂载的应用程序。如果您打算将其作为现有应用程序的补充,但不单独运行,则可以将其作为引擎。

于 2011-07-09T08:11:54.853 回答
2

我相信,不同之处在于可挂载应用程序与主机应用程序隔离,因此它们不能共享类 - 模型、帮助程序等。这是因为可挂载应用程序是 Rack 端点(即本身就是 Rack 应用程序) )。

免责声明:和大多数人一样,我才刚刚开始使用 Rails 3.1。

于 2011-06-02T09:47:38.753 回答