web-dev-qa-db-fra.com

Rails 3.1: moteur vs application montable

Quelqu'un peut-il m'aider à comprendre les différences entre un moteur Rails et une application montable? Dans Rails 3.1, vous pouvez créer l'un ou l'autre avec le "nouveau plugin Rails - _ __ "commande.

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

Quand voudriez-vous utiliser l'un par rapport à l'autre? Je sais que vous pouvez emballer un moteur comme un joyau, pour commencer. N'est-ce pas le cas pour les applications montables? Quelles sont les autres différences?

119
Jeremy Raines

J'ai remarqué ce qui suit:

Moteur complet

Avec un moteur complet, l'application parent hérite des itinéraires du moteur. Il n'est pas nécessaire de spécifier quoi que ce soit dans parent_app/config/routes.rb. La spécification de la gemme dans Gemfile suffit à l'application parente pour hériter des modèles, des itinéraires, etc. Les itinéraires du moteur sont spécifiés comme suit:

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

Aucun espace de noms des modèles, contrôleurs, etc. Ceux-ci sont immédiatement accessibles à l'application parente.

Moteur montable

L'espace de noms du moteur est isolé par défaut:

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

Avec un moteur montable, les routes sont à espace de noms et l'application parent peut regrouper cette fonctionnalité sous une seule route:

# 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 

Les modèles, contrôleurs, etc. sont isolés de l'application parente - bien que les aides puissent être partagées facilement.

Ce sont les principales différences que j'ai repérées. Il y en a peut-être d'autres? J'ai demandé plus ici , mais je n'ai pas encore reçu de réponse.

Mon impression est que, comme un moteur complet ne s'isole pas de l'application parent, il est préférable de l'utiliser en tant qu'application autonome adjacente à l'application parent. Je pense que des conflits de noms pourraient se produire.

Un moteur montable peut être utilisé dans les situations où vous souhaitez éviter les conflits de noms et regrouper le moteur sous une route spécifique dans l'application parente. Par exemple, je travaille à la construction de mon premier moteur conçu pour le service client. L'application parent pourrait regrouper ses fonctionnalités sous une seule route, comme:

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

Si je suis loin de mes hypothèses, quelqu'un me le fait savoir et je corrigerai cette réponse. J'ai fait un petit article sur le sujet ici Bravo!

140
astjohn

Les deux options généreront un moteur . La différence est que --mountable créera le moteur dans un espace de noms isolé, tandis que --full créera un moteur qui partage l'espace de noms de l'application principale.

Les différences se manifesteront de 3 manières:

1) Le fichier de classe de moteur appellera 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) Le moteur config/routes.rb le fichier sera à espace de noms:

Moteur complet:

Rails.application.routes.draw do
end

Moteur monté:

MyMountableEngine::Engine.routes.draw do
end

3) La structure des fichiers pour les contrôleurs, les assistants, les vues et les ressources sera à espace de noms:

créer une application/contrôleurs/ my_mountable_engine /application_controller.rb
créer app/helpers/ my_mountable_engine /application_helper.rb
créer application/mailers créer application/modèles
créer une application/vues/mises en page/ my_mountable_engine /application.html.erb
créer une application/ressources/images/ my_mountable_engine
créez app/assets/stylesheets/ my_mountable_engine /application.css
créez app/assets/javascripts/ my_mountable_engine /application.js
créer config/routes.rb créer lib/my_mountable_engine.rb
créez lib/tasks/my_mountable_engine.rake
créez lib/my_mountable_engine/version.rb
créez lib/my_mountable_engine/engine.rb


Explication

Le cas d'utilisation du --full L'option semble très limitée. Personnellement, je ne peux penser à aucune bonne raison pour laquelle vous voudriez séparer votre code en un moteur sans isoler également l'espace de noms - Cela vous donnerait essentiellement deux applications étroitement couplées partageant des structures de fichiers identiques et tous les conflits et les fuites de code cela implique.

Chaque document que j'ai vu montre le --mountable option, et en effet l'actuel Edge guide vous encourage fortement à inclure isolate namespace- ce qui revient à dire utiliser --mountable plus de --full.

Enfin, il y a une confusion terminologique: malheureusement Rails plugin -h affiche les descriptions suivantes:

[--full] # Générer un moteur Rails avec une application groupée Rails pour les tests)
[- montable] # Génère une application isolée montable

Cela donne l'impression que vous utilisez --full pour créer un "moteur" et --mountable pour créer quelque chose d'autre appelé "application montable", alors qu'en fait ce sont tous les deux des moteurs - un espace de nom et un pas. Cela risque de créer de la confusion, car les utilisateurs qui cherchent à créer un moteur supposeront probablement que --full est l'option la plus pertinente.

Conclusion

  • Rails plugin new something --full = Moteur dans l'espace de noms de votre application. (Pourquoi voudrais-tu?)
  • Rails plugin new something --mountable = Moteur avec son propre espace de noms. (Impressionnant)

Les références

38
Yarin

je me demandais la même chose et, par conséquent, je me suis retrouvé ici. il me semble que les réponses précédentes couvrent essentiellement la question, mais j'ai pensé que les éléments suivants pourraient également aider:

# 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

un intérêt particulier (pour moi) est le fait qu'il n'y a pas de différence entre

Rails plugin new test-plugin -T --mountable

et

Rails plugin new test-plugin -T --full --mountable
17
Corey Innis

Ma compréhension de la différence est que les moteurs sont comme des plugins et ajoutent des fonctionnalités aux applications existantes. Les applications montables sont essentiellement une application et peuvent être autonomes.

Donc, si vous voulez pouvoir l'exécuter seul ou dans une autre application, vous feriez une application montable. Si vous voulez qu'il soit un ajout aux applications existantes, mais qu'il ne soit pas exécuté seul, vous en feriez un moteur.

8
JDutil

La différence, je crois, est que les applications montables sont isolées de l'application hôte, donc elles ne peuvent pas partager de classes - modèles, aides, etc. ).

Avis de non-responsabilité: comme la plupart, je viens juste de commencer à jouer avec Rails 3.1.

2
Kris