Ruby on Rails
Routing
Suche…
Einführung
Bemerkungen
Unter "Routing" werden im Allgemeinen URLs von Ihrer App "behandelt". Im Fall von Rails ist es in der Regel der Controller und welche Aktion des Controllers für eine bestimmte eingehende URL. In Rails-Apps werden Routen normalerweise in der Datei config/routes.rb
abgelegt.
Ressourcenrouting (Basic)
Routen sind in config/routes.rb
. Sie werden häufig als Gruppe zusammengehöriger Routen definiert, wobei die resources
oder resource
werden.
resources :users
erstellt die folgenden sieben Routen, die alle den Aktionen von UsersController
:
get '/users', to: 'users#index'
post '/users', to: 'users#create'
get '/users/new', to: 'users#new'
get '/users/:id/edit', to: 'users#edit'
get '/users/:id', to: 'users#show'
patch/put '/users/:id', to: 'users#update'
delete '/users/:id', to: 'users#destroy'
Aktionsnamen werden nach dem #
im Parameter to
oben angezeigt. Methoden mit denselben Namen müssen in app/controllers/users_controller.rb
wie folgt definiert werden:
class UsersController < ApplicationController
def index
end
def create
end
# continue with all the other methods…
end
Sie können die generierten Aktionen only
except
einschränken:
resources :users, only: [:show]
resources :users, except: [:show, :index]
Sie können alle Routen Ihrer Anwendung jederzeit anzeigen, indem Sie Folgendes ausführen:
$ rake routes
$ rake routes
# OR
$ rails routes
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
So zeigen Sie nur die Routen an, die einem bestimmten Controller zugeordnet sind:
$ rake routes -c static_pages
static_pages_home GET /static_pages/home(.:format) static_pages#home
static_pages_help GET /static_pages/help(.:format) static_pages#help
$ rake routes -c static_pages
static_pages_home GET /static_pages/home(.:format) static_pages#home
static_pages_help GET /static_pages/help(.:format) static_pages#help
# OR
$ rails routes -c static_pages
static_pages_home GET /static_pages/home(.:format) static_pages#home
static_pages_help GET /static_pages/help(.:format) static_pages#help
Sie können mit der Option -g
nach Routen suchen. Dies zeigt jede Route, die teilweise mit dem Namen der Hilfsmethode, dem URL-Pfad oder dem HTTP-Verb übereinstimmt:
$ rake routes -g new_user # Matches helper method
$ rake routes -g POST # Matches HTTP Verb POST
$ rake routes -g new_user # Matches helper method
$ rake routes -g POST # Matches HTTP Verb POST
# OR
$ rails routes -g new_user # Matches helper method
$ rails routes -g POST # Matches HTTP Verb POST
Wenn Sie den rails
server im Entwicklungsmodus ausführen, können Sie außerdem auf eine Webseite zugreifen, die alle Ihre Routen mit einem von oben nach unten übereinstimmenden <hostname>/rails/info/routes
. Es wird so aussehen:
Helfer | HTTP-Verb | Pfad | Controller Nr. Aktion |
---|---|---|---|
Pfad / URL | [Pfadübereinstimmung] | ||
Benutzerpfad | ERHALTEN | /users(.:format) | Benutzer # Index |
POST | /users(.:format) | Benutzer # erstellen | |
new_user_path | ERHALTEN | /users/new(.:format) | Benutzer # neu |
edit_user_path | ERHALTEN | /users/:id/edit(.:format) | Benutzer # bearbeiten |
user_path | ERHALTEN | /users/:id(.:format) | Benutzer # anzeigen |
PATCH | /users/:id(.:format) | Benutzer # Update | |
STELLEN | /users/:id(.:format) | Benutzer # Update | |
LÖSCHEN | /users/:id(.:format) | Benutzer zerstören |
Routen können für nur Mitgliedern zur Verfügung deklariert werden (nicht Sammlungen) unter Verwendung des Verfahrens resource
anstelle von resources
in routes.rb
. Bei einer resource
wird eine index
nicht standardmäßig erstellt, sondern nur, wenn explizit nach einer der folgenden Optionen gefragt wird:
resource :orders, only: [:index, :create, :show]
Einschränkungen
Sie können mithilfe von Einschränkungen filtern, welche Routen verfügbar sind.
Es gibt verschiedene Möglichkeiten, Einschränkungen zu verwenden, darunter:
Beispielsweise eine angeforderte Einschränkung, die nur den Zugriff einer bestimmten IP-Adresse auf eine Route zulässt:
constraints(ip: /127\.0\.0\.1$/) do
get 'route', to: "controller#action"
end
Weitere ähnliche Beispiele anzeigen ActionDispatch :: Routing :: Mapper :: Scoping .
Wenn Sie etwas komplexeres machen möchten, können Sie erweiterte Einschränkungen verwenden und eine Klasse erstellen, um die Logik zu umschließen:
# lib/api_version_constraint.rb
class ApiVersionConstraint
def initialize(version:, default:)
@version = version
@default = default
end
def version_header
"application/vnd.my-app.v#{@version}"
end
def matches?(request)
@default || request.headers["Accept"].include?(version_header)
end
end
# config/routes.rb
require "api_version_constraint"
Rails.application.routes.draw do
namespace :v1, constraints: ApiVersionConstraint.new(version: 1, default: true) do
resources :users # Will route to app/controllers/v1/users_controller.rb
end
namespace :v2, constraints: ApiVersionConstraint.new(version: 2) do
resources :users # Will route to app/controllers/v2/users_controller.rb
end
end
Ein Formular, mehrere Schaltflächen zum Senden
Sie können den Wert der Übergabe-Tags eines Formulars auch als Einschränkung verwenden, um zu einer anderen Aktion weiterzuleiten. Wenn Sie über ein Formular mit mehreren Senden-Schaltflächen verfügen (z. B. "Vorschau" und " routes.rb
"), können Sie diese Einschränkung direkt in der routes.rb
, anstatt Javascript zu schreiben, um die Ziel-URL des Formulars zu ändern. Zum Beispiel können Sie mit dem commit_param_routing gem die Schienen submit_tag
submit_tag
ersten Parameter von Rails submit_tag
können Sie den Wert Ihres Formular-Commit-Parameters ändern
# app/views/orders/mass_order.html.erb
<%= form_for(@orders, url: mass_create_order_path do |f| %>
<!-- Big form here -->
<%= submit_tag "Preview" %>
<%= submit_tag "Submit" %>
# => <input name="commit" type="submit" value="Preview" />
# => <input name="commit" type="submit" value="Submit" />
...
<% end %>
# config/routes.rb
resources :orders do
# Both routes below describe the same POST URL, but route to different actions
post 'mass_order', on: :collection, as: 'mass_order',
constraints: CommitParamRouting.new('Submit'), action: 'mass_create' # when the user presses "submit"
post 'mass_order', on: :collection,
constraints: CommitParamRouting.new('Preview'), action: 'mass_create_preview' # when the user presses "preview"
# Note the `as:` is defined only once, since the path helper is mass_create_order_path for the form url
# CommitParamRouting is just a class like ApiVersionContraint
end
Scoping-Routen
Rails bietet mehrere Möglichkeiten, um Ihre Routen zu organisieren.
Umfang nach URL :
scope 'admin' do
get 'dashboard', to: 'administration#dashboard'
resources 'employees'
end
Dies generiert die folgenden Routen
get '/admin/dashboard', to: 'administration#dashboard'
post '/admin/employees', to: 'employees#create'
get '/admin/employees/new', to: 'employees#new'
get '/admin/employees/:id/edit', to: 'employees#edit'
get '/admin/employees/:id', to: 'employees#show'
patch/put '/admin/employees/:id', to: 'employees#update'
delete '/admin/employees/:id', to: 'employees#destroy'
Auf der Serverseite kann es sinnvoller sein, einige Ansichten in einem anderen Unterordner zu speichern, um Administratoransichten von Benutzeransichten zu trennen.
Umfang nach Modul
scope module: :admin do
get 'dashboard', to: 'administration#dashboard'
end
module
sucht die Controller-Dateien unter dem Unterordner des angegebenen Namens
get '/dashboard', to: 'admin/administration#dashboard'
Sie können das Pfadhilfspräfix umbenennen, indem Sie einen as
Parameter hinzufügen
scope 'admin', as: :administration do
get 'dashboard'
end
# => administration_dashboard_path
Rails bietet eine bequeme Möglichkeit, all dies mit der namespace
Methode namespace
. Die folgenden Erklärungen sind gleichwertig
namespace :admin do
end
scope 'admin', module: :admin, as: :admin
Umfang durch Controller
scope controller: :management do
get 'dashboard'
get 'performance'
end
Diese generieren diese Routen
get '/dashboard', to: 'management#dashboard'
get '/performance', to: 'management#performance'
Flache Schachtelung
Ressourcenwege akzeptieren eine :shallow
Option, mit der sich URLs nach Möglichkeit verkürzen lassen. Ressourcen sollten nicht mehr als eine Ebene tief verschachtelt sein. Eine Möglichkeit, dies zu vermeiden, ist das Erstellen von flachen Routen. Das Ziel ist, die URL-Segmente der übergeordneten Sammlung dort zu lassen, wo sie nicht benötigt werden. Das Endergebnis ist, dass die einzigen geschachtelten Routen für die :index
Aktionen generiert werden :index
:create
und :new
Aktionen. Der Rest wird in einem eigenen flachen URL-Kontext gehalten. Es gibt zwei Optionen für den Umfang der benutzerdefinierten flachen Routen:
: shallow_path: Stellt einen angegebenen Parameter den Mitgliederpfaden voran
scope shallow_path: "sekret" do resources :articles do resources :comments, shallow: true end end
: shallow_prefix: Fügt den benannten Helfern angegebene Parameter hinzu
scope shallow_prefix: "sekret" do resources :articles do resources :comments, shallow: true end end
Wir können shallow
Wege auch anhand folgender shallow
veranschaulichen:
resources :auctions, shallow: true do
resources :bids do
resources :comments
end
end
alternativ wie folgt codiert (wenn Sie blockglücklich sind):
resources :auctions do
shallow do
resources :bids do
resources :comments
end
end
end
Die resultierenden Routen sind:
Präfix | Verb | URI-Muster |
---|---|---|
bid_comments | ERHALTEN | /bids/:bid_id/comments(.:format) |
POST | /bids/:bid_id/comments(.:format) | |
new_bid_comment | ERHALTEN | /bids/:bid_id/comments/new(.:format) |
edit_comment | ERHALTEN | /comments/:id/edit(.:format) |
Kommentar | ERHALTEN | /comments/:id(.:format) |
PATCH | /comments/:id(.:format) | |
STELLEN | /comments/:id(.:format) | |
LÖSCHEN | /comments/:id(.:format) | |
auction_bids | ERHALTEN | /auctions/:auction_id/bids(.:format) |
POST | /auctions/:auction_id/bids(.:format) | |
new_auction_bid | ERHALTEN | /auktionen/:auction_id/bids/new(.:format) |
edit_bid | ERHALTEN | /bids/:id/edit(.:format) |
bieten | ERHALTEN | /bids/:id(.:format) |
PATCH | /bids/:id(.:format) | |
STELLEN | /bids/:id(.:format) | |
LÖSCHEN | /bids/:id(.:format) | |
Auktionen | ERHALTEN | /auctions(.:format) |
POST | /auctions(.:format) | |
new_auction | ERHALTEN | /auctions/new(.:format) |
edit_auction | ERHALTEN | /auctions/:id/edit(.:format) |
Versteigerung | ERHALTEN | /auctions/:id(.:format) |
PATCH | /auctions/:id(.:format) | |
STELLEN | /auctions/:id(.:format) | |
LÖSCHEN | /auctions/:id(.:format) |
Wenn Sie die erstellten Routen sorgfältig analysieren, werden Sie feststellen, dass die verschachtelten Teile der URL nur dann enthalten sind, wenn sie zur Ermittlung der anzuzeigenden Daten benötigt werden.
Sorgen
Um Wiederholungen in verschachtelten Routen zu vermeiden, bieten Bedenken eine gute Möglichkeit, gemeinsame Ressourcen zu verwenden, die wiederverwendbar sind. Um ein Anliegen zu erstellen, verwenden Sie die Methode concern
in der Datei routes.rb
. Die Methode erwartet ein Symbol und einen Block:
concern :commentable do
resources :comments
end
Obwohl keine Routen selbst erstellt werden, ermöglicht dieser Code die Verwendung des Attributs :concerns
für eine Ressource. Das einfachste Beispiel wäre:
resource :page, concerns: :commentable
Die entsprechende verschachtelte Ressource würde folgendermaßen aussehen:
resource :page do
resource :comments
end
Dies würde zum Beispiel die folgenden Routen erstellen:
/pages/#{page_id}/comments
/pages/#{page_id}/comments/#{comment_id}
Damit Anliegen sinnvoll sind, müssen mehrere Ressourcen vorhanden sein, die das Anliegen nutzen. Zusätzliche Ressourcen könnten eine der folgenden Syntax zum Aufrufen des Problems verwenden:
resource :post, concerns: %i(commentable)
resource :blog do
concerns :commentable
end
Umleitung
Sie können eine Umleitung in Rails-Routen wie folgt durchführen:
get '/stories', to: redirect('/posts')
match "/abc" => redirect("http://example.com/abc")
Sie können auch alle unbekannten Routen zu einem bestimmten Pfad umleiten:
match '*path' => redirect('/'), via: :get
# or
get '*path' => redirect('/')
match '*path' => redirect('/')
Mitglieder- und Sammelrouten
Durch das Definieren eines Mitgliederblocks in einer Ressource wird eine Route erstellt, die auf ein einzelnes Mitglied dieser ressourcenbasierten Route einwirken kann:
resources :posts do
member do
get 'preview'
end
end
Dadurch wird die folgende Memberroute generiert:
get '/posts/:id/preview', to: 'posts#preview'
# preview_post_path
Sammlungsrouten ermöglichen das Erstellen von Routen, die sich auf eine Sammlung von Ressourcenobjekten auswirken können:
resources :posts do
collection do
get 'search'
end
end
Dadurch wird die folgende Sammlungsroute generiert:
get '/posts/search', to: 'posts#search'
# search_posts_path
Eine alternative Syntax:
resources :posts do
get 'preview', on: :member
get 'search', on: :collection
end
URL-Params mit einem Punkt
Wenn Sie einen URL-Parameter unterstützen möchten, der komplexer als eine ID-Nummer ist, können Probleme mit dem Parser auftreten, wenn der Wert einen Punkt enthält. Alles, was auf einen Punkt folgt, wird als Format angenommen (z. B. Json, XML).
Sie können diese Einschränkung umgehen, indem Sie eine Einschränkung verwenden, um die akzeptierte Eingabe zu erweitern .
Wenn Sie beispielsweise einen Benutzerdatensatz anhand der E-Mail-Adresse in der URL referenzieren möchten:
resources :users, constraints: { id: /.*/ }
Wurzelroute
Sie können Ihrer App eine Startseite-Route mit der root
Methode hinzufügen.
# config/routes.rb
Rails.application.routes.draw do
root "application#index"
# equivalent to:
# get "/", "application#index"
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def index
render "homepage"
end
end
Im Terminal werden auf rake routes
( rails routes
in Rails 5) Folgendes erzeugt:
root GET / application#index
Da die Startseite normalerweise die wichtigste Route ist und die Routen in der Reihenfolge, in der sie angezeigt werden, priorisiert werden, sollte die root
normalerweise die erste in der Routendatei sein.
Zusätzliche RESTful-Aktionen
resources :photos do member do get 'preview' end collection do get 'dashboard' end end
Dadurch werden die folgenden Routen zusätzlich zu den standardmäßig 7 RESTful-Routen erstellt :
get '/photos/:id/preview', to: 'photos#preview'
get '/photos/dashboards', to: 'photos#dashboard'
Wenn Sie dies für einzelne Zeilen tun möchten, können Sie Folgendes verwenden:
resources :photos do get 'preview', on: :member get 'dashboard', on: :collection end
Sie können dem /new
Pfad auch eine Aktion hinzufügen:
resources :photos do get 'preview', on: :new end
Was wird schaffen:
get '/photos/new/preview', to: 'photos#preview'
Achten Sie beim Hinzufügen von Aktionen zu Ihren REST-Routen, wahrscheinlich fehlt Ihnen eine andere Ressource!
Verfügbare Gebietsschemas
Wenn Ihre Anwendung in verschiedenen Sprachen verfügbar ist, wird normalerweise das aktuelle Gebietsschema in der URL angezeigt.
scope '/(:locale)', locale: /#{I18n.available_locales.join('|')}/ do
root 'example#root'
# other routes
end
Ihr Stamm ist über die in I18n.available_locales
definierten I18n.available_locales
.
Mounten Sie eine andere Anwendung
mount wird verwendet, um eine andere Anwendung (hauptsächlich Rack-Anwendung) oder Schienen-Engines für die Verwendung in der aktuellen Anwendung zu installieren
Syntax:
mount SomeRackApp, at: "some_route"
Jetzt können Sie mit dem some_rack_app_path
oder some_rack_app_url
auf die oben eingebaute Anwendung some_rack_app_url
.
Wenn Sie diesen Helfernamen umbenennen möchten, können Sie dies folgendermaßen tun:
mount SomeRackApp, at: "some_route", as: :myapp
Dadurch werden die Helfer myapp_path
und myapp_url
generiert, mit denen Sie zu dieser myapp_url
App navigieren können.
Weiterleitungen und Wildcard-Routen
Wenn Sie Ihrem Benutzer eine URL zur Verfügung stellen möchten, die sich jedoch direkt auf eine andere bezieht, die Sie bereits verwenden. Verwenden Sie eine Weiterleitung:
# config/routes.rb
TestApp::Application.routes.draw do
get 'courses/:course_name' => redirect('/courses/%{course_name}/lessons'), :as => "course"
end
Nun, das wurde schnell interessant. Das grundlegende Prinzip besteht darin, einfach die #redirect
Methode zu verwenden, um eine Route an eine andere Route zu senden. Wenn Ihre Route recht einfach ist, ist dies eine sehr unkomplizierte Methode. Wenn Sie jedoch auch die ursprünglichen Parameter senden möchten, müssen Sie etwas Gymnastik machen, indem Sie den Parameter in %{here}
erfassen. Beachten Sie die einfachen Anführungszeichen um alles herum.
Im obigen Beispiel haben wir die Route auch umbenannt, indem Sie einen Alias mit dem Parameter: as verwenden. Dadurch können wir diesen Namen in Methoden wie den #_path-Helfern verwenden. Testen Sie erneut Ihre $ rake routes
mit Fragen.
Trennen Sie die Routen in mehrere Dateien
Wenn Ihre Routendatei überwältigend groß ist, können Sie Ihre Routen in mehreren Dateien ablegen und jede der Dateien mit der Ruby- require_relative
Methode aufnehmen:
config/routes.rb
: YourAppName::Application.routes.draw do
require_relative 'routes/admin_routes'
require_relative 'routes/sidekiq_routes'
require_relative 'routes/api_routes'
require_relative 'routes/your_app_routes'
end
config/routes/api_routes.rb
: YourAppName::Application.routes.draw do
namespace :api do
# ...
end
end
Verschachtelte Routen
Wenn Sie verschachtelte Routen hinzufügen möchten, können Sie den folgenden Code in routes.rb
Datei routes.rb
schreiben.
resources :admins do
resources :employees
end
Dadurch werden folgende Routen generiert:
admin_employees GET /admins/:admin_id/employees(.:format) employees#index
POST /admins/:admin_id/employees(.:format) employees#create
new_admin_employee GET /admins/:admin_id/employees/new(.:format) employees#new
edit_admin_employee GET /admins/:admin_id/employees/:id/edit(.:format) employees#edit
admin_employee GET /admins/:admin_id/employees/:id(.:format) employees#show
PATCH /admins/:admin_id/employees/:id(.:format) employees#update
PUT /admins/:admin_id/employees/:id(.:format) employees#update
DELETE /admins/:admin_id/employees/:id(.:format) employees#destroy
admins GET /admins(.:format) admins#index
POST /admins(.:format) admins#create
new_admin GET /admins/new(.:format) admins#new
edit_admin GET /admins/:id/edit(.:format) admins#edit
admin GET /admins/:id(.:format) admins#show
PATCH /admins/:id(.:format) admins#update
PUT /admins/:id(.:format) admins#update
DELETE /admins/:id(.:format) admins#destroy