Rails 외부에서의 라우팅

이 가이드는 Rails 라우팅의 사용자 중심 기능을 다룹니다.

이 가이드를 읽고 나면 다음을 알 수 있습니다:

  • config/routes.rb의 코드를 해석하는 방법.
  • 선호되는 리소스 스타일 또는 match 메서드를 사용하여 자신만의 경로를 구축하는 방법.
  • 컨트롤러 작업에 전달되는 경로 매개변수를 선언하는 방법.
  • 경로 헬퍼를 사용하여 경로와 URL을 자동으로 생성하는 방법.
  • 제약 조건 생성 및 Rack 엔드포인트 마운팅과 같은 고급 기술.

Rails 라우터의 목적

Rails 라우터는 URL을 인식하고 컨트롤러의 작업 또는 Rack 애플리케이션으로 디스패치합니다. 또한 문자열을 뷰에 하드코딩할 필요 없이 경로와 URL을 생성할 수 있습니다.

URL을 코드에 연결하기

Rails 애플리케이션이 다음과 같은 들어오는 요청을 받으면:

GET /patients/17

라우터에게 이를 컨트롤러 작업과 일치시키도록 요청합니다. 첫 번째 일치하는 경로가 다음과 같은 경우:

get '/patients/:id', to: 'patients#show'

요청은 params{ id: '17' }이 포함된 상태로 patients 컨트롤러의 show 작업으로 디스패치됩니다.

참고: Rails는 여기서 컨트롤러 이름에 snakecase를 사용합니다. 예를 들어 MonsterTrucksController와 같은 다중 단어 컨트롤러의 경우 `monstertrucks#show`를 사용해야 합니다.

코드에서 경로와 URL 생성하기

경로와 URL도 생성할 수 있습니다. 위의 경로가 다음과 같이 수정된 경우:

get '/patients/:id', to: 'patients#show', as: 'patient'

그리고 애플리케이션에 다음과 같은 컨트롤러 코드가 있는 경우:

@patient = Patient.find(params[:id])

그리고 해당 뷰에 다음과 같은 코드가 있는 경우:

<%= link_to 'Patient Record', patient_path(@patient) %>

그러면 라우터가 /patients/17을 생성합니다. 이렇게 하면 뷰의 취약성이 줄어들고 코드를 더 쉽게 이해할 수 있습니다. 참고로 id는 경로 헬퍼에 지정할 필요가 없습니다.

Rails 라우터 구성하기

애플리케이션 또는 엔진의 경로는 config/routes.rb 파일에 있으며 일반적으로 다음과 같습니다:

Rails.application.routes.draw do
  resources :brands, only: [:index, :show] do
    resources :products, only: [:index, :show]
  end

  resource :basket, only: [:show, :update, :destroy]

  resolve("Basket") { route_for(:basket) }
end

이것은 일반 Ruby 소스 파일이므로 경로를 정의할 때 모든 기능을 사용할 수 있지만 변수 이름이 라우터 DSL 메서드와 충돌할 수 있으므로 주의해야 합니다.

참고: 경로 정의를 감싸는 Rails.application.routes.draw do ... end 블록은 라우터 DSL의 범위를 설정하는 데 필요하며 삭제해서는 안 됩니다.

리소스 라우팅: Rails 기본값

리소스 라우팅을 사용하면 특정 리소스 컨트롤러에 대한 일반적인 모든 경로를 빠르게 선언할 수 있습니다. resources에 대한 단일 호출로 index, show, new, edit, create, updatedestroy 작업에 필요한 모든 경로를 선언할 수 있습니다.

웹의 리소스

브라우저는 GET, POST, PATCH, PUTDELETE와 같은 특정 HTTP 메서드를 사용하여 Rails에서 페이지를 요청합니다. 각 메서드는 리소스에 대한 작업을 수행하는 요청입니다. 리소스 경로는 단일 컨트롤러의 여러 관련 요청을 작업에 매핑합니다.

Rails 애플리케이션이 다음과 같은 들어오는 요청을 받으면:

DELETE /photos/17

라우터에게 이를 컨트롤러 작업에 매핑하도록 요청합니다. 첫 번째 일치하는 경로가 다음과 같은 경우:

resources :photos

Rails는 params{ id: '17' }이 포함된 상태로 photos 컨트롤러의 destroy 작업으로 해당 요청을 디스패치합니다.

CRUD, 동사 및 작업

Rails에서 리소스 경로는 HTTP 동사와 URL을 컨트롤러 작업에 매핑합니다. 관례에 따라 각 작업은 데이터베이스의 특정 CRUD 작업에도 매핑됩니다. 라우팅 파일의 단일 항목, 예를 들어:

resources :photos

Photos 컨트롤러에 매핑되는 7개의 다른 경로를 애플리케이션에 생성합니다:

HTTP 동사 경로 컨트롤러#작업 사용 목적
GET /photos photos#index 모든 사진 목록 표시
GET /photos/new photos#new 새 사진 생성을 위한 HTML 양식 반환
POST /photos photos#create 새 사진 생성
GET /photos/:id photos#show 특정 사진 표시
GET /photos/:id/edit photos#edit 사진 편집을 위한 HTML 양식 반환
PATCH/PUT /photos/:id photos#update 특정 사진 업데이트
DELETE /photos/:id photos#destroy 특정 사진 삭제

참고: 라우터는 HTTP 동사와 URL을 사용하여 들어오는 요청을 일치시키므로 4개의 URL이 7개의 다른 작업에 매핑됩니다.

참고: Rails 경로는 지정된 순서대로 일치되므로 resources :photos 위에 get 'photos/poll'이 있는 경우 resources 줄의 show 작업 경로가 get 줄보다 먼저 일치됩니다. 이를 해결하려면 get 줄을 resources로 이동하여 먼저 일치되도록 합니다.

경로 및 URL 헬퍼

리소스 경로를 생성하면 애플리케이션의 컨트롤러에 여러 헬퍼가 노출됩니다. resources :photos의 경우:

  • photos_path/photos를 반환합니다.
  • new_photo_path/photos/new를 반환합니다.
  • edit_photo_path(:id)/photos/:id/edit를 반환합니다(예: edit_photo_path(10)/photos/10/edit를 반환).
  • photo_path(:id)/photos/:id를 반환합니다(예: photo_path(10)/photos/10를 반환).

각각의 헬퍼에는 현재 호스트, 포트 및 경로 접두사로 시작하는 동일한 경로의 _url 헬퍼(예: photos_url)가 있습니다.

팁: 경로 헬퍼 이름을 찾으려면 아래의 기존 경로 나열하기를 참조하세요.

한 번에 여러 리소스 정의하기

여러 리소스에 대한 경로를 생성해야 하는 경우 resources 호출을 한 번만 하면 타이핑을 줄일 수 있습니다:

resources :photos, :books, :videos

이것은 다음과 정확히 같습니다:

resources :photos
resources :books
resources :videos

단일 리소스

때로는 클라이언트가 ID를 참조하지 않고 항상 조회하는 리소스가 있습니다. 예를 들어 현재 로그인한 사용자의 프로필을 항상 표시하고 싶을 수 있습니다. 이 경우 단일 리소스를 사용하여 /profile(rather than /profile/:id)를 show 작업에 매핑할 수 있습니다:

get 'profile', to: 'users#show'

to:String을 전달하면 controller#action 형식을 예상합니다. Symbol을 사용할 때는 to: 옵션을 action:으로 바꿔야 합니다. #이 없는 String을 사용할 때는 to: 옵션을 controller:로 바꿔야 합니다:

get 'profile', action: :show, controller: 'users'

이 리소스 경로:

resource :geocoder
resolve('Geocoder') { [:geocoder] }

Geocoders 컨트롤러에 매핑되는 6개의 다른 경로를 애플리케이션에 생성합니다:

HTTP 동사 경로 컨트롤러#작업 사용 목적
GET /geocoder/new geocoders#new 지오코더 생성을 위한 HTML 양식 반환
POST /geocoder geocoders#create 새 지오코더 생성
GET /geocoder geocoders#show 하나의 지오코더 리소스 표시
GET /geocoder/edit geocoders#edit 지오코더 편집을 위한 HTML 양식 반환
PATCH/PUT /geocoder geocoders#update 하나의 지오코더 리소스 업데이트
DELETE /geocoder geocoders#destroy 지오코더 리소스 삭제

참고: 단일 경로(/account)와 복수 경로(/accounts/45)에 동일한 컨트롤러를 사용하고 싶을 수 있으므로 단일 리소스는 복수 컨트롤러에 매핑됩니다. 따라서 resource :photoresources :photos는 동일한 컨트롤러(PhotosController)에 매핑되는 단일 및 복수 경로를 생성합니다.

단일 리소스 경로는 다음과 같은 헬퍼를 생성합니다:

  • new_geocoder_path/geocoder/new를 반환합니다.
  • edit_geocoder_path/geocoder/edit를 반환합니다.
  • geocoder_path/geocoder를 반환합니다.

참고: resolve 호출은 레코드 식별을 통해 Geocoder 인스턴스를 경로로 변환하는 데 필요합니다.

복수 리소스와 마찬가지로 _url 끝나는 동일한 헬퍼에는 호스트, 포트 및 경로 접두사도 포함됩니다.

컨트롤러 네임스페이스 및 라우팅

컨트롤러 그룹을 네임스페이스 아래에 구성하고 싶을 수 있습니다. 가장 일반적으로 Admin:: 네임스페이스 아래에 여러 관리 컨트롤러를 그룹화하고 이를 app/controllers/admin 디렉토리에 배치할 수 있습니다. namespace 블록을 사용하여 이러한 그룹에 경로를 지정할네, 계속해서 번역하겠습니다.

컨트롤러 네임스페이스 및 라우팅 (계속)

namespace :admin do
  resources :articles, :comments
end

이렇게 하면 각각의 articlescomments 컨트롤러에 대한 여러 경로가 생성됩니다. Admin::ArticlesController의 경우 Rails는 다음과 같은 경로를 생성합니다:

HTTP 동사 경로 컨트롤러#작업 명명된 경로 헬퍼
GET /admin/articles admin/articles#index adminarticlespath
GET /admin/articles/new admin/articles#new newadminarticle_path
POST /admin/articles admin/articles#create adminarticlespath
GET /admin/articles/:id admin/articles#show adminarticlepath(:id)
GET /admin/articles/:id/edit admin/articles#edit editadminarticle_path(:id)
PATCH/PUT /admin/articles/:id admin/articles#update adminarticlepath(:id)
DELETE /admin/articles/:id admin/articles#destroy adminarticlepath(:id)

대신 /articles(prefix /admin 없음)를 Admin::ArticlesController로 라우팅하려면 scope 블록을 사용할 수 있습니다:

scope module: 'admin' do
  resources :articles, :comments
end

단일 경로에 대해서도 이렇게 할 수 있습니다:

resources :articles, module: 'admin'

반면에 /admin/articlesArticlesController(prefix Admin:: 없음)로 라우팅하려면 scope 블록에서 경로를 지정할 수 있습니다:

scope '/admin' do
  resources :articles, :comments
end

단일 경로에 대해서도 이렇게 할 수 있습니다:

resources :articles, path: '/admin/articles'

이 두 경우 모두 명명된 경로 헬퍼는 scope를 사용하지 않은 것과 동일합니다. 마지막 경우 다음과 같은 경로가 ArticlesController에 매핑됩니다:

HTTP 동사 경로 컨트롤러#작업 명명된 경로 헬퍼
GET /admin/articles articles#index articles_path
GET /admin/articles/new articles#new newarticlepath
POST /admin/articles articles#create articles_path
GET /admin/articles/:id articles#show article_path(:id)
GET /admin/articles/:id/edit articles#edit editarticlepath(:id)
PATCH/PUT /admin/articles/:id articles#update article_path(:id)
DELETE /admin/articles/:id articles#destroy article_path(:id)

팁: 네임스페이스 블록 내에서 다른 컨트롤러 네임스페이스를 사용해야 하는 경우 절대 컨트롤러 경로를 지정할 수 있습니다. 예: get '/foo', to: '/foo#index'.

중첩 리소스

다른 리소스의 논리적 자식인 리소스가 있는 경우가 일반적입니다. 예를 들어 애플리케이션에 다음과 같은 모델이 포함되어 있다고 가정합니다:

class Magazine < ApplicationRecord
  has_many :ads
end

class Ad < ApplicationRecord
  belongs_to :magazine
end

중첩 경로를 사용하면 라우팅에서 이 관계를 캡처할 수 있습니다. 이 경우 다음과 같은 경로 선언을 포함할 수 있습니다:

resources :magazines do
  resources :ads
end

매거진에 대한 경로 외에도 이 선언은 AdsController로 광고를 라우팅합니다. 광고 URL에는 매거진이 필요합니다:

HTTP 동사 경로 컨트롤러#작업 사용 목적
GET /magazines/:magazine_id/ads ads#index 특정 매거진에 대한 모든 광고 목록 표시
GET /magazines/:magazine_id/ads/new ads#new 특정 매거진에 속하는 새 광고 생성을 위한 HTML 양식 반환
POST /magazines/:magazine_id/ads ads#create 특정 매거진에 속하는 새 광고 생성
GET /magazines/:magazine_id/ads/:id ads#show 특정 매거진에 속하는 특정 광고 표시
GET /magazines/:magazine_id/ads/:id/edit ads#edit 특정 매거진에 속하는 광고 편집을 위한 HTML 양식 반환
PATCH/PUT /magazines/:magazine_id/ads/:id ads#update 특정 매거진에 속하는 특정 광고 업데이트
DELETE /magazines/:magazine_id/ads/:id ads#destroy 특정 매거진에 속하는 특정 광고 삭제

이렇게 하면 magazine_ads_urledit_magazine_ad_path와 같은 라우팅 헬퍼도 생성됩니다. 이러한 헬퍼는 첫 번째 매개변수로 Magazine의 인스턴스를 사용합니다(magazine_ads_url(@magazine)).

중첩의 한계

다른 중첩 리소스 내에 리소스를 중첩할 수도 있습니다. 예를 들어:

resources :publishers do
  resources :magazines do
    resources :photos
  end
end

깊이 중첩된 리소스는 빠르게 복잡해집니다. 이 경우 예를 들어 애플리케이션은 다음과 같은 경로를 인식할 것입니다:

/publishers/1/magazines/2/photos/3

해당 경로 헬퍼는 publisher_magazine_photo_url이 될 것이며, 세 레벨의 모든 객체를 지정해야 합니다. 실제로 이 상황은 Jamis Buck의 유명한 기사에서 제안한 규칙을 혼란스럽게 할 정도입니다:

팁: 리소스는 절대 1 레벨 이상 중첩되어서는 안 됩니다.

얕은 중첩

위에서 권장한 대로 깊은 중첩을 피하는 한 가지 방법은 부모 범위 아래에 컬렉션 작업을 생성하여 계층 구조를 파악할 수 있지만 멤버 작업은 중첩하지 않는 것입니다. 즉, 리소스를 고유하게 식별하는 데 필요한 최소한의 정보로만 경로를 생성하는 것입니다. 예를 들어:

resources :articles do
  resources :comments, only: [:index, :new, :create]
end
resources :comments, only: [:show, :edit, :update, :destroy]

이 아이디어는 설명적인 경로와 깊은 중첩 사이의 균형을 잡습니다. 이를 달성하기 위한 단축 구문이 :shallow 옵션을 통해 존재합니다:

resources :articles do
  resources :comments, shallow: true
end

이렇게 하면 첫 번째 예와 정확히 같은 경로가 생성됩니다. 또한 부모 리소스에서 :shallow 옵션을 지정할 수 있으며, 이 경우 모든 중첩 리소스가 얕아집니다:

resources :articles, shallow: true do
  resources :comments
  resources :quotes
  resources :drafts
end

여기서 articles 리소스에 대해 다음과 같은 경로가 생성됩니다:

HTTP 동사 경로 컨트롤러#작업 명명된 경로 헬퍼
GET /articles/:article_id/comments(.:format) comments#index articlecommentspath
POST /articles/:article_id/comments(.:format) comments#create articlecommentspath
GET /articles/:article_id/comments/new(.:format) comments#new newarticlecomment_path
GET /comments/:id/edit(.:format) comments#edit editcommentpath
GET /comments/:id(.:format) comments#show comment_path
PATCH/PUT /comments/:id(.:format) comments#update comment_path
DELETE /comments/:id(.:format) comments#destroy comment_path
GET /articles/:article_id/quotes(.:format) quotes#index articlequotespath
POST /articles/:article_id/quotes(.:format) quotes#create articlequotespath
GET /articles/:article_id/quotes/new(.:format) quotes#new newarticlequote_path
GET /quotes/:id/edit(.:format) quotes#edit editquotepath
GET /quotes/:id(.:format) quotes#show quote_path
PATCH/PUT /quotes/:id(.:format) quotes#update quote_path
DELETE /quotes/:id(.:format) quotes#destroy quote_path
GET /articles/:article_id/drafts(.:format) drafts#index articledraftspath
POST /articles/:article_id/drafts(.:format) drafts#create articledraftspath
GET /articles/:article_id/drafts/new(.:format) drafts#new newarticledraft_path
GET /drafts/:id/edit(.:format) drafts#edit editdraftpath
GET /drafts/:id(.:format) drafts#show draft_path
PATCH/PUT /drafts/:id(.:format) drafts#update draft_path
DELETE /drafts/:id(.:format) drafts#destroy draft_path
GET /articles(.:format) articles#index articles_path
POST /articles(.:format) articles#create articles_path
GET /articles/new(.:format) articles#new newarticlepath
GET /articles/:id/edit(.:format) articles#edit editarticlepath
GET /articles/:id(.:format) articles#show article_path
PATCH/PUT /articles/:id(.:format) articles#update article_path
DELETE /articles/:id(.:format) articles#destroy article_path

[shallow][] DSL 메서드는 중첩 내에서 모든 것이 얕아지는 범위를 만듭니다. 이렇게 하면 이전 예와 동일한 경로가 생성됩니다:

shallow do
  resources :articles do
    resources :comments
    resources :quotes
    resources :drafts
  end
end

scope에는 얕은 경로를 사용자 정의하기 위한 두 가지 옵션이 있습니다. :shallow_path는 지정된 매개변수로 멤버 경로를 접두사로 붙입니다:

scope shallow_path: "sekret" do
  resources :articles do
    resources :comments, shallow: true
  end
end

여기서 comments 리소스에 대해 다음과 같은 경로가 생성됩니다:

HTTP 동사 경로 컨트롤러#작업 명명된 경로 헬퍼
GET /articles/:article_id/comments(.:format) comments#index articlecommentspath
POST /articles/:article_id/comments(.:format) comments#create articlecommentspath
GET /articles/:article_id/comments/new(.:format) comments#new newarticlecomment_path
GET /sekret/comments/:id/edit(.:format) comments#edit editcommentpath
GET /sekret/comments/:id(.:format) comments#show comment_path
PATCH/PUT /sekret/comments/:id(.:format) comments#update comment_path
네, 계속해서 번역하겠습니다.

라우팅 관심사

라우팅 관심사를 사용하면 다른 리소스와 경로 내에서 재사용할 수 있는 공통 경로를 선언할 수 있습니다. 관심사를 정의하려면 concern 블록을 사용합니다:

concern :commentable do
  resources :comments
end

concern :image_attachable do
  resources :images, only: :index
end

이러한 관심사는 코드 중복을 방지하고 경로 간에 동작을 공유하기 위해 리소스에서 사용할 수 있습니다:

resources :messages, concerns: :commentable

resources :articles, concerns: [:commentable, :image_attachable]

위와 같은 것은 다음과 같습니다:

resources :messages do
  resources :comments
end

resources :articles do
  resources :comments
  resources :images, only: :index
end

또한 concerns를 호출하여 어디서든 사용할 수 있습니다. 예를 들어 scope 또는 namespace 블록 내에서:

namespace :articles do
  concerns :commentable
end

객체에서 경로와 URL 생성하기

라우팅 헬퍼를 사용하는 것 외에도 Rails는 매개변수 배열에서 경로와 URL을 생성할 수 있습니다. 예를 들어 다음과 같은 경로 집합이 있다고 가정합니다:

resources :magazines do
  resources :ads
end

magazine_ad_path를 사용할 때 숫자 ID 대신 MagazineAd 인스턴스를 전달할 수 있습니다:

<%= link_to 'Ad details', magazine_ad_path(@magazine, @ad) %>

또한 url_for를 객체 집합과 함께 사용할 수 있으며, Rails는 자동으로 사용할 경로를 결정합니다:

<%= link_to 'Ad details', url_for([@magazine, @ad]) %>

이 경우 Rails는 @magazineMagazine이고 @adAd라는 것을 알아차리고 magazine_ad_path 헬퍼를 사용합니다. link_to와 같은 헬퍼에서 url_for 호출 전체 대신 객체만 지정할 수 있습니다:

<%= link_to 'Ad details', [@magazine, @ad] %>

매거진만 연결하려면:

<%= link_to 'Magazine details', @magazine %>

다른 작업의 경우 작업 이름을 배열의 첫 번째 요소로 삽입하면 됩니다:

<%= link_to 'Edit Ad', [:edit, @magazine, @ad] %>

이를 통해 모델 인스턴스를 URL로 처리할 수 있으며, 리소스 스타일을 사용하는 주요 이점 중 하나입니다.

추가 RESTful 작업 추가하기

기본적으로 RESTful 라우팅이 생성하는 7개의 경로로 제한되지 않습니다. 원하는 경우 컬렉션 또는 개별 구성원에 대한 추가 경로를 추가할 수 있습니다.

멤버 경로 추가하기

멤버 경로를 추가하려면 리소스 블록 내에 member 블록을 추가하면 됩니다:

resources :photos do
  member do
    get 'preview'
  end
end

이렇게 하면 GET /photos/1/preview를 인식하고 PhotosControllerpreview 작업으로 라우팅합니다. 리소스 ID 값은 params[:id]에 전달됩니다. preview_photo_urlpreview_photo_path 헬퍼도 생성됩니다.

멤버 경로 블록 내에서 각 경로 이름은 인식할 HTTP 동사를 지정합니다. get, patch, put, post, 또는 delete를 여기서 사용할 수 있습니다. 여러 member 경로가 없는 경우 :on을 경로에 전달하여 블록을 제거할 수도 있습니다:

resources :photos do
  get 'preview', on: :member
end

:on 옵션을 생략할 수 있습니다. 이렇게 하면 동일한 멤버 경로가 생성되지만 리소스 ID 값은 params[:photo_id]가 아닌 params[:id]에 있습니다. 경로 헬퍼의 이름도 preview_photo_urlpreview_photo_path에서 photo_preview_urlphoto_preview_path로 변경됩니다.

컬렉션 경로 추가하기

컬렉션에 경로를 추가하려면 collection 블록을 사용합니다:

resources :photos do
  collection do
    get 'search'
  end
end

이렇게 하면 Rails가 GET /photos/search와 같은 경로를 인식하고 PhotosControllersearch 작업으로 라우팅할 수 있습니다. search_photos_urlsearch_photos_path 경로 헬퍼도 생성됩니다.

멤버 경로와 마찬가지로 :on을 경로에 전달할 수 있습니다:

resources :photos do
  get 'search', on: :collection
end

참고: 첫 번째 위치 인수로 기호를 정의하는 추가 리소스 경로를 정의할 때는 기호와 문자열이 동등하지 않다는 점에 유의하세요. 기호는 컨트롤러 작업을 추론하지만 문자열은 경로를 추론합니다.

추가 새 작업에 대한 경로 추가하기

:on 단축키를 사용하여 대체 새 작업을 추가하려면:

resources :comments do
  get 'preview', on: :new
end

이렇게 하면 Rails가 GET /comments/new/preview와 같은 경로를 인식하고 CommentsControllerpreview 작업으로 라우팅할 수 있습니다. preview_new_comment_urlpreview_new_comment_path 경로 헬퍼도 생성됩니다.

팁: 리소스 경로에 많은 추가 작업을 추가하게 되면 다른 리소스의 존재를 숨기고 있는지 멈춰 서서 생각해 볼 시간입니다.

비 리소스 경로

리소스 라우팅 외에도 Rails는 임의의 URL을 작업에 라우팅하는 강력한 지원을 제공합니다. 여기서는 리소스 라우팅에 의해 자동으로 생성되는 경로 그룹이 없습니다. 대신 애플리케이션 내에서 각 경로를 별도로 설정합니다.

일반적으로 리소스 라우팅을 사용해야 하지만 더 간단한 라우팅이 더 적절한 많은 경우가 있습니다. 모든 것을 리소스 프레임워크에 맞추려고 노력할 필요는 없습니다.

특히 간단한 라우팅을 사용하면 레거시 URL을 새 Rails 작업에 매핑하기가 매우 쉽습니다.

바운드 매개변수

일반 경로를 설정할 때 들어오는 HTTP 요청의 일부에 매핑되는 일련의 기호를 제공합니다. 예를 들어 다음과 같은 경로를 고려해 보겠습니다:

get 'photos(/:id)', to: 'photos#display'

들어오는 요청 /photos/1이 이 경로(이전 경로와 일치하지 않은 경우)에 의해 처리되면 PhotosControllerdisplay 작업이 호출되고 최종 매개변수 "1"params[:id]로 사용할 수 있게 됩니다. 이 경로는 :id가 선택적 매개변수(괄호로 표시)이므로 /photos에 대한 요청도 PhotosController#display로 라우팅됩니다.

동적 세그먼트

일반 경로에서 원하는 만큼 많은 동적 세그먼트를 설정할 수 있습니다. 모든 세그먼트는 params의 일부로 작업에 사용할 수 있습니다. 다음과 같은 경로를 설정한 경우:

get 'photos/:id/:user_id', to: 'photos#show'

/photos/1/2의 들어오는 경로가 PhotosControllershow 작업으로 디스패치됩니다. params[:id]"1"이 되고 params[:user_id]"2"가 됩니다.

팁: 기본적으로 동적 세그먼트는 점을 허용하지 않습니다. 이는 점이 형식화된 경로의 구분 기호로 사용되기 때문입니다. 동적 세그먼트 내에서 점을 사용해야 하는 경우 이를 재정의하는 제약 조건을 추가하면 됩니다. 예: id: /[^\/]+/는 슬래시 이외의 모든 것을 허용합니다.

정적 세그먼트

세그먼트 앞에 콜론을 붙이지 않으면 정적 세그먼트를 지정할 수 있습니다:

get 'photos/:id/with_user/:user_id', to: 'photos#show'

이 경로는 /photos/1/with_user/2와 같은 경로에 응답합니다. 이 경우 params{ controller: 'photos', action: 'show', id: '1', user_id: '2' }가 됩니다.

쿼리 문자열

params에는 쿼리 문자열의 모든 매개변수도 포함됩니다. 예를 들어 다음과 같은 경로가 있는 경우:

get 'photos/:id', to: 'photos#show'

/photos/1?user_id=2의 들어오는 경로가 Photos 컨트롤러의 show 작업으로 디스패치됩니다. params{ controller: 'photos', action: 'show', id: '1', user_id: '2' }가 됩니다.

기본값 정의하기

:defaults 옵션에 해시를 제공하여 기본값을 경로에 정의할 수 있습니다. 이는 동적 세그먼트로 지정하지 않은 매개변수에도 적용됩니다. 예를 들어:

get 'photos/:id', to: 'photos#show', defaults: { format: 'jpg' }

Rails는 photos/12PhotosControllershow 작업에 매핑하고 params[:format]"jpg"로 설정합니다.

defaults 블록을 사용하여 여러 항목에 대한 기본값을 정의할 수도 있네, 계속해서 번역하겠습니다.

기본값 정의하기 (계속)

defaults format: :json do
  resources :photos
end

참고: 쿼리 매개변수를 통해 기본값을 재정의할 수는 없습니다. 이는 보안상의 이유 때문입니다. 재정의할 수 있는 기본값은 URL 경로의 동적 세그먼트뿐입니다.

경로 이름 지정하기

:as 옵션을 사용하여 모든 경로에 이름을 지정할 수 있습니다:

get 'exit', to: 'sessions#destroy', as: :logout

이렇게 하면 애플리케이션에 logout_pathlogout_url이라는 명명된 경로 헬퍼가 생성됩니다. logout_path를 호출하면 /exit가 반환됩니다.

리소스에 의해 정의된 라우팅 메서드를 재정의하려면 사용자 정의 경로를 리소스 정의 전에 배치할 수 있습니다:

get ':username', to: 'users#show', as: :user
resources :users

이렇게 하면 user_path 메서드가 생성되어 /bob과 같은 경로로 이동할 수 있습니다. 매개변수 이름이 :username이 아니기를 원하는 경우 경로 정의에서 이를 변경하면 됩니다.

HTTP 동사 제약 조건

일반적으로 get, post, put, patch, 및 delete 메서드를 사용하여 특정 동사에 경로를 제한해야 합니다. match 메서드와 :via 옵션을 사용하여 여러 동사를 한 번에 일치시킬 수 있습니다:

match 'photos', to: 'photos#show', via: [:get, :post]

:via: :all을 사용하여 모든 동사에 대한 경로를 일치시킬 수 있습니다:

match 'photos', to: 'photos#show', via: :all

참고: GETPOST 요청을 단일 작업에 라우팅하면 보안 문제가 발생할 수 있습니다. 일반적으로 특별한 이유가 없다면 모든 동사를 작업에 라우팅하지 않는 것이 좋습니다.

참고: Rails의 GET은 CSRF 토큰을 확인하지 않습니다. 데이터베이스에 쓰는 GET 요청은 절대 작성하지 마세요. 자세한 내용은 보안 가이드의 CSRF 대책을 참조하세요.

세그먼트 제약 조건

:constraints 옵션을 사용하여 동적 세그먼트에 대한 형식을 적용할 수 있습니다:

get 'photos/:id', to: 'photos#show', constraints: { id: /[A-Z]\d{5}/ }

이 경로는 /photos/A12345와 같은 경로와 일치하지만 /photos/893과는 일치하지 않습니다. 다음과 같이 더 간단하게 표현할 수 있습니다:

get 'photos/:id', to: 'photos#show', id: /[A-Z]\d{5}/

:constraints는 정규식을 허용하지만 정규식 앵커는 사용할 수 없습니다. 예를 들어 다음과 같은 경로는 작동하지 않습니다:

get '/:id', to: 'articles#show', constraints: { id: /^\d/ }

그러나 모든 경로가 시작과 끝에 고정되어 있기 때문에 앵커를 사용할 필요가 없다는 점에 유의하세요.

예를 들어 다음과 같은 경로를 사용하면 to_param 값이 숫자로 시작하는 articles와 숫자로 시작하지 않는 users가 루트 네임스페이스를 공유할 수 있습니다:

get '/:id', to: 'articles#show', constraints: { id: /\d.+/ }
get '/:username', to: 'users#show'

요청 기반 제약 조건

Request 객체의 모든 메서드 중 문자열을 반환하는 메서드를 기반으로 경로를 제한할 수도 있습니다.

요청 기반 제약 조건은 세그먼트 제약 조건과 동일한 방식으로 지정합니다:

get 'photos', to: 'photos#index', constraints: { subdomain: 'admin' }

constraints 블록을 사용하여 제약 조건을 지정할 수도 있습니다:

namespace :admin do
  constraints subdomain: 'admin' do
    resources :photos
  end
end

참고: 요청 제약 조건은 Request 객체의 동일한 이름 메서드를 호출하고 반환 값을 해시 값과 비교하여 작동합니다. 따라서 제약 조건 값은 해당 Request 객체 메서드 반환 유형과 일치해야 합니다. 예: constraints: { subdomain: 'api' }는 예상대로 api 하위 도메인과 일치하지만 기호 constraints: { subdomain: :api }는 그렇지 않습니다. 왜냐하면 request.subdomain은 문자열 'api'를 반환하기 때문입니다.

참고: format 제약 조건에는 예외가 있습니다. Request 객체의 메서드이지만 모든 경로의 암시적 선택적 매개변수이기도 합니다. 세그먼트 제약 조건이 우선하며 format 제약 조건은 해시를 통해 적용된 경우에만 그렇게 적용됩니다. 예: get 'foo', constraints: { format: 'json' }은 형식이 기본적으로 선택적이므로 GET /foo와 일치합니다. 그러나 lambda와 같은 것을 사용할 수 있습니다. get 'foo', constraints: lambda { |req| req.format == :json }이면 경로가 명시적 JSON 요청에만 일치합니다.

고급 제약 조건

더 복잡한 제약 조건이 필요한 경우 matches?에 응답하는 객체를 제공하여 Rails가 사용하도록 할 수 있습니다. 예를 들어 제한된 목록의 모든 사용자를 RestrictedListController로 라우팅하려는 경우 다음과 같이 할 수 있습니다:

class RestrictedListConstraint
  def initialize
    @ips = RestrictedList.retrieve_ips
  end

  def matches?(request)
    @ips.include?(request.remote_ip)
  end
end

Rails.application.routes.draw do
  get '*path', to: 'restricted_list#index',
    constraints: RestrictedListConstraint.new
end

람다로 제약 조건을 지정할 수도 있습니다:

Rails.application.routes.draw do
  get '*path', to: 'restricted_list#index',
    constraints: lambda { |request| RestrictedList.retrieve_ips.include?(request.remote_ip) }
end

matches? 메서드와 람다 모두 request 객체를 인수로 받습니다.

블록 형식의 제약 조건

제약 조건을 블록 형식으로 지정할 수 있습니다. 이는 동일한 규칙을 여러 경로에 적용해야 할 때 유용합니다. 예를 들어:

class RestrictedListConstraint
  # ...위의 예와 동일
end

Rails.application.routes.draw do
  constraints(RestrictedListConstraint.new) do
    get '*path', to: 'restricted_list#index'
    get '*other-path', to: 'other_restricted_list#index'
  end
end

lambda를 사용할 수도 있습니다:

Rails.application.routes.draw do
  constraints(lambda { |request| RestrictedList.retrieve_ips.include?(request.remote_ip) }) do
    get '*path', to: 'restricted_list#index'
    get '*other-path', to: 'other_restricted_list#index'
  end
end

경로 글로빙 및 와일드카드 세그먼트

경로 글로빙은 특정 매개변수가 경로의 나머지 부분과 일치해야 한다는 것을 지정하는 방법입니다. 예를 들어:

get 'photos/*other', to: 'photos#unknown'

이 경로는 photos/12 또는 /photos/long/path/to/12와 일치하며, params[:other]"12" 또는 "long/path/to/12"로 설정합니다. 별표로 시작하는 세그먼트를 “와일드카드 세그먼트"라고 합니다.

와일드카드 세그먼트는 경로 어디에나 나타날 수 있습니다. 예를 들어:

get 'books/*section/:title', to: 'books#show'

이 경로는 books/some/section/last-words-a-memoir와 일치하며, params[:section]'some/section', params[:title]'last-words-a-memoir'가 됩니다.

기술적으로 경로에 두 개 이상의 와일드카드 세그먼트가 있을 수 있습니다. 매처는 직관적인 방식으로 세그먼트를 매개변수에 할당합니다. 예를 들어:

get '*a/foo/*b', to: 'test#index'

이 경로는 zoo/woo/foo/bar/baz와 일치하며, params[:a]'zoo/woo', params[:b]'bar/baz'가 됩니다.

참고: '/foo/bar.json'을 요청하면 params[:pages]'foo/bar'가 되고 요청 형식이 JSON이 됩니다. 3.0.x의 이전 동작을 원하는 경우 다음과 같이 format: false를 제공할 수 있습니다:

get '*pages', to: 'pages#show', format: false

참고: 형식 세그먼트를 필수로 만들어 생략할 수 없게 하려면 format: true를 제공하면 됩니다:

get '*pages', to: 'pages#show', format: true

리디렉션

redirect 헬퍼를 사용하여 모든 경로를 다른 경로로 리디렉션할 수 있습니다:

get '/stories', to: redirect('/articles')

동적 세그먼트를 재사용하여 경로를 리디렉션할 수도 있습니다:

get '/stories/:name', to: redirect('/articles/%{name}')

또한 redirect에 블록을 제공하여 경로 매개변수와 요청 객체를 받을 수 있습니다:

get '/stories/:name', to: redirect { |path_params, req| "/articles/#{path_params[:name].pluralize}" }
get '/stories', to: redirect { |path_params, req| "/articles/#{req.subdomain}" }

기본 리디렉션은 301 "영구 이동” 리디렉션임을 유의하세요. 일부 웹 브라우저 또는 프록시 서버가 이 유형의 리디렉션을 캐시하여 이전 페이지에 액세스할 수 없게 만들 수 있습니다. :status 옵션을 사용하여 응답 상태를 변경할 수 있습니다:

get '/stories/:name', to: redirect('/articles/%{name}', status: 302)

이러한 모든 경우에 선행 호스트(http://www.example.com)를 제공하지 않으면 Rails는 현재 요청의 세부 정보를 사용합니다.

Rack 애플리케이션에 라우팅하기

'articles#index'와 같은 문자열 대신 [Rack 애네, 계속해서 번역하겠습니다.

Rack 애플리케이션에 라우팅하기 (계속)

플리케이션](railsonrack.html)을 매처의 엔드포인트로 지정할 수 있습니다:

match '/application.js', to: MyRackApp, via: :all

MyRackAppcall에 응답하고 [status, headers, body]를 반환하는 한 라우터는 Rack 애플리케이션과 작업 간의 차이를 알지 못합니다. 이는 via: :all을 사용하는 적절한 경우입니다. Rack 애플리케이션이 모든 동사를 적절하게 처리할 수 있기 때문입니다.

참고: 호기심 많은 분들을 위해 말씀드리면 'articles#index'는 실제로 ArticlesController.action(:index)로 확장되며, 이는 유효한 Rack 애플리케이션을 반환합니다.

참고: 프로시저/람다는 call에 응답하는 객체이므로 매우 간단한 경로(예: 상태 확인)를 인라인으로 구현할 수 있습니다.
get '/health', to: ->(env) { [204, {}, ['']] }

Rack 애플리케이션을 매처의 엔드포인트로 지정하는 경우 수신 애플리케이션에서 경로가 변경되지 않는다는 것을 기억하세요. 다음과 같은 경로가 있는 경우 Rack 애플리케이션은 /admin을 예상해야 합니다:

match '/admin', to: AdminApp, via: :all

대신 Rack 애플리케이션이 루트 경로에서 요청을 받도록 하려면 mount를 사용하세요:

mount AdminApp, at: '/admin'

root 사용하기

root 메서드를 사용하여 Rails가 '/'로 라우팅해야 하는 것을 지정할 수 있습니다:

root to: 'pages#main'
root 'pages#main' # 위의 축약형

root 경로를 파일 맨 위에 배치해야 합니다. 가장 많이 사용되는 경로이므로 먼저 일치해야 합니다.

참고: root 경로는 GET 요청만 main 작업으로 라우팅합니다.

네임스페이스와 범위 내에서도 root를 사용할 수 있습니다. 예를 들어:

namespace :admin do
  root to: "admin#index"
end

root to: "home#index"

유니코드 문자 경로

유니코드 문자 경로를 직접 지정할 수 있습니다. 예를 들어:

get 'こんにちは', to: 'welcome#index'

직접 경로

direct를 호출하여 사용자 정의 URL 헬퍼를 직접 만들 수 있습니다. 예를 들어:

direct :homepage do
  "https://rubyonrails.org"
end

# >> homepage_url
# => "https://rubyonrails.org"

블록의 반환 값은 url_for 메서드에 대한 유효한 인수여야 합니다. 따라서 유효한 문자열 URL, 해시, 배열, Active Model 인스턴스 또는 Active Model 클래스를 전달할 수 있습니다.

direct :commentable do |model|
  [ model, anchor: model.dom_id ]
end

direct :main do
  { controller: 'pages', action: 'index', subdomain: 'www' }
end

resolve 사용하기

resolve 메서드를 사용하면 모델의 다형성 매핑을 사용자 정의할 수 있습니다. 예를 들어:

resource :basket

resolve("Basket") { [:basket] }
<%= form_with model: @basket do |form| %>
  <!-- basket form -->
<% end %>

이렇게 하면 일반적인 /baskets/:id 대신 /basket과 같은 단일 URL이 생성됩니다.

리소스 경로 사용자 정의하기

resources에 의해 생성된 기본 경로와 헬퍼가 일반적으로 잘 작동하지만 때로는 이를 사용자 정의해야 할 수 있습니다. Rails를 사용하면 경로의 거의 모든 일반적인 부분을 사용자 정의할 수 있습니다.

사용할 컨트롤러 지정하기

:controller 옵션을 사용하면 리소스에 대해 명시적으로 사용할 컨트롤러를 지정할 수 있습니다. 예를 들어:

resources :photos, controller: 'images'

이렇게 하면 /photos로 시작하는 들어오는 경로를 인식하지만 Images 컨트롤러로 라우팅합니다:

HTTP 동사 경로 컨트롤러#작업 명명된 경로 헬퍼
GET /photos images#index photos_path
GET /photos/new images#new newphotopath
POST /photos images#create photos_path
GET /photos/:id images#show photo_path(:id)
GET /photos/:id/edit images#edit editphotopath(:id)
PATCH/PUT /photos/:id images#update photo_path(:id)
DELETE /photos/:id images#destroy photo_path(:id)

참고: photos_path, new_photo_path 등을 사용하여 이 리소스에 대한 경로를 생성합니다.

네임스페이스가 지정된 컨트롤러의 경우 디렉토리 표기법을 사용할 수 있습니다. 예를 들어:

resources :user_permissions, controller: 'admin/user_permissions'

이렇게 하면 Admin::UserPermissions 컨트롤러로 라우팅됩니다.

참고: 디렉토리 표기법만 지원됩니다. Ruby 상수 표기법(예: controller: 'Admin::UserPermissions')으로 컨트롤러를 지정하면 라우팅 문제가 발생할 수 있으며 경고가 발생합니다.

제약 조건 지정하기

:constraints 옵션을 사용하여 암시적 id에 필수 형식을 지정할 수 있습니다. 예를 들어:

resources :photos, constraints: { id: /[A-Z][A-Z][0-9]+/ }

이 선언은 :id 매개변수가 제공된 정규식과 일치해야 한다고 지정합니다. 따라서 이 경우 라우터는 /photos/1과 더 이상 일치하지 않습니다. 대신 /photos/RR27이 일치합니다.

여러 경로에 적용할 단일 제약 조건을 지정하려면 블록 형식을 사용할 수 있습니다:

constraints(id: /[A-Z][A-Z][0-9]+/) do
  resources :photos
  resources :accounts
end

참고: 물론 비 리소스 경로에서 사용할 수 있는 더 고급 제약 조건을 이 컨텍스트에서 사용할 수 있습니다.

팁: 기본적으로 :id 매개변수는 점을 허용하지 않습니다. 이는 점이 형식화된 경로의 구분 기호로 사용되기 때문입니다. 점이 필요한 경우 이를 재정의하는 제약 조건을 추가하세요. 예: id: /[^\/]+/는 슬래시 이외의 모든 것을 허용합니다.

명명된 경로 헬퍼 재정의하기

:as 옵션을 사용하면 일반적인 명명된 경로 헬퍼 이름을 재정의할 수 있습니다. 예를 들어:

resources :photos, as: 'images'

이렇게 하면 /photos로 시작하는 들어오는 경로를 인식하고 PhotosController로 라우팅하지만 :as 옵션의 값을 사용하여 헬퍼를 이름 지정합니다.

HTTP 동사 경로 컨트롤러#작업 명명된 경로 헬퍼
GET /photos photos#index images_path
GET /photos/new photos#new newimagepath
POST /photos photos#create images_path
GET /photos/:id photos#show image_path(:id)
GET /photos/:id/edit photos#edit editimagepath(:id)
PATCH/PUT /photos/:id photos#update image_path(:id)
DELETE /photos/:id photos#destroy image_path(:id)

newedit 세그먼트 재정의하기

:path_names 옵션을 사용하면 자동으로 생성된 newedit 세그먼트를 재정의할 수 있습니다:

resources :photos, path_names: { new: 'make', edit: 'change' }

이렇게 하면 다음과 같은 경로를 인식하도록 라우팅이 변경됩니다:

/photos/make
/photos/1/change

참고: 작업 이름은 이 옵션에 의해 변경되지 않습니다. 표시된 두 경로는 여전히 newedit 작업으로 라우팅됩니다.

팁: 모든 경로에 대해 이 옵션을 일괄적으로 변경하려면 범위를 사용할 수 있습니다:

scope path_names: { new: 'make' } do
  # 나머지 경로
end

명명된 경로 헬퍼 접두사 지정하기

:as 옵션을 사용하여 Rails가 경로에 대해 생성하는 명명된 경로 헬퍼의 접두사를 지정할 수 있습니다. 경로 범위 간 이름 충돌을 방지하려면 이 옵션을 사용하세요. 예를 들어:

scope 'admin' do
  resources :photos, as: 'admin_photos'
end

resources :photos

이렇게 하면 /admin/photos에 대한 경로 헬퍼가 photos_path, new_photos_path 등 대신 admin_photos_path, new_admin_photo_path 등이 됩니다. as: 'admin_photos'resources :photos에 추가하지 않으면 비범위 resources :photos에 경로 헬퍼가 생성되지 않습니다.

그룹의 경로 헬퍼에 접두사를 지정하려면 scope:as를 사용하세요:

scope 'admin', as: 'admin' do
  resources :photos, :accounts
end

resources :photos, :accounts

마찬가지로 이렇게 하면 /admin 범위 리소스 헬퍼가 admin_photos_pathadmin_accounts_path가 되고, 범위 없는 리소스는 photos_pathaccounts_path를 사용할 수 있습니다.

참고: namespace 범위는 자동으로 :as:module, :path 접두사를 추가합니다.

매개변수화된 범위

경로를 명명된 매개변수로 접두사 지정할 수 있습니다:

scope ':account_id', as: 'account', constraints: { account_id: /\d+/ } do
  resources :articles
end

이렇게 하면 /1/articles/9와 같은 경로를 제공하고 params[:account_id]에 경로네, 계속해서 번역하겠습니다.

명명된 매개변수로 경로 접두사 지정하기 (계속)

account_id 부분을 컨트롤러, 헬퍼 및 뷰에서 사용할 수 있게 됩니다.

또한 account_로 시작하는 경로 및 URL 헬퍼를 생성하며, 여기에 객체를 예상대로 전달할 수 있습니다:

account_article_path(@account, @article) # => /1/article/9
url_for([@account, @article])            # => /1/article/9
form_with(model: [@account, @article])   # => <form action="/1/article/9" ...>

제약 조건을 사용하여 범위를 ID 유사 문자열로 제한하고 있습니다. 필요에 따라 제약 조건을 변경하거나 완전히 생략할 수 있습니다. :as 옵션도 엄격히 필요하지는 않지만, 이를 사용하지 않으면 url_for([@account, @article]) 또는 form_with과 같은 헬퍼를 평가할 때 오류가 발생합니다.

생성된 경로 제한하기

기본적으로 Rails는 각 RESTful 경로에 대해 7개의 기본 작업(index, show, new, create, edit, updatedestroy)에 대한 경로를 생성합니다. :only:except 옵션을 사용하여 이 동작을 미세 조정할 수 있습니다. :only 옵션은 Rails에 지정된 경로만 생성하도록 지시합니다:

resources :photos, only: [:index, :show]

이제 /photos에 대한 GET 요청은 성공하지만 /photos에 대한 POST 요청(일반적으로 create 작업으로 라우팅됨)은 실패합니다.

:except 옵션은 Rails가 생성하지 않을 경로 또는 경로 목록을 지정합니다:

resources :photos, except: :destroy

이 경우 Rails는 destroy 작업(즉, /photos/:id에 대한 DELETE 요청)을 제외한 모든 일반적인 경로를 생성합니다.

팁: 애플리케이션에 많은 RESTful 경로가 있는 경우 :only:except를 사용하여 실제로 필요한 경로만 생성하면 메모리 사용량을 줄이고 라우팅 프로세스를 가속화할 수 있습니다.

번역된 경로

scope를 사용하여 resources에 의해 생성된 경로 이름을 변경할 수 있습니다:

scope(path_names: { new: 'neu', edit: 'bearbeiten' }) do
  resources :categories, path: 'kategorien'
end

Rails는 이제 CategoriesController에 대한 경로를 생성합니다.

HTTP 동사 경로 컨트롤러#작업 명명된 경로 헬퍼
GET /kategorien categories#index categories_path
GET /kategorien/neu categories#new newcategorypath
POST /kategorien categories#create categories_path
GET /kategorien/:id categories#show category_path(:id)
GET /kategorien/:id/bearbeiten categories#edit editcategorypath(:id)
PATCH/PUT /kategorien/:id categories#update category_path(:id)
DELETE /kategorien/:id categories#destroy category_path(:id)

단일 형식 재정의하기

리소스의 단일 형식을 재정의하려면 inflections를 통해 인플렉터에 추가 규칙을 추가해야 합니다:

ActiveSupport::Inflector.inflections do |inflect|
  inflect.irregular 'tooth', 'teeth'
end

:as를 중첩 리소스에서 사용하기

:as 옵션은 자동으로 생성된 중첩 경로 헬퍼의 리소스 이름을 재정의합니다. 예를 들어:

resources :magazines do
  resources :ads, as: 'periodical_ads'
end

이렇게 하면 magazine_periodical_ads_urledit_magazine_periodical_ad_path와 같은 라우팅 헬퍼가 생성됩니다.

명명된 경로 매개변수 재정의하기

:param 옵션은 기본 리소스 식별자 :id(경로를 생성하는 데 사용되는 동적 세그먼트)를 재정의합니다. 이 세그먼트는 params[<:param>]에서 컨트롤러에 액세스할 수 있습니다.

resources :videos, param: :identifier
    videos GET  /videos(.:format)                  videos#index
           POST /videos(.:format)                  videos#create
 new_video GET  /videos/new(.:format)              videos#new
edit_video GET  /videos/:identifier/edit(.:format) videos#edit
Video.find_by(identifier: params[:identifier])

관련 모델의 ActiveRecord::Base#to_param을 재정의하여 URL을 구성할 수 있습니다:

class Video < ApplicationRecord
  def to_param
    identifier
  end
end
video = Video.find_by(identifier: "Roman-Holiday")
edit_video_path(video) # => "/videos/Roman-Holiday/edit"

매우 큰 경로 파일을 여러 작은 파일로 나누기

대규모 애플리케이션에서 수천 개의 경로가 있는 경우 단일 config/routes.rb 파일이 번거롭고 읽기 어려워질 수 있습니다.

Rails는 draw 매크로를 사용하여 거대한 단일 routes.rb 파일을 여러 작은 파일로 나누는 방법을 제공합니다.

관리 영역에 대한 admin.rb 경로, API 관련 리소스에 대한 api.rb 파일 등을 가질 수 있습니다.

# config/routes.rb

Rails.application.routes.draw do
  get 'foo', to: 'foo#bar'

  draw(:admin) # `config/routes/admin.rb`에 있는 다른 경로 파일을 로드합니다.
end
# config/routes/admin.rb

namespace :admin do
  resources :comments
end

Rails.application.routes.draw 블록 내에서 draw(:admin)을 호출하면 인수로 제공된 이름과 동일한 이름의 경로 파일(admin.rb의 경우)을 로드하려고 시도합니다. 파일은 config/routes 디렉토리 또는 하위 디렉토리(config/routes/admin.rb 또는 config/routes/external/admin.rb)에 있어야 합니다.

일반 config/routes.rb 파일과 달리 admin.rb 라우팅 파일 내에서 정상적인 라우팅 DSL을 사용할 수 있지만 Rails.application.routes.draw 블록으로 감싸서는 안 됩니다.

정말 필요한 경우가 아니라면 이 기능을 사용하지 마세요

여러 라우팅 파일을 사용하면 발견성과 이해도가 낮아집니다. 대부분의 애플리케이션(수백 개의 경로가 있는 경우에도)에서는 개발자가 단일 라우팅 파일을 가지는 것이 더 쉽습니다. Rails 라우팅 DSL은 이미 namespacescope를 통해 경로를 체계적으로 구분하는 방법을 제공합니다.

경로 검사 및 테스트

Rails는 경로를 검사하고 테스트하는 기능을 제공합니다.

기존 경로 나열하기

애플리케이션에서 사용 가능한 모든 경로 목록을 보려면 서버가 개발 환경에서 실행 중일 때 http://localhost:3000/rails/info/routes에 액세스하세요. 또한 터미널에서 bin/rails routes 명령을 실행하여 동일한 출력을 얻을 수 있습니다.

두 방법 모두 config/routes.rb에 나타나는 순서대로 모든 경로를 나열합니다. 각 경로에 대해 다음이 표시됩니다:

  • 경로 이름(있는 경우)
  • 사용된 HTTP 동사(경로가 모든 동사에 응답하지 않는 경우)
  • 일치시킬 URL 패턴
  • 경로에 대한 라우팅 매개변수

예를 들어 RESTful 경로에 대한 작은 섹션은 다음과 같습니다:

    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

--expanded 옵션을 사용하여 확장된 테이블 형식 모드를 켤 수도 있습니다.

$ bin/rails routes --expanded

--[ Route 1 ]----------------------------------------------------
Prefix            | users
Verb              | GET
URI               | /users(.:format)
Controller#Action | users#index
--[ Route 2 ]----------------------------------------------------
Prefix            |
Verb              | POST
URI               | /users(.:format)
Controller#Action | users#create
--[ Route 3 ]----------------------------------------------------
Prefix            | new_user
Verb              | GET
URI               | /users/new(.:format)
Controller#Action | users#new
--[ Route 4 ]----------------------------------------------------
Prefix            | edit_user
Verb              | GET
URI               | /users/:id/edit(.:format)
Controller#Action | users#edit

grep 옵션 -g를 사용하여 경로를 검색할 수 있습니다. 이렇게 하면 URL 헬퍼 메서드 이름, HTTP 동사 또는 URL 경로와 부분적으로 일치하는 모든 경로가 출력됩니다.

$ bin/rails routes -g new_comment
$ bin/rails routes -g POST
$ bin/rails routes -g admin

특정 컨트롤러에 매핑되는 경로만 보려면 -c 옵션을 사용하세요.

$ bin/rails routes -c users
$ bin/rails routes -c admin/users
$ bin/rails routes -c Comments
$ bin/rails routes -c Articles::CommentsController

팁: 터미널 창을 충분히 넓게 하면 bin/rails routes 출력의 가독성이 크게 향상됩니다.

경로 테스트하기

경로는 애플리케이션의 나머지 부분(컨트롤러, 모델 등)과 마찬가지로 테스트 전략에 포함되어야 합니다. Rails는 경로 테스트를 더 쉽게 만들기 위해 3개의 내장 어설션을 제공합니다:

assert_generates 어설션

assert_generates는 특정 옵션 집합이 특정 경로를 생성한다고 어설션하며 기본 경로 또는 사용자 정의 경로에서 사용할 수 있습니다. 예를 들어:

assert_generates '/photos/1', { controller: 'photos', action: 'show', id: '1' }
assert_generates '/about', controller: 'pages', action: 'about'

assert_recognizes 어설션

assert_recognizesassert_generates의 반대입니다. 주어진 경로가 인식되고 애플리케이션의 특정 위치로 라우팅된다고 어설네, 계속해서 번역하겠습니다.

경로 테스트하기 (계속)

션합니다. 예를 들어:

assert_recognizes({ controller: 'photos', action: 'show', id: '1' }, '/photos/1')

:method 인수를 제공하여 HTTP 동사를 지정할 수 있습니다:

assert_recognizes({ controller: 'photos', action: 'create' }, { path: 'photos', method: :post })

assert_routing 어설션

assert_routing 어설션은 경로를 양방향으로 확인합니다. 경로가 옵션을 생성하고 옵션이 경로를 생성한다는 것을 테스트합니다. 따라서 assert_generatesassert_recognizes의 기능을 결합합니다:

assert_routing({ path: 'photos', method: :post }, { controller: 'photos', action: 'create' })