csiszarattila.com / Rubysztán

Haml szövegbeviteli(textarea) mezőkben

Nemsokkal az első Rails-es alkalmazáson megírása után elkezdtem használni a Haml-t, ami egy remek HTML templétező vagy sablon motor. Annak aki még nem ismerné, javaslom mindenképpen vessen rá egy pillantást.

A blogmotorom írása közben ötlött fel a gondolat, mi lenne ha integrálnám a használatát a szövegbeviteli mezőkbe is, hiszen így sokkal egyszerűbb lenne formázott bevitelt előállítani. A Haml ugyanis nem rugaszkodik el teljesen a HTML nyelvtől, mint teszi azt sok sablon nyelv, másrészt nem igényel olyan összetett megoldást, mint például a TinyMCE.

Maga a Haml alapú szöveg előállítása, elmentése, és megjelenítése nem igényel túl sok problémát, de mit tegyünk, ha valamilyen hibát vétünk a formázás közben, hiszen ekkor a Haml fordító kivételt küld.

1.lépés: A kivételek elkapása

Fordítsuk előnyükre és használjuk ki a Haml kivételkezelését: ellenőrizzük még elmentés előtt a bejegyzés szövegét megfelel-e a szabályoknak.

def validate_haml_syntax
  begin
    Haml::Engine.new(read_attribute :body).render unless body.nil?1
  rescue Haml::SyntaxError => e2
    line = e.line.nil? ? 1 : e.line+1
    errors.add(:body,"Haml error on line #{line}: #{e.message}")3
  end
end

Elsőként egy új Haml objektumot hozunk létre, majd meghívjuk rá a render metódust1. Ami hiba esetén Haml::SyntaxError-t dob2, ezt próbáljuk meg lekezelni. Az átadott kivétel-objektum tartalmazza: a hiba üzenetét(message) illetve a hiba sorszámát(line). Ezt a kettőt hozzáadva a modellünk errors tömbjéhez két dolog következik be: egyrészt a Rails érzékeli, hogy hibás a modellünk és újrahívja az előző kontrollert (pl. update vagy create), megjelenítve a hiba üzenetet (error_messages helper).

2.lépés: Validálás hozzáadása

Egyszerűen meghívjuk a validate_haml_syntax() metódusunkat a modell validate() metódusában, amely automatikusan végrehajtódik a modell elmentése előtt.

def validate
  validate_haml_syntax()
end

3.lépés: A szöveg "fordítása" HTML-re

Már csak egy dolgot kell megoldanunk, az adatbázisban Hamlként tárolt szöveg visszaalakítását Html-é, ami tulajdonképpen a Haml::Engine(text).render meghívását jelenti.

Akár felülbíráhatnánk ezzel a modellünk body attribútumának olvasási metódusát - body() - így viszont a szerkesztési felületen is a Html szöveg jellene meg mentés után, mi viszont ragaszkodunk a Haml formázott szöveghez.

Vagy hozzáadhatnánk akár egy to_html metódust a modellünkhöz, viszont mennyivel egyértelműbb lenne, ha x.to_html helyett x.body.to_html()-t használhatnánk.

Ehhez két ismeretre van szükségünk. Először is minden Rails modell rendelkezik egy after_initialize() metódussal1, ami megoldja a initialize() metódus felülbírálási gondjait, másodszor a Ruby lehetővé teszi, hogy objektumokhoz egyed v. példány metódusokat rendeljünk!2

def after_initialize1
  class << body 
    def to_html2
      Haml::Engine.new(self).render
    end
  end
end

Hozzáadhattuk volna magát a metódust a String osztály megnyitásával is - a body elemünk String példány, ekkor azonban minden további String osztályú objektumunk is rendelkezne a metódussal, amit szeretnénk elkerülni.