Rails 5 -reitityksen keittokirja: 10 reseptiä aloittelevalle Rails-kehittäjälle ja pidemmälle

Tulee muistaa, että Rails on mielipidekehys ja yksi sen perusperiaatteista on konfiguroinnin sijasta sopiminen. Tämä tarkoittaa sitä, että ellei sinulla ole erittäin hyvää syytä, sinun ei pitäisi rikkoa mitään edellä mainituista malleista ja nimeämiskäytännöistä.

Jos esimerkiksi päättäisin koodata index-toiminnon muotoon get 'cars/index' tai create-toiminnon muotoon post 'car/create', tämä rikkoisi Railsin out-of-the-box-käyttäytymisen apumetodeille, kuten form_for, link_to ja redirect_to.

Konventioiden rikkomisesta ilman tarkoitusta seuraa kaaos, ja siitä syntyy sotkuinen sotku, joka saa sinut taistelemaan kehystä vastaan tuntikausia.

Photo by Daniele Levis Pelusi on Unsplash

Singulaaristen resurssien reitit

Mahdollista on myös reitit singulaarisille resursseille, eli resursseja, joita voidaan hakea ilman :id:n määrittelyä, kuten current_user:lle tai current_account:lle sovellettavat reitit. Tämä voidaan toteuttaa käyttämällä Railsin sisäänrakennettuja singulaarisia resursseja.

resource :profile 

Sisäkkäiset reitit

Joskus on tarpeen sijoittaa resursseja toisten resurssien sisään. Jos esimerkiksi haluan luoda varauksen tietylle autotallissani olevalle autolle, voi olla kätevämpää napata kyseisen auton :id URL-osoitteesta kuin lomakkeen piilotetusta kentästä, jota pahantahtoinen käyttäjä voisi peukaloida. Tapa, jolla luomme sisäkkäisiä resursseja railsissa, on seuraava:

resources :cars do 
resources :bookings
end

Tämä luo kaikki seitsemän CRUD-toimintoa autoihin sisäkkäin sijoitetuille varauksille. Yleensä et kuitenkaan tarvitse kaikkia seitsemää reittiä. Ja vaikka tarvitsisitkin, kaikkia niistä ei varmasti tarvitse sijoittaa toisiinsa. Oletetaan, että tarvitsemme toiminnon varauksen luomiseen (oletamme, että varauksen luomiseen tarkoitettu lomake on auton show-toiminnossa) ja olemassa olevan varauksen muokkaamiseen ja päivittämiseen. Pitääkö minun tietää auton :id, jotta voin muokata/päivittää varausta? Vastaus on luonnollisesti ei. Siksi haluan, että sovellukseni vastaa seuraaviin URL-osoitteisiin:

# to CREATE a booking
POST request to http://my-ruby-garage.com/cars/:id/bookings/create# to EDIT a booking
GET request to http://my-ruby-garage.com/bookings/:id/edit# to UPDATE a booking
PATCH request to http://my-ruby-garage.com/bookings/:id/

Jotka generoidaan seuraavalla koodilla:

resources :cars do 
resources :bookings, only:
end
resources :bookings, only:

Rails antaa meidän muuttaa sitä, mitkä vakiomuotoisista CRUD-reiteistä generoidaan, antamalla symbolijoukko tai yksittäinen symboli vaihtoehtoon :only tai sen vastakohtaan :except.

Muut kuin CRUD-reitit

Emme ole rajoitettuja seitsemään CRUD-resurssireittiin. Voimme myös määritellä reittejä, jotka koskevat yhtä resurssia (jäsenreitit) tai useita resursseja (kokoelmareitit).

Jäsenreitit

Jatkamalla RubyGarage-esimerkkiämme, autot voidaan pysäköidä autotalliin tai poistaa sieltä. Kuvitellaan, että meillä on ohjaimen toimintoja, jotka pystyvät suorittamaan näitä toimintoja, jotka muuttavat tietyn auton jotakin attribuuttia.

resources :cars do 
member do
patch :park
patch :remove
end
end

Yllä olevan avulla voimme lähettää korjauspyynnöt osoitteisiin http://my-ruby-garage.com/cars/:id/park ja http://my-ruby-garage.com/cars/:id/remove ja etsiä tietyn auton ohjaimesta ennen resurssin muuttamista sen mukaisesti.

Kokoelmareitit

Samoin toisinaan halutaan suorittaa jokin toiminto useisiin resursseihin samanaikaisesti. Esimerkiksi ehkä meidän täytyy pysäköidä ja poistaa kerralla kokoelma autoja. Voimme käyttää seuraavaa koodia:

resources :cars do 
collection do
post :park, as: :bulk_park
post :remove, as: :bulk_remove
end
end

Tässä asetamme sovelluksemme vastaamaan http://my-ruby-garage.com/cars/park ja http://my-ruby-garage.com/cars/remove ja vastaavasti nimeämme nämä toiminnot bulk_park ja bulk_remove. Muista, että voimme käyttää nimettyjä polkuja URL-polkujen luomiseen sovelluksemme sisällä. Rakentaaksemme polkuyhteyden pysäköidäksemme kokoelman autoja, voisimme käyttää:

<%= link_to "Park Cars", bulk_park_path, method: :post, class: "button" %>

Nimenomaiset reitit

Nimenomaiset reitit edeltää nimiavaruuslohkon sisällä olevien resurssien URL-polkua ja yrittää paikantaa asiaankuuluvat ohjaimet sellaisen moduulin alta, jolla on sama nimi kuin nimiavaruudella. Tyypillisiä käyttökohteita tälle kuviolle ovat admin-nimiavaruudet ja api-nimiavaruudet.

namespace :factory do 
resources :cars
end

Tämä esimerkki rakentaa seuraavat reitit:

Prefix Verb URI Pattern Controller#Action factory_cars GET /factory/cars(.:format) factory/cars#index
POST /factory/cars(.:format) factory/cars#create factory_car GET /factory/cars/:id(.:format) factory/cars#show
PATCH /factory/cars/:id(.:format) factory/cars#update
PUT /factory/cars/:id(.:format) factory/cars#update
DELETE /factory/cars/:id(.:format) factory/cars#destroy

Ja myös kontrollerin pitäisi olla namespaced :

class Factory::CarsController < ApplicationController
# ...
end

Scoped Routes

Menetelmän scope avulla voimme pysyä DRY:nä ja yhdistää toisiinsa liittyvät reitityssäännöt. Kun sitä käytetään ilman optioita, se on samanlainen kuin namespace, mutta asiaankuuluvien ohjainten ei tarvitse olla moduulin nimitilassa.

scope :factory do 
resources :cars
end

Generoi seuraavat reitit:

Prefix Verb URI Pattern Controller#Action factory_cars GET /factory/cars(.:format) cars#index
POST /factory/cars(.:format) cars#create factory_car GET /factory/cars/:id(.:format) cars#show
PATCH /factory/cars/:id(.:format) cars#update
PUT /factory/cars/:id(.:format) cars#update
DELETE /factory/cars/:id(.:format) cars#destroy

Scope tukee kolmea optiota: moduuli, polku ja as.

Esitettäköön, että meillä on monivaiheinen ohjattu ohjattu toiminto, jonka avulla luodaan uusi auto tehtaalle ja jota käsittelee ohjain, joka asuu ohjattujen ohjainten moduulissa. Haluamme, että polku näkyy selaimessa muodossa http://my-ruby-garage.com/create-a-car ja että voimme viitata tähän reittiin sovelluksemme sisällä muodossa create_car. On olemassa moduuli Wizard::Car, joka tuntee ohjatun toiminnon jokaisen vaiheen.

scope module: 'wizards', path: 'create-a-car', as: 'create_car' do
Wizard::Car::STEPS.each do |step|
get step, to: "cars##{step}"
end
post :validate-step, to: 'cars#validate_step'
end

Yllä oleva koodi luo saman kuvion jokaiselle vaiheelle. Esimerkiksi askel1 on saatavilla selaimessa URL-osoitteen http://my-ruby-garage.com/create-a-car/step1 kautta, sitä vastaava lomake lähettää post-pyynnön osoitteeseen http://my-ruby-garage.com/create-a-car/validate-step, ja polku voidaan kutsua kutsumalla create_car_step1_path.

Reitin uudelleenohjaukset

Rails antaa meidän myös tehdä uudelleenohjauksia suoraan routes.rb:ssa. Edellisessä esimerkissä haluan ehkä, että kaikki, jotka laskeutuvat kohtaan http://my-ruby-garage.com/create-a-car, ohjataan automaattisesti ensimmäiseen vaiheeseen. Tämä voidaan toteuttaa seuraavalla koodilla:

get 'create-a-car', 
to: redirect("/create-a-car/#{Wizard::SpotAccount::STEPS.first}")

Reitin oletusarvot

Voidaan määritellä oletusarvoparametreja reitissä välittämällä :defaults-vaihtoehdolle hash.

resources :cars do
collection do
get :export, defaults: { format: 'csv' }
end
end

Käymällä tällä tavalla vieraileva http://my-ruby-garage.com/cars/export kutsuu autojen ohjaimessa olevaa export-toimintoa ja vastaava ohjaimen toiminto vastaa oletusarvoisesti csv:llä.

Route Globbing

Käyttämällä jokerimerkkisegmenttejä (fragmentteja, joiden etuliitteenä on tähti) voimme määrittää, että reitin loput osat on sovitettava tiettyyn parametriin. Tätä kutsutaan route globbingiksi.

get '/rent/*slugs', to: 'cars#index', as: :rent_cars

Tämä reitti vastaisi http://my-ruby-garage.com/rent/lisbon/suv-sedan ja asettaisi parametriksi ”lisbon/suv-sedan”. Tätä voitaisiin sitten käyttää haku- tai suodatusjärjestelmässä tietokantaamme vastaan löytääkseen Lissabonissa olevia autoja, jotka ovat tyyppiä suv tai sedan.

Kirjoitan gem Slugcatcheria tätä toiminnallisuutta silmällä pitäen, jotta voidaan merkitä Railsin mallit, joita voidaan hakea reitin sluggina.

Vastaa

Sähköpostiosoitettasi ei julkaista.