Hi!
Folgendes Problem: Ich habe ne Portalseite und möchte diese aus
verschiedenen Elementen der Seite zusammensetzen, als Beispiel jetzt mal
mit dem News und dem Umfrage Modul.
Doch wie realisiere ich das? Ich muss ja in meinem PortalController die
Ressourcen für das Template zur Verfügung stellen. Ich möchte mich aber
mit dem Code fürs News auflisten nicht wiederholen, also habe ich
einfach mal versucht die Klasse vom NewsController direkt anzusteuern,
also hab News.index() aufgerufen. Macht Rails natürlich nicht mit, habs
auch schon fast erwartet.
Wie realisiere ich das Problem? Steh voll aufm Schlauch, wäre nett wenn
ihr mir helfen könnt!
Da würde mich auch mal ein vernünftiges Pattern für interessieren -
wir machen es momentan mit einer halb-schmutzigen Herangehensweise:
fat models, skinny controllers: Die Controller tun nicht viel, die
meiste Logik steckt in den Modellen (das ist ja sowieso meistens eine
gute Idee…), dazu gehören alle möglichen Methoden, um Daten
einheitlich aufzubereiten, und vor allem finder-Methoden, die wir mit
scope_out (einem Vorläufer von named_scope) bauen, in denen schon viel
der Geschäftslogik steckt (z.B. scope_out :chapters, :conditions =>
[“status=? and container_type_id=?”, STATUS[:published],
TYPES[:chapter]], :order => “ordinal_number ASC”, :include =>
[:container_type], in dem drin steckt, dass Kapitel immer publiziert
sein müssen, einen bestimmten Typ haben und standardmäßig eine
definierten Sortierung haben - das läßt sich ja bis zum Exzess treiben
(http://blog.caboo.se/articles/2008/8/26/the-awesomest-filter-and-sort-ever
) - so weit, so sauber.
(Achtung, hier wird’s jetzt schmutzig): Dazu dann partials, die sich
ihre Daten aus den Modellen ziehen und dann auf der Seite darstellen.
Also z.B. mit for container in Container.find_chapters(:all) usw. -
solche Konstrukte haben wir in verschiedensten Varianten im Einsatz,
meistens mit der etwas abgemilderten Variante, dass der Controller
dafür zuständig ist, ein Einstiegsobjekt zu finden (also z.B. einen
Container zu laden und denn dann als @container dem view zur Verfügung
zu stellen).
Auch wenn das Ganze nicht sehr sauber ist, kann man halbwegs
vernünftig damit arbeiten: Die partials bleiben bei den views, zu
denen sie ursprünglich gehören, normalerweise wissen sie nicht, wo und
ob sie in verschiedenen Kontexten benutzt werden. Die Geschäftslogik
bleibt an einer Stelle(nämlich in den Models), auch wenn der View
jetzt etwas mehr Wissen über die Objektstrutur hat, als gut für ihn
ist. Natürlich ist das Häresie wider die reine Lehre des MVC, vor
allem weil der Controller in der Mitte ausgespart wird - aber
zumindest für reine Anzeige-Sachen erfüllt das seinen Zweck.
Mann kann das von da aus sicher noch sehr viel weiter treiben (die
partials nicht hart-kodieren, sondern von einem Helper auflösen
lassen, Portlet als Model einführen usw.) und man muss sich was
einfallen lassen, wenn’s auch mal ein Update sein soll (das machen wir
selten und wenn dann mit AJAX über die ursprünglichen Controller) -
aber für einfache Fälle reicht das allemal…
Aber wie gesagt, mich würde da auch ein sauberer Ansatz
interessieren…
GrüßeStefan
Am 02.09.2008 um 00:51 schrieb Julian Stöver:
einfach mal versucht die Klasse vom NewsController direkt anzusteuern,
Posted via http://www.ruby-forum.com/.
Okay danke für eure Tipps. Hatte mir das mit den Models auch schon
überlegt fand die Lösung aber auch nicht so toll. Aber werds dann auch
so machen!
Ich denke dieser Ansatz ist schon der richtige. Vor langer Zeit gab es
mal die “Components” und man konnte aus einem Controller direkt auf eine
Methode eines anderen Controllers zugreifen, dort was rendern lassen und
das dann einfügen. Aus Performance (und einigen anderen) Gründen wurden
die “Components” jedoch aus dem Core entfernt.
Der Ansatz mit dem Auslagern von Findern in die Models und dem Rendern
von “Partials” ist auf jeden Fall der gewünschte Ansatz. “before_filter”
können ebenfalls sehr hilfreich dazu eingesetzt werden, vor irgendeiner
Methode was anderes zu instanzieren.