Plugin & session

Bonjour,

je suis en train de développer un plugin, et à l’intérieur de celui-ci
j’appele la méthode session.
Le problème est que mon plugin n’a pas accès à la méthode session. J’ai
bien
inclue les différents modules
qui y font référence, et hérité ma classe, mais rien n’y fait.

ma classe se présente comme ceci :
class Filters_and_conditions
def self.init(index)
session[index] = Generate_condition.new
end
end

Et je l’appele depuis mon controlleur comme ceci :
Filters_and_conditions.init(:page)

j’obtiens cette erreur :

undefined local variable or method `session’ for
GenerateCondition::Filters_and_conditions:Class

Je pourrais certes instancier Filters_and_conditions dans une session de
mon
controlleur, mais le but est que le plugin gère lui même les sessions,
pas
le controlleur.

2006/9/15, Frédéric Logier [email protected]:

ma classe se présente comme ceci :
class Filters_and_conditions
def self.init(index)
session[index] = Generate_condition.new
end
end

Et je l’appele depuis mon controlleur comme ceci :
Filters_and_conditions.init(:page)

J’ai trouvé une solution en passant l’objet controlleur au plugin, mais
je
trouve pas ça très propre Filters_and_conditions.init(self, page)

class Filters_and_conditions
def self.init(controller_objet, index)
controller_objet.session[index] = Generate_condition.new
end

Sinon, pourquoi ne pas faire de ta classe Filters_and_conditions un
module, que tu intègrerais à tes contrôleurs ?

module Filters_and_conditions
def init(index)
session[index] = Generate_condition.new
end
end

class ApplicationController < ActionController::Base
require “Filters_and_conditions”
include Filters_and_conditions
end

Salut,

je suis en train de développer un plugin, et à l’intérieur de celui-ci
j’appele la méthode session.
Le problème est que mon plugin n’a pas accès à la méthode
session. J’ai bien inclue les différents modules
qui y font référence, et hérité ma classe, mais rien n’y fait.
(…)
Je pourrais certes instancier Filters_and_conditions dans une
session de mon controlleur, mais le but est que le plugin gère
lui même les sessions, pas le controlleur.

A mon avis, une solution serait d’utiliser la voie “classique”,
c’est à dire d’utiliser le callback included, ie de faire en sorte
que ActionController::Base inclue ton module qui définit les
méthodes de classe et méthode d’instance que tu souhaites
implémenter. init.rb envoie un message include à AC::B,
dans ton code proprement dit tu auras par exemple :

module Fredix
module Filters_and_conditions
def self.included(base)
base.extend ClassMethods
base.send( :include, InstanceMethods)
# d’autres choses eventuellement
end

module ClassMethods
  def ma_belle_methode
     # ...
  end
end

module InstanceMethods
  def ma_jolie_methode
     # ...
  end

end
end

“Classiquement”, on met les méthodes de classe dans un
module, celles d’instance dans un autre.

A niveau là , tu peux donc appeler une méthode de classe
qui fera office de macro/DSL :

class FooController < AC::B
filters_and_conditions # avec arguments eventuels
end

#filters_and_conditions se chargeant à grands coups
de métaprogrammation de créer des préfiltres ou postfiltres
qui vont bien (before_filter et cie). Tu auras accès à #session
et au reste.

РJean-Fran̤ois.

PS : à part ça, pour les spécialistes, included c’est mieux
qu’append_features parce que t’as pas besoin de faire un super ?

2006/9/15, Frédéric Logier [email protected]:

J’ai trouvé une solution en passant l’objet controlleur au plugin, mais je
trouve pas ça très propre Filters_and_conditions.init(self, page)

class Filters_and_conditions
def self.init(controller_objet, index)
controller_objet.session[index] = Generate_condition.new
end

Merci pour vos réponses. Pour l’instant je laisse comme ceci car plus
simple
pour moi. En fait ma classe est déjà dans un module inclu dans
application.rb
C’est un plugin générant le conditions au paginate à partir d’un
formulaire
de recherche, que je devrais diffuser bientôt. Je vous en reparlerai Ã
ce
moment.

Le Ven 15 septembre 2006 16:54, Jean-François a écrit :

class FooController < AC::B
filters_and_conditions # avec arguments eventuels
end

C’est la méthode “à la ActiveRecord” mais globalement ce n’est pas un
pattern à suivre. Ici, par exemple, ça coupe la hiérarchie avec le
ApplicationControler qui devrait être la racine des contrôleurs.
De plus ça commence à ne plus être de la méta programmation mais plus de
la “magie”. Pire, ça n’est même pas plus compréhensible.

Perso je vois quelques cas :

  • tu as seulement quelques méthodes, autant les ajouter directement dans
    le ApplicationControler plutot que de faire une classe et/ou un module à
    part.

  • tu as une paire de méthodes, mais qui restent vraiment liées au
    controleur, et dans ce cas tu peux les mettre dans une classe X qui hérite
    de ApplicationControler et demander à tes controleur d’hériter de X plutot
    que de ApplicationControler

  • tu as une paire de méthodes qui ne te paraissent vraiment pas appartenir
    au contrôleur et qui n’utilisent pas grand chose du contrôleur. Dans ce
    cas tu peux utiliser le très moche binding_of_caller, qui te permet
    d’utiliser … hum … les variables de la méthode appelante. Oui, c’est
    très gruik, mais au moins ça me parait moins moche que l’enchantement des
    classes à la ActiveRecord. Le coté gruik reste dans ce qu’on rajoute et ne
    vient pas s’implanter dans la base classique de ton application (le
    controleur).

  • tu as une paire de méthodes qui ne te paraissent vraiment pas appartenir
    au contrôleur et qui n’utilisent pas grand chose du contrôleur et tu te
    refuses aux gruikeries. Dans ce cas le plus simple est encore
    d’effectivement passer ce dont tu as besoin en paramètre. Donc récupérer
    ta session, et l’envoyer à ton objet ou singleton Filters_and_conditions.
    Ca me parait d’ailleurs la solution la plus logique et c’est loin d’être
    la plus moche. Pour courroner le tout c’est aussi la solution la plus
    “classique”, celle qu’on ferait dans tous les autres langages.

  • Tu as beaucoup de méthodes et qui utilisent beaucoup de choses dans ton
    contrôleur mais qui ne sont pas des méthodes appartenant à un controleur.
    Il te reste effectivement la voie du module, mais plutot que de chercher
    des enchantement, je te conseille vraiment de garder la syntaxe
    habituelle
    des modules. Ca ne te prendra qu’une seule ligne (le include) mais
    surtout
    ça ne pourrira pas ta hiérarchie de classe et ne sera pas inutilement
    “magique”.

A priori, de ce que j’ai vu, ce que je te conseille c’est :

  • Ajouter un accesseur de classe pour gérer @@session dans ta classe
    Filters_and_conditions
  • Ajouter bêtement une méthode filters_and_conditions à ton
    ApplicationControler. Cette méthode ira prendre la classe
    Filters_and_conditions, enregistrer l’objet de session dedans (grace à
    l’accesseur), et te retourner la classe.

Au final au lieu de faire Filters_and_conditions.init(:page) dans tes
controleurs tu feras filters_and_conditions.init(:page). Ce n’est pas
une
grande différence et ça sera suffisament simple, pas trop magique.


Eric D.