Was ist scope / named_scope in Schienen?

105

Ich habe vor kurzem ein Praktikum begonnen. Mein Arbeitgeber verwendet Rubin auf Schienen, und ich stoße häufig auf eine neue Syntax, die ich nachschlagen muss, um sie zu verstehen. Ich habe nach einer guten Erklärung für named_scope gegoogelt, aber was ich bisher gefunden habe, sind hauptsächlich Blog-Posts, die großes Lob dafür geben, eher eine klare Definition oder Einführung.

Was genau heißt named_scope (jetzt einfach scope genannt) in Ruby on Rails?

Ziggy
quelle
2
Dieser Blog-Beitrag war für mich von unschätzbarem Wert, als ich benannte Bereiche lernte: ryandaigle.com/articles/2008/8/20/…
Peter Brown
@notapatch der Link ist tot hast du noch einen?
Mbigras
Ryan Daigle: Named Scope: Es ist nicht nur für Bedingungen, weißt du?: Web.archive.org/web/20160306110506/http://…
notapatch

Antworten:

212

Ein Bereich ist eine Teilmenge einer Sammlung. Klingt kompliziert? Ist es nicht. Stell dir das vor:

Sie haben Benutzer. Einige dieser Benutzer haben jetzt Ihren Newsletter abonniert. Sie haben diejenigen markiert, die einen Newsletter erhalten, indem Sie der Benutzerdatenbank ein Feld hinzugefügt haben (user.subscribed_to_newsletter = true). Natürlich möchten Sie manchmal diejenigen Benutzer erhalten, die Ihren Newsletter abonniert haben.

Das können Sie natürlich immer tun:

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

Anstatt dies immer zu schreiben, könnten Sie jedoch so etwas tun.

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

Wenn Sie Rails 4 oder höher verwenden , gehen Sie stattdessen folgendermaßen vor:

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

Auf diese Weise können Sie einfach auf Ihre Abonnenten zugreifen:

User.newsletter.each do #something

Dies ist ein sehr einfaches Beispiel, aber im Allgemeinen können Bereiche sehr leistungsfähige Werkzeuge sein, um Ihre Arbeit zu vereinfachen.

Schauen Sie sich diesen Link an: API-Beschreibung

Michael Schäfermeyer
quelle
7
Kann ich fragen, welche Vorteile dies gegenüber der Definition einer Methode in der Benutzerklasse mit dem Namen "subscribedUsers" hat? zB 'def self.subscribedUsers self.where (: subscribed_to_newsletter => true) end
redroot
3
@redroot der Vorteil ist, dass die scopeSyntax viel sauberer ist, Sie erhalten das gleiche Ergebnis, aber mit nur einer Zeile
Aldo 'xoen' Giambelluca
9
@redroot Früher gab es einen großen Effizienzvorteil, da Bereiche die Datenbank träge abfragten, während Methoden dies eifrig taten. In Rails 3 wurden die Methoden ebenfalls faul, sodass der Unterschied jetzt syntaktischer ist. Quelle
evanrmurphy
API-Dokument-Link ist defekt, bitte aktualisieren Sie api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/…
Lohith MV
Auch ermöglicht scoped Routen mit Link
Benjineer
34

Der Bereich im aktiven Datensatz ähnelt Klassenmethoden, gibt jedoch das Relation-Objekt zurück. Dies bedeutet, dass Sie einen anderen Bereich oder eine andere Methode zur Abfrage aktiver Datensätze aufrufen können.

Wenn Sie beispielsweise ein Zombie-Modell (Zombietabelle) mit den unten genannten Bereichsmethoden haben,

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

Und du rufst an

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

In SQL wird Folgendes übersetzt:

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

Das obige Beispiel basiert auf der Rails 4-Syntax

Akshatha
quelle
Ich kann in keiner Dokumentation ein Beispiel für die Reihenfolge (: created_at ,: desc) finden. Ist es möglich, dass du gemeint hast scope :recent, -> { order(created_at: :desc) }? apidock.com/rails/v4.2.9/ActiveRecord/QueryMethods/order
notapatch
7

Der beste Weg, um die Details zu verstehen, ist die API-Dokumentation.

Sie erhalten die vollständigen Details und die Möglichkeiten, wie wir Scopes verwenden können.

API-Dokumentation des Umfangs

123
quelle
7

Bereiche sind nichts anderes als Klassenmethoden.

Warum sie benutzen?

Mit dem Gültigkeitsbereich können Sie häufig verwendete Abfragen angeben (dies kann als Verknüpfung für lange oder am häufigsten verwendete Abfragen betrachtet werden), die als Methodenaufrufe für die Zuordnungsobjekte oder -modelle referenziert werden können. Mit diesen Bereichen können Sie alle zuvor behandelten Methoden verwenden, z. B. where, joins und include. Alle Bereichsmethoden geben ein ActiveRecord :: Relation-Objekt zurück, mit dem weitere Methoden (z. B. andere Bereiche) aufgerufen werden können.

Um einen einfachen Bereich zu definieren, verwenden wir die Bereichsmethode innerhalb der Klasse und übergeben die Abfrage, die wir ausführen möchten, wenn dieser Bereich aufgerufen wird:

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

Dies entspricht genau der Definition einer Klassenmethode, und die von Ihnen verwendete Methode ist eine Frage Ihrer persönlichen Präferenz:

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

Bitte folgen Sie dem folgenden Link für eine vollständige Beschreibung mit Beispiel. Ich hoffe, dies wird dir helfen.

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

Imran Ahmad
quelle
3
Es ist nicht genau das Gleiche wie das Definieren einer Klassenmethode . Klassenmethoden kehren nilin einigen Fällen zurück und sind daher unter bestimmten Bedingungen nicht verkettbar.
Arslan Ali
1
  • Stellen Sie sich vor, Sie haben ein Modell: Person .

Stellen Sie sich jetzt vor:

  • will alle Menschen auf der Welt, die rote Haare haben.
  • will alle Menschen auf der Welt, die Cricket spielen

Sie könnten diese bestimmten Klassen von Menschen erhalten, indem Sie ein Zielfernrohr verwenden!

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.

Das war doch nicht so schwer, oder?

BKSpurgeon
quelle