Démarrer Rails 4, Model.scoped
Est désormais obsolète.
DEPRECATION WARNING: Model.scoped is deprecated. Please use Model.all instead.
Mais, il y a une différence entre Model.scoped
Et Model.all
, C'est-à-dire que scoped.scoped
Renvoie une étendue, tandis que all.all
Exécute la requête.
On Rails 3:
> Model.scoped.scoped.is_a?(ActiveRecord::Relation)
=> true
On 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 (e.g. `Post.where(published: true).load`). If you want to get an array of records from a relation, you can call #to_a (e.g. `Post.where(published: true).to_a`).
=> false
Il y a des cas d'utilisation dans les bibliothèques/préoccupations qui retournent scoped
quand il y a une condition pour faire quelque chose ou rien, comme ceci:
module AmongConcern
extend ActiveSupport::Concern
module ClassMethods
def among(ids)
return scoped if ids.blank?
where(id: ids)
end
end
end
Si vous changez ce scoped
en all
, vous rencontrerez des problèmes aléatoires selon l'endroit où le among
a été utilisé dans la chaîne de portée. Par exemple, Model.where(some: value).among(ids)
exécuterait la requête au lieu de renvoyer une étendue.
Ce que je veux, c'est une méthode idempotente sur ActiveRecord::Relation
Qui renvoie simplement une portée.
Que dois-je faire ici?
Il semble que where(nil)
soit un véritable remplacement de scoped
, qui fonctionne à la fois sur Rails 3 et 4. :(
Sur Rails 4.1 (beta 1), les travaux suivants fonctionnent:
Model.all.all.is_a?(ActiveRecord::Relation)
=> true
Il semble donc que ce problème a été corrigé, et dans 4.1.0 Model.scoped
a été complètement supprimé.
Comme mentionné dans l'un des commentaires, all
est censé renvoyer une portée selon la documentation .
La documentation est correcte - elle retourne un ActiveRecord :: Relation, mais vous devez utiliser un point-virgule si vous voulez le voir dans la console:
pry(main)> u = User.all;
pry(main)> u.class
=> ActiveRecord::Relation::ActiveRecord_Relation_User
En plus d'utiliser where(nil)
, vous pouvez également appeler clone
si vous savez que self
est une relation et obtenez le comportement identique d'appeler scoped
sans argument , sans l'avertissement de dépréciation.
MODIFIER
J'utilise maintenant ce code en remplacement de scoped
car je n'aime pas utiliser where(nil)
partout où j'ai besoin de me procurer l'étendue actuelle:
# 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
Je ne vois pas pourquoi les auteurs AR ne pourraient pas avoir fait quelque chose de similaire car comme l'OP le souligne all
et scoped
font pas se comportent de la même manière.