Ruby on Rails
routing
Sök…
Introduktion
Anmärkningar
"Routing" i allmänhet är hur URL: er "hanteras" av din app. I Rails-fall är det vanligtvis vilken kontroller och vilken åtgärd för den kontrollen som hanterar en viss inkommande URL. I Rails-appar placeras rutter vanligtvis i filen config/routes.rb
.
Resursruting (grundläggande)
Rutter definieras i config/routes.rb
. De definieras ofta som en grupp relaterade rutter med hjälp av resources
eller resource
.
resources :users
skapar följande sju rutter, alla mappar till handlingar från 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'
Åtgärdens namn visas efter #
i to
parametern ovan. Metoder med samma namn måste definieras i app/controllers/users_controller.rb
enligt följande:
class UsersController < ApplicationController
def index
end
def create
end
# continue with all the other methods…
end
Du kan begränsa de åtgärder som genereras med only
eller except
:
resources :users, only: [:show]
resources :users, except: [:show, :index]
Du kan visa alla rutter för din ansökan när som helst genom att köra:
$ 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
Så här ser du bara de rutter som kartlägger till en viss controller:
$ 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
Du kan söka igenom rutter med alternativet -g
. Detta visar alla rutter som delvis matchar hjälpmedelsnamnet, URL-banan eller HTTP-verbet:
$ 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
När du kör rails
i utvecklingsläge kan du dessutom komma åt en webbsida som visar alla dina rutter med ett sökfilter, matchat i prioritet från topp till botten, på <hostname>/rails/info/routes
. Det kommer att se ut så här:
Hjälpare | HTTP Verb | Väg | Controller # Action |
---|---|---|---|
Sökväg / URL | [Path Match] | ||
users_path | SKAFFA SIG | /users(.:format) | användare # index |
POSTA | /users(.:format) | användarnas # skapar | |
new_user_path | SKAFFA SIG | /users/new(.:format) | användare # nya |
edit_user_path | SKAFFA SIG | /users/:id/edit(.:format) | användare # redigera |
user_path | SKAFFA SIG | /users/:id(.:format) | användare # show |
LAPPA | /users/:id(.:format) | användare # update | |
SÄTTA | /users/:id(.:format) | användare # update | |
RADERA | /users/:id(.:format) | användarnas # förstör |
Rutter kan förklaras tillgängliga för endast medlemmar (inte samlingar) med resource
istället för resources
i routes.rb
. Med resource
, en index
är rutten inte skapas som standard, men bara när det uttryckligen ber om en så här:
resource :orders, only: [:index, :create, :show]
begränsningar
Du kan filtrera vilka rutter som är tillgängliga med begränsningar.
Det finns flera sätt att använda begränsningar inklusive:
Till exempel en begärd baserad begränsning som endast tillåter en specifik IP-adress att komma åt en rutt:
constraints(ip: /127\.0\.0\.1$/) do
get 'route', to: "controller#action"
end
Se andra liknande exempel ActionDispatch :: Routing :: Mapper :: Scoping .
Om du vill göra något mer komplicerat kan du använda mer avancerade begränsningar och skapa en klass för att radera logiken:
# 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
En form, flera skicka knappar
Du kan också använda värdet på skicka taggarna i ett formulär som en begränsning för att väg till en annan åtgärd. Om du har ett formulär med flera skicka-knappar (t.ex. "förhandsvisning" och "skicka"), kan du fånga denna begränsning direkt i dina routes.rb
, istället för att skriva javascript för att ändra destinationsadressen till formuläret. Till exempel med commit_param_routing pärla kan du dra nytta av rails submit_tag
Rails submit_tag
första parameter låter dig ändra värdet på din formuläråtgärdsparameter
# 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
Omfattningsvägar
Rails ger flera sätt att organisera dina rutter.
Räckvidd efter URL :
scope 'admin' do
get 'dashboard', to: 'administration#dashboard'
resources 'employees'
end
Detta genererar följande rutter
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'
Det kan vara mer meningsfullt, på serversidan, att behålla vissa vyer i en annan undermapp, att separera adminvyer från användarvyer.
Omfattning efter modul
scope module: :admin do
get 'dashboard', to: 'administration#dashboard'
end
module
letar efter kontrollfilerna under undermappen med det givna namnet
get '/dashboard', to: 'admin/administration#dashboard'
Du kan byta namn på väg hjälpare prefix genom att lägga till en as
parameter
scope 'admin', as: :administration do
get 'dashboard'
end
# => administration_dashboard_path
Rails är ett bekvämt sätt att göra allt ovan med hjälp av namespace
. Följande förklaringar är likvärdiga
namespace :admin do
end
scope 'admin', module: :admin, as: :admin
Omfattning av styrenheten
scope controller: :management do
get 'dashboard'
get 'performance'
end
Detta genererar dessa rutter
get '/dashboard', to: 'management#dashboard'
get '/performance', to: 'management#performance'
Grunt bo
Resursvägar accepterar ett :shallow
alternativ som hjälper till att förkorta webbadresser där det är möjligt. Resurser bör inte häckas mer än en nivå djup. Ett sätt att undvika detta är genom att skapa grunda rutter. Målet är att släppa URL-segment från förälderssamlingen där de inte behövs. Slutresultatet är att de enda kapslade rutter som genereras är för :index
:create
och :new
åtgärder. Resten förvaras i sitt eget grunt URL-sammanhang. Det finns två alternativ för räckvidd för anpassade grunda rutter:
: grunt_väg: Prefixerar medlemsvägar med en specificerad parameter
scope shallow_path: "sekret" do resources :articles do resources :comments, shallow: true end end
: grunt_prefix : Lägg till specificerade parametrar till nämnda hjälpare
scope shallow_prefix: "sekret" do resources :articles do resources :comments, shallow: true end end
Vi kan också illustrera shallow
rutter mer genom:
resources :auctions, shallow: true do
resources :bids do
resources :comments
end
end
alternativt kodas enligt följande (om du är blocklycklig):
resources :auctions do
shallow do
resources :bids do
resources :comments
end
end
end
De resulterande vägarna är:
Prefix | Verb | URI-mönster |
---|---|---|
bid_comments | SKAFFA SIG | /bids/:bid_id/comments(.:format) |
POSTA | /bids/:bid_id/comments(.:format) | |
new_bid_comment | SKAFFA SIG | /bids/:bid_id/comments/new(.:format) |
edit_comment | SKAFFA SIG | /comments/:id/edit(.:format) |
kommentar | SKAFFA SIG | /comments/:id(.:format) |
LAPPA | /comments/:id(.:format) | |
SÄTTA | /comments/:id(.:format) | |
RADERA | /comments/:id(.:format) | |
auction_bids | SKAFFA SIG | /auctions/:auction_id/bids(.:format) |
POSTA | /auctions/:auction_id/bids(.:format) | |
new_auction_bid | SKAFFA SIG | /auctions/:auction_id/bids/new(.:format) |
edit_bid | SKAFFA SIG | /bids/:id/edit(.:format) |
bud | SKAFFA SIG | /bids/:id(.:format) |
LAPPA | /bids/:id(.:format) | |
SÄTTA | /bids/:id(.:format) | |
RADERA | /bids/:id(.:format) | |
auktioner | SKAFFA SIG | /auctions(.:format) |
POSTA | /auctions(.:format) | |
new_auction | SKAFFA SIG | /auctions/new(.:format) |
edit_auction | SKAFFA SIG | /auctions/:id/edit(.:format) |
auktion | SKAFFA SIG | /auctions/:id(.:format) |
LAPPA | /auctions/:id(.:format) | |
SÄTTA | /auctions/:id(.:format) | |
RADERA | /auctions/:id(.:format) |
Om du analyserar de rutter som genererats noggrant kommer du att märka att de kapslade delarna av URL: en endast inkluderas när de behövs för att avgöra vilken information som ska visas.
oro
För att undvika upprepning i kapslade rutter är bekymmer ett bra sätt att dela gemensamma resurser som är återanvändbara. För att skapa en oro använda metoden concern
inom routes.rb
filen. Metoden förväntar sig en symbol och ett block:
concern :commentable do
resources :comments
end
Medan man inte skapar några rutter i sig, tillåter denna kod attributet :concerns
på en resurs. Det enklaste exemplet skulle vara:
resource :page, concerns: :commentable
Den motsvarande kapslade resursen ser ut så här:
resource :page do
resource :comments
end
Detta skulle till exempel bygga följande rutter:
/pages/#{page_id}/comments
/pages/#{page_id}/comments/#{comment_id}
För att bekymmer ska vara meningsfulla måste det finnas flera resurser som utnyttjar oroen. Ytterligare resurser kan använda någon av följande syntaxer för att ringa problemet:
resource :post, concerns: %i(commentable)
resource :blog do
concerns :commentable
end
Omdirigering
Du kan utföra omdirigering i Rails-rutter enligt följande:
get '/stories', to: redirect('/posts')
match "/abc" => redirect("http://example.com/abc")
Du kan också omdirigera alla okända rutter till en given väg:
match '*path' => redirect('/'), via: :get
# or
get '*path' => redirect('/')
match '*path' => redirect('/')
Medlemmar och samlingar
Att definiera ett medlemsblock inuti en resurs skapar en rutt som kan agera på en enskild medlem av den resursbaserade rutten:
resources :posts do
member do
get 'preview'
end
end
Detta genererar följande medlemsväg:
get '/posts/:id/preview', to: 'posts#preview'
# preview_post_path
Samlingsvägar gör det möjligt att skapa rutter som kan agera på en samling resursobjekt:
resources :posts do
collection do
get 'search'
end
end
Detta genererar följande insamlingsväg:
get '/posts/search', to: 'posts#search'
# search_posts_path
En alternativ syntax:
resources :posts do
get 'preview', on: :member
get 'search', on: :collection
end
URL-parametrar med en period
Om du vill stödja en url-parameter som är mer komplex än ett ID-nummer kan du stöta på problem med parsaren om värdet innehåller en period. Allt efter en period antas vara ett format (dvs json, xml).
Du kan lösa denna begränsning genom att använda en begränsning för att bredda den accepterade inmatningen.
Om du till exempel vill hänvisa till en användarpost via e-postadress i url:
resources :users, constraints: { id: /.*/ }
Rotväg
Du kan lägga till en hemsidesrutt till din app med root
.
# 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
Och i terminalen kommer rake routes
( rails routes
i Rails 5) att producera:
root GET / application#index
Eftersom hemsidan är oftast den viktigaste vägen och vägar prioriteras i den ordning de visas i root
bör vägen brukar vara den första i rutter fil.
Ytterligare RESTful handlingar
resources :photos do member do get 'preview' end collection do get 'dashboard' end end
Detta skapar följande rutter utöver standard 7 RESTful rutter :
get '/photos/:id/preview', to: 'photos#preview'
get '/photos/dashboards', to: 'photos#dashboard'
Om du vill göra detta för enstaka rader kan du använda:
resources :photos do get 'preview', on: :member get 'dashboard', on: :collection end
Du kan också lägga till en åtgärd på /new
sökväg:
resources :photos do get 'preview', on: :new end
Vilket skapar:
get '/photos/new/preview', to: 'photos#preview'
Var uppmärksam när du lägger till åtgärder till dina RESTful rutter, förmodligen saknar du en annan resurs!
Tillgängliga platser
Om din ansökan är tillgänglig på olika språk visar du vanligtvis det aktuella språket i URL: en.
scope '/(:locale)', locale: /#{I18n.available_locales.join('|')}/ do
root 'example#root'
# other routes
end
Din rot kommer att vara tillgänglig via de platser som definieras i I18n.available_locales
.
Montera en annan applikation
mount används för att montera en annan applikation (i princip rackapplikation) eller rälsmotorer som ska användas inom den aktuella applikationen
syntax:
mount SomeRackApp, at: "some_route"
Nu kan du komma åt ovanstående monterad applikation med hjälp av some_rack_app_path
eller some_rack_app_url
.
Men om du vill byta namn på detta hjälparnamn kan du göra det som:
mount SomeRackApp, at: "some_route", as: :myapp
Detta genererar myapp_path
och myapp_url
som kan användas för att navigera till denna monterade app.
Omdirigeringar och jokerteckenrutter
Om du vill ange en URL av bekvämlighet för din användare men kartlägga den direkt till en annan som du redan använder. Använd en omdirigering:
# config/routes.rb
TestApp::Application.routes.draw do
get 'courses/:course_name' => redirect('/courses/%{course_name}/lessons'), :as => "course"
end
Det blev intressant snabbt. Den grundläggande principen här är att bara använda #redirect
metoden för att skicka en rutt till en annan rutt. Om din rutt är ganska enkel är det en riktigt enkel metod. Men om du också vill skicka de ursprungliga parametrarna måste du göra lite gymnastik genom att fånga parametern inuti %{here}
. Notera de enskilda citaten kring allt.
I exemplet ovan har vi också bytt namn på rutten för enkelhets skull genom att använda ett alias med parametern: som. Detta låter oss använda det namnet på metoder som #_path-hjälpare. Testa igen dina $ rake routes
med frågor.
Dela rutter i flera filer
Om din ruttfil är överväldigande stor kan du lägga dina rutter i flera filer och inkludera var och en av filerna med Rubys require_relative
metod:
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
Kapslade rutter
Om du vill lägga till kapslade rutter kan du skriva följande kod i filen routes.rb
.
resources :admins do
resources :employees
end
Detta genererar följande rutter:
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