web-dev-qa-db-fra.com

Qu'est-ce que scope / named_scope dans les rails?

J'ai récemment commencé un stage. Mon employeur utilise Ruby on Rails, et je rencontre fréquemment de nouvelles syntaxes que je dois rechercher pour comprendre. J'ai cherché sur Google pour une bonne explication de named_scope, mais ce que j'ai trouvé loin est principalement des articles de blog qui en font l'éloge, plutôt une définition ou une introduction directe.

Quel est exactement named_scope (maintenant simplement appelé scope) dans Ruby on rails?

94
Ziggy

Une étendue est un sous-ensemble d'une collection. Cela semble compliqué? Ce n'est pas le cas. Imagine ça:

Vous avez des utilisateurs. Maintenant, certains de ces utilisateurs sont abonnés à votre newsletter. Vous avez marqué ceux qui reçoivent une newsletter en ajoutant un champ à la base de données des utilisateurs (user.subscribed_to_newsletter = true). Naturellement, vous souhaitez parfois obtenir les utilisateurs qui sont abonnés à votre newsletter.

Vous pouvez bien sûr toujours faire ceci:

User.where(subscribed_to_newsletter: true).each do #something

Au lieu de toujours écrire cela, vous pouvez cependant faire quelque chose comme ça.

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, where(subscribed_to_newsletter: true)
  #yada yada
end

Si vous utilisez Rails 4 ou plus récent , faites-le à la place:

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, -> { where(subscribed_to_newsletter: true) }
  #yada yada
end

Cela vous permet d'accéder à vos abonnés simplement en procédant comme suit:

User.newsletter.each do #something

Il s'agit d'un exemple très simple, mais en général, les portées peuvent être des outils très puissants pour faciliter votre travail.

Consultez ce lien: Description de l'API

190

la portée dans l'enregistrement actif est similaire aux méthodes de classe, mais elles renvoient un objet Relation, ce qui signifie que vous pouvez appeler une autre portée ou une méthode de requête d'enregistrement actif dessus.

Par exemple, si vous avez un modèle Zombie (table zombies) avec les méthodes d'étendue mentionnées ci-dessous,

class Zombie
  scope :rotting, -> { where(rotting: true) }
  scope :fresh, -> { where('age < ?', 25) }
  scope :recent, -> { order(:created_at, :desc) }
end

Et tu appelles

Zombie.rotting.fresh.recent.limit(3)

Cela se traduit par ci-dessous en SQL,

select "zombies.*" from "zombies" where "zombies"."rotting" = 't' and (age<20) order by create_at desc limit 3

L'exemple ci-dessus est basé sur la syntaxe Rails 4

29
Akshatha

La meilleure façon de comprendre les détails est d'aller à la documentation de l'API.

Vous obtiendrez les détails complets et les façons dont nous pouvons utiliser les étendues.

Documentation API de la portée

7
123

Les étendues ne sont que des méthodes de classe.

Pourquoi les utiliser?

La portée vous permet de spécifier les requêtes couramment utilisées (il peut être considéré comme un raccourci pour les requêtes longues ou les plus fréquemment utilisées) qui peuvent être référencées comme des appels de méthode sur les objets ou modèles d'association. Avec ces étendues, vous pouvez utiliser toutes les méthodes précédemment couvertes, telles que où, les jointures et les inclusions. Toutes les méthodes d'étendue renverront un objet ActiveRecord :: Relation qui permettra d'appeler d'autres méthodes (telles que d'autres étendues).

Pour définir une portée simple, nous utilisons la méthode scope à l'intérieur de la classe, en passant la requête que nous aimerions exécuter lorsque cette portée est appelée:

class Article < ActiveRecord::Base
  scope :published, -> { where(published: true) }
end

C'est exactement la même chose que la définition d'une méthode de classe, et que vous utilisez est une question de préférence personnelle:

class Article < ActiveRecord::Base
  def self.published
    where(published: true)
  end
end

Veuillez suivre le lien suivant pour une description complète avec un exemple. J'espère que cela t'aidera.

http://guides.rubyonrails.org/active_record_querying.html

7
Imran
  • Imaginez que vous ayez un modèle: Personne.

Imaginez-vous maintenant:

  • veulent toutes les personnes dans le monde qui ont les cheveux roux.
  • veulent tous les gens du monde qui jouent au cricket

Vous pourriez obtenir ces classes particulières de personnes en utilisant une portée!

Person.red_hair.cricket ## finds all people with red hair who play cricket
Person.red_hair ## finds all people with red hair
Person.cricket ## finds all people who play cricket.

Maintenant, ce n'était pas si difficile, n'est-ce pas?

1
BKSpurgeon