Anulación de "buscar" en ActiveRecord de forma SECO
-
09-06-2019 - |
Pregunta
Tengo algunos modelos a los que se les deben aplicar condiciones de búsqueda personalizadas.Por ejemplo, si tengo un modelo de Contacto, cada vez que se llama a Contact.find, quiero restringir los contactos devueltos que solo pertenecen a la Cuenta en uso.
Encontré esto a través de Google (que he personalizado un poco):
def self.find(*args)
with_scope(:find => { :conditions => "account_id = #{$account.id}" }) do
super(*args)
end
end
Esto funciona muy bien, excepto en algunas ocasiones en las que account_id es ambiguo, así que lo adapté a:
def self.find(*args)
with_scope(:find => { :conditions => "#{self.to_s.downcase.pluralize}.account_id = #{$account.id}" }) do
super(*args)
end
end
Esto también funciona muy bien, sin embargo, quiero que esté SECO.Ahora tengo algunos modelos diferentes en los que quiero que se utilice este tipo de función.¿Cuál es la mejor manera de hacer esto?
Cuando responda, incluya el código para ayudar a nuestras mentes a comprender la metaprogramación Ruby-fu.
(Estoy usando Rails v2.1)
Solución
No nos dice qué versión de Rails está utilizando [editar: está en Rails 2.1, por lo que seguir los consejos es totalmente operativo], pero le recomendaría que utilice el siguiente formulario en lugar de sobrecargarlo:
account.contacts.find(...)
esto envolverá automáticamente la búsqueda en un alcance donde se incluye la cláusula de usuario (dado que tiene account_id, asumo que tiene la cuenta en algún lugar cercano)
Le sugiero que consulte los siguientes recursos sobre alcances.
Otros consejos
El consejo de Jean es acertado.Suponiendo que sus modelos se vean así:
class Contact < ActiveRecord::Base
belongs_to :account
end
class Account < ActiveRecord::Base
has_many :contacts
end
Deberías estar usando el contacts
asociación de la cuenta actual para garantizar que solo obtenga Contact
registros con alcance para esa cuenta, así:
@account.contacts
Si desea agregar más condiciones a su consulta de contactos, puede especificarlas usando buscar:
@account.contacts.find(:conditions => { :activated => true })
Y si constantemente busca usuarios activados, puede refactorizarlo en un alcance con nombre:
class Contact < ActiveRecord::Base
belongs_to :account
named_scope :activated, :conditions => { :activated => true }
end
Que luego usarías así:
@account.contacts.activated
para dar una respuesta específica a su problema, sugeriría mover el método mencionado anteriormente a un módulo que se incluirá en los modelos en cuestión;entonces tendrías
class Contact
include NarrowFind
...
end
PD.tenga cuidado con el escape SQL de account_id, probablemente debería usar el :conditions=>[".... =?", $account_id]
sintaxis.