poniedziałek, 13 czerwca 2011

Template inheritance w Rails 3.1 - DRY niczym Briana Banks

Wielkimi krokami zbliża się wersja 3.1 frameworka Ruby on Rails, a wraz z nią wiele ciekawych ficzerów jak na przykład reversible migrations czy mountable engines. Jako genialny wynalazek zostało również wprowadzone template inheritance:
As the name implies, inherited templates make template lookup follow the controller inheritance heirarchy if it can’t find a template for the current controller.
Najłatwiej będzie to opisać fragmentami kodu.


Fragment kodu, który odpowiada za menu możemy przenieść do katalogu app/views/application, ponieważ każdy kontroler dziedziczy po ApplicationController.


Do tej pory wszystko wygląda wspaniale. Co jednak, jeżeli chcielibyśmy dodać jedną pozycję w menu np. dla NewsController? Nic prostrzego. Tworzymy app/views/news/_menu.html.erb w którym dodajemy link. Wspaniale! Co jednak, jeżeli mamy bardzo rozbudowane menu a dla jednego kontrolera chcemy dodać 1 (JEDNĄ!) pozycję? Tak! Musimy skopiować cały plik i dodać tylko ten 1 link. Don't Repeat Yourself pełną gębą.

System szablonów (nie mówię o języku szablonów, ale bardziej o tym jak działa mechanizm ich ładowania, przekazywania do nich zmiennych itd.) w Rails nigdy mnie nie powalał. Dużo bardziej podoba mi się ten znany z Django. Mamy w nim tzw. bloki. Przenosząc ten mechanizm na nasz przykład mielibyśmy blok menu w głównym szablonie (application.html.erb) i bloki rozszerzające go w poszczególnych szablonach. Wyglądałoby to mniej więcej tak:


Prawda że wygodniej, schludniej i bardziej DRY?




Briana Banks (ur. 21 maja 1978 w Monachium) - niemiecka aktorka występująca w filmach pornograficznych. [wikipedia.org] [która zdecydowanie nie jest dry (sucha) - autor]

3 komentarze:

  1. Przecież w Rails robi to się elegancko za pomocą kombinacji content_for i yield. NIe wiem jak w tym kretyńskim Bloggerze formatować kod w komentarzu, więc wklejam to tu https://gist.github.com/1023798

    OdpowiedzUsuń
  2. Wiem, że da się to uzyskać przez content_for, ale dalej nie jest to aż tak dobre rozwiązanie jak w Django. Poza tym nie jest to element wprowadzonego właśnie template inheritance.

    Poza tym czytałem gdzieś (wydaje mi się, że na blogu Yehudy) opinię, która nie zalecała używania tego rozwiązania.

    OdpowiedzUsuń
  3. W sumie jak zapoznałem się trochę bardziej z content_for (wcześniej nie było mi jakoś potrzebne) to przyznaję racje :)

    Dalej tylko nie rozumiem tego podniecania się template inheritance.

    OdpowiedzUsuń