76 votes

Avec Rails 4, Model.scoped est obsolète mais Model.all ne peut pas le remplacer.

Départ Rails 4, Model.scoped est maintenant obsolète.

DEPRECATION WARNING: Model.scoped is deprecated. Please use Model.all instead.

Mais, il y a une différence enModel.scoped et Model.all, qui est, scoped.scoped renvoie un champ d'application, tout all.all exécute la requête.

Sur Les Rails De 3:

> Model.scoped.scoped.is_a?(ActiveRecord::Relation)
=> true

Sur Les Rails De 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 des bibliothèques et des préoccupations qui renvoie scoped quand il y a une condition à faire quelque chose ou rien, comme suit:

module AmongConcern
  extend ActiveSupport::Concern

  module ClassMethods
    def among(ids)
      return scoped if ids.blank?

      where(id: ids)
    end
  end
end

Si vous souhaitez modifier cette scoped de all, vous feriez face à des problèmes aléatoires selon l'endroit où l' among a été utilisé dans le champ d'application de la chaîne. Par exemple, Model.where(some: value).among(ids) exécutez la requête au lieu de retourner un champ d'application.

Ce que je veux, c'est un idempotent de la méthode sur ActiveRecord::Relation qui retourne simplement une portée.

Que dois-je faire ici?

63voto

kenn Points 1314

Il semble que where(nil) soit un véritable remplacement de scoped , qui fonctionne aussi bien sur les rails 3 que sur 4. 4. :(

25voto

Olivier Lacan Points 554

Sur Rails 4.1 (beta 1), les travaux suivants:

 Model.all.all.is_a?(ActiveRecord::Relation)
=> true
 

Il semble donc que ce problème a été résolu et qu’en 4.1.0 Model.scoped a été complètement supprimé.

9voto

Jason Rust Points 146

Comme mentionné dans l'un des commentaires, all est supposé renvoyer une étendue en fonction de la documentation .

Les docs sont corrects - ils renvoient un ActiveRecord :: Relation, mais vous devez utiliser un point-virgule si vous voulez le voir dans la console:

pry(main)> u = User.all;

levier (principal)> u.class

=> ActiveRecord :: Relation :: ActiveRecord_Relation_User

4voto

Andrew Hacking Points 2348

En plus de l'utilisation de where(nil) vous pouvez aussi téléphoner clone si vous savez qu' self est une Relation et obtenir le même comportement de l'appelant scoped sans arguments, sans la dépréciation d'avertissement.

MODIFIER

Je suis maintenant en utilisant ce code en remplacement de scoped car je n'aime pas utiliser where(nil) partout j'ai besoin d'obtenir le champ d'application actuel:

     # 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 l'AR auteurs ne pouvais pas avoir fait quelque chose de semblable depuis que les OP souligne all et scoped ne pas se comporter de la même.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X