有人能帮我理解Rails引擎和可安装应用程序之间的区别吗?在Rails 3.1中,您可以使用"Rails new plugin___"命令创建其中一个。
rails plugin new forum --full # Engine
rails plugin new forum --mountable # Mountable App
你想在什么时候使用一种与另一种?我知道你可以把引擎包装成宝石。可安装应用程序不是这样吗?还有什么不同之处?
我注意到以下内容:
全引擎
使用完整引擎时,父应用程序将继承引擎中的路由。不需要在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"
如果我的假设有偏差,请有人告诉我,我会解决这个问题。我在这里写了一篇关于这个主题的小文章。
这两个选项都将生成一个引擎。不同之处在于,--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)控制器、助手、视图和资产的文件结构将按名称命名:
创建app/controllers/my_mountable_engine/application_controller.rb
创建app/helpers/my_mountable_engine/application_helper.rb
创建应用/邮件创建应用/模型
创建app/views/layouts/my_mountable_engine/application.html.erb
创建app/assets/images/my_mountable_engine
创建app/assets/stylesheets/my_mountable_engine/application.css
创建app/assets/javascripts/my_mountable_engine/application.js
create-config/routes.rb create-lib/mymountable_engine.rb
创建lib/tasks/mymountable_engine.rake
创建lib/mymountable_engine/version.rb
创建lib/my_mountable_engine/engine.rb
解释
--full
选项的用例似乎非常有限。就我个人而言,我想不出有什么好的理由可以让你在不隔离命名空间的情况下将代码分离到一个引擎中——这本质上只是让你两个紧密耦合的应用程序共享相同的文件结构,以及由此产生的所有冲突和代码泄漏。
我看到的每一篇文档都演示了--mountable
选项,事实上,当前的边缘指南强烈鼓励您包含isolate namespace
,这与使用--mountable
而不是--full
是一样的。
最后是术语混乱:不幸的是,rails plugin -h
显示了以下描述:
[-full]#使用捆绑的rails应用程序生成rails引擎进行测试
[-mountable]#生成可挂载的隔离应用
这给人的印象是,您使用CCD_;发动机";以及CCD_ 13来创建被称为";可安装应用程序";,事实上,它们都是引擎——一个同名,一个不同名。这势必会导致混乱,因为希望创建引擎的用户可能会认为--full
是更相关的选项。
结论
rails plugin new something --full
=应用程序命名空间中的引擎。(你为什么要?)rails plugin new something --mountable
=具有自己名称空间的引擎。(太棒了)
参考文献
- http://edgeguides.rubyonrails.org/engines.html
- http://api.rubyonrails.org/classes/Rails/Engine.html
- http://railscasts.com/episodes/277-mountable-engines
- https://github.com/rails/rails/pull/6499
我也有同样的想法,因此,我来到了这里。在我看来,前面的答案基本上涵盖了这个问题,但我认为以下可能也会有所帮助:
# 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
我对区别的理解是,引擎就像插件,为现有应用程序添加功能。而可挂载应用程序本质上是一个应用程序,可以独立运行。
因此,如果你想自己或在另一个应用程序中运行它,你可以制作一个可安装的应用程序。如果你想让它成为现有应用程序的一个补充,但不是自己运行的,那么你就把它变成了一个引擎。
我认为,不同之处在于,可安装的应用程序与主机应用程序是隔离的,因此它们不能共享类-型号、助手等。这是因为可安装应用程序是机架端点(即机架应用程序本身)。
免责声明:我和大多数人一样,才刚刚开始玩Rails 3.1。