On Jun 2, 2007, at 1:44 AM, Michael Schuerig wrote:
On Friday 01 June 2007, Stefan Tilkov wrote:
On Jun 1, 2007, at 7:06 PM, Michael Schuerig wrote:
Ich habe gerade das sehr empfehlenswerte Buch "RESTful Web
Services" von
Leonard Richardson und Sam Ruby gelesen.
Ah, mein Lieblingsthema :-) ... und ein gutes Buch, siehe auch
http:// www.infoq.com/articles/richardson-ruby-restful-ws
Für eine Frage, die mir unter
den Nägeln brennt, habe ich dort leider keine Antwort gefunden. Die
Frage hat auch eigentlich nicht mit einem Web*service* sondern mit
einer Web*anwendung* zu tun.
Genau genommen würde ich da gar keinen Unterschied sehen ;-)
Was soll ich sagen? Wenn ich einen so großen Unterschied sähe,
würde ich
wohl nicht fragen. :-)
In Rails gehört es inzwischen zum guten Ton, Anwendungen REST-gemäß
zu strukturieren. Das funktioniert allgemein für die üblichen
Aktionen auch völlig problemlos. Nicht so einfach finde ich es für
Ajax-Requests. Konkret habe ich zwei Fälle
update_ui
Manche Formulare sind dynamisch und zwar nicht nur so, dass Teile
ein- und ausgeblendet werden könnten, sondern die
Auswahlmöglichkeiten in Listen hängen davon ab, welcher Wert in
einer anderen Liste ausgewählt wurden. Die genauen Zusammenhänge
sind Teil der Geschäftslogik gehören dementsprechend in eine
Model-Klasse.
Wenn der Benutzer nun eine Eingabe vornimmt, die eine Änderung des
Formulars erfordert, so wird ein Ajax-Request an den Server
geschickt, der entscheidet, was passieren soll und per RJS ein
geeignetes JavaScript an den Client zurück schickt.
Wie strukturierst Du Deine Anwendung? Funktioniert sie auch, wenn
JavaScript deaktiviert ist? Wenn ja, lässt sich die RJS-Variante als
eine andere Repräsentation der Ressource sehen, die Du im Nicht-JS-
Fall verwendest?
Nein, ohne JS läuft da gar nichts. Da es sich um eine interne
Anwendung
handelt ist das so auch in Ordnung. Öffentlich würde ich das anders
angehen.
Hm, vielleicht ist es dann einfach OK, das ganze nicht RESTful zu
realisieren. Ich würde behaupten, dass die Vorteile (wie z.B.
"Bookmarkability") auch für interne Anwendungen gelten, aber das ist
letztlich eine Designentscheidung.
Wenn Du es aber RESTful realisieren würdest, hast Du ja eigentlich
nur deswegen ein Problem, weil Du RJS auf dem Server machst -
richtig? Das konzeptionelle Modell wird sozusagen "verletzt", weil
durch RJS Logik, die eigentlich in den Client gehört, im Server
sitzt. Oder anders gesagt: würdest Du plain Javascript in Deine HTML-
Seite einbetten, könntest Du mit Ressourcen auf dem Server agieren,
ohne einen Seitenwechsel zu provozieren.
poll
Der Client sendet regelmäßig einen Ajax-Request an den Server, der
u.a.
die Versionsnummer des bearbeiteten Objekts enthält. Der Server
prüft, ob diese Version noch aktuell ist, wenn nicht, sendet er ein
JavaScript
zurück, dass eine Nachricht anzeigt und das Formular sperrt.
Ditto - wobei ich in diesem Fall fragen würde, ob das (R)JS nicht
eher in den View gehört?
Das (R)JS wird im Controller erzeugt, allerdings ist das dort nur eine
dünne Verpackungsschicht über den Daten, die gemäß der Geschäftslogik
aus den jeweiligen Model geliefert werden. In diesem konkreten Fall
haben alle relevanten Models eine Klassenmethode #stale?. Die
Standardmethoden der Controller erzeuge ich dynamisch, wobei dann
http://example.com/things/poll/7/10 (id/revision) von dieser Methode
behandelt wird
def do_poll(model_class, params)
if model_class.respond_to?(:stale?)
if params[:id].to_i != 0
if model_class.stale?(params[:id], params[:revision].to_i)
render :update do |page|
page.application.show_message "Another user has changed
the #{model_class.name.humanize} in the meantime.", 'error'
page.application.object_is_stale
end
return
end
end
end
render :nothing => true
end
In application.js sind
var Application = {
showMessage: function(...) { ... },
objectIsStale: function() { ... }
};
definiert.
Cool :-) Aber im Prinzip gilt das gleiche - die Funktionalität, eine
Ressource zu fragen, ob sie sich seit dem letzten Zugriff geändert
hat, ist in HTTP schon drin (ETags/Last-modified header usw.) Wenn Du
darauf aus dem Client zugreifen würdest, wäre alles in Butter ...
Edge Rails macht auch schon ETags, das könnte man mit einer Lösung
kombinieren, die Deinen Use Case generisch löst ... nettes Spielfeld.
Nun könnte ich möglicherweise mit ein paar Namensänderungen einfach
behaupten, dass auch diese Requests eigentlich auf Ressourcen
zugreifen. Und JavaScript ist ja neben HTML und XML auch nur eine
Repräsentation unter anderen. -- Vielleicht hat aber schon jemand
einen
eleganten Weg gefunden.
JS (bzw. code on demand) ist zwar durchaus RESTful, aber in Bezug auf
die Sichtbarkeit Deiner Ressourcen immer ein wenig kritisch. Kannst
Du Deinen Fall noch detaillieren?
Ich konstruiere mal ein vergleichbares Beispiel, einen Konfigurator
für
einen Neuwagen. Angegeben werden müssen Model, Variante, Motor, Farbe,
Polsterfarbe, Bereifung. Zwischen diesen Parametern gibt es einige
Constraints. Für manche Varianten werden nur bestimmte Farben und
Polsterfarben angeboten, wobei auch die Farbe die Polsterfarben
einschränkt.
Ein gutes Beispiel, u.a. weil ich mich schon tierisch oft geärgert
habe, dass diese verdammten Konfiguratoren es mir nicht erlauben,
einen Link auf eine Kombination an jemand anderen zu schicken :-)
Wenn der Benutzer nur einmal oder nur selten durch eine solche
Konfiguration durch müsste, dann würde ich sie über mehrere
Bildschirmseiten verteilen. In meinem konkreten Fall ist das
anders, da
sollen alle Parameter in einem Fenster sichtbar und änderbar sein, was
häufig vorkommen kann.
Im Augenblick handhabe ich das so, dass bei allen Parameteränderungen,
von denen clientseitig bekannt ist, dass sie die Auswahlmöglichkeiten
ändern, ein Request an den Server geschickt wird, der JS
zurückliefert,
welches wiederum das Formular geeignet anpasst.
Je länger ich darüber nachdenke, um so mehr komme ich zu der Meinung,
dass das nicht zusammenzubringen ist - der Server müsste reine Daten,
nicht Code liefern, wenn das (an dieser Stelle) RESTful sein soll.
Das funktioniert nur, weil beide Seiten viel von einander wissen. Der
Client weiss, explizit in JavaScript hinein programmiert, welche
Änderungen er dem Server mitteilen muss; der Server weiss, wie er die
clientseitige Darstellung beeinflussen kann. Für eine Web*anwendung*
halte ich das so gerade für vertretbar.
Yep, sehe ich ein. Vielleicht kannst Du diesen Teil der Anwendung
einfach als eine Schicht oberhalb Deines Kerns betrachten, der dann
wiederum RESTful sein kann ...
Für einen *Service* wäre es
unbrauchbar.
+1
Es ist aber eine Anwendung (puh!). Ausserdem: als ich
diesen Teil programmiert habe, war ich noch minder erleuchtet (oh!).
Ein großer Vorzug ist obendrein, dass der Code insgesamt ziemlich
überschaubar ist. Ich habe, sinngemäß
http://example.com/cars/update_ui/7?model=X&variant=Y&...
was einen RJS-generierten Mischmasch aus Funktionsaufrufen und
HTML-Fragmenten liefert, die irgendwie das richtige tun.
Resource-oriented könnte ich eine ganze Reihe von "algorithmischen"
(berechneten, parametrisierten) Ressourcen definieren
http://example.com/cars/available_motors?model=X&variant=Y&...
http://example.com/cars/available_colors?model=X&variant=Y&...
...
die zweifellos allgemeiner wären.
Ja, und auch im Sinne eines Web Services verwendbar ...
Mir aber clientseitig viel mehr Mühe
bereiten würden: mehrere Ajax-Requests statt nur eines einzelnen.
Warum mehr Requests?
Vermutlich mehr Arbeit, die erhaltenen Daten ins DOM einzusortieren.
Einverstanden. Vielleicht könntest Du alternativ ein link_to_function
() mit einem GET auf eine Ressource kombinieren; das GET besorgt Dir
die Daten, und RJS kannst Du auch in den rhtml-Templates benutzen,
ohne dass der Server Code zurückgibt?
Da
gibt es für eifrige RESTronauten sicherlich einige Hektar Spielwiese.
So, ich habe viel geschrieben, aber viel schlauer bin ich trotzdem
noch
nicht.
Trotzdem danke ... ich habe zwar schon viel mit REST, aber extrem
wenig mit Ajax gemacht und finde das deswegen eine sehr interessante
Diskussion.
Viele Grüße,
Stefan
--
Stefan Tilkov, http://www.innoq.com/blog/st/
Michael
--
Michael Schuerig
mailto:[EMAIL PROTECTED]
http://www.schuerig.de/michael/
_______________________________________________
rubyonrails-ug mailing list
[email protected]
http://mailman.headflash.com/mailman/listinfo/rubyonrails-ug
_______________________________________________
rubyonrails-ug mailing list
[email protected]
http://mailman.headflash.com/mailman/listinfo/rubyonrails-ug