Ruby on Rails
routing
Zoeken…
Invoering
Opmerkingen
'Routing' is in het algemeen hoe URL's door uw app worden 'verwerkt'. In het geval van Rails is het meestal welke controller en welke actie van die controller een bepaalde inkomende URL verwerkt. In Rails-apps worden routes meestal in het bestand config/routes.rb
.
Resource routing (basis)
Routes worden gedefinieerd in config/routes.rb
. Ze worden vaak gedefinieerd als een groep verwante routes, met behulp van de resources
of resource
methoden.
resources :users
maakt de volgende zeven routes, alle toewijzingen aan acties van 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'
Actienamen worden weergegeven na het #
in de parameter to
hierboven. Methoden met dezelfde namen moeten als volgt worden gedefinieerd in app/controllers/users_controller.rb
:
class UsersController < ApplicationController
def index
end
def create
end
# continue with all the other methods…
end
U kunt de acties beperken die worden gegenereerd met only
of except
:
resources :users, only: [:show]
resources :users, except: [:show, :index]
U kunt op elk gewenst moment alle routes van uw applicatie bekijken door te draaien:
$ 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
Alleen de routes bekijken die naar een bepaalde controller verwijzen:
$ 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
U kunt routes doorzoeken met de optie -g
. Dit toont elke route die gedeeltelijk overeenkomt met de naam van de helpermethode, het URL-pad of het HTTP-werkwoord:
$ 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
Bovendien kunt u, wanneer u rails
server in de ontwikkelingsmodus gebruikt, toegang krijgen tot een webpagina waarop al uw routes worden weergegeven met een zoekfilter, van boven naar beneden afgestemd op <hostname>/rails/info/routes
. Het ziet er zo uit:
Helper | HTTP Verb | Pad | Controller # Actie |
---|---|---|---|
Pad / URL | [Padovereenkomst] | ||
users_path | KRIJGEN | /users(.:format) | gebruikers # index |
POST | /users(.:format) | gebruikers # maak | |
new_user_path | KRIJGEN | /users/new(.:format) | gebruikers # nieuwe |
edit_user_path | KRIJGEN | /users/:id/edit(.:format) | gebruikers # bewerken |
user_path | KRIJGEN | /users/:id(.:format) | gebruikers # tonen |
PATCH | /users/:id(.:format) | gebruikers #-update | |
LEGGEN | /users/:id(.:format) | gebruikers #-update | |
DELETE | /users/:id(.:format) | gebruikers # vernietigen |
Routes kunnen alleen beschikbaar worden verklaard voor leden (geen collecties) met behulp van de methode resource
plaats van resources
in routes.rb
. Met resource
wordt een index
niet standaard gemaakt, maar alleen wanneer expliciet om een dergelijke wordt gevraagd:
resource :orders, only: [:index, :create, :show]
constraints
U kunt filteren welke routes beschikbaar zijn met behulp van beperkingen.
Er zijn verschillende manieren om beperkingen te gebruiken, waaronder:
Een aangevraagde gebaseerde beperking om alleen een specifiek IP-adres toegang te geven tot een route:
constraints(ip: /127\.0\.0\.1$/) do
get 'route', to: "controller#action"
end
Bekijk andere soortgelijke voorbeelden ActionDispatch :: Routing :: Mapper :: Scoping .
Als je iets complexers wilt doen, kun je geavanceerdere beperkingen gebruiken en een klasse maken om de logica te omzeilen:
# 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
Eén formulier, meerdere verzendknoppen
U kunt ook de waarde van de verzendtags van een formulier gebruiken als beperking om naar een andere actie te routeren. Als u een formulier hebt met meerdere verzendknoppen (bijv. "Preview" en "submit"), kunt u deze beperking direct in uw routes.rb
, in plaats van javascript te schrijven om de bestemmings-URL van het formulier te wijzigen. Met de commit_param_routing- edelsteen kun je bijvoorbeeld profiteren van rails submit_tag
Met Rails submit_tag
first parameter kunt u de waarde van uw formulier commit parameter wijzigen
# 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
Scope routes
Rails biedt verschillende manieren om uw routes te organiseren.
Bereik op URL :
scope 'admin' do
get 'dashboard', to: 'administration#dashboard'
resources 'employees'
end
Dit genereert de volgende routes
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'
Het kan logischer zijn, aan de serverzijde, om sommige views in een andere submap te houden, om admin views van gebruikers views te scheiden.
Bereik per module
scope module: :admin do
get 'dashboard', to: 'administration#dashboard'
end
module
zoekt naar de controllerbestanden onder de submap van de opgegeven naam
get '/dashboard', to: 'admin/administration#dashboard'
U kunt de prefix padhelpers hernoemen door een parameter as
toe te voegen
scope 'admin', as: :administration do
get 'dashboard'
end
# => administration_dashboard_path
Rails biedt een handige manier om al het bovenstaande te doen, met behulp van de namespace
. De volgende verklaringen zijn gelijkwaardig
namespace :admin do
end
scope 'admin', module: :admin, as: :admin
Bereik per controller
scope controller: :management do
get 'dashboard'
get 'performance'
end
Dit genereert deze routes
get '/dashboard', to: 'management#dashboard'
get '/performance', to: 'management#performance'
Ondiep nestelen
Bronroutes accepteren een :shallow
optie die helpt om URL's waar mogelijk in te korten. Bronnen mogen niet meer dan één niveau diep worden genest. Een manier om dit te voorkomen is door ondiepe routes te maken. Het doel is om URL-segmenten van bovenliggende collecties weg te laten waar ze niet nodig zijn. Het eindresultaat is dat de enige gegenereerde geneste routes zijn voor de :index
:create
en :new
actions. De rest wordt bewaard in hun eigen ondiepe URL-context. Er zijn twee opties voor bereik tot aangepaste ondiepe routes:
: shallow_path: prefixeert lidpaden met een opgegeven parameter
scope shallow_path: "sekret" do resources :articles do resources :comments, shallow: true end end
: shallow_prefix : voeg gespecificeerde parameters toe aan genoemde helpers
scope shallow_prefix: "sekret" do resources :articles do resources :comments, shallow: true end end
We kunnen shallow
routes ook meer illustreren door:
resources :auctions, shallow: true do
resources :bids do
resources :comments
end
end
alternatief gecodeerd als volgt (als je tevreden bent met de blokken):
resources :auctions do
shallow do
resources :bids do
resources :comments
end
end
end
De resulterende routes zijn:
Voorvoegsel | Werkwoord | URI-patroon |
---|---|---|
bid_comments | KRIJGEN | /bids/:bid_id/comments(.:format) |
POST | /bids/:bid_id/comments(.:format) | |
new_bid_comment | KRIJGEN | /bids/:bid_id/comments/new(.:format) |
edit_comment | KRIJGEN | /comments/:id/edit(.:format) |
commentaar | KRIJGEN | /comments/:id(.:format) |
PATCH | /comments/:id(.:format) | |
LEGGEN | /comments/:id(.:format) | |
DELETE | /comments/:id(.:format) | |
auction_bids | KRIJGEN | /auctions/:auction_id/bids(.:format) |
POST | /auctions/:auction_id/bids(.:format) | |
new_auction_bid | KRIJGEN | /auctions/:auction_id/bids/new(.:format) |
edit_bid | KRIJGEN | /bids/:id/edit(.:format) |
bod | KRIJGEN | /bids/:id(.:format) |
PATCH | /bids/:id(.:format) | |
LEGGEN | /bids/:id(.:format) | |
DELETE | /bids/:id(.:format) | |
veilingen | KRIJGEN | /auctions(.:format) |
POST | /auctions(.:format) | |
new_auction | KRIJGEN | /auctions/new(.:format) |
edit_auction | KRIJGEN | /auctions/:id/edit(.:format) |
veiling | KRIJGEN | /auctions/:id(.:format) |
PATCH | /auctions/:id(.:format) | |
LEGGEN | /auctions/:id(.:format) | |
DELETE | /auctions/:id(.:format) |
Als u de gegenereerde routes zorgvuldig analyseert, zult u merken dat de geneste delen van de URL alleen worden opgenomen wanneer ze nodig zijn om te bepalen welke gegevens moeten worden weergegeven.
Bedenkingen
Om herhaling in geneste routes te voorkomen, bieden zorgen een geweldige manier om gemeenschappelijke bronnen te delen die herbruikbaar zijn. Gebruik de methode concern
in het bestand routes.rb
om een probleem te creëren. De methode verwacht een symbool en blok:
concern :commentable do
resources :comments
end
Hoewel er zelf geen routes worden gemaakt, kunt u met deze code het kenmerk :concerns
op een resource gebruiken. Het eenvoudigste voorbeeld zou zijn:
resource :page, concerns: :commentable
De equivalente geneste bron ziet er als volgt uit:
resource :page do
resource :comments
end
Dit zou bijvoorbeeld de volgende routes bouwen:
/pages/#{page_id}/comments
/pages/#{page_id}/comments/#{comment_id}
Wil bezorgdheid zinvol zijn, dan moeten er meerdere bronnen zijn die de zorg gebruiken. Aanvullende bronnen kunnen een van de volgende syntaxis gebruiken om het probleem op te lossen:
resource :post, concerns: %i(commentable)
resource :blog do
concerns :commentable
end
Redirection
U kunt omleiding in Rails-routes als volgt uitvoeren:
get '/stories', to: redirect('/posts')
match "/abc" => redirect("http://example.com/abc")
Je kunt ook alle onbekende routes omleiden naar een bepaald pad:
match '*path' => redirect('/'), via: :get
# or
get '*path' => redirect('/')
match '*path' => redirect('/')
Routes voor leden en collecties
Door een ledenblok in een resource te definiëren, wordt een route gecreëerd die kan reageren op een individueel lid van die resource-gebaseerde route:
resources :posts do
member do
get 'preview'
end
end
Dit genereert de volgende ledenroute:
get '/posts/:id/preview', to: 'posts#preview'
# preview_post_path
Met verzamelingsroutes kunnen routes worden gemaakt die kunnen werken op een verzameling resourceobjecten:
resources :posts do
collection do
get 'search'
end
end
Dit genereert de volgende verzamelroute:
get '/posts/search', to: 'posts#search'
# search_posts_path
Een alternatieve syntaxis:
resources :posts do
get 'preview', on: :member
get 'search', on: :collection
end
URL-parameters met een punt
Als u een meer complexe URL-parameter dan een id-nummer wilt ondersteunen, kunt u problemen ondervinden met de parser als de waarde een punt bevat. Alles wat volgt op een punt wordt verondersteld een formaat te zijn (dwz json, xml).
U kunt deze beperking omzeilen door een beperking te gebruiken om de geaccepteerde invoer te verbreden .
Als u bijvoorbeeld wilt verwijzen naar een gebruikersrecord op e-mailadres in de url:
resources :users, constraints: { id: /.*/ }
Hoofdroute
U kunt een startpaginaroute toevoegen aan uw app met de 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
En in de terminal zullen rake routes
( rails routes
in Rails 5) het volgende produceren:
root GET / application#index
Omdat de startpagina meestal de belangrijkste route is en routes prioriteit krijgen in de volgorde waarin ze verschijnen, moet de root
route meestal de eerste zijn in je routes-bestand.
Aanvullende RESTful acties
resources :photos do member do get 'preview' end collection do get 'dashboard' end end
Dit maakt de volgende routes naast de standaard 7 RESTful-routes :
get '/photos/:id/preview', to: 'photos#preview'
get '/photos/dashboards', to: 'photos#dashboard'
Als u dit voor enkele lijnen wilt doen, kunt u het volgende gebruiken:
resources :photos do get 'preview', on: :member get 'dashboard', on: :collection end
U kunt ook een actie toevoegen aan het /new
pad:
resources :photos do get 'preview', on: :new end
Welke zal creëren:
get '/photos/new/preview', to: 'photos#preview'
Let op bij het toevoegen van acties aan je RESTful-routes, je mist waarschijnlijk een andere bron!
Beschikbare locaties
Als uw toepassing beschikbaar is in verschillende talen, geeft u meestal de huidige landinstelling weer in de URL.
scope '/(:locale)', locale: /#{I18n.available_locales.join('|')}/ do
root 'example#root'
# other routes
end
Je root is toegankelijk via de landinstellingen die zijn gedefinieerd in I18n.available_locales
.
Mount een andere applicatie
mount wordt gebruikt om een andere applicatie (in principe rackapplicatie) of railmotoren te monteren voor gebruik in de huidige applicatie
syntaxis:
mount SomeRackApp, at: "some_route"
Nu kunt u toegang krijgen tot de bovenstaande gemonteerde toepassing met behulp van route helper some_rack_app_path
of some_rack_app_url
.
Maar als u deze helpernaam wilt hernoemen, kunt u dit doen als:
mount SomeRackApp, at: "some_route", as: :myapp
Dit genereert de myapp_path
en myapp_url
helpers die kunnen worden gebruikt om naar deze gekoppelde app te navigeren.
Omleidingen en jokertekens
Als u voor uw gemak een URL wilt opgeven, maar deze rechtstreeks wilt toewijzen aan een andere URL die u al gebruikt. Gebruik een omleiding:
# config/routes.rb
TestApp::Application.routes.draw do
get 'courses/:course_name' => redirect('/courses/%{course_name}/lessons'), :as => "course"
end
Nou, dat werd snel interessant. Het basisprincipe hier is om alleen de #redirect
methode te gebruiken om de ene route naar een andere route te verzenden. Als je route vrij eenvoudig is, is het een heel eenvoudige methode. Maar als u ook de originele parameters wilt verzenden, moet u een beetje gymnastiek doen door de parameter vast te leggen in %{here}
. Let op de enkele aanhalingstekens rondom alles.
In het bovenstaande voorbeeld hebben we de route voor het gemak ook hernoemd met behulp van een alias met de parameter: as. Hiermee kunnen we die naam gebruiken in methoden zoals de #_path helpers. Nogmaals, test je $ rake routes
met vragen.
Split routes in meerdere bestanden
Als je routesbestand overweldigend groot is, kun je je routes in meerdere bestanden plaatsen en elk van de bestanden opnemen met Ruby's require_relative
methode:
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
Geneste routes
Als u geneste routes wilt toevoegen, kunt u de volgende code in routes.rb
bestand schrijven.
resources :admins do
resources :employees
end
Dit genereert de volgende routes:
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