Starting Rails 4, Model.scoped
ahora está en desuso.
DEPRECATION WARNING: Model.scoped is deprecated. Please use Model.all instead.
Sin embargo, existe una diferencia en Model.scoped
y Model.all
, es decir, scoped.scoped
devuelve un ámbito, mientras que all.all
ejecuta la consulta.
En Rails 3:
> Model.scoped.scoped.is_a?(ActiveRecord::Relation) => true
En Rails 4:
> Model.all.all.is_a?(ActiveRecord::Relation) DEPRECATION WARNING: Relation#all is deprecated. If you want to eager-load a relation, you can call #load (eg `Post.where(published: true).load`). If you want to get an array of records from a relation, you can call #to_a (eg `Post.where(published: true).to_a`). => false
Hay casos de uso en bibliotecas / inquietudes que devuelven un scoped
cuando hay un condicional para hacer algo o nada, como ese:
module AmongConcern extend ActiveSupport::Concern module ClassMethods def among(ids) return scoped if ids.blank? where(id: ids) end end end
Si cambiara este scoped
para all
, se enfrentarían a problemas aleatorios dependiendo de dónde se utilizó el among
en la cadena de scope. Por ejemplo, Model.where(some: value).among(ids)
ejecutaría la consulta en lugar de devolver un ámbito.
Lo que quiero es un método idempotente en ActiveRecord::Relation
que simplemente devuelva un scope.
¿Qué debería hacer aquí?
Parece que where(nil)
es un reemplazo real del scoped
, que funciona tanto en Rails 3 como en 4. 🙁
En Rails 4.1 (beta 1), funciona lo siguiente:
Model.all.all.is_a?(ActiveRecord::Relation) => true
Por lo tanto, parece que este problema se ha solucionado, y en 4.1.0 Model.scoped
se ha eliminado por completo.
Como se menciona en uno de los comentarios, se supone que all
debe devolver un scope de acuerdo con los documentos .
Los documentos son correctos, devuelve una relación ActiveRecord ::, pero debe usar un punto y coma si desea verla en la consola:
pry(main)> u = User.all; pry(main)> u.class => ActiveRecord::Relation::ActiveRecord_Relation_User
Además de usar where(nil)
, también puede llamar a clone
si sabe que self
es una relación y obtiene el mismo comportamiento de llamada con scoped
sin argumentos, sin la advertencia de desaprobación.
EDITAR
Ahora estoy usando este código como un reemplazo en el scoped
porque no me gusta usar where(nil)
todas partes necesito tener acceso al scope actual:
# config/initializers/scoped.rb class ActiveRecord::Base # do things the modern way and silence Rails 4 deprecation warnings def self.scoped(options=nil) options ? where(nil).apply_finder_options(options, true) : where(nil) end end
No veo por qué los autores de AR no podrían haber hecho algo similar, ya que, como OP lo señala all
scoped
no se comporta de la misma manera.