podstawowe konwencje routingu
przyjrzyjmy się naszym trasom w obecnej postaci, używając 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
jednym z kluczowych spostrzeżeń dotyczących konwencji Rails jest to, że aplikacje skoncentrowane na danych (lub Aplikacje CRUDy) mają bardzo podobne sposoby pozwalania użytkownikom na interakcję z aplikacją, które są:
- strona do wyświetlenia listy czegoś
- zobacz coś
- Pokaż formularz do utworzenia nowej instancji czegoś
- faktycznie Utwórz coś
- Pokaż formularz do edycji instancji czegoś
- faktycznie zaktualizuj coś
- Usuń coś
te siedem „wzorców interakcji” jest tak powszechne, że rails zapewnia silny zestaw konwencji, od routingu po kontrolery, widoki i formularze, aby ułatwić te przepływy pracy. Skupmy się teraz na routingu.
w przypadku routingu, konwencja jest taka, że zamiast wymyślać wzorce URL, Rails zaleca, abyśmy uporządkowali adresy URL i odpowiadające im akcje kontrolera w następujący sposób:
Workflow | czasownik HTTP | ścieżka | Akcja kontrolera |
---|---|---|---|
Pokaż listę postów | Pobierz | / posty | posty#index |
Pokaż post | Pobierz | / posty/:id | posty # Pokaż |
Pokaż stronę do utworzenia postu | Pobierz | / posty / nowe | posty # nowe |
utwórz post | POST | / posty | posty # Utwórz |
Pokaż stronę do edycji postu | Pobierz | / posts/: id / edit | posts#edit |
Update a post | PUT / PATCH | / posts/: id | posts#update |
Usuń post | Usuń | / posty/:id | posty # destroy |
możemy zmienić część post
naszego obecnego routingu, aby była zgodna z tą konwencją:
# 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
i w pliku 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
zauważ, że w tym nowym wzorze jest o wiele mniej czasowników w samym adresie URL, ale opieramy się na czasownikach HTTP (GET
/POST
/PUT
/PATCH
/DELETE
) aby podać semantykę dla tych samych wzorców URL, na przykład /posts/:id
.
zauważ, że PUT
był używany do aktualizacji zasobów do niedawna, kiedy PATCH
uznano za lepsze dopasowanie semantyczne dla tej akcji. Od tego czasu Rails przeszedł do preferowania PATCH
, ale zezwalając na aktualizacje obu czasowników.
kolejna zmiana, którą zobaczymy później, to przekierowanie wszystkich adresów URL związanych z postami na PostsController
zamiast obsługi wszystkiego w ApplicationController
. Nazwy akcji PostController
- new
- index
- show
- create
- edit
- update
- destroy
są również konwencjami odpowiadającymi 7 interakcjom wzory.
to najsilniejszy zestaw konwencji, które Rails nakłada na Ciebie jako programistę aplikacji. Poprosimy cię, abyś spróbował go zapamiętać. Będziemy wracać do tego wiele razy w całej książce, aby pomóc ci to zrobić, jak również.
Routing dla wielu zasobów
często musimy mieć wiele zasobów obecnych w adresie URL. Na przykład w przypadku naszej aplikacji blogowej, gdy potrzebujemy trasy do utworzenia komentarza, bardzo ważne jest, abyśmy wiedzieli, na którym poście ten komentarz jest tworzony.
:
post 'create_comment_for_post/:post_id' => 'application#create_comment'
konwencja Rails adresu URL z wieloma powiązanymi zasobami rozpoczyna się od zasobu „zawierającego” aż do zasobu „najskrytszego”. Na przykład nasze trasy komentarzy zmieniłyby się na:
post '/posts/:id/comments' => 'comments#create' delete '/posts/:post_id/comments/:id' => 'comments#destroy' get '/comments' => 'comments#index'
semantyka tych adresów URL reprezentuje: „Utwórz komentarz pod określonym postem” i „Usuń komentarz pod określonym postem”. Ostatnia trasa, „Pokaż wszystkie komentarze w systemie”, nie musi być” scoped „pod postem, więc adres URL nie musi prowadzić przez”/posts”.
jeśli potrzebujemy mieć wiele zasobów w adresie URL z ich identyfikatorami, konwencja jest taka, że ostatni zasób będzie używał symbolu zastępczego :id
, a cała reszta będzie :resource_id
, takich jak :post_id
.
Restful
REST oznacza „transfer Państwa Reprezentacyjnego”. Jest to styl architektury oprogramowania i wytyczne do tworzenia skalowalnych usług internetowych. Reszta, jako sposób na strukturę aplikacji internetowych, ma wiele aspektów, ale spójrzmy, jak odnosi się do interfejsu, którego używamy do interakcji z aplikacjami internetowymi, adresów URL.
aby zobaczyć, jak REST upraszcza semantykę adresów URL, przejdźmy przez przykład. Załóżmy, że budujemy usługę zamawiania pizzy online. Naiwna implementacja interfejsów serwisu (adresów URL) byłaby:
/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
RESTful projekt interfejsu wyglądałby tak:
GET /orders/2 POST /orders GET /pizzas/1 POST /orders/12/payments DELETE /orders/3 POST /orders/13/expeditions
jak widać, Interfejsy RESTful skupiają się wokół „rzeczowników” lub „zasobów”, usuwając „czasowniki” z interfejsów, ale polegając na standardowych czasownikach HTTP(GET
/POST
/PUT
/DELETE
) dostarczenie semantyki CRUD do działań. Czasowniki takie jak check
, place
, cancel
są mapowane bezpośrednio do czasowników HTTP GET
, aby pobrać, POST
aby utworzyć i DELETE
aby zniszczyć zasób order
. pay
i expedite
są skonstruowane jako tworzenie (HTTP POST) zasobów podrzędnych payments
i expeditions
pod zasobem orders
.
Interfejsy RESTful ustandaryzowane wzorce interakcji aplikacji internetowych, aby ułatwić ich zrozumienie i zaprogramowanie. Ponieważ interfejsy skupiają się na manipulowaniu zasobami, odpowiedzi są znacznie bardziej przewidywalne. Analogią tego, w jaki sposób schemat architektury RESTful upraszcza interakcję z usługami sieciowymi, jest sposób, w jaki relacyjna baza danych i język SQL upraszczają przechowywanie danych. Przed relacyjną bazą danych i SQL dane były zazwyczaj przechowywane w systemach zastrzeżonych z określoną logiką interakcji z nimi, oznaczało to, że w każdym projekcie trzeba było nauczyć się innego zestawu instrukcji do interakcji z danymi. Relacyjne bazy danych i SQL dały wspólną strukturę danych (rekordy danych jako wiersze i kolumny przechowywane w tabelach) oraz zestaw wspólnych interfejsów-cztery proste czasowniki SELECT
, INSERT
, UPDATE
i DELETE
, które mogą obsługiwać wszystkie typy aplikacji.
zastosowanie interfejsu RESTful dla Twojej aplikacji internetowej usprawni również Twoją aplikację, aby dostosować ją do sposobu przechowywania danych zaplecza w bazach danych, i ułatwi tworzenie aplikacji. Zobaczymy to w kolejnych rozdziałach.
notacja zasobów
rozmawialiśmy o konwencjach routingu Rails i wzorcach RESTful URL. Teraz nasz plik routes.rb
wyglądałby następująco:
### 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
w rzeczywistości trasy, takie jak te, które mamy w sekcji posts
, są bardzo powszechne, więc Rails zapewnia specjalną notację resources
, która pomaga wygenerować je dla Ciebie.
możemy po prostu zrobić:
resources :posts
ta linia automatycznie wygeneruje 8 linii, które mieliśmy wcześniej. Zauważ, że dla akcji update
, Rails dopuszcza zarówno czasownik PUT
, jak i PATCH
, ze względu na kompatybilność.
możesz uruchomić bundle exec rake routes
w środowisku wiersza poleceń, aby sprawdzić, czy generuje on dokładnie ten sam zestaw tras.
zauważ, że ta pojedyncza linia wygeneruje 8 tras. W naszym przypadku potrzebujemy tutaj wszystkich tras, ale jeśli potrzebujesz tylko podzbioru tras, możesz zdefiniować je bardziej wyraźnie jako:
resources :posts, only:
ta linia powyżej wygeneruje tylko 3 trasy dla Ciebie-wpisz bundle exec rake routes
, aby to sprawdzić.
zagnieżdżone zasoby
Rails pozwala nam również zagnieżdżać zasoby do tworzenia wzorców URL z wieloma zasobami, patrz poniżej:
### config/routes.rb ### Rails.application.routes.draw do resources :posts do resources :comments, only: end resources :comments, only: :index end
Uruchom bundle exec rake routes
i zobacz wyjście-powinno być takie samo jak wcześniej.
Pomocnicy ścieżek
po uruchomieniu bundle exec rake routes
zwróć uwagę na kolumnę Prefix
dla niektórych z tych tras. Są one tutaj, aby pomóc nam dowiedzieć się, jak korzystać z pomocników ścieżek dostarczanych przez Rails na naszych trasach. Możemy użyć tych prefiksów, po których następuje _path
w naszych kontrolerach i widokach, aby łatwo budować ścieżki.
na przykład:
posts_path # => '/posts' post_id = 123 post_comments_path(post_id) # => '/posts/123/comments'
Jaka jest zaleta używania pomocników URL, zamiast twardego kodowania ścieżek, takich jak /posts/123/comments
bezpośrednio w kodzie? (na przykład w akcji kontrolera?) Powodem, dla którego chcesz używać pomocników ścieżek, jest to, że jeśli chcesz zmienić wzorce URL w aplikacji, o wiele łatwiej jest użyć pomocników URL, aby zwrócić inną ścieżkę – spójrzmy na przykład:
get '/register', to: 'users#new', as: 'register'
kiedy dodamy klauzulę ” as ” do tej trasy, jeśli uruchomisz bundle exec rake routes
, zobaczysz kolumnę Prefix
z register
i możesz użyć register_path
, aby uzyskać /register
ścieżkę. Teraz, jeśli chcemy zmienić ścieżkę na /login
, wystarczy, że:
get '/login', to: 'users#new', as: 'register'
teraz nasz register_path
daje nam /login
. Nie musimy w ogóle zmieniać naszego kodu w aplikacji Rails.
więcej Konwencji routingu
zanim przejdziemy dalej, rzućmy okiem na kilka odmian tego, co już widzieliśmy, a także kilka innych funkcji dostępnych dla nas w routingu Rails:
### 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
Podzielmy wszystkie funkcje wymienione powyżej po kolei.
-
root:
root
służy do określenia, jakie mapy akcji ” /”(adres URL najwyższego poziomu naszej witryny, który nie ma ścieżki).Główny adres URL witryny / aplikacji jest najczęściej używany, ponieważroot
powinien być określony na górze pliku routes. -
mecz + via:
match
służy do dopasowania wzorców URL do jednej lub więcej tras. Możemy również określić, który czasownik HTTP może być użyty do dopasowania do adresu URL z tym wzorcem. Robimy to przekazując hash do metodymatch
. Kluczem do tego skrótu jestvia
, a wartością jest tablica czasowników HTTP.match
jest bardziej ogólną formą niektórych powszechnie używanych metod routingu HTTP, takich jakget
,post
idelete
. Może wymagać wszystkich tych samych opcji, co te metody, ale w porównaniu z tymi metodami daje nieco większą elastyczność.
na przykład, używającmatch
możemy określić adres URL pasujący do dwóch różnych tras, z których każda odpowiada dwóm różnym czasownikom HTTP. Normalnie, robienie tego wymagałoby dwóch komend, zamiast jednej. Możemy to zobaczyć w naszym przykładzie powyżej, gdzie dopasowujemy wzorzec URL'/authors/:id'
do akcji'authors#update'
. Następnie określamy, jakie czasowniki HTTP mogą być użyte do wysłania żądania dla tego adresu URL za pomocąvia:
. Zawsze określaj metodę HTTP podczas używaniamatch
, nie robienie tego może mieć negatywny wpływ na bezpieczeństwo aplikacji.match
prezentuje inną opcję routingu do określonych akcji w Rails. Ogólnie rzecz biorąc, najlepiej jest trzymać się powszechnie stosowanych metodHttpHelpers
, takich jakget
ipost
. -
as: wspomnieliśmy nieco wcześniej, że opcja
as:
może być używana z naszą deklaracją trasy do zmiany prefiksu dla naszych pomocników URL. Można to wykorzystać na różne sposoby. Możemy użyćas:
, aby nasi pomocnicy URL lepiej dopasowywali niestandardowe adresy URL. Innym zastosowaniem jest zmiana bieżącego pomocnika ścieżki URL na coś bardziej intuicyjnego lub coś, co lepiej pasuje do zasobów w aplikacji. -
trasa zbierania: zobacz, jak powyżej zagnieżdżamy naszą trasę
/popular
pod zasobemposts
. Następnie używamyon: :collection
, aby określić, w jakiej części zasobu zagnieżdżamy tę trasę. Mamy wiele postów, więc jest to uważane za kolekcję. Określającon: :collection
mówimy, „Dopasuj adres URL do ścieżki/posts/popular
.”Jeśli nie dodaliśmyon: :collection
, Rails założy, że ta trasa odpowiada innemu zasobowi powiązanemu z jednym członkiem naszej kolekcji posts. W takim przypadku nasza trasa byłaby/posts/:id/popular
. Możemy również określić wiele tras kolekcji za pomocą formatu blokowego.
collection do get 'popular' end
- przekazanie dodatkowego parametru: możemy określić domyślny parametr, który zawsze jest przekazywany z naszym skrótem
params
, gdy jesteśmy dopasowani do określonych adresów URL. Istnieją dwa sposoby określenia tego; jeden sposób jest taki sam jak powyżej:
get 'popular', on: :collection, action: :index, popular: true
popular: true
zostanie przekazana do naszej akcji, z którą popularna trasa pasuje za pomocą skrótu params
. Będzie miał klucz :popular
i wartość true
. Możemy również użyć bardziej jawnej składni, przekazując hash do naszej metody route get
, gdzie kluczem jest defaults:
, a wartością jest inny hash zawierający nazwę parametru, który chcemy przekazać do naszej akcji.
get 'popular', on: :collection, action: :index, defaults: { popular: true}
-
trasa członkowska: możemy użyć
on: member
, aby określić, że nasza trasa pasuje do elementu kolekcji. Jeśli użyjemy tego, segment dynamiczny pojawi się jako:id
. Helper URL zostanie również utworzony jakopreview_post
. Określając tę trasę za pomocąon: member
, informujemy Rails, że jest to element tego konkretnego zasobu. Że nie jest to tylko kolejny zasób zagnieżdżony pod postami, ale ściślej powiązany lub powiązany z naszymi postami w tej aplikacji. Wiele tras członkowskich może być zdefiniowanych przy użyciu formatu bloku; ten format używa tej samej składni co format bloku do definiowania wielu tras kolekcji, wystarczy zastąpićcollection
member
. -
przekierowanie: jest jeszcze jedna koncepcja, o której można mówić w naszym przykładzie powyżej, a mianowicie przekierowanie. Rails daje nam możliwość przekierowania z jednej ścieżki do drugiej za pomocą redirect helper w połączeniu z trasą.
get '/home', to: redirect('/')
. Jeśli ktoś spróbuje uzyskać dostęp do ścieżki/home
, zostanie natychmiast przekierowany do ścieżki głównej/
. Oczywiście nie jest to ograniczone tylko do jednej ścieżki URL; możemy również mieć coś takiego:get '/home', to: redirect('/travel')
.
przegląd
trasy Rails stoją przed aplikacją. Trasa interpretuje przychodzące żądanie HTTP i:
- dopasowuje żądanie do akcji kontrolera w oparciu o kombinację czasownika HTTP i wzorzec URL żądania
- przechwytuje dane w adresie URL, które będą dostępne w
params
w akcjach kontrolera - Rails zachęca programistów do korzystania z wzorców Url RESTful podczas konfigurowania tras, z konceptualizacją manipulowania zasobami za pomocą czasowników HTTP.
- możesz użyć makra
resources
do bardzo szybkiego generowania tras RESTful.