Routen und Ressourcen

Grundlegende Routingkonventionen

Werfen wir einen Blick auf unsere Routen, wie sie jetzt sind, mit rake routes:

$ rake routes Prefix Verb URI Pattern Controller#Action list_posts GET /list_posts(.:format) application#list_posts GET /show_post/:id(.:format) application#show_post new_post GET /new_post(.:format) application#new_post create_post POST /create_post(.:format) application#create_post GET /edit_post/:id(.:format) application#edit_post POST /update_post/:id(.:format) application#update_post POST /delete_post/:id(.:format) application#delete_post POST /create_comment_for_post/:post_id(.:format) application#create_comment POST /list_posts/:post_id/delete_comment/:comment_id(.:format) application#delete_comment list_comments GET /list_comments(.:format) application#list_comments 

Eine der wichtigsten Erkenntnisse für Rails-Konventionen ist, dass datenzentrierte Apps (oder grobe Apps) in der Regel sehr ähnliche Möglichkeiten haben, Benutzer mit der Anwendung interagieren zu lassen:

  • eine Seite, um eine Liste von etwas anzuzeigen
  • etwas anzeigen
  • ein Formular anzeigen, um eine neue Instanz von etwas zu erstellen
  • tatsächlich etwas erstellen
  • ein Formular anzeigen, um eine Instanz von etwas zu bearbeiten
  • tatsächlich etwas aktualisieren
  • etwas löschen

Diese sieben „Interaktionsmuster“ sind so häufig, dass Rails eine Reihe von Konventionen vom Routing zu Controllern, Ansichten und Formularen bereitstellt, um diese Workflows zu vereinfachen. Wir werden uns jetzt auf den Routing-Teil konzentrieren.

Für das Routing gilt die Konvention, dass Rails empfiehlt, die URLs und die entsprechenden Controller-Aktionen folgendermaßen zu strukturieren, anstatt die URL-Muster zu erstellen:

Workflow HTTP-VERB PFAD Controller-Aktion
Zeige eine Liste der Beiträge GET /posts posts#index
Zeige einen Beitrag GET /posts/:id beiträge#anzeigen
Zeige die zu erstellende Seite post GET /posts/new posts#new
Erstelle einen Beitrag BEITRAG /Beiträge Beiträge#erstellen
Zeige die Seite, um einen Beitrag zu bearbeiten GET /posts/:id/edit posts#edit
Aktualisieren Sie einen Beitrag PUT/PATCH /posts/:id posts#update
Einen Beitrag löschen LÖSCHEN /Beiträge/:id Beiträge#destroy

Wir können den post Teil unseres aktuellen Routings ändern, um dieser Konvention zu folgen:

# posts GET /list_posts -> GET /posts posts#index GET /show_post/:id -> GET /posts/:id posts#show GET /new_post -> GET /posts/new posts#new POST /create_post -> POST /posts posts#create GET /edit_post/:id -> GET /posts/:id/edit posts#edit POST /update_post/:id -> PUT/PATCH /posts/:id posts#update POST /delete_post/:id -> DELETE /posts/:id posts#destroy 

Und in der routes.rb -Datei,

Rails.application.routes.draw do ### posts ### get '/posts' => 'posts#index' get '/posts/new' => 'posts#new' get '/posts/:id' => 'posts#show' post '/posts' => 'posts#create' get '/posts/:id/edit' => 'posts#edit' patch '/posts/:id' => 'posts#update' put '/posts/:id' => 'posts#update' delete '/posts/:id' => 'posts#destroy' # comments later.. ... end 

Beachten Sie, dass mit diesem neuen Muster die URL selbst viel weniger Verben enthält, wir uns jedoch auf die HTTP-Verben verlassen (GET/POST/PUT/PATCH/DELETE) um die Semantik für ansonsten gleiche URL-Muster bereitzustellen, z. B. /posts/:id .

Beachten Sie, dass PUT bis vor kurzem zum Aktualisieren von Ressourcen verwendet wurde, als PATCH als bessere semantische Übereinstimmung für diese Aktion ermittelt wurde. Seitdem hat Rails PATCH bevorzugt, aber beide Verben für Updates zugelassen.

Eine weitere Änderung, die wir später sehen werden, ist, dass wir alle URLs, die sich auf Beiträge beziehen, an PostsController anstatt alles in ApplicationController . Die Aktionsnamen von PostController

  • new
  • index
  • show
  • create
  • edit
  • update
  • destroy

sind ebenfalls Konventionen, die der 7-Interaktion entsprechen muster.

Dies ist die stärkste Reihe von Konventionen, die Rails Ihnen als Anwendungsentwickler auferlegt. Wir werden Sie bitten, sich zu bemühen, es auswendig zu lernen. Wir werden dies im Laufe des Buches viele Male wiederholen, um Ihnen dabei zu helfen.

Routing für mehrere Ressourcen

Oft müssen mehrere Ressourcen in der URL vorhanden sein. Wenn wir beispielsweise für unsere Blog-App eine Route zum Erstellen eines Kommentars benötigen, ist es sehr wichtig, dass wir wissen, auf welchem Beitrag dieser Kommentar erstellt wird.

Wir machen das gerade:

post 'create_comment_for_post/:post_id' => 'application#create_comment' 

Die Rails-Konvention einer URL mit mehreren zugeordneten Ressourcen besteht darin, mit der „enthaltenden“ Ressource bis zur „innersten“ Ressource zu beginnen. Zum Beispiel würden sich unsere Routen für Kommentare ändern in:

post '/posts/:id/comments' => 'comments#create' delete '/posts/:post_id/comments/:id' => 'comments#destroy' get '/comments' => 'comments#index' 

Die Semantik dieser URLs lautet: „Kommentar unter einem bestimmten Beitrag erstellen“ und „Kommentar unter einem bestimmten Beitrag löschen“. Die letzte Route, „Alle Kommentare im System anzeigen“, muss nicht unter einem Post „scoped“ sein, so dass die URL nicht mit „/ posts“ führen muss.

Wenn wir mehrere Ressourcen in der URL mit ihren IDs haben müssen, ist die Konvention so, dass die letzte Ressource den Platzhalter :id und der ganze Rest :resource_id wie :post_id .

Restful

REST steht für „Representational State Transfer“. Es ist ein Softwarearchitekturstil und eine Richtlinie zum Erstellen skalierbarer Webdienste. REST, als eine Möglichkeit, Webanwendungen zu strukturieren, hat viele Facetten, aber schauen wir uns nur an, wie es auf die Schnittstelle zutrifft, die wir für die Interaktion mit Webanwendungen verwenden, die URLs.

Um zu sehen, wie REST die Semantik von URLs vereinfacht, gehen wir durch ein Beispiel. Nehmen wir an, wir bauen einen Online-Pizza-Bestellservice auf. Eine naïve Implementierung der Schnittstellen des Dienstes (URLs) wäre:

/check_order?order_id=2 /place_new_order /pizza_details?type=1 /pay_for_my_order?order_id=12 /cancel_order?order_id=3 /expedite_order?order_id=13 

Ein RESTful Interface Design würde so aussehen:

GET /orders/2 POST /orders GET /pizzas/1 POST /orders/12/payments DELETE /orders/3 POST /orders/13/expeditions 

Sie können sehen, RESTful-Schnittstellen konzentrieren sich auf „Substantive“ oder „Ressourcen“, Entfernen von „Verben“ aus den Schnittstellen, verlassen sich jedoch stattdessen auf die standardisierten HTTP-Verben (GET/POST/PUT/DELETE) CRUD-Semantik für die Aktionen bereitzustellen. Verben wie check, place, cancel werden direkt den HTTP-Verben GET zum Abrufen, POST zum Erstellen und DELETE zum Zerstören der Ressource order zugeordnet. pay und expedite sind als Erstellung (HTTP POST) von Unterressourcen von payments und expeditions unter Ressource orders strukturiert.

RESTful Interfaces standardisierte Interaktionsmuster für Webanwendungen, um sie einfacher zu verstehen und zu programmieren. Da sich die Schnittstellen auf die Manipulation von Ressourcen konzentrieren, sind die Antworten viel vorhersehbarer. Eine Analogie dazu, wie das RESTful-Architekturmuster die Interaktion mit Webdiensten vereinfacht, wäre, wie die relationale Datenbank und die SQL-Sprache die Datenspeicherung vereinfachen. Vor relationalen Datenbanken und SQL wurden Daten typischerweise in proprietären Systemen mit spezifischer Logik gespeichert, um mit ihnen zu interagieren, was bedeutete, dass Sie bei jedem Projekt einen anderen Satz von Anweisungen lernen mussten, um mit Daten zu interagieren. Relationale Datenbanken und SQL gaben eine gemeinsame Datenstruktur (Datensätze als Zeilen und Spalten in Tabellen gespeichert) und eine Reihe von gemeinsamen Schnittstellen – vier einfache Verben von SELECT, INSERT, UPDATE und DELETE, die alle Arten von Anwendungen unterstützen können.

Durch die Verwendung einer RESTful-Schnittstelle für Ihre Webanwendung wird Ihre Anwendung auch an die Art und Weise angepasst, wie die Backend-Daten in Datenbanken gespeichert werden, und die Entwicklung wird vereinfacht. Das werden wir in den folgenden Kapiteln sehen.

Ressourcennotation

Wir haben über die Routingkonventionen von Rails und RESTful-URL-Muster gesprochen. Jetzt würde unsere routes.rb -Datei wie folgt aussehen:

### config/routes.rb ### Rails.application.routes.draw do ### posts ### get '/posts' => 'posts#index' get '/posts/new' => 'posts#new' get '/posts/:id' => 'posts#show' post '/posts' => 'posts#create' get '/posts/:id/edit' => 'posts#edit' patch '/posts/:id' => 'posts#update' put '/posts/:id' => 'posts#update' delete '/posts/:id' => 'posts#destroy' ### comments ### get '/comments' => 'comments#index' post '/posts/:id/comments' => 'comments#create' delete '/posts/:post_id/comments/:id' => 'comments#destroy' end 

Tatsächlich sind die Routen wie im Abschnitt posts sehr häufig, daher bietet Rails eine spezielle resources -Notation, mit der Sie diese für Sie generieren können.

Wir können einfach:

resources :posts 

Diese Zeile generiert automatisch die 8 Zeilen, die wir zuvor hatten. Beachten Sie, dass Rails für die Aktion update aus Kompatibilitätsgründen sowohl PUT als auch PATCH zulässt.

Sie können bundle exec rake routes in Ihrer Befehlszeilenumgebung ausführen, um zu überprüfen, ob genau derselbe Routensatz generiert wird.

Beachten Sie, dass diese einzelne Zeile 8 Routen generiert. In unserem Fall benötigen wir hier zufällig alle Routen, aber wenn Sie nur eine Teilmenge der Routen benötigen, können Sie sie expliziter definieren als:

resources :posts, only: 

Diese Zeile oben würde nur 3 Routen für Sie generieren – geben Sie bundle exec rake routes ein, um es zu überprüfen.

Verschachtelte Ressourcen

Rails ermöglicht es uns auch, Ressourcen zu verschachteln, um URL-Muster mit mehreren Ressourcen zu erstellen, siehe unten:

### config/routes.rb ### Rails.application.routes.draw do resources :posts do resources :comments, only: end resources :comments, only: :index end 

Führen Sie bundle exec rake routes aus und sehen Sie die Ausgabe – sie sollte dieselbe sein wie zuvor.

Pfadhelfer

Wenn Sie bundle exec rake routes ausführen, beachten Sie die Spalte Prefix für einige dieser Routen. Diese sollen uns helfen, die von Rails bereitgestellten Pfadhelfer für unsere Routen zu verwenden. Wir können diese Präfixe gefolgt von _path in unseren Controllern und Ansichten verwenden, um Pfade einfach zu erstellen.

Zum Beispiel:

posts_path # => '/posts' post_id = 123 post_comments_path(post_id) # => '/posts/123/comments' 

Was ist der Vorteil der Verwendung von URL-Helfern, anstatt die Pfade wie /posts/123/comments direkt in Ihrem Code fest zu codieren? (zum Beispiel in Ihrer Controller-Aktion?) Der Grund, warum Sie Pfadhelfer verwenden möchten, ist, dass es viel einfacher ist, die URL-Helfer zu verwenden, um einen anderen Pfad zurückzugeben, wenn Sie die URL-Muster in Ihrer App ändern möchten:

get '/register', to: 'users#new', as: 'register' 

Wenn wir dieser Route die „as“ -Klausel hinzufügen und bundle exec rake routes ausführen, wird die Spalte Prefix mit register angezeigt, und Sie können register_path verwenden, um /register den Pfad abzurufen. Wenn wir nun den Pfad in /login ändern möchten, müssen wir nur Folgendes tun:

get '/login', to: 'users#new', as: 'register' 

Jetzt gibt uns unser register_path /login . Wir müssen unseren Code in der Rails-App überhaupt nicht ändern.

Weitere Routing-Konventionen

Bevor wir fortfahren, werfen wir einen kurzen Blick auf einige Variationen dessen, was wir bereits gesehen haben, sowie auf einige andere Funktionen, die uns in Rails Routing zur Verfügung stehen:

### config/routes.rb ### Rails.application.routes.draw do # pointing our homepage (root path) to posts#index root to: 'posts#index' # `match` & `via:` allow us to define one route and use several HTTP verbs # `as:` lets us define the name of the route prefix match '/authors/:id' => 'authors#update', via: , as: :update_author # update_author PUT|PATCH /authors/:id(.:format) authors#update resources :posts do # define extra params to pass for requests to a route get 'popular', on: :collection, action: :index, popular: true # popular_posts GET /posts/popular(.:format) posts#index {:popular=>true} get 'preview', on: :member # ... end # we can even use routes to redirect get '/home', to: redirect('/') end 

Lassen Sie uns alle oben aufgeführten Funktionen einzeln aufschlüsseln.

  • root: root wird verwendet, um anzugeben, welche Aktion „/“ zugeordnet wird (die URL der obersten Ebene unserer Site, die keinen Pfad enthält).Die Root-URL Ihrer Website / App wird am häufigsten verwendet, daher sollte root oben in der Routendatei angegeben werden.

  • spiel + über: match wird verwendet, um URL-Muster einer oder mehreren Routen zuzuordnen. Wir können auch angeben, welches HTTP-Verb für den Abgleich mit einer URL mit diesem Muster verwendet werden darf. Wir tun dies, indem wir einen Hash an die match -Methode übergeben. Der Schlüssel für diesen Hash ist via, und der Wert ist ein Array von HTTP-Verben. match ist eine allgemeinere Form einiger häufiger verwendeter HTTP-Routing-Methoden, z. B. get, post und delete. Es können alle die gleichen Optionen wie diese Methoden verwendet werden, aber im Vergleich zu diesen Methoden bietet es etwas mehr Flexibilität.
    Zum Beispiel können wir mit match eine URL angeben, die für zwei verschiedene Routen übereinstimmt, die jeweils zwei verschiedenen HTTP-Verben entsprechen. Normalerweise würde dies zwei Befehle anstelle von einem erfordern. Wir können dies in unserem obigen Beispiel sehen, in dem wir das URL-Muster '/authors/:id' mit der Aktion 'authors#update' abgleichen. Wir geben dann an, welche HTTP-Verben verwendet werden können, um die Anforderung für diese URL mit via: . Geben Sie bei Verwendung von match immer eine HTTP-Methode an, da dies negative Auswirkungen auf die Sicherheit Ihrer Anwendung haben kann.
    match stellt eine weitere Option für das Routing zu bestimmten Aktionen in Rails dar. Im Allgemeinen ist es am besten, bei den häufiger verwendeten HttpHelpers -Methoden wie get und post zu bleiben.

  • as: Wir haben bereits erwähnt, dass die Option as: mit unserer Routendeklaration verwendet werden kann, um das Präfix für unsere URL-Helfer zu ändern. Dies kann auf verschiedene Arten verwendet werden. Wir können as: , damit unsere URL-Helfer besser mit benutzerdefinierten URLs übereinstimmen. Eine andere Verwendung besteht darin, den aktuellen URL-Pfad-Helfer in etwas Intuitiveres oder etwas zu ändern, das besser mit den Ressourcen innerhalb einer Anwendung übereinstimmt.

  • sammelroute: Siehe oben, wie wir unsere /popular -Route unter der posts -Ressource verschachteln. Wir verwenden dann on: :collection , um anzugeben, unter welchem Teil einer Ressource wir diese Route verschachteln. Wir haben viele Beiträge, so dass eine Sammlung betrachtet wird. Durch Angabe von on: :collection sagen wir: „Passen Sie eine URL an den Pfad /posts/popular an.“ Wenn wir on: :collection nicht hinzugefügt haben, geht Rails davon aus, dass diese Route einer anderen Ressource entspricht, die einem einzelnen Mitglied unserer Posts-Sammlung zugeordnet ist. In diesem Fall würde unsere Route /posts/:id/popular . Wir können auch mehrere Sammelrouten angeben, indem wir ein Blockformat verwenden.

collection do get 'popular' end 
  • übergeben eines zusätzlichen Parameters: Wir können einen Standardparameter angeben, der immer mit unserem params -Hash übergeben wird, wenn wir mit bestimmten URLs abgeglichen werden. Es gibt zwei Möglichkeiten, dies anzugeben; Ein Weg ist der gleiche wie oben:
get 'popular', on: :collection, action: :index, popular: true 

popular: true wird an unsere Aktion übergeben, mit der die beliebte Route über den Hash params übereinstimmt. Es hat einen Schlüssel von :popular und einen Wert von true. Wir können auch eine explizitere Syntax verwenden, indem wir einen Hash an unsere Routenmethode get übergeben, wobei der Schlüssel defaults: und der Wert ein weiterer Hash ist, der den Namen des Parameters enthält, den wir an unsere Aktion übergeben möchten.

get 'popular', on: :collection, action: :index, defaults: { popular: true} 
  • member route: Mit on: member können wir angeben, dass unsere Route mit einem Member einer Sammlung übereinstimmt. Wenn wir dies verwenden, wird das dynamische Segment als :id angezeigt. Ein URL-Helfer wird ebenfalls als preview_post erstellt. Indem wir diese Route mit on: member angeben, teilen wir Rails mit, dass dies ein Mitglied dieser bestimmten Ressource ist. Dass es sich nicht nur um eine weitere Ressource handelt, die unter Posts verschachtelt ist, sondern enger mit unseren Posts in dieser Anwendung verknüpft oder verwandt ist. Dieses Format verwendet die gleiche Syntax wie das Blockformat zum Definieren mehrerer Sammlungsrouten, ersetzen Sie einfach collection durch member .

  • umleitung: Es gibt noch ein anderes Konzept, über das in unserem obigen Beispiel gesprochen werden kann, und zwar die Umleitung. Rails gibt uns die Möglichkeit, von einem Pfad zu einem anderen umzuleiten, indem wir einen Umleitungshelfer in Verbindung mit einer Route verwenden.get '/home', to: redirect('/'). Wenn jemand versucht, auf den Pfad /home zuzugreifen, wird er sofort zum Stammpfad / weitergeleitet. Dies ist natürlich nicht nur auf einen URL-Pfad beschränkt; Wir könnten auch so etwas haben: get '/home', to: redirect('/travel') .

Review

Schienenrouten stehen vor einer Anwendung. Eine Route interpretiert eine eingehende HTTP-Anforderung und:

  • passt eine Anforderung an eine Controller-Aktion an, die auf der Kombination eines HTTP-Verbs und des Anforderungs-URL-Musters basiert
  • erfasst Daten in der URL, die in params in Controller-Aktionen verfügbar sein sollen
  • Rails ermutigt Entwickler, beim Einrichten von Routen RESTful-URL-Muster zu verwenden, wobei Ressourcen mit HTTP-Verben manipuliert werden.
  • Mit dem Makro resourceskönnen Sie sehr schnell RESTful-Routen generieren.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.