2010. január 25., hétfő

Ruby on Rails ORM

Bár még nincs Ruby on Rails-es projekt az irodában, de több érdeklődés is volt már ügyfelek részéről. Most az egyik meglévő ügyfelünk is fontolóra vette egy már futó projekt kiszervezését hozzánk. Így aztán gyakorlásként elkezdődött egy bloghoz hasonló kis webes alkalmazás fejlesztése, ahol lehet regisztrálni, bejegyzéseket írni, mások bejegyzéseit elolvasni, és kommenteket írni a bejegyzésekhez.

Ennek egy részfeladata a 'Legfrissebbek' link, amely megjeleníti a legutóbb kommentelt bejegyzéseket az oldalon. A szokásoktól eltérően ez nem egyszerűen az utolsó néhány komment kiírását jelenti, hanem azon bejegyzések egyedi listáját, amelyeket a legutóbb kommenteltek.

A bejegyzés és a komment osztály között természetesen 1-n kapcsolatot adunk meg:

class Note <>
has_many :comment
...
end

class Comment <>
belongs_to :note
...
end

Az első próbálkozás: JOIN

Note.all(:joins => [:comment], :order => "comments.created_at DESC", :limit => 6)

A Rails a következő lekérdezést generálta ehhez:

SELECT `notes`.* FROM `notes` INNER JOIN `comments` ON comments.note_id = notes.id ORDER BY comments.created_at DESC LIMIT 6

Ezzel az a probléma hogy az eredményben többször is előfordult egy bejegyzés ha több új komment is tartozott hozzá.


Második próbálkozás: DISTINCT

Note.all(:select => "DISTINCT `notes`.*", :joins => [:comment], :order => "comments.created_at DESC", :limit => 6)

Így 6 különböző bejegyzést kapunk, és látszólag megoldottuk a problémát.

Kerestünk egy Rails hosting szolgáltatást: http://heroku.com. A free regisztráció nem ad sok tárhelyet, sem nagy teljesítményt, de egy kis forgalmú blognak megfelelő. Fontos, hogy a remote git repo-ba kell feltennünk a programunkat, és ehhez git kliens is kell, pl. http://code.google.com/p/msysgit/

A fenti megoldás MySQL (5.0) alatt működött, de a Heroku PostgreSQL-t használ, ahol ebben a formában hibás volt a query (olyan mezőre is rendez, amelyet nem kérdez le). Olyan megoldást kerestünk, amely könnyen beilleszthető az ActiveRecord-ba is.


Harmadik próbálkozás: DISTINCT nélkül kérjük le a bejegyzések egyedi listáját, majd kiiratjuk a bejegyzéseket.

comment_list = Comment.all(:select => "note_id, max(created_at)", :group => "note_id", :order => "max(created_at) DESC", :limit => 6)
note_ids = []
comment_list.each { |comment|
note_ids <<>
}
Note.find(note_ids)

A generált lekérdezés már hiba nélkül lefutott PostgreSQL-en is:

SELECT note_id, max(created_at) FROM `comments` GROUP BY note_id ORDER BY max(created_at) DESC LIMIT 6

A fenti kis kódrészletből is látszik, milyen kifejezően írhatunk lekérdezéseket ill. kezelhetünk listákat Ruby-ban.

A Rails egy open-source web framework, amellyel MVC architektúrájú webes alkalmazásokat fejleszthetünk. Bővebben: http://guides.rubyonrails.org/

G.Z.

Nincsenek megjegyzések:

Megjegyzés küldése