¿Hay alguna manera de combinar ámbitos con nombre en un nuevo ámbito con nombre?
-
09-06-2019 - |
Pregunta
Tengo
class Foo < ActiveRecord::Base
named_scope :a, lambda { |a| :conditions => { :a => a } }
named_scope :b, lambda { |b| :conditions => { :b => b } }
end
Me gustaría
class Foo < ActiveRecord::Base
named_scope :ab, lambda { |a,b| :conditions => { :a => a, :b => b } }
end
pero prefiero hacerlo en SECO.Puedo obtener el mismo efecto usando
Foo.a(something).b(something_else)
pero no es particularmente hermoso.
Solución
Bueno, todavía soy nuevo en Rails y no estoy seguro exactamente de qué es lo que buscas aquí, pero si solo buscas reutilizar código, ¿por qué no usar un método de clase normal?
def self.ab(a, b)
a(a).b(b)
end
Podrías hacerlo más flexible tomando *args en lugar de a y b, y luego posiblemente hacer que uno u otro sea opcional.Si estás atascado en el ámbito_nombre, ¿no puedes extenderlo para que haga lo mismo?
Avísame si estoy totalmente equivocado con lo que quieres hacer.
Otros consejos
Al menos desde 3.2 hay una solución inteligente:
scope :optional, ->() {where(option: true)}
scope :accepted, ->() {where(accepted: true)}
scope :optional_and_accepted, ->() { self.optional.merge(self.accepted) }
Al convertirlo en un método de clase, no podrás encadenarlo a un proxy de asociación, como:
@category.products.ab(x, y)
Una alternativa es aplicar este parche para habilitar una opción: a través de name_scope:
named_scope :a, :conditions => {}
named_scope :b, :conditions => {}
named_scope :ab, :through => [:a, :b]
Sí Reutilizar el ámbito_nombre para definir otro ámbito_nombre
Lo copio aquí para vuestra comodidad:
Puedes usar proxy_options para reciclar un name_scope en otro:
class Thing
#...
named_scope :billable_by, lambda{|user| {:conditions => {:billable_id => user.id } } }
named_scope :billable_by_tom, lambda{ self.billable_by(User.find_by_name('Tom').id).proxy_options }
#...
end
De esta manera se puede encadenar con otros ámbitos nombrados.
Lo uso en mi código y funciona perfectamente.
Espero que ayude.
@pijama:ya sabes, lo había considerado, pero lo descarté porque pensé que luego no podría encadenar un tercero alcance nombrado, así:
Foo.ab(x, y).c(z)
Pero desde ab(x, y)
devuelve lo que sea b(y)
Volvería, creo que la cadena funcionaría.¡Qué manera de hacerme repensar lo obvio!
Verificar:
http://github.com/binarylogic/searchlogic
¡Impresionante!
Ser especifico:
class Foo < ActiveRecord::Base
#named_scope :ab, lambda { |a,b| :conditions => { :a => a, :b => b } }
# alias_scope, returns a Scope defined procedurally
alias_scope :ab, lambda {
Foo.a.b
}
end