[plugin dev.] Klassenmethode analog zu before_filter

Hallo zusammen,

gibt es eine Möglichkeit, via Plugin eine Klassenmethode im
ApplicationController zu platzieren, welche auf die folgende Art und
Weise aufgerufen werden kann:

ApplicationController < ActionController::Base

load_widget :sidebar, :quicksearch

end

Das Problem hierbei ist, dass der ApplicationController bereits vor dem
Laden der Plugins eingebunden zu werden zu scheint.

Gibt es generell best practices zur Implementierung solcher Methoden
über Plugins? Genauer geht es darum, wo ich in diesem Falle
Informationen ablegen kann, da beim Aufruf der Methode aus diesem
Kontext heraus ja noch kein Objekt der Klasse existiert.
Derzeit lege ich herfür eine Klassenvariable an, bin mir aber nicht
sicher, ob das so eine gute Lösung ist.

Grüße

On Saturday 27 June 2009, Wer S. wrote:

end
Muss es ein Plugin sein? Du könntest die Methode doch einfach im
ApplicationController definieren:

ApplicationController < ActionController::Base
def self.load_widget

end
load_widget :sidebar, :quicksearch
end

Falls du wirklich ein Plugin brauchst, dann solltest du die gewünschte
Methode in einer Erweiterung für ActionController::Base definieren:

vendor/plugins/wer_sie_widgets/lib/wer_sie/controller_extensions.rb

module WerSie
module ControllerExtensions
def self.included(base)
base.extend(SingletonMethods)
end
module SingletonMethods
def load_widget

end
end
end
end

vendor/plugins/wer_sie_widgets/rails/init.rb

ActionController::Base.class_eval do
include WerSie::ControllerExtensions
end

Gibt es generell best practices zur Implementierung solcher Methoden
über Plugins? Genauer geht es darum, wo ich in diesem Falle
Informationen ablegen kann, da beim Aufruf der Methode aus diesem
Kontext heraus ja noch kein Objekt der Klasse existiert.
Derzeit lege ich herfür eine Klassenvariable an, bin mir aber nicht
sicher, ob das so eine gute Lösung ist.

Geht es um Konfigurationsinformationen? Dann sind
class_inheritable_attribute und Konsorten wahrscheinlich besser. Siehe

gems/1.8/gems/activesupport-2.3.2/lib/active_support/core_ext/class/inheritable_attributes.rb

Wahrscheinlich ist es auch sehr hilf- und lehrreich, wenn du dir den
Code von ein paar Plugins/Gems ansiehst, die etwas ähnliches machen, wie
das, was du erreichen willst.

Michael


Michael S.
mailto:[email protected]
http://www.schuerig.de/michael/

Hi,

das Ganze soll als Plugin eingebunden werden, hinter der Methode
verbirgt sich noch etwas mehr…
Sorry, ich hätte mich klarer ausdrücken sollen, das entwprechende Modul,
welches in den ApplicationController gemixt werden soll, habe ich
bereits geschrieben.

Wenn ich meine Methode nun in einem konkreten Controller aufrufe,
funktioniert das Ganze auch wunderbar. Sobald ich die Methode jedoch im
ApplicationController aufrufe, bricht Rails beim Starten des Servers ab,
da die Methode nicht bekannt sei.

Füge ich den Methodenaufruf jedoch erst nach dem Starten des Servers im
ApplicationController hinzu, funktioniert es.

Kann mir das irgendwie nicht erklären :-/.

Hier mal meine Code dazu in Ausschnitten:

init.rb:
module WidgetPool
class << self
def enable
ActionView::Base.send :include, ViewHelpers
ActionController::Base.send :include, Loader
end
end
end

WidgetPool.enable

widget_pool.rb:
module WidgetPool
module Loader
def self.included base
base.extend ClassMethods
end

module ClassMethods
  def load_widget pool, *options
    [...]
  end
  [...]
end

end
end

vielleicht hilft dir das hier weiter:

http://railsguts.com/initialization.html

Am 27.06.2009 um 18:31 schrieb Kjell S.:

Ah, nach stundenlangem Suchen, HowTos und Quellcode lesen habe ich die
Ursache endlich gefunden.
Mein Plugin enthält eine Klasse, welche von ApplicationController erbt,
was wohl erklärt, dass dieser zu früh geladen wird.

Jetzt könnte ich diese Datei natürlich einfach laden, nachdem ich
ActionController::Base erweitert habe, was aber sich zu eventuellen
Problemen mit anderen Plugins führen könnte :-/.

Ich brauche in dieser Klasse Zugriff auf die Methoden und Attribute des
ApplicationController. Welche Möglichkeiten bleiben noch, um das zu
erreichen?

On Saturday 27 June 2009, Kjell S. wrote:

Wenn ich meine Methode nun in einem konkreten Controller aufrufe,
funktioniert das Ganze auch wunderbar. Sobald ich die Methode jedoch
im ApplicationController aufrufe, bricht Rails beim Starten des
Servers ab, da die Methode nicht bekannt sei.

Das klingt so, als ob die ApplicationController-Klasse aus irgendeinem
Grund geladen wird, bevor dein Plugin ActionController::Base um die
benötigte Methode erweitert.

Füge ich den Methodenaufruf jedoch erst nach dem Starten des Servers
im ApplicationController hinzu, funktioniert es.

Daraus kann ich nicht entnehmen, was du machst. Das gilt auch für den
Rest deiner Beschreibung. Im Nebel stochern kann man damit, dir
ernsthaft helfen nicht.

Michael


Michael S.
mailto:[email protected]
http://www.schuerig.de/michael/

2009/6/28 Kjell S. [email protected]:

ich möchte nocheinmal kurz auf das ablegen von Information innerhalb der
Klassenmethode zurückkommen.
Hierzu habe ich ein Objekt, in welchem ich diverse Informationen
speichere. Diese gelten aber nur für den aktuellen Request. Wenn ich
dieses nun aber in einer Klassenvariable im Controller ablege, sind (in
production) alle Daten aus dem vorheriegen Request noch vorhanden.
Also wohin damit, so dass ich bei jedem Request wieder ein
jungfräuliches Objekt habe? :wink:

Innerhalb einer Singleton-Methode an der Klasse ActionController::Base
koenntest du z.B. einen Filter erstellen a la:

attr_accessor :widgets

def self.load_widget(*widgets)
before_filter do |controller|
controller.widgets = widgets
end
end

Die Magie von Closures erledigt hier den rest.

Cheers, Mathias

Besten Dank! :slight_smile:

Geht es um Konfigurationsinformationen? Dann sind
class_inheritable_attribute und Konsorten wahrscheinlich besser. Siehe

Hi Michael,

ich möchte nocheinmal kurz auf das ablegen von Information innerhalb der
Klassenmethode zurückkommen.
Hierzu habe ich ein Objekt, in welchem ich diverse Informationen
speichere. Diese gelten aber nur für den aktuellen Request. Wenn ich
dieses nun aber in einer Klassenvariable im Controller ablege, sind (in
production) alle Daten aus dem vorheriegen Request noch vorhanden.
Also wohin damit, so dass ich bei jedem Request wieder ein
jungfräuliches Objekt habe? :wink:

Danke & Grüße
Kjell