zaczynam z railsami i mam zapewne trywialny problem ale nie mogę znaleźć podpowiedzi:
mam tabelę w bazie o nazwie arts zawierającą dane na temat dzieł sztuki, chciałbym stworzyć w modelu metodę która po podaniu parametrów selekcjonowałaby grupę przedmiotów spełniających podane kryteria i zwracała ich w postaci kolekcji. Zrobiłem to przy pomocy SQL-a, działa ale jest obrzydliwie prostackie:
def self.pokaz(author,status,typ,order)
case status
when ‘na_sprzedaz’: status = “rezerwacja is null and order_id is null”
when ‘sprzedane’: status = “order_id is not null”
when ‘rezerwacja’: status = “rezerwacja is not null”
else
status = “id is not null”
end
if !author.blank?
status = status + " and author_id=’"+author+"’"
end
if !typ.blank?
status = status + " and typ = ‘" +typ +"’"
end
if order.blank?
order = “tytul”
end
find(:all, :conditions => [status], :order => [order])
end
def self.search(options = {})
find(:all, :conditions => options
end
W wywołaniu podajesz Art.search(:status => ‘rezerwacja’, :typ => ‘jakis typ’). Coś w tym stylu pewnie będzie ładniejsze. Polecam railscast gdzie Ryan przedstawia jak można używać metodę find z różnymi parametrami - tabele, nile, hashe.
wielkie dzięki za odpowiedź, ale jak mam okazję to chciałbym się jeszcze dowiedzieć jak mogę znaleźć przy pomocy tego rozwiązania przedmioty które mają np. cenę>1000 (cena jest atrybutem modelu Art)? I jeszcze tak trochę z innej strony - jak usuwać poszczególne elementy istniejącej kolekcji?
Jeśli zastosujemy tego typu składnie (tzn. z nawiasem kwadratowym i pytajnikiem), to “wartosc_minimalna” jest escapowane (nie trzeba się przejmować SQL injection).
To zależy czy chcesz je usunąć z kolekcji - wtedy delete, czy usunąć całkowicie (=zniszczyć, usunąć z bazy),
wtedy destroy. Dodatkowo jest wersja destroy!, która w przypadku niepowodzenia rzuca wyjątek.
Przykładowo - chcemy usunąć wszystkie obiekty klasy Art o jakimś tam parametrze “title”:
Tutaj też masz kilka opcji - zależnie od tego, czy chcesz, żeby było to wydajne, czy prostsze
Opcja najprostsza - wyciągasz z bazy wszystkie obiekty Author i odsiewasz te, które nie mają żadnych elementów Art:
Author.find_by_sql("select * from (select a1.name name, count(arts.id) count from authors a1 left outer " +
"join arts on a1.id = arts.author_id group by a1.id) as authors where count > 0")
No cóż - to rozwiązanie jest oczywiście najwydajniejsze, ale niezbyt miłe dla oka
Ostatni rozwiązani - chyba najlepszy kompromis, polega na dodaniu w tabeli authors pola arts_count, a w modelu przy asocjacji włączeniu zliczania powiązanych obiektów (:counter_cache => true). Wtedy zapytanie będzie wyglądało następująco:
Jedyna wada tego rozwiązania jest taka, że sami musimy pamiętać o zaktualizowaniu licznika, kiedy przenosimy np. jakiś produkt artystyczny z jednego autora do innego.