, Štefan Húska
Pomenované varianty v Active Storage: prečo prestať písať helper metódy na model
Pôvodná implementácia vyzerala takto — tri metódy, každá s vlastnými rozmermi:
def variant_cover
file.variant(resize_to_fill: [600, 400])
end
def variant_medium
file.variant(resize_to_limit: [1200, 1200])
end
def variant_full
file.variant(resize_to_limit: [2400, 2400])
end
Problém nie je v tom, že by to nefungovalo. Problém je v tom, že rozhodnutia o spracovaní obrázkov — čo je infraštruktúrna záležitosť — sú roztrúsené po business logike modelu. Navyše, ak niekde v šablóne potrebujete thumbnail, píšete image.file.variant(resize_to_fill: [150, 150]) priamo do ERB, čím sa rozmery duplikujú na viacerých miestach.
Nový prístup: varianty v bloku has_one_attached
Rails od verzie 7 umožňuje definovať pomenované varianty priamo pri deklarácii attachmentu:
has_one_attached :file do |attachable|
attachable.variant :cover, resize_to_fill: [600, 400]
attachable.variant :medium, resize_to_limit: [1200, 1200]
attachable.variant :full, resize_to_limit: [2400, 2400]
attachable.variant :thumb, resize_to_fill: [150, 150]
end
Všetky štyri varianty sú teraz na jednom mieste. Volanie v šablónach sa zjednotí na image.file.variant(:medium) namiesto image.variant_medium. Rozdiel je jemný, ale významný — variant je teraz vlastnosťou attachmentu, nie modelu. Model Image sa stará o galérie, slugy a väzby; spracovanie súborov patrí k attachmentu.
Dopad na šablóny
Zmena sa prejavila naprieč celou aplikáciou. Vo view komponentoch aj v admin paneli sa volania zjednotili:
<%# Predtým %>
<%= image_tag url_for(image.variant_medium), class: image_css %>
<a href="<%= url_for(image.variant_full) %>">
<%# Potom %>
<%= image_tag url_for(image.file.variant(:medium)), class: image_css %>
<a href="<%= url_for(image.file.variant(:full)) %>">
Najväčší prínos bol pri thumbnailoch. Predtým sa resize_to_fill: [150, 150] opakovalo v piatich rôznych ERB súboroch — v admin editácii sekcií, v galériových pickeri, v náhľadoch. Teraz všetky používajú jednoducho image.file.variant(:thumb). Ak sa niekedy rozhodnem zmeniť veľkosť thumbnailu, stačí upraviť jedno miesto v modeli.
Čo si z toho odniesť
Pomenované varianty nie sú nová funkcia — sú v Rails od verzie 7. Napriek tomu je bežné vidieť projekty, kde sa varianty definujú ako metódy na modeli alebo sa rozmery kopírujú priamo do šablón. Dôvod je jednoduchý: helper metódy fungujú a nikto nemá motiváciu ich refaktorovať.
Kľúčový argument pre pomenované varianty je single source of truth. Keď máte štyri varianty definované v bloku has_one_attached, každý nový vývojár okamžite vidí, aké veľkosti obrázkov aplikácia používa. Nemusí hľadať metódy po modeli ani grep-ovať šablóny. A hlavne — keď sa rozmery zmenia, menia sa na jednom mieste.