85 votes

Rails / lib modules et

Je vous écris un wrapper personnalisé pour le plugin open_flash_chart. Il est placé dans/lib et charger un module dans ApplicationController.

Cependant, j’ai un problème de hiérarchie ou qch de classe.

De n’importe quel contrôleur je peux accéder à des fonctions d’open_flash_chart comme OpenFlashChart, ligne etc.

Toutefois, dans une classe dans un module/lib, il ne fonctionne pas !

Toutes les idées ?

149voto

Yehuda Katz Points 18277

Il existe deux façons d'obtenir les fichiers chargés dans les Rails:

  • Il est inscrit dans le processus de chargement automatique, et vous faites référence à une constante qui correspond au nom de fichier. Par exemple, si vous avez app/controllers/pages_controller.rb et de référence PagesController, app/controllers/pages_controller.rb sera automatiquement chargé. Ce qui se passe pour un preset de la liste de répertoires dans le chemin de chargement. C'est une caractéristique des Rails, et n'est pas normal de Ruby processus de chargement.
  • Les fichiers sont explicitement required. Si un fichier est - required, Ruby on regarde à travers l'ensemble de la liste des chemins d'accès dans vos chemins de chargement, et de trouver le premier cas où le fichier required est dans le chemin de chargement. Vous pouvez voir l'intégralité du chemin de chargement par l'inspection $LOAD_PATH (un alias pour $:).

Depuis lib est dans votre chemin de chargement, vous avez deux options: soit le nom de vos fichiers avec le même nom que les constantes, de sorte que les Rails automatiquement les chercher quand vous faites référence à la constante en question, ou exiger explicitement le module.

Je remarque aussi que vous pourriez être confus au sujet d'une autre chose. ApplicationController est pas l'objet racine dans le 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 aurez besoin d'inclure le module dans n'importe quelle autre classe que vous souhaitez utiliser.

class AnotherClass
  include MyModule
end

AnotherClass.new.im_awesome
# AnotherClass is so awesome

Bien sûr, pour être en mesure d'inclure le module en premier lieu, vous aurez besoin d'avoir à disposition (en utilisant l'une des techniques ci-dessus).

87voto

diegopau Points 586

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/**/"]
 

25voto

Fernando Fabreti Points 705

Ce qui a fonctionné pour moi, en plus de décommentant la config.autoload_paths (je suis sur des Rails 3.1.3), était de créer un initialiseur comme ceci:

#config/initializers/myapp_init.rb
require 'my_module'    
include MyModule

De cette façon, je peux appeler mymodule méthodes à partir de n'importe où et que les méthodes de la classe Model.mymodule_method ou que les méthodes d'instance mymodel.mymodule_method

Peut-être que certains experts peuvent expliquer les implications de cette. Maintenant, vous l'utilisez à vos propres risques.

Edit: Après, je pense qu'un meilleur approuch serait:

créer un initialiseur comme ceci:

#config/initializers/myapp_init.rb
require ‘my_module'

Inclure le module en cas de besoin, comme ceci:

1) si vous voulez l'utiliser comme "les Méthodes de la Classe" utiliser "étendre":

class Myclass < ActiveRecord::Base
   extend MyModule
   def self.method1
      Myclass.my_module_method
   end
end

2) si vous voulez l'utiliser comme "les Méthodes d'Instance" de l'inclure à l'intérieur de la définition de la 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 exigé en premier

0voto

Cela pourrait être le cas que vous voulez charger explicitement fichier(s) sous répertoire lib au moment de l'initialisation de l'application.
Dans ma config/application.rb, j'ai une entrée,
config.autoload_paths += %W(#{config.root}/lib)

Aussi cela peut être le cas que le nom du module/de la hiérarchie n'est pas même que c'est dans le fichier ou l'emplacement/nom de fichier n'est pas la même que celle de la hiérarchie, donc, l'auto-chargement de ce fichier est également pas possible. Alors, quand j'ai ajouté une entrée au bas de config/application.rb comme,
require "./lib/file_name_without_extention
il a bien fonctionné.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X