Sostituire "trova" in ActiveRecord in modo DRY
-
09-06-2019 - |
Domanda
Ho alcuni modelli su cui è necessario inserire condizioni di ricerca personalizzate.Ad esempio, se ho un modello Contact, ogni volta che viene chiamato Contact.find, voglio limitare i contatti restituiti che appartengono solo all'Account in uso.
Ho trovato questo tramite Google (che ho personalizzato un po'):
def self.find(*args)
with_scope(:find => { :conditions => "account_id = #{$account.id}" }) do
super(*args)
end
end
Funziona alla grande, tranne alcune occasioni in cui account_id è ambiguo, quindi l'ho adattato a:
def self.find(*args)
with_scope(:find => { :conditions => "#{self.to_s.downcase.pluralize}.account_id = #{$account.id}" }) do
super(*args)
end
end
Anche questo funziona benissimo, tuttavia, voglio che sia ASCIUTTO.Ora ho alcuni modelli diversi in cui desidero che venga utilizzato questo tipo di funzione.Qual è il modo migliore per farlo?
Quando rispondi, includi il codice per aiutare le nostre menti a comprendere la metaprogrammazione di Ruby-fu.
(Sto usando Rails v2.1)
Soluzione
Non ci dici quale versione di rail stai utilizzando [modifica: è su rails 2.1, quindi seguire i consigli è pienamente operativo], ma ti consiglierei di utilizzare il seguente modulo invece di sovraccaricarti:
account.contacts.find(...)
questo avvolgerà automaticamente la ricerca in un ambito in cui è inclusa la clausola utente (dato che hai l'account_id presumo che tu abbia l'account da qualche parte vicino)
Ti suggerisco di controllare le seguenti risorse sugli ambiti
Altri suggerimenti
Il consiglio di Jean è valido.Supponendo che i tuoi modelli assomiglino a questo:
class Contact < ActiveRecord::Base
belongs_to :account
end
class Account < ActiveRecord::Base
has_many :contacts
end
Dovresti usare il contacts
associazione del conto corrente per assicurarti di ricevere solo Contact
record limitati a quell'account, in questo modo:
@account.contacts
Se desideri aggiungere ulteriori condizioni alla query dei tuoi contatti, puoi specificarle utilizzando trova:
@account.contacts.find(:conditions => { :activated => true })
E se ti ritrovi costantemente a cercare utenti attivati, puoi rifattorizzarli in un ambito denominato:
class Contact < ActiveRecord::Base
belongs_to :account
named_scope :activated, :conditions => { :activated => true }
end
Che poi utilizzeresti in questo modo:
@account.contacts.activated
per dare una risposta concreta al tuo problema, suggerirei di spostare il metodo sopra citato in un modulo da includere nei modelli in questione;quindi avresti
class Contact
include NarrowFind
...
end
PS.fai attenzione all'escape sql di account_id, probabilmente dovresti usare il file :conditions=>[".... =?", $account_id]
sintassi.