J'écris un wrapper personnalisé pour le plugin open_flash_chart
. Il est placé dans /lib
et le charge en tant que module dans ApplicationController
.
Cependant, j'ai une certaine hiérarchie de classe ou un petit problème.
Depuis n'importe quel contrôleur, je peux accéder aux fonctions open_flash_chart
en tant que OpenFlashChart
, Line
etc.
Cependant, dans une classe d'un module /lib
, cela ne fonctionne pas!
Des idées?
Les fichiers sont chargés dans Rails de deux manières:
app/controllers/pages_controller.rb
et référence à PagesController, app/controllers/pages_controller.rb
sera automatiquement chargé. Cela se produit pour une liste prédéfinie de répertoires dans le chemin de chargement. Ceci est une fonctionnalité de Rails et ne fait pas partie du processus de chargement Ruby normal.require
d. Si un fichier est require
d, Ruby parcourt la liste complète des chemins dans vos chemins de chargement et trouve le premier cas où le fichier que vous avez require
d se trouve dans le chemin de chargement. Vous pouvez voir le chemin de chargement complet en inspectant $ LOAD_PATH (un alias pour $ :).Puisque lib
se trouve dans votre chemin de chargement, vous avez deux options: nommer vos fichiers avec les mêmes noms que les constantes. Rails les prendra automatiquement lorsque vous référencez la constante en question ou exigez explicitement le module.
Je remarque également que vous pourriez être confus sur une autre chose. ApplicationController est not l'objet racine du système. Observer:
module MyModule
def im_awesome
puts "#{self} is so awesome"
end
end
class ApplicationController < ActionController::Base
include MyModule
end
class AnotherClass
end
AnotherClass.new.im_awesome
# NoMethodError: undefined method `im_awesome' for #<AnotherClass:0x101208ad0>
Vous devrez inclure le module dans la classe dans laquelle vous souhaitez l’utiliser.
class AnotherClass
include MyModule
end
AnotherClass.new.im_awesome
# AnotherClass is so awesome
Bien entendu, pour pouvoir inclure le module en premier lieu, vous devez le disposer (en utilisant l'une des techniques ci-dessus).
Dans Rails 3/lib, les modules ne sont pas chargés automatiquement.
C'est parce que la ligne:
# config.autoload_paths += %W(#{config.root}/extras)
inside config/application.rb est commenté.
Vous pouvez essayer de décommenter cette ligne ou, (cela a fonctionné encore mieux pour moi), laisser cette commentaire (pour référence future) et ajouter ces deux lignes:
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Ce qui a fonctionné pour moi, outre le fait de ne pas commenter config.autoload_paths (je suis sur Rails 3.1.3), a été de créer un initialiseur comme celui-ci:
#config/initializers/myapp_init.rb
require 'my_module'
include MyModule
De cette façon, je peux appeler les méthodes mymodule de n'importe où et en tant que méthodes de classe Model.mymodule_method
ou en tant que méthodes d'instance mymodel.mymodule_method
Peut-être qu'un expert peut expliquer les implications de cela. A présent, utilisez-le à vos risques et périls.
Edit: Après, je pense qu'un meilleur approuch serait:
créez un initialiseur comme ceci:
#config/initializers/myapp_init.rb
require ‘my_module’
Incluez le module si nécessaire, comme ceci:
1) si vous voulez l’utiliser en tant que "Méthodes de classe", utilisez "extend":
class Myclass < ActiveRecord::Base
extend MyModule
def self.method1
Myclass.my_module_method
end
end
2) si vous voulez l'utiliser comme "méthodes d'instance", incluez-le dans la définition de classe:
class Myclass < ActiveRecord::Base
include MyModule
def method1
self.my_module_method
end
end
3) rappelez-vous que include MyModule
fait référence à un fichier my_module.rb
dans votre chemin de chargement qui doit être requis en premier
Il se peut que vous souhaitiez explicitement charger un ou plusieurs fichiers dans le répertoire lib au moment de l’initialisation de l’application.
Dans ma config/application.rb, j'ai une entrée comme,config.autoload_paths += %W(#{config.root}/lib)
Cela pourrait également être le cas si le nom/la hiérarchie du module n’est pas identique à celui indiqué dans le fichier ou l’emplacement/le nom du fichier n’est pas identique à cette hiérarchie; le chargement automatique de ce fichier n’est donc pas possible. Donc, quand j'ai ajouté une entrée au bas de config/application.rb en tant que,require "./lib/file_name_without_extention
Cela a bien fonctionné.