2012. augusztus 21., kedd

Ruby on Rails izzadás

Hozzámvágtak egy szép nagy Ruby on Rails alkalmazást, több mint 4 tucat entity class-szal, pár rake fájllal, meg ez valami webapp, tehát mindenféle cucc van még itt. Szerencsére nekem csak a rake-ekkel kell foglalkozni, melyek kisebb-nagyobb crawler-eket rejtenek, taszkokba csomagolva.

Ruby-vel (vagy -val?! :D) az egyetemen Script nyelvek órán foglalkoztunk pár előadást, a végén. A Ruby on Rails összetétel jó, ha egyáltalán elhangzott. Nem mélyültünk el a nyelvben, de az alapokat azért átvettük anno, most nézem, még osztályokat is tanultunk definiálni. Ezekből én semmire nem emlékeztem, szóval a rake fájlok olvasgatásával építettem újra a nyelvet a fejemben. :D

Történik egyszer, hogy miután kiegészítettem egy rake fájlt, futtattam, és az első két hibát elhárítottam, ismét megakadt. Valami olyasmit írt, hogy váratlanul nil-t kaptam valahol, ahol nem kéne, és valami nil.update_attribute válthatta ki. Persze a rake fájlban az update szó sem szerepelt.

Olyan helyen dobta a hibát (körbe puts-olással találtam meg, mert luxus lenne sorindexet kiírnia a rake-nek...), ahol egy entitást akar létrehozni a korábbi programozó:

akarmi = Akarmi.create(
    :masvalami_id => ertek1
    :mezo => ertek2
  )
A hibaüzenetből én arra következtettem, hogy talán rossz mezőt akar valahol módosítani. Ránéztem az Akarmi osztály definíciójára. Hát rögtön az első mezőnév hiányzik, a masvalami_id. Viszont lejjebb van valami ilyesmi, hogy belongs to :masvalami, :class_name => "Masvalami". Érdekes, és nagyon furcsa, de kapisgálom, hogy ez is ilyen ORM szerű cucc lehet, mint a JPA.

Utána akartam olvasni a Ruby accessoroknak (a kettősponttal kezdődő izék). Nem találtam azt, amit kerestem. Aztán rákerestem az ActiveRecord::Base-re, mert ezt is írta a hibaüzi, meg látom az Akarmi osztályban, hogy ez az őse. Megtaláltam a doksiját, ahol érdekes dolgokat tudtam meg.

Például ezek a find_by_*, meg find_or_create_by_* metódusok dinamikusan generálódnak, és bármilyen mezőnevet a * helyére lehet írni - állati! :D

Innen gondolva... akkor a masvalami_id is generálódhat dinamikusan, tehát akkor azzal talán mégsem kéne gondnak lenni.

A doksi oldal tetején azt láttam, hogy 3 féleképp is létre lehet hozni ilyen ActiveRecord cuccot: a fenti módon, a create-tel, blokkos módon, meg teljesen szétszedve akarmi.mezo=value utasításokra. Próbaképpen átírtam a kódot az alábbi formára:
akarmi = Akarmi.new do |a|
    a.masvalami_id = ertek1
    a.mezo = ertek2
end
És beraktam mindegyik belső utasítás után egy puts-ot, hogy lássam, hol hasal el.

Legnagyobb meglepetésemre lefutott hiba nélkül! Pedig azt hittem, hogy az accessor dinamikus csak. De nem... sőt. :D

Nem értem, hogy mi a különbség a két változat között, elvileg ekvivalensek a cikk szerint, dehát mégsem.

1-0 ide! :D

Folytatás

4 megjegyzés:

Richard O. Legendi írta...

RoR-hoz nem értek -- és igen, Ruby-val írják :-) --, de esetleg pingesd meg a topicot StackOverflown. Nyakamat rá, hogy 5 percen belül választ kapsz :-)

Ez meg egy kis motiváció a projecthez (5 perces, humoros kis lightning talk Ruby-s okosságokkal kapcsolatban):

https://www.destroyallsoftware.com/talks/wat

juzraai írta...

Jó ötlet, lehet, hogy majd felvetem. :)

Ezzel a -val/-vel dologgal azért vagyok bizonytalan, mert valahogy én franciásan akarnám kiejteni: "rübi"-nek, s így akkor "rübivel" lenne a jó.:D De sejtettem amúgy, meg hallom, hogy u-val szokás mondani, és köszi a megerősítést.:)

Hát ez a videó meg hatalmas:D főleg az utolsó trükk:D

Branni írta...

Kicsit régi a téma de azért hozzászólok :)
A kettő nem ekvivalens!
A create metódus létrehoz egy objektumot és utána egyből menti is, míg a new csak létrehozza magát az objektumot de csak a save metódus meghívas után menti az ORM (ActiveRecord). Tehát a hibát azért nem kaptad így mert nem is hívtad meg az update_attributes metódust.
És a ruby accessorok nem a "kettősponttal kezdődő izék", azok a symbolumok ;)

juzraai írta...

Igen, a create és new különbségére, meg még pár dologra rájöttem azóta :), le is írtam a cikk folytatásában.

Köszi a pontosítást! :)