Rails 3.1:エンジンとマウント可能なアプリ


120

Rails EngineとMountableアプリの違いを理解するのを手伝ってくれる人はいますか?Rails 3.1では、「rails new plugin _ __」コマンドを使用していずれかを作成できます。

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

どちらを使いたいですか?Engineをgemとしてパッケージ化できることは知っています。マウント可能なアプリの場合はそうではありませんか?他にどんな違いがありますか?

回答:


143

私は次のことに気づきました:

フルエンジン

完全なエンジンでは、親アプリケーションはエンジンからルートを継承します。で何も指定する必要はありません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" 

私が想定から外れている場合は、誰かに知らせてください。この応答を修正します。私はここで主題についての小さな記事を作りました 乾杯!


1
マウント可能なエンジンを親アプリのルートにルーティング/マウントできますか?
Slick23、2011

3
@JustinMあなたが試すことができますmount MyEngine::Engine => "/"。リソースに対しては機能しますが、エンジンについても同様です。
Benoit Garret、2011

2
@astjohnあなたのブログの素晴らしいまとめ。しかし、それは逆のことではないでしょうか?フルエンジンは「不完全」であり、親アプリが機能する必要がありますが、マウント可能なエンジンは親アプリから「分離」されているため、スタンドアロンで機能しますか?
Theo Scholiadis

39

どちらのオプションでもエンジンが生成されます。違いは--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オプションのユースケースは非常に限られているようです。個人的には、名前空間も分離せずにコードをエンジンに分離したい理由は考えられません-基本的に、同じファイル構造とすべての競合とコード漏洩を共有する2つの密結合アプリケーションを提供するだけです。それが必要です。

私が見たすべてのドキュメンテーションは--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=独自の名前空間を持つエンジン。(驚くばかり)

参考文献


9
使用する理由が1つあり--fullます。RailsWebサイトの一部があり、統合されたまま(分離された名前空間ではない)であり、異なるRailsプロジェクト間で共有したい場合。また、それよりも単純な場合もあります。おそらく、gemはそれほど追加されないかもしれませんが、gemを正しくフックできるようにする必要があります。
nathanvda 2013年

2
@nathanvda-そうですが、複数のプロジェクト間で何かを共有している場合は、基本的にプラグインとして使用しているため、名前空間を指定する必要があります
Yarin

Admin::AdminService.some_actionEmberアプリなどの他のクライアント側アプリケーションがコードに関連するルートを使用する場合は、ファイルを分離したり、呼び出しサイトの名前空間を指定したり、ルートを変更する必要がない場合は、-fullを使用することをお勧めします。分離したい。--fullは、実装が容易な中間ステップのようです。
Jwan622

私は現在、国固有の規制を処理する必要がある国際的なアプリケーションに取り組んでいますが、同じインターフェースを世界に公開しています。国ごとに「コア」のインスタンスが1つあるので、一度にすべてを処理する必要はありません。「国のエンジン」はそれ自体では意味がないため、「コア」アプリとの結合は問題になりません。ただし、コアアプリが動作する国をコアアプリが認識してはならないため、それらを独自の名前空間に配置したくありません。「フル」エンジンは、ファイルとクラスをモジュール方式で整理するようなものですが、「モノリス」はそのままにします。
マンカラ2018

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

多分それ--fullは優先順位が高いから--mountableでしょうか?
マンカラ

8

違いを理解すると、エンジンはプラグインのようなものであり、既存のアプリケーションに機能を追加します。マウント可能なアプリは基本的にアプリケーションであり、スタンドアロンで使用できます。

したがって、それを単独で、または別のアプリケーション内で実行したい場合は、マウント可能なアプリを作成します。既存のアプリケーションへの追加を意図しているが、それ自体では実行しない場合は、それをエンジンにします。


2

違いは、マウント可能なアプリはホストアプリから分離されているため、クラス、モデル、ヘルパーなどを共有できないことです。これは、マウント可能なアプリがラックエンドポイント(つまり、独自のラックアプリ)であるためです。 )。

免責事項:私は、ほとんどのように、Rails 3.1をいじったばかりです。


同意した。奇妙に思われることの1つは、デフォルトでは、エンジンは「モデル」フォルダーを提供しますが、マウント可能なアプリは提供しないことです。「ベストプラクティス」は、インクルードするアプリのモデルを作成するジェネレーターを用意することでしょうか。これは、エンジン/マウスでの移行を望まないようです
Jeremy Raines
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.