web-dev-qa-db-fra.com

Comment sont requis, require_dependency et le rechargement des constantes dans Rails?

En quoi require et require_dependency Sont-ils différents?
Comment require_dependency Peut-il recharger automatiquement les classes en développement mais require ne peut pas?

J'ai creusé dans le code ActiveSupport::Dependencies Et dispatcher.rb de Rails. Ce que j'ai vu dans le code de require_dependency, C'est qu'il ajoute essentiellement les constantes à un tableau autoloaded_constants. Mais il est effacé dans clear_application À l'intérieur du répartiteur après chaque demande.

Quelqu'un peut-il donner une explication claire ou me diriger vers des ressources qui vous aideront?

64
wei

require (et son cousin load) sont les principales méthodes Ruby. require_dependency est une méthode qui aide Rails à gérer le problème de la gestion des dépendances. Bref, elle permet à Rails de recharger les classes en mode développement pour que vous ne pas besoin de redémarrer le serveur chaque fois que vous apportez un changement de code. Le framework Rails va require_dependency votre code pour qu'il puisse le suivre et le recharger lorsque des modifications sont apportées. Le standard Ruby require ne fait pas cela. En tant que développeur d'application (ou de plugin/moteur), vous ne devriez pas avoir à vous soucier de require_dependency car cela est purement interne à Rails.

La magie du processus de chargement de classe Rails se trouve dans le module ActiveSupport :: Dependencies. Ce code étend le comportement par défaut Ruby pour autoriser le code à l'intérieur de votre Rails app pour charger automatiquement les modules (y compris les classes qui héritent de Module) en utilisant le chemin d'accès et les conventions de dénomination des fichiers. Cela évite au programmeur de surcharger son code d'appels require comme vous serait dans une simple Ruby application.

En d'autres termes, cela vous permet de définir class Admin::User à l'intérieur du fichier app/models/admin/user.rb et avoir Rails sait de quoi vous parlez lorsque vous appelez Admin::User.new d'une autre partie de l'application comme un contrôleur. Sans ActiveSupport :: Dépendances impliquées, vous devrez manuellement require tout ce dont vous avez besoin.

Si vous venez d'un langage de type statique comme C #, Java, etc., cela pourrait être une surprise: Rails n'est pas chargé tant qu'il n'est pas nécessaire. Par exemple, un User la classe de modèle n'est pas définie et user.rb n'est chargé qu'après avoir essayé d'appeler User.whatever_method_here. Rails empêche Ruby de se plaindre de cette constante manquante, charge le code pour User, puis autorise Ruby = pour continuer comme d'habitude.

Bien que je ne puisse pas parler pour votre besoin spécifique, je serais très surpris si vous aviez réellement besoin d'utiliser le require_dependency méthode depuis un plugin ou un moteur. Si vous suivez les conventions Rails, vous ne devriez pas non plus avoir à modifier manuellement $ LOAD_PATH. Ce n'est pas "la méthode Rails").

Dans le monde de Ruby et aussi Rails la simplicité et la clarté sont la clé. Si tout ce que vous voulez faire est d'écrire un plugin ou un moteur et vous plongez déjà profondément) en interne alors vous pouvez envisager d'aborder votre problème sous un angle différent. Mon instinct me dit que vous essayez peut-être de faire quelque chose qui est inutilement compliqué. Mais là encore, je n'ai aucune idée de ce que vous faites exactement !! :)

123
MDaubs

require_dependency est utile dans un moteur lorsque vous souhaitez rouvrir une classe qui n'est pas définie dans votre moteur (par exemple dans un autre moteur ou Rails app) et la faire recharger. Dans ce cas quelque chose comme ça fonctionne:

# app/controllers/my_engine/documents_controller.rb
require_dependency MyEngine::Engine.root.join('app', 'controllers', 'my_engine', 'documents_controller').to_s

module MyEngine
  class DocumentsController
    def show
      render :text => 'different'
    end
  end
end
19
Kris