Rails 3.1:引擎与可安装应用程序

时间:2011-05-25 02:29:11

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

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

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

你想什么时候使用一个?我知道你可以将Engine打包成一个宝石。可安装应用程序的情况不是这样吗?还有什么其他差异?

5 个答案:

答案 0 :(得分:139)

我注意到以下内容:

完整引擎

使用完整引擎,父应用程序将继承引擎中的路由。没有必要在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 

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

这些是我发现的主要差异。也许还有其他人?我问过here,但尚未收到回复。

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

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

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

如果我在假设中离开,有人请告诉我,我会解决这个问题。我做了一篇关于这个主题的小文章here干杯!

答案 1 :(得分:38)

这两个选项都会生成engine。不同之处在于--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 / mailers创建app / models
  创建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 / 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选项,实际上当前edge guide强烈建议您加入isolate namespace - 这与使用{相同} {1}}超过--mountable

终于出现了术语混淆:不幸的是--full显示了以下描述:

  

[ - full]#使用捆绑的Rails应用程序生成 rails engine 以进行测试   [--mountable]#生成可安装的隔离应用程序

这给人的印象是您使用rails plugin -h来创建&#34;引擎&#34;并--full创建一个名为&#34;可安装的应用程序&#34;的东西,实际上它们都是引擎 - 一个是命名空间而另一个不是。当用户希望创建引擎时,可能会认为--mountable是更相关的选项。

结论

  • --full =您应用的命名空间中的引擎。 (你为什么这么做?)
  • rails plugin new something --full =引擎拥有自己的命名空间。 (真棒)

参考

答案 2 :(得分: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

答案 3 :(得分:8)

我对差异的理解是引擎就像插件,并为现有应用程序添加功能。虽然可安装的应用程序本质上是一个应用程序,但可以独立使用。

因此,如果您希望能够自行运行或在其他应用程序中运行它,您可以创建一个可安装的应用程序。如果您打算将它添加到现有应用程序中,但不能单独运行,那么您可以将其作为引擎。

答案 4 :(得分:2)

我认为,不同之处在于可安装的应用程序与主机应用程序隔离,因此无法共享类 - 模型,助手等。这是因为可安装的应用程序是机架端点(即机架中的应用程序)它自己的权利。)

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