2008-09-17 25 views
5

Mam kilka modeli, które muszą mieć niestandardowe warunki wyszukiwania umieszczone na nich. Na przykład, jeśli mam model kontaktu, za każdym razem, gdy wywoływana jest funkcja Contact.find, chcę ograniczyć zwracane kontakty, które należą tylko do używanego konta.Nadpisywanie "Znajdź" w ActiveRecord DRY way

Uważam to za pośrednictwem Google (który ja trochę dostosowane):

def self.find(*args) 
    with_scope(:find => { :conditions => "account_id = #{$account.id}" }) do 
    super(*args) 
    end 
end 

Działa to doskonale, z wyjątkiem kilku okazjach gdzie ACCOUNT_ID jest niejednoznaczna więc dostosować go do:

def self.find(*args) 
    with_scope(:find => { :conditions => "#{self.to_s.downcase.pluralize}.account_id = #{$account.id}" }) do 
    super(*args) 
    end 
end 

Działa to również świetnie, ale chcę, aby był suchy. Teraz mam kilka różnych modeli, które chcę używać tego rodzaju funkcji. Jaki jest najlepszy sposób na zrobienie tego?

Po udzieleniu odpowiedzi, proszę dołączyć kod, aby pomóc naszym umysłom zrozumieć metaprogramowanie Ruby-fu.

(Używam Rails v2.1)

Odpowiedz

8

Nie nam powiedzieć, która wersja szyn używasz [edit - to na szynach 2,1 zatem następujące rada jest w pełni sprawna], ale chciałbym polecam skorzystać z poniższego formularza zamiast przeciążenia znaleźć się:

account.contacts.find(...) 

będzie to automatycznie owinąć znalezienia w zakresie, w którym klauzula użytkownik jest zawarty (skoro masz ACCOUNT_ID Zakładam, że masz konto gdzieś blisko)

Proponuję sprawdzić następujące Zasoby na teleskopach

+0

Dzięki Jean, który będzie działał uczta i jest chyba właściwa droga aby to zrobić. Wprowadzenie konta jest nowym dodatkiem do istniejącego kodu, więc domyślam się, że komplikowałem rzeczy, wychodząc z tej perspektywy. Po prostu przejdę i zmodyfikuję istniejący kod, który ma być zakreślony przez Konto. –

0

dać konkretną odpowiedź na swój problem, polecam przemieszczania wyżej wymienionego sposobu na moduł, który ma być włączony do danych modeli; więc będziesz mieć

class Contact 
    include NarrowFind 
    ... 
end 

PS. uważaj na sql ucieczki z account_id, powinieneś prawdopodobnie użyć składni :conditions=>[".... =?", $account_id].

+0

Najprawdopodobniej jest to zły pomysł, aby całkowicie zastąpić wyszukiwarkę podstawową modelu, ponieważ mogłoby to naruszyć oczekiwania wszystkich osób spoza zespołu, w tym autorów wtyczek (wtyczka wyszukiwania myśli), nie wspominając o ryzyku złamania samego szyny (mało prawdopodobne, ale niemożliwe) – Jean

5

Rada Jeana jest dobra.Zakładając, że modele wyglądają tak:

class Contact < ActiveRecord::Base 
    belongs_to :account 
end 

class Account < ActiveRecord::Base 
    has_many :contacts 
end 

Powinieneś pomocą stowarzyszenie contacts rachunku bieżącym w celu zapewnienia, że ​​dostajesz tylko Contact rekordy zawężona do tego konta, tak jak poniżej:

@account.contacts 

Jeśli chcesz dodać kolejne warunki do zapytania kontaktów, można określić je przy użyciu znajdują się:

@account.contacts.find(:conditions => { :activated => true }) 

A jeśli znajdziesz się co nstantly zapytań dla aktywnych użytkowników, można byłaby go w nazwie zakresie:

class Contact < ActiveRecord::Base 
    belongs_to :account 
    named_scope :activated, :conditions => { :activated => true } 
end 

Które następnie użyć tak:

@account.contacts.activated