Statické metody has_one, has_many, belongs_to, habtm a has_many :through z ActiveRecord::Associations jsou kromě validací základními stavebními kameny ActiveRecordu. Metody které tito pomocníci generují umí mnohem víc než najít všechny objekty platné pro danou asociaci.
Toto se týká se především násobných asociací jako je například has_many. Dejme tomu, že mám modely firma a zaměstnananec ve vztahu (1:N).
class Employee < ActiveRecord::Base belongs_to :company end class Company < ActiveRecord::Base has_many :employees end
Když potřebuji najít všechny zaměstnance s platem vyšším než 10 korun stačí napsat jednoduchý dotaz pomocí metody find:
Employee.find(:all, :conditions => ["salary > ?", 10])
Nicméně tento příklad moc realitu příliš nepostihuje. Většinou mě zajímají jenom zaměstnanci určité firmy:
Employee.find(
:all,
:conditions => [ "company_id = ? AND salary > ?",
my_company.id, 10]
)
Tady je taky vše v pořádku. Kód funguje a dělá přesně to, co po něm chci. Problém je v tom, že princip DRY (neopakujmež se!) dostává ránu pálkou do rozkroku. Na filtrování zaměstnanců naší firmy přece máme metodu _employees_ ve třídě Company:
my_company.employees.each do |employee| # something clever end
Na první pohled se zdá, že company.employees nevrací nic jiného než pole. Company#employees přitom vrací cosi, co se chová jako pole (nebo taky seznam, prostě Enumerable), ale je to objekt mnohem chytřejší (je to Asociace). Dobře placené zaměstnance naší firmy najdu zkráceně takto:
my_company.employees.find(:all, :conditions => ["salary > ?", 10])
Asi stojí za vysvětlení, že prosté volání my_company.employees nikdy nezpůsobí vykonání SQL dotazu. Dotaz do databáze se provede až ve chvíli kdy je jisté, co skutečně potřebuji (např. při zavolání each nebo find).