grundläggande Routingkonventioner
Låt oss ta en titt på våra rutter som de är nu, med hjälp avrake 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
en av de viktigaste insikterna för Rails-konventioner är att datacentrerade appar (eller grova appar) tenderar att ha mycket liknande sätt att låta användare interagera med applikationen, som är:
- en sida för att visa en lista med något
- visa något
- visa ett formulär för att skapa en ny instans av något
- skapa faktiskt något
- visa ett formulär för att redigera en instans av något
- uppdatera faktiskt något
- ta bort något
dessa sju ”interaktionsmönster” är så vanliga, att rails ger en stark uppsättning konventioner från routing till controllers, vyer och former för att göra dessa arbetsflöden enklare. Vi kommer att fokusera på routingdelen nu.
för routing är konventionen att istället för att vi måste komma med URL-mönstren rekommenderar Rails att vi strukturerar webbadresserna och motsvarande kontrollåtgärder på följande sätt:
arbetsflöde | HTTP-VERB | sökväg | kontrollåtgärd |
---|---|---|---|
visa en lista med inlägg | få | / inlägg | inlägg # index |
visa ett inlägg | få | / inlägg/:id | inlägg # visa |
Visa sidan för att skapa inlägg | få | / inlägg / nytt | inlägg # nytt |
skapa ett inlägg | inlägg | / inlägg | inlägg # skapa |
Visa sidan för att redigera ett inlägg | få | / inlägg/: id / redigera | inlägg # redigera |
Uppdatera ett inlägg | PUT / PATCH | / inlägg/: id | inlägg # uppdatering |
radera ett inlägg | radera | / inlägg/:id | inlägg # förstöra |
vi kan ändra post
– delen av vår nuvarande routing för att följa denna konvention:
# 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
och i filen 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 later.. ... end
Lägg märke till att med det här nya mönstret finns det mycket mindre verb i själva webbadressen, men vi litar på HTTP-verben (GET
/POST
/PUT
/PATCH
/DELETE
) för att leverera semantiken för annars samma URL-mönster, till exempel /posts/:id
.
Observera att PUT
hade använts för att uppdatera resurser tills nyligen, när PATCH
bestämdes vara en bättre semantisk matchning för denna åtgärd. Sedan dess har Rails flyttat till att föredra PATCH
, men tillåter båda verben för uppdateringar.
en annan ändring som vi kommer att se senare är att vi kommer att dirigera alla webbadresser relaterade till inlägg till en PostsController
istället för att hantera allt i ApplicationController
. PostController
åtgärdsnamn
- nytt
- index
- visa
- skapa
- redigera
- uppdatera
- förstör
är också konventioner som motsvarar 7-interaktionen mönster .
Detta är den starkaste uppsättning konventioner som Rails ålägger dig som applikationsutvecklare. Vi ber dig att göra ett försök att memorera det. Vi kommer att återkomma detta många gånger i hela boken för att hjälpa dig att göra det också.
Routing för flera resurser
ofta måste vi ha flera resurser som finns i webbadressen. Till exempel för vår bloggapp när vi behöver ha en rutt för att skapa en kommentar är det mycket viktigt att vi vet vilket inlägg den här kommentaren skapas på.
vi gör för närvarande detta:
post 'create_comment_for_post/:post_id' => 'application#create_comment'
Rails-konventionen för en URL med flera associerade resurser är att börja med den ”innehållande” resursen hela vägen till den ”innersta” resursen. Till exempel skulle våra vägar för kommentarer ändras till:
post '/posts/:id/comments' => 'comments#create' delete '/posts/:post_id/comments/:id' => 'comments#destroy' get '/comments' => 'comments#index'
semantiken för dessa webbadresser representerar:” skapa en kommentar under ett specifikt inlägg ”och”ta bort en kommentar under ett specifikt inlägg”. Den sista rutten, ”visa alla kommentarer i systemet”, behöver inte vara ”scoped” under ett inlägg, så webbadressen behöver inte leda med ”/inlägg”.
om vi behöver ha flera resurser i webbadressen med deras ID, är konventionen sådan att den sista resursen kommer att använda platshållaren :id
och resten kommer att vara :resource_id
som :post_id
.
Restful
REST står för ”Representational State Transfer”. Det är en mjukvaruarkitektur stil och riktlinje för att skapa skalbara webbtjänster. Vila, som ett sätt att strukturera webbapplikationer, har många aspekter på det, men låt oss bara titta på hur det gäller gränssnittet som vi använder för att interagera med webbappar, webbadresserna.
för att se hur REST förenklar semantiken för webbadresser, låt oss gå igenom ett exempel. Låt oss säga att vi bygger en online pizza beställningstjänst. En na-implementering av gränssnitten för tjänsten (URL: er) skulle vara:
/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
en vilsam gränssnittsdesign skulle se ut så här:
GET /orders/2 POST /orders GET /pizzas/1 POST /orders/12/payments DELETE /orders/3 POST /orders/13/expeditions
du kan se, vilsamma gränssnitt centrerar kring ”substantiv” eller ”resurser”, tar bort ”verb” från gränssnitten men förlitar sig istället på de standardiserade HTTP-verben (GET
/POST
/PUT
/DELETE
) att leverera CRUD semantik för åtgärderna. Verb som check
, place
, cancel
mappas direkt till HTTP-verb av GET
för att hämta, POST
för att skapa och DELETE
för att förstöra resurs order
. pay
och expedite
är strukturerade som skapande (HTTP POST) av underresurser av payments
och expeditions
under resurs orders
.
RESTful interfaces standardiserade interaktionsmönster för webbapplikationer för att göra dem lättare att förstå och programmera mot. Eftersom gränssnitten är centrerade kring att manipulera resurser är svaren mycket mer förutsägbara. En analogi av hur RESTful architecture-mönstret förenklar interaktionen med webbtjänster skulle vara hur relationsdatabasen och SQL-språket förenklar datalagring. Innan relationsdatabas och SQL lagrades data vanligtvis i egna system med specifik logik för att interagera med dem, vilket innebar att du på varje projekt måste lära dig en annan uppsättning instruktioner för att interagera med data. Relationsdatabaser och SQL gav en gemensam datastruktur (dataposter som rader och kolumner lagrade i tabeller) och en uppsättning gemensamma gränssnitt – fyra enkla verb av SELECT
, INSERT
, UPDATE
och DELETE
som kan stödja alla typer av applikationer.
att anta ett vilsamt gränssnitt för din webbapp kommer också att effektivisera din applikation för att anpassa sig till hur backend-data lagras i databaser och underlättar utvecklingen. Vi får se det i följande kapitel.
Resursnotation
vi har pratat om Rails routingkonventioner och vilsamma URL-mönster. Nu skulle vår routes.rb
– fil se ut som följande:
### 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
faktum är att rutterna som vad vi har i avsnittet posts
är mycket vanliga, så Rails ger en speciell resources
notation som hjälper till att generera dem åt dig.
vi kan helt enkelt göra:
resources :posts
denna linje genererar automatiskt de 8 linjerna vi hade tidigare. Observera att för åtgärden update
tillåter Rails både PUT
och PATCH
verb, av kompatibilitetsskäl.
du kan köra bundle exec rake routes
i din kommandoradsmiljö för att verifiera att den genererar exakt samma uppsättning rutter.
Observera att denna enda rad kommer att generera 8 rutter. I vårt fall behöver vi alla rutter här, men om du bara behöver en delmängd av rutterna kan du definiera dem mer uttryckligen som:
resources :posts, only:
den här raden ovan skulle bara generera 3 rutter för dig – Skriv bundle exec rake routes
för att kolla in den.
kapslade resurser
Rails tillåter oss också att bo resurser för att skapa URL-mönster med flera resurser, se nedan:
### config/routes.rb ### Rails.application.routes.draw do resources :posts do resources :comments, only: end resources :comments, only: :index end
kör bundle exec rake routes
och se utgången – den ska vara densamma som vad vi hade tidigare.
Path Helpers
när du kör bundle exec rake routes
, Lägg märke till kolumnen Prefix
för några av dessa rutter. Dessa är här för att hjälpa oss att veta hur man använder Rails tillhandahållna väghjälpare för våra rutter. Vi kan använda dessa prefix följt av _path
i våra kontroller och vyer för att enkelt bygga vägar.
till exempel:
posts_path # => '/posts' post_id = 123 post_comments_path(post_id) # => '/posts/123/comments'
Vad är fördelen med att använda URL-hjälpare, snarare än hårdkodning av sökvägar som /posts/123/comments
direkt i din kod? (till exempel i din controller action?) Anledningen till att du vill använda sökvägshjälpare är att om du vill ändra URL-mönstren i din app är det mycket lättare att använda URL-hjälparna för att returnera en annan sökväg-låt oss titta på ett exempel:
get '/register', to: 'users#new', as: 'register'
när vi lägger till ”as” – klausulen till den här rutten, om du kör bundle exec rake routes
, ser du kolumnen Prefix
med register
, och du kan använda register_path
för att få /register
sökvägen. Nu, om vi vill ändra sökvägen till /login
, behöver vi bara göra:
get '/login', to: 'users#new', as: 'register'
nu ger vår register_path
oss /login
. Vi behöver inte ändra vår kod i Rails-appen alls.
fler Routingkonventioner
innan vi går vidare, Låt oss ta en snabb titt på ett par varianter av vad vi redan har sett, liksom några andra funktioner som är tillgängliga för oss i Rails routing:
### 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
låt oss bryta ner alla funktioner som anges ovan en i taget.
-
root:
root
används för att ange vilka åtgärdskartor till ”/”(den översta webbadressen till vår webbplats som inte har någon sökväg).Root-webbadressen till din webbplats/app är den vanligaste, på grund av dettaroot
bör specificeras högst upp i ruttfilen. -
match + via:
match
används för att matcha URL-mönster till en eller flera rutter. Vi kan också ange vilket HTTP-verb som kan användas för att matcha en URL med detta mönster. Vi gör detta genom att skicka in en hash tillmatch
– metoden. Nyckeln för denna hash ärvia
, och värdet är en uppsättning HTTP-verb.match
är en mer generell form av några mer vanliga HTTP-routingmetoder, såsomget
,post
ochdelete
. Det kan ta alla samma alternativ som dessa metoder, men jämfört med dessa metoder ger det lite mer flexibilitet.
till exempel, genom att användamatch
kan vi ange en URL som matchar för två olika rutter, var och en motsvarar två olika HTTP-verb. Normalt skulle detta kräva två kommandon istället för en. Vi kan se detta från vårt exempel ovan, där vi matchar URL-mönstret'/authors/:id'
till åtgärden'authors#update'
. Vi anger sedan vilka HTTP-verb som kan användas för att utfärda begäran om den webbadressen medvia:
. Ange alltid en HTTP-metod när du användermatch
, om du inte gör det kan det få negativa konsekvenser för programmets säkerhet.match
presenterar ett annat alternativ för dirigering till vissa åtgärder i Rails. I allmänhet är det bäst att hålla fast vid de vanligasteHttpHelpers
– metoderna, somget
ochpost
. -
as: vi nämnde lite tidigare att alternativet
as:
kan användas med vår ruttdeklaration för att ändraprefixet för våra URL-hjälpare. Detta kan användas på olika sätt. Vi kan användaas:
för att göra våra URL-hjälpare bättre matcha anpassade webbadresser. En annan användning är att ändra den aktuella URL – sökvägshjälpen till något mer intuitivt eller något som matchar bättre med resurserna i en applikation. -
samlingsväg: se hur ovan Vi Bo vår
/popular
rutt underposts
resurs. Vi använder sedanon: :collection
för att ange vilken del av en resurs vi häckar denna rutt under. Vi har många inlägg så det anses vara en samling. Genom att angeon: :collection
säger vi, ” matcha en URL med sökväg/posts/popular
.”Om vi inte lägger tillon: :collection
, kommer Rails att anta att denna rutt motsvarar en annan resurs som är associerad med en enda medlem i vår postsamling. I så fall skulle vår rutt bli/posts/:id/popular
. Vi kan också ange flera samlingsvägar med hjälp av ett blockformat.
collection do get 'popular' end
- passerar en extra parameter: vi kan ange en standardparameter som alltid får skickas in med vår
params
hash när vi matchas med vissa webbadresser. Det finns två sätt att specificera detta; ett sätt är på samma sätt som vi gör ovan:
get 'popular', on: :collection, action: :index, popular: true
popular: true
kommer att skickas till vår åtgärd som den populära rutten matchar med via params
hash. Den kommer att ha en nyckel på :popular
och ett värde på true
. Vi kan också använda mer explicit syntax genom att skicka en hash till vår ruttmetod get
, varnyckeln är defaults:
och värdet är en annan hash som innehåller namnet på parametern vi vill överföra till vår åtgärd.
get 'popular', on: :collection, action: :index, defaults: { popular: true}
-
medlemsrutt: vi kan använda
on: member
för att ange att vår rutt matchar en medlem i en samling. Om vi använder detta kommer det dynamiska segmentet att visas som:id
. En URL-hjälpare kommer också att skapas sompreview_post
. Genom att ange denna rutt medon: member
berättar vi Rails att detta är medlem i den här resursen. Att det inte bara är en annan resurs kapslad under inlägg, men närmare kopplad eller relaterad till våra inlägg i den här applikationen. Flera medlemsrutter kan definieras med ett blockformat; detta format använder samma syntax som blockformatet för att definiera flera samlingsrutter, ersätt baracollection
medmember
. -
omdirigering: det finns ett annat koncept att prata om som visas i vårt exempel ovan, och det är omdirigering. Rails ger oss möjlighet att omdirigera från en väg till en annan genom att använda en omdirigeringshjälpare i samband med en rutt.
get '/home', to: redirect('/')
. Om någon försöker komma åt sökvägen/home
omdirigeras de omedelbart till rotvägen/
. Detta är naturligtvis inte begränsat till bara en URL-sökväg; vi kan också ha något så här:get '/home', to: redirect('/travel')
.
Review
Rails rutter står framför en ansökan. En rutt tolkar en inkommande HTTP-begäran och:
- matchar en begäran till en kontrolleråtgärd baserad på kombinationen av ett HTTP-verb och begäran URL-mönstret
- fångar data i webbadressen för att vara tillgänglig i
params
i kontrolleråtgärder - Rails uppmuntrar utvecklare att använda vilsamma URL-mönster när de konfigurerar rutter, med konceptualisering av att manipulera resurser med HTTP-verb.
- du kan använda makrot
resources
för att generera vilsamma rutter mycket snabbt.