Wohin stech ich das?

Hi,

ich bin noch frisch in der Rails-Entwicklung und habe ein paar Fragen,
die Google und Co mir noch nicht beantworten konnten.

  1. Caching

Ich möchte externe Calls (z.B. zu Twitter) reduzieren und sie für n-
Minuten vorhalten.

In den standard-Rails-Caching-Methoden habe ich hierfür keine Lösung
gefunden (Mem-Cache-Lösung ist nicht möglich). Weshalb ich im Moment
in der environement.rb eine Ruby-Cache-Instanz erzeuge und als
Konstante definiere, die ich dann in allen Controllern benutzen kann.

Ich kann mir einfach nicht vorstellen, dass es hierfür nicht eine
“Saubere” Lösung gibt.

  1. Monkey-Patching

Ich möchte der Array-Klasse eine eigene Sortierungs-Funktion
verpassen. Wenn ich meine Gepatchte-Klasse ins Lib-Verzeichnis lege,
dann ist die Methode nicht aufrufbar. Ich nehme an, dass ich mich dort
irgendwie im Rails-Namespace bewege.
Wenn ich die Klasse im environment.rb definiere, dann geht es,
allerdings erscheint mir auch dies sehr unsauber.

  1. Kontext

Gibt es einen “globalen” Anwendungs-Kontext in dem ich Werte
definieren kann? So dass ich z.b. im Controller so etwas wie
context.put aufrufen kann um einen Wert zu schreiben oder einen
Counter zu erhöhen?

Wäre schön, wenn ihr mir etwas Feedback hierzu geben könntet.

Ahoi

On Saturday 20 June 2009, peter schröder wrote:

gefunden (Mem-Cache-Lösung ist nicht möglich). Weshalb ich im Moment
in der environement.rb eine Ruby-Cache-Instanz erzeuge und als
Konstante definiere, die ich dann in allen Controllern benutzen kann.

Du könntest einfach Rails.cache verwenden.

  1. Monkey-Patching

Ich möchte der Array-Klasse eine eigene Sortierungs-Funktion
verpassen. Wenn ich meine Gepatchte-Klasse ins Lib-Verzeichnis lege,
dann ist die Methode nicht aufrufbar. Ich nehme an, dass ich mich
dort irgendwie im Rails-Namespace bewege.
Wenn ich die Klasse im environment.rb definiere, dann geht es,
allerdings erscheint mir auch dies sehr unsauber.

Ich bin nicht sicher, aber ich glaube, du bist auf dem falschen Weg.
Wozu brauchst du eine eigene Sortiermethode? Hast du schon einen Blick
auf Array#sort_by geworfen? Geht es darum, Objekte zu sortieren, die aus
der Datenbank kommen? Dann ist vermutlich eine :order-Option an
“geeigneter” Stelle der richtige Ansatz.

In environment.rb solltest du nichts definieren, dafür gibt es
Initializer in config/initializers.

  1. Kontext

Gibt es einen “globalen” Anwendungs-Kontext in dem ich Werte
definieren kann? So dass ich z.b. im Controller so etwas wie
context.put aufrufen kann um einen Wert zu schreiben oder einen
Counter zu erhöhen?

Nein, gibt es nicht und kann es, ohne zusätzlichen Aufwand, nicht geben.
Die Anwendungsarchitektur (Stichwort: “shared nothing”) von Rails sieht
vor, dass jeder Request von einem einzelnen Prozess verarbeitet wird und
umgekehrt jeder Prozess nur an einem Request zur Zeit arbeitet. Um
gleichzeitig mehrere Requests verarbeiten zu können, sind also mehrere
Rails-Prozesse nötig, die jeweils gegeneinander isoliert sind.

Wenn du nun einen gemeinsamen Kontext brauchst, bedeutet das, dass du
eine Ressource in der Architektur etablierst, die von mehreren Rails-
Prozessen geteilt wird. Zugriffe auf eine solche Ressource müssen
synchronisiert werden und sie ist ein (weiterer, neben der Datenbank)
Flaschenhals und Fehlerpunkt. Was natürlich nichts daran ändert, dass
die Funktionalität oft trotzdem gebraucht wird. Memcached ist genau
dafür ein Beispiel.

Michael


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

Am 20.06.2009 um 11:42 schrieb peter schröder:

  1. Monkey-Patching

Ich möchte der Array-Klasse eine eigene Sortierungs-Funktion
verpassen. Wenn ich meine Gepatchte-Klasse ins Lib-Verzeichnis lege,
dann ist die Methode nicht aufrufbar. Ich nehme an, dass ich mich
dort irgendwie im Rails-Namespace bewege.
Wenn ich die Klasse im environment.rb definiere, dann geht es,
allerdings erscheint mir auch dies sehr unsauber.

wenn du lib/array_monkey.rb hast dann musst du im environment.rb noch
require ‘array_monkey’ machen.
Die Dateien und Klassen im lib verzeichnis stehen nicht automatisch
zur Verfügung.

ciao, tom


Thomas R. “TomK32” Koll || http://tomk32.de || http://ananasblau.com
just a geek trying to change the world
Skype: TomK32 || Mail: [email protected]
About Thomas R. Koll | Flickr

Hi,

vielen Dank für eure Antworten. Genau diese Informationen haben mir
gefehlt!

Leider hatte ich die E-Mail-Sammelfunktion der Mailing-List aktiviert,
deshalb kann ich nicht auf die einzelnen Antworten zurückschreiben…

Für mich wichtige Punkte liste ich hier noch mal auf:

Die Anwendungsarchitektur (Stichwort: “shared nothing”) von Rails
sieht
vor, dass jeder Request von einem einzelnen Prozess verarbeitet wird
und
umgekehrt jeder Prozess nur an einem Request zur Zeit arbeitet.

Dies wird sicherlich noch eine inressanter Aspekt wenn meine Anwendung
unter JRuby in einem Application-Container läuft.

Du hast einen Sonderfall erwischt :wink: Der Code in lib wird von Rails
nicht sofort geladen, sondern das Verzeichnis wird nur dem load path
hinzugefügt. Die Klassen werden also erst geladen, wenn sie das erste
mal im Code verwendet werden.

Das erscheint mir logisch, ich hab allerdings keine Erklärung dafür in
der Doku gesehen.

Das Problem kannst Du z.B. lösen, indem Du den Code in einer Datei
array_ext.rb im Verzeichnis config/initializers ablegst. Dann wird er
schon beim Start der App geladen.

Hört sich gut an, werde ich ausprobieren.

Wenn sie nicht zur Domänge gehören: Eine simple Lösung für einen
globalen Store wäre ein OpenStruct zu verwenden. Folgende 2 Zeilen
unter lib/context.rb ablegen:

Danke für das Beispiel, soetwas habe ich gesucht, da meine Anwendung
komplett ohne DB auskommen soll. Es werden lediglich externe APIs
genutzt (Twitter, Google, Amazon).

Vielen Dank!

Am 21.06.2009 um 12:00 schrieb [email protected]:

Hi Peter,

Ich kann mir einfach nicht vorstellen, dass es hierfür nicht eine
“Saubere” Lösung gibt.

Die anderen Cache-Backends in Rails unterstützen AFAIK tatsächlich
keine expiry. Hier ein Backend, dass das könnte (gerade eben schnell
gehackt, nur als “proof of concept” gedacht)

Um es zu verwenden in environment.rb config.cache_store
= :memory_store_with_expiry setzen.

Aber … willst Du die Applikation später deployen und (ein bischen)
skalieren? Wenn ja wirst Du einen Cache brauchen auf den von mehreren
Prozessen aus zugegriffen werden kann. Egal ob deployment via Mongrel
Cluster oder mod_passenger. D.h. MemCache oder FileStore.

  1. Monkey-Patching

Ich möchte der Array-Klasse eine eigene Sortierungs-Funktion
verpassen. Wenn ich meine Gepatchte-Klasse ins Lib-Verzeichnis lege,
dann ist die Methode nicht aufrufbar. Ich nehme an, dass ich mich
dort irgendwie im Rails-Namespace bewege.

Nee, das ist nicht das Problem.

Wenn ich die Klasse im environment.rb definiere, dann geht es,
allerdings erscheint mir auch dies sehr unsauber.

Du hast einen Sonderfall erwischt :wink: Der Code in lib wird von Rails
nicht sofort geladen, sondern das Verzeichnis wird nur dem load path
hinzugefügt. Die Klassen werden also erst geladen, wenn sie das erste
mal im Code verwendet werden. Das funktioniert bei noch nicht
definierten Klassen wunderbar. Aber nachdem die Array-Klasse schon
bekannt ist, schaut Rails nicht in dem Verzeichnis nach und Dein Code
wird nicht geladen :frowning:

Das Problem kannst Du z.B. lösen, indem Du den Code in einer Datei
array_ext.rb im Verzeichnis config/initializers ablegst. Dann wird er
schon beim Start der App geladen.

  1. Kontext

Gibt es einen “globalen” Anwendungs-Kontext in dem ich Werte
definieren kann? So dass ich z.b. im Controller so etwas wie
context.put aufrufen kann um einen Wert zu schreiben oder einen
Counter zu erhöhen?

Was genau sind das für Werte? Globale Konfiguration? Wieder Cache?
Wenn sie irgendwie zur Domäne gehören würde ich sie auf bestehenden
oder auch neuen Models ablegen.

Wenn sie nicht zur Domänge gehören: Eine simple Lösung für einen
globalen Store wäre ein OpenStruct zu verwenden. Folgende 2 Zeilen
unter lib/context.rb ablegen:

require ‘ostruct’
Context = OpenStruct.new

test in script/console:

Context.foo = ‘Bar’
=> “Bar”
Context.foo
=> “Bar”

Wenns noch Fragen gibt würdes uns sicher helfen, wenn Du die konkreten
Probleme beschreibst … dann muss man nicht so viel mutmaßen :wink:

Hope this helps,
Phillip

On Jun 21, 2009, at 12:20 PM, peter schröder wrote:

Danke für das Beispiel, soetwas habe ich gesucht, da meine Anwendung
komplett ohne DB auskommen soll. Es werden lediglich externe APIs
genutzt (Twitter, Google, Amazon).

… wobei ich mich in diesem Fall fragen würde, ob Rails die richtige
Wahl ist und nicht vielleicht z.B. Sinatra eine bessere wäre.

Stefan

Stefan T., Stefan Tilkov’s Blog [Stefan Tilkov’s Blog]

wenn man erfahrungen mit rails sammeln will, dann sicherlich nicht.

ich weiß, dass rails von grund auf sehr datenbank getrieben ist.
trotzdem konnte ich mit meinem kleinen projekt schon sehr viele dinge
für mich herausziehen und habe etwas gefühl für die arbeit mit rails
bekommen.

wenn es jemanden interessiert: http://www.phoet.de/

als nächstes möchte ich mich noch intensiv mit den test-möglichkeiten
von rails beschäftigen.

in der nächsten iteration will ich dann noch einige teile mit jquery
dynamisch laden.

in einem letzten schritt dann evtl. noch ein wenig mit models und der
anbindung einer datenbank arbeiten.

Am 21.06.2009 um 12:57 schrieb Stefan T.: