2009-10-07 4 views
11

J'étends une classe (qui est un plug-in) en incluant un module, cela se fait dans un initialiseur.Comment étendre une classe à partir d'un initialiseur et la recharger dans un environnement de développement?

require 'qwerty/core/user' 
User.send :include, Qwerty::Core::Extensions::User 

Cependant dans le développement avant chaque demande (et après reload! Est appelé dans la console) tous les modèles sont rechargées, mais parce que les initialiseurs ne sont pas exécutés à nouveau le module ne sont pas compris. Laisser un modèle avec des 'parties manquantes'.

Parce que le modèle est un plugin il ne semble pas judicieux d'inclure le code directement dans la classe qui serait l'approche habituelle.

Pour l'instant j'ai simplement ajouté un before_filter qui comprend le module que si l'environnement de développement. Mais je copier/coller et ont le code en double dans le contrôleur initialiseur et de l'application.

# Class extensions in initalizers are over-writtern each request 
    def development_loading 
    if RAILS_ENV == 'development'  
     User.send :include, Qwerty::Core::Extensions::User 
    end 
    end 

Y a-t-il un meilleur moyen?

Comme une note de côté le plug-in est à moi, donc je pourrais ajouter du code pour, mais les extensions détenues dans le module ne sont pas toujours présents ...

Répondre

11

environment.rb

config.to_prepare do 
    User.send :include, Qwerty::Core::Extensions::User 
end 

Le code est le bloc est exécuté avant chaque demande en mode développement et une fois en mode de production.

+1

Cela a fonctionné pour moi, mais dans application.rb (rails 3.0.20), pas environnement.rb – tekniklr

+0

Ceci est parfaitement fonctionne dans les rails 4 si l'ajouter à engine.rb dans les rails moteur. Merci! –

0

Pourquoi utilisez-vous initializers pour inclure la fonctionnalité?

Effectuez les opérations suivantes au lieu:

require 'qwerty/core/user' 
class User < ActiveRecord::Base 
    include Qwerty::Core::Extensions::User 
    # bla bla 
end 
+0

Parce qu'il ne veut que ce code inclus en mode développement. – SFEley

+0

Parce que le modèle est dans un plugin, alors que c'est un plugin que je développe, je le traite comme un plugin tiers, donc je ne veux pas toucher le code à l'intérieur. Donc je dois étendre ces classes de l'extérieur. – Kris

1

Au début, j'allais quelque chose au sujet d'ajouter un répertoire « développement » à l'avant de votre chemin de charge en mode développement, afin que vos révisions seraient toujours se rechargées d'abord ... Mais ensuite, il m'est apparu que vous avez dit quelque chose de déroutant.

Le modèle que vous essayez d'étendre. C'est dans un plugin ? Les plugins ne sont pas supposés être rechargés par défaut en mode développement, à moins que l'application ne le dise explicitement dans sa configuration en définissant Config.reload_plugins? sur false.

Mais si, pour une raison quelconque, votre plug-in est de toute façon et vous rechargeait ne pas le souhaitez, vous pouvez mettre dans votre plug-in pour dire explicitement de init.rb il ne devrait pas recharger:

Dependencies.load_once_paths << lib_path 

Voir les rails docs sur la classe de configuration pour plus de détails: http://api.rubyonrails.org/classes/Rails/Configuration.html#M002536

+0

Oui, j'ai reload_plugins? mis à vrai parce que je développe activement le plugin. Je veux trouver un moyen d'étendre les modèles dans le plugin depuis l'application Rails (c'est-à-dire sans toucher au code du plugin). Un peu déroutant oui! Dans mon init.rb j'ai: si RAILS_ENV == 'développement' ActiveSupport :: Dependencies.load_once_paths.reject! {| X | x = ~/^ #{Regexp.escape(File.dirname(__FILE__))}/} fin – Kris

+0

Je pense que mon problème est que j'essaye de faire deux choses à la fois - travailler sur un plugin (recharger chaque requête) et étendez le plugin depuis l'application Rails. Un peu attraper 22 ... – Kris

+0

Pourquoi? Pourquoi vous donner toutes ces contraintes? Vous ne voulez pas ajouter de code de développement au plugin, vous ne voulez pas le charger une seule fois, et vous voulez inverser le _idea_ d'un plugin en étendant votre plugin depuis votre application (ce qui est philosophiquement en arrière). Que gagnez-vous dans tous ces cas spéciaux? Est-ce que l'ajout de certaines conditions 'if RAILS_ENV == 'development'' dans votre plugin va casser quelque chose? Vous pouvez toujours le retirer plus tard, ou placer les extensions dans des fichiers qui ne vivent que dans une branche Git spéciale. Cessez de combattre la rivière. Aller avec le flux. Laissez Rails être Rails. Faites-le. – SFEley

3

solution légèrement plus élégante que celle acceptée car il peut être mis dans un initialiseur:

require 'dispatcher' 

Dispatcher.to_prepare do 
    # stuff that needs to happen once per initialization 
end 
6

3.x Rails vous pouvez configurer un bloc pour exécuter chaque fois que rechargements se produisent (en mode développement, ou quand config.cache_classes = false).Cela irait dans un initialiseur:

ActionDispatch::Callbacks.to_prepare do 
    # configure stuff or initialize 
end 
Questions connexes