Jeden z najviac zneužívaných, nepochopených a zanedbávaných zo všetkých Koľajnice vstavaných štruktúr je pohľad pomocník . Nachádza sa vo vašom app/helpers
adresár a sú generované predvolene pri každom novom projekte Rails, majú pomocníci často zlú povesť, že sú skládkou jednorazových metód používaných v celej vrstve zobrazenia aplikácie. Samotný Rails, bohužiaľ, podporuje tento nedostatok štruktúry a zlú organizáciu tým, že predvolene zahŕňa všetkých pomocníkov do každého pohľadu, čím vytvára znečistený globálny priestor názvov.
Čo však v prípade, ak by vaši pomocníci mohli byť sémantickejší, lepšie organizovaní a dokonca opakovane použiteľní v rámci projektov? Čo ak by to mohli byť viac než len jednorazové funkcie obsypané celým zobrazením, ale výkonné metódy, ktoré ľahko generovali zložité značky a ponechali vaše zobrazenia bez podmienenej logiky a kódu?
Pozrime sa, ako to urobiť pri vytváraní obrazového kolotoča, so známym rámcom Twitter Bootstrap a starým dobrým staromódnym objektovo orientovaným programovaním.
Vo vrstve zobrazenia aplikácie Rails je možné použiť veľa rôznych návrhových vzorov: uvádzať, zdobiť, zdobiť, čiastočne aj pomáhať. Moje jednoduché pravidlo je, že pomocníci fungujú skvele, keď chcete generovať značky HTML, ktoré vyžadujú určitú štruktúru, špecifické triedy CSS, podmienenú logiku alebo opätovné použitie na rôznych stránkach.
Najlepší príklad sily pomocníkov Rails predvádzajú FormBuilder
so všetkými súvisiacimi metódami na generovanie vstupných polí, výber značiek, štítkov a iných štruktúr HTML. Tieto užitočné metódy pre vás generujú značky so všetkými relevantnými atribútmi nastavenými správne. Takéto pohodlie je dôvod, prečo sme sa do Rails zamilovali predovšetkým my všetci.
Výhody plynúce z použitia dobre vytvorených pomocníkov sú rovnaké ako všetky dobre napísané a čisté kódy: zapuzdrenie, zníženie opakovania kódu (DRY) a vylúčenie logiky z dohľadu.
Twitter Bootstrap je a široko používaný front-endový rámec ktorá je dodávaná so vstavanou podporou bežných komponentov, ako sú modály, karty a obrazové kolotoče. Tieto komponenty Bootstrap sú skvelým prípadom použitia pre vlastných pomocníkov, pretože označenie je vysoko štruktúrované, vyžaduje správne nastavenie určitých tried, ID a atribútov údajov, aby JavaScript fungoval správne, a nastavenie týchto atribútov si vyžaduje trochu podmienenej logiky.
Kolotoč Bootstrap 3 má nasledujúce označenie:
...
Ako vidíte, existujú tri hlavné štruktúry: (1) indikátory (2) obrázkové snímky (3) ovládacie prvky snímky.
Cieľom je byť schopný zostaviť jednu pomocnú metódu, ktorá zoberie kolekciu obrázkov a vykreslí celú túto súčasť karuselu, čím zabezpečí, že údaje, id
, href
atribúty a triedy CSS sú nastavené správne.
Začnime základným obrysom pomocníka:
# app/helpers/carousel_helper.rb module CarouselHelper def carousel_for(images) Carousel.new(self, images).html end class Carousel def initialize(view, images) @view, @images = view, images end def html # TO FILL IN end private attr_accessor :view, :images end end
Pomocná metóda carousel_for
vráti kompletné označenie karuselu pre dané adresy URL obrázkov. Namiesto vytvárania balíka jednotlivých metód na vykreslenie každej časti karuselu (čo by vyžadovalo, aby sme ku každej metóde prechádzali zbierku obrázkov a ďalšie stavové informácie), vytvoríme novú triedu plain-old-Ruby s názvom Carousel
reprezentovať dáta karuselu. Táto trieda vystaví html
metóda, ktorá vráti úplne vykreslené označenie. Inicializujeme ho zbierkou webových adries obrázkov images
a kontextom zobrazenia view
.
Upozorňujeme, že view
parameter je inštancia ActionView
, do ktorej sú zamiešaní všetci pomocníci Rails. Predáme ho našej inštancii objektu, aby sme získali prístup k zabudovaným pomocným metódam Rails, ako sú link_to
, content_tag
, image_tag
a safe_join
, ktoré sme použije na vytvorenie značiek v rámci triedy. Pridáme tiež delegate
makro , takže môžeme tieto metódy zavolať priamo bez toho, aby sme odkazovali na view
:
def html content = view.safe_join([indicators, slides, controls]) view.content_tag(:div, content, class: 'carousel slide') end private attr_accessor :view, :images delegate :link_to, :content_tag, :image_tag, :safe_join, to: :view def indicators # TO FILL IN end def slides # TO FILL IN end def controls # TO FILL IN end
Vieme, že karusel sa skladá z troch samostatných komponentov, takže poďme vyradiť metódy, ktoré nám nakoniec dajú označenie pre každú z nich, potom máme html
metóda ich spojiť do kontajnera div
značka, aplikujúca potrebné triedy Bootstrap pre samotný kolotoč.
safe_join
je praktická vstavaná metóda, ktorá spája reťazec reťazcov a volá html_safe
na výsledku. Pamätajte, že k týmto metódam máme prístup prostredníctvom view
parameter, ktorý sme odovzdali pri vytváraní inštancie.
def indicators items = images.count.times.map indicator_tag(index) content_tag(:ol, safe_join(items), class: 'carousel-indicators') end def indicator_tag(index) options = { class: (index.zero? ? 'active' : ''), data: { target: uid, slide_to: index } } content_tag(:li, '', options) end
Indikátory sú jednoduchým zoradeným zoznamom ol
ktorá má položku zoznamu li
prvok pre každý obrázok v zbierke. Indikátor aktívneho obrázka vyžaduje active
Triedu CSS, takže sa ubezpečíme, že je nastavená na prvý indikátor, ktorý vytvoríme. Toto je skvelý príklad logiky, ktorá by za normálnych okolností musela byť v samotnom pohľade.
Všimnite si, že ukazovatele musia odkazovať na jedinečný id
obsahujúceho prvku karuselu (v prípade, že sa na stránke nachádza viac ako jeden karusel). Toto môžeme ľahko vygenerovať id
v inicializátore a používať ho po zvyšok triedy (konkrétne v rámci indikátorov a ovládacích prvkov). Ak to urobíte programovo vo vnútri pomocnej metódy, zaistí to, že id
bude konzistentné naprieč prvkami kolotoča. Mnohokrát dôjde k malému preklepu alebo zmene id
na jednom mieste, ale nie na iných, spôsobí zlomenie kolotoča; to sa tu nestane, pretože všetky prvky odkazujú automaticky na to isté id
.
def initialize(view, images) # ... @uid = SecureRandom.hex(6) end attr_accessor :uid
def slides items = images.map.with_index slide_tag(image, index.zero?) content_tag(:div, safe_join(items), class: 'carousel-inner') end def slide_tag(image, is_active) options = { class: (is_active ? 'item active' : 'item'), } content_tag(:div, image_tag(image), options) end
Jednoducho iterujeme každý z obrázkov, ktoré sme odovzdali Carousel
inštancie a vytvorte správne označenie: značka obrázka zabalená do div
pomocou item
Trieda CSS, znova nezabudnite pridať active
triedy do prvej, ktorú vytvoríme.
def controls safe_join([control_tag('left'), control_tag('right')]) end def control_tag(direction) options = { class: '#{direction} carousel-control', data: { slide: direction == 'left' ? 'prev' : 'next' } } icon = content_tag(:i, nil, class: 'glyphicon glyphicon-chevron-#{direction}') control = link_to(icon, '##{uid}', options) end
Vytvárame odkazy, ktoré riadia pohyb kolotoča tam a späť medzi obrázkami. Všimnite si použitie uid
ešte raz; nemusíte sa obávať nepoužívania správneho ID na rôznych miestach v rámci štruktúry karuselu, je to automaticky konzistentné a jedinečné.
S tým je náš pomocník v kolotoči hotový. Tu je to v celom rozsahu:
# app/helpers/carousel_helper.rb module CarouselHelper def carousel_for(images) Carousel.new(self, images).html end class Carousel def initialize(view, images) @view, @images = view, images @uid = SecureRandom.hex(6) end def html content = safe_join([indicators, slides, controls]) content_tag(:div, content, id: uid, class: 'carousel slide') end private attr_accessor :view, :images, :uid delegate :link_to, :content_tag, :image_tag, :safe_join, to: :view def indicators items = images.count.times.map content_tag(:ol, safe_join(items), class: 'carousel-indicators') end def indicator_tag(index) options = { class: (index.zero? ? 'active' : ''), data: { target: uid, slide_to: index } } content_tag(:li, '', options) end def slides items = images.map.with_index content_tag(:div, safe_join(items), class: 'carousel-inner') end def slide_tag(image, is_active) options = { class: (is_active ? 'item active' : 'item'), } content_tag(:div, image_tag(image), options) end def controls safe_join([control_tag('left'), control_tag('right')]) end def control_tag(direction) options = { class: '#{direction} carousel-control', data: { slide: direction == 'left' ? 'prev' : 'next' } } icon = content_tag(:i, '', class: 'glyphicon glyphicon-chevron-#{direction}') control = link_to(icon, '##{uid}', options) end end end
Na záver, aby sme sa dostali domov, pozrime sa na rýchly príklad toho, ako nám tento pomocník môže uľahčiť život. Povedzme, že vytvárame webovú stránku pre zoznamy prenájmov bytov. Každý Apartment
objekt má zoznam adries URL obrázkov:
class Apartment def image_urls # ... end end
Pomocou nášho pomocníka na kolotoči môžeme vykresliť celý kolotoč Bootstrap jediným volaním na carousel_for
, čím úplne odstránime pomerne zložitú logiku z pohľadu:
# ...
Nie ste si istí, kedy použiť pomocníkov v zobrazení Rails? Tu je ukážka. Tweet Pomocou tejto jednoduchej, ale výkonnej techniky sme presunuli to, čo by predstavovalo značné množstvo značiek a logiky, z vrstvy zobrazenia a do pomocnej funkcie, ktorú je možné použiť na vykreslenie komponentov karuselu kdekoľvek iba pomocou carousel_for(some_images)
hovor. Tento všeobecný pomocník je použiteľný vo všetkých vašich projektoch Rails, kedykoľvek používate Twitter Bootstrap. Najdôležitejšie je, že vo svojej súprave nástrojov máte teraz nový nástroj, ktorý môžete použiť aj pre komponenty špecifické pre projekt.
Až sa teda nabudúce ocitnete pri písaní a opätovnom zadávaní rovnakého druhu značiek a vkladaní podmienenej logiky do svojich zobrazení, skontrolujte, či pomocná funkcia čaká na napísanie, ktorá vám uľahčí život.