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

Antwort per Email an