rubyonrails.org에서 더 보기:

이 파일을 GITHUB에서 읽지 마세요. 가이드는 https://guides.rubyonrails.org 에서 제공됩니다.

외부에서 보는 Rails 라우팅

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

이 가이드를 읽은 후에는 다음을 알 수 있습니다:

  • config/routes.rb의 코드를 해석하는 방법
  • resourceful 스타일이나 match 메소드를 사용하여 자신만의 라우트를 구성하는 방법
  • 컨트롤러 액션으로 전달되는 라우트 파라미터를 선언하는 방법
  • 라우트 헬퍼를 사용하여 경로와 URL을 자동으로 생성하는 방법
  • 제약 조건 생성과 Rack 엔드포인트 마운팅과 같은 고급 기술

1 Rails 라우터의 목적

Rails 라우터는 들어오는 HTTP 요청을 URL 경로를 기반으로 Rails 애플리케이션의 특정 컨트롤러 액션과 매칭합니다. (또한 Rack 애플리케이션으로도 전달할 수 있습니다.) 라우터는 또한 라우터에 설정된 리소스를 기반으로 경로와 URL 헬퍼를 생성합니다.

1.1 들어오는 URL을 코드로 라우팅하기

Rails 애플리케이션이 들어오는 요청을 받으면, router에게 이를 controller action(일명 method)과 매칭하도록 요청합니다. 예를 들어, 다음과 같은 들어오는 요청을 살펴보겠습니다:

GET /users/17

첫 번째로 일치하는 route가 다음과 같다면:

get "/users/:id", to: "user#show"

요청은 UsersController 클래스의 show 액션과 매치되며 params 해시에 { id: '17' }이 포함됩니다.

to: 옵션은 문자열이 전달될 때 controller#action 형식을 기대합니다. 또는 to: 대신 심볼을 전달하고 action: 옵션을 사용할 수 있습니다. # 없이 문자열을 전달할 수도 있는데, 이 경우 to: 대신 controller: 옵션이 사용됩니다. 예를 들면:

get "/users/:id", controller: "users", action: :show

Rails는 라우트를 지정할 때 컨트롤러 이름에 snake_case를 사용합니다. 예를 들어, UserProfilesController라는 컨트롤러가 있다면, show action으로 가는 라우트를 user_profiles#show와 같이 지정합니다.

1.2 코드에서 Path와 URL 생성하기

Router는 자동으로 애플리케이션의 path와 URL helper method를 생성합니다. 이러한 method들을 사용하면 하드코딩된 path와 URL 문자열을 피할 수 있습니다.

예를 들어, 다음과 같은 route를 정의하면 user_pathuser_url helper method를 사용할 수 있습니다:

get "/users/:id", to: "users#show", as: "user"

위 구문은 users#show action으로 요청을 라우팅하고 매개변수 id와 함께 user_path helper를 생성합니다.

as: 옵션은 route에 대한 사용자 지정 이름을 제공하는데 사용되며, URL과 path 헬퍼를 생성할 때 사용됩니다.

컨트롤러에 다음과 같은 코드가 포함되어 있다고 가정해보겠습니다:

@user = User.find(params[:id])

그리고 이것을 해당 view에 작성합니다:

<%= link_to '사용자 정보', user_path(@user) %>

router는 user_path(@user)로부터 /users/17 경로를 생성합니다. user_path 헬퍼를 사용하면 view에서 경로를 하드코딩하지 않아도 됩니다. 이는 나중에 route를 다른 URL로 이동할 때 유용한데, 그에 해당하는 view를 업데이트할 필요가 없기 때문입니다.

또한 비슷한 목적의 user_url도 생성합니다. user_path/users/17와 같은 상대 URL을 생성하는 반면, user_url은 위 예시에서 https://example.com/users/17와 같은 절대 URL을 생성합니다.

1.3 Rails Router 설정하기

라우트는 config/routes.rb에 위치합니다. 다음은 일반적인 Rails 애플리케이션에서 라우트가 어떻게 보이는지 보여주는 예시입니다. 이어지는 섹션에서는 이 파일에서 사용된 다양한 route helper들을 설명할 것입니다:

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

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

  # Basket 모델에 대한 라우팅 헬퍼를 정의합니다.
  # 예: basket_path와 같은 라우팅 헬퍼가 자동으로 생성됩니다.
  resolve("Basket") { route_for(:basket) }
end

일반적인 Ruby 소스 파일이므로, 라우트를 정의할 때 모든 Ruby 기능(조건문과 반복문 같은)을 사용할 수 있습니다.

라우트 정의를 감싸는 Rails.application.routes.draw do ... end 블록은 router DSL(Domain Specific Language)의 스코프를 설정하는 데 필요하므로 삭제해서는 안 됩니다.

routes.rb에서 변수명을 사용할 때는 router의 DSL 메서드와 충돌할 수 있으므로 주의하세요.

2 Resource Routing: Rails의 기본

Resource routing을 사용하면 주어진 resource 컨트롤러에 대한 모든 공통 라우트를 빠르게 선언할 수 있습니다. 예를 들어, resources를 한 번 호출하면 각 라우트를 따로 선언할 필요 없이 index, show, new, edit, create, update, destroy 액션에 필요한 모든 라우트가 선언됩니다.

2.1 웹상의 Resources

브라우저는 GET, POST, PATCH, PUT, DELETE와 같은 특정 HTTP verb를 사용하여 URL에 대한 요청을 수행함으로써 Rails에 페이지를 요청합니다. 각 HTTP verb는 resource에 대한 작업을 수행하기 위한 요청입니다. resource route는 관련 요청들을 단일 controller의 actions에 매핑합니다.

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

DELETE /photos/17

라우터에게 이를 컨트롤러 액션에 매핑하도록 요청합니다. 첫 번째로 매칭되는 라우트가 다음과 같다면:

resources :photos

이는 애플리케이션에서 RESTful한 방식으로 photos를 위한 URL을 선언하게 됩니다. 또한 여러 URL 헬퍼 메소드를 생성하여 controller에서 URL을 처리할 수 있게 해줍니다.

Rails는 해당 요청을 params{ id: '17' }과 함께 PhotosControllerdestroy action으로 전달합니다.

2.2 CRUD, Verbs, 그리고 Actions

Rails에서 resourceful 라우트는 들어오는 요청(HTTP verb + URL의 조합)을 컨트롤러 액션에 매핑합니다. 관례에 따라 각 액션은 일반적으로 데이터에 대한 특정 CRUD 작업에 매핑됩니다. 라우팅 파일의 단일 항목은 다음과 같습니다:

resources :photos

photos를 다루는 RESTful한 routes를 정의합니다.

애플리케이션에 다음과 같이 7개의 서로 다른 라우트를 생성하며, 모두 PhotosController 액션에 매핑됩니다:

HTTP Verb Path Controller#Action Used to
GET /photos photos#index 모든 photos 목록 표시
GET /photos/new photos#new 새로운 photo 생성을 위한 HTML 폼 반환
POST /photos photos#create 새로운 photo 생성
GET /photos/:id photos#show 특정 photo 표시
GET /photos/:id/edit photos#edit photo 수정을 위한 HTML 폼 반환
PATCH/PUT /photos/:id photos#update 특정 photo 업데이트
DELETE /photos/:id photos#destroy 특정 photo 삭제

라우터는 HTTP verb path를 사용하여 들어오는 요청을 매칭하기 때문에, 4개의 URL이 7개의 서로 다른 컨트롤러 액션에 매핑될 수 있습니다. 예를 들어, 동일한 photos/ 경로가 verb가 GET일 때는 photos#index에 매칭되고 verb가 POST일 때는 photos#create에 매칭됩니다.

routes.rb 파일에서 순서가 중요합니다. Rails 라우트는 지정된 순서대로 매칭됩니다. 예를 들어, get 'photos/poll' 위에 resources :photos가 있다면, resources 라인의 show 액션 라우트가 get 라인보다 먼저 매칭될 것입니다. photos/poll 라우트가 먼저 매칭되길 원한다면, get 라인을 resources 라인 위로 이동시켜야 합니다.

2.3 Path와 URL Helper

리소스풀 라우트를 생성하면 애플리케이션의 컨트롤러와 뷰에서 사용할 수 있는 여러 helper가 노출됩니다.

예를 들어, route 파일에 resources :photos를 추가하면 다음과 같은 _path helper가 생성됩니다:

Path Helper Returns URL
photos_path /photos
new_photo_path /photos/new
edit_photo_path(:id) /photos/:id/edit`
photo_path(:id) /photos/:id

위의 :id와 같은 path helper의 파라미터는 생성된 URL로 전달되어, edit_photo_path(10)/photos/10/edit를 반환합니다.

이러한 각각의 _path helper는 해당하는 _url helper(예: photos_url)도 가지고 있으며, 이는 현재 host, port, path prefix가 앞에 추가된 동일한 경로를 반환합니다.

"_path"와 "_url" 앞에 붙는 접두사는 route 이름이며 rails routes 명령어 출력의 "prefix" 열에서 확인할 수 있습니다. 자세한 내용은 아래의 기존 Route 나열하기를 참조하세요.

2.4 여러 Resource를 동시에 정의하기

여러 resource에 대한 route를 생성해야 하는 경우 하나의 resources 호출로 모두 정의하면 약간의 타이핑을 줄일 수 있습니다:

resources :photos, :books, :videos

photos, books, videos에 대한 RESTful routes를 한 번에 여러 개 선언합니다.

위의 내용은 다음의 축약형입니다:

resources :photos
resources :books
resources :videos

리소스를 한 번에 여러 개 정의하고 싶으면, 단 한 줄로도 가능합니다. 한 줄로 표현한 위 코드는 각각의 리소스를 여러 줄로 나누어 선언한 것과 정확하게 동일한 결과를 만듭니다.

2.5 Singular Resources

때로는 사용자가 하나만 가질 것으로 예상되는 리소스가 있습니다(즉, 해당 리소스의 모든 값을 나열하는 index 액션을 갖는 것이 의미가 없는 경우). 이러한 경우 resources 대신 resource(단수)를 사용할 수 있습니다.

아래의 resourceful 라우트는 애플리케이션에서 6개의 라우트를 생성하며, 모두 Geocoders 컨트롤러에 매핑됩니다:

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

resource 헬퍼를 사용하면 이는 아래의 내용과 같은 정의가 생성됩니다:

resolve 호출은 레코드 식별을 통해 Geocoder 인스턴스를 단수 라우트로 변환하는데 필요합니다.

다음은 단수 리소스에 대해 생성되는 모든 라우트입니다:

HTTP Verb Path Controller#Action Used to
GET /geocoder/new geocoders#new geocoder 생성을 위한 HTML 폼 반환
POST /geocoder geocoders#create 새로운 geocoder 생성
GET /geocoder geocoders#show 하나뿐인 geocoder 리소스 표시
GET /geocoder/edit geocoders#edit geocoder 수정을 위한 HTML 폼 반환
PATCH/PUT /geocoder geocoders#update 하나뿐인 geocoder 리소스 업데이트
DELETE /geocoder geocoders#destroy geocoder 리소스 삭제

단수 리소스는 복수형 컨트롤러에 매핑됩니다. 예를 들어, geocoder 리소스는 GeocodersController에 매핑됩니다.

단수 리소스 라우트는 다음과 같은 헬퍼를 생성합니다:

  • new_geocoder_path/geocoder/new를 반환
  • edit_geocoder_path/geocoder/edit를 반환
  • geocoder_path/geocoder를 반환

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

2.6 Controller Namespaces와 Routing

대규모 애플리케이션에서는 controller 그룹을 namespace로 구성하고 싶을 수 있습니다. 예를 들어 app/controllers/admin 디렉터리 안에 있는 Admin:: namespace 아래에 여러 controller를 가질 수 있습니다. 이러한 그룹에는 namespace 블록을 사용하여 routing할 수 있습니다:

namespace :admin do
  resources :articles
end

의 결과로, Rails는 /admin/articles URL에 매칭되는 라우트들을 생성하고 ArticlesController를 Admin::ArticlesController 내에 위치하도록 요구할 것입니다.

articlescomments 컨트롤러 각각에 대해 여러 라우트가 생성됩니다. Admin::ArticlesController의 경우 Rails는 다음과 같이 생성합니다:

HTTP Verb Path Controller#Action Named Route Helper
GET /admin/articles admin/articles#index admin_articles_path
GET /admin/articles/new admin/articles#new new_admin_article_path
POST /admin/articles admin/articles#create admin_articles_path
GET /admin/articles/:id admin/articles#show admin_article_path(:id)
GET /admin/articles/:id/edit admin/articles#edit edit_admin_article_path(:id)
PATCH/PUT /admin/articles/:id admin/articles#update admin_article_path(:id)
DELETE /admin/articles/:id admin/articles#destroy admin_article_path(:id)

위 예시에서 모든 경로는 namespace의 기본 규칙에 따라 /admin 접두사를 갖습니다.

2.6.1 Module 사용하기

만약 Admin::ArticlesController에 대해 (/admin 접두사 없이) /articles로 라우팅하고 싶다면, scope를 사용하여 module을 지정할 수 있습니다:

scope module: "admin" do # articles_url이 /articles를 가리키고
  resources :articles    # articles_controller는 Admin::ArticlesController가 됨
end

위 내용을 작성하는 다른 방법:

resources :articles, module: "admin"

"admin" module 아래에 articles resource를 생성합니다.

2.6.2 Scope 사용하기

또는, /admin/articlesArticlesController로 라우팅할 수도 있습니다(Admin:: 모듈 접두사 없이). scope 블록을 사용하여 경로를 지정할 수 있습니다:

scope "/admin" do
  resources :articles
end

"/admin" path를 scope 내의 모든 routes에 추가합니다.

위의 내용을 작성하는 다른 방법:

resources :articles, path: "/admin/articles"

articles resource를 "/articles" 대신 "/admin/articles"에 매핑할 것입니다.

이러한 대안들(경로에 /admin이 없고 모듈 접두사에 Admin::이 없는 경우)에서는 named route helper가 scope를 사용하지 않은 경우와 동일하게 유지됩니다.

마지막 경우에서는 다음 경로들이 ArticlesController에 매핑됩니다:

HTTP Verb Path Controller#Action Named Route Helper
GET /admin/articles articles#index articles_path
GET /admin/articles/new articles#new new_article_path
POST /admin/articles articles#create articles_path
GET /admin/articles/:id articles#show article_path(:id)
GET /admin/articles/:id/edit articles#edit edit_article_path(:id)
PATCH/PUT /admin/articles/:id articles#update article_path(:id)
DELETE /admin/articles/:id articles#destroy article_path(:id)

namespace 블록 내에서 다른 controller namespace를 사용해야 하는 경우, 절대 controller 경로를 지정할 수 있습니다. 예: get '/foo', to: '/foo#index'.

2.7 중첩된 Resources

다른 resource의 논리적 자식인 resource를 가지는 것은 일반적입니다. 예를 들어 애플리케이션이 다음과 같은 model을 포함한다고 가정해봅시다:

class Magazine < ApplicationRecord
  has_many :ads
end 

class Ad < ApplicationRecord
  belongs_to :magazine 
end

중첩된 route 선언을 사용하면 라우팅에서 이러한 관계를 표현할 수 있습니다:

resources :magazines do
  resources :ads
end

magazine이 여러 개의 ad를 포함하는 관계를 표현한 nested route입니다.

magazines에 대한 라우트 외에도, 이 선언은 ads를 AdsController로 라우팅할 것입니다. 다음은 중첩된 ads 리소스에 대한 모든 라우트입니다:

HTTP Verb Path Controller#Action Used to
GET /magazines/:magazine_id/ads ads#index 특정 magazine의 모든 ad 목록 표시
GET /magazines/:magazine_id/ads/new ads#new 특정 magazine에 속한 새로운 ad를 생성하기 위한 HTML 폼 반환
POST /magazines/:magazine_id/ads ads#create 특정 magazine에 속한 새로운 ad 생성
GET /magazines/:magazine_id/ads/:id ads#show 특정 magazine에 속한 특정 ad 표시
GET /magazines/:magazine_id/ads/:id/edit ads#edit 특정 magazine에 속한 ad를 수정하기 위한 HTML 폼 반환
PATCH/PUT /magazines/:magazine_id/ads/:id ads#update 특정 magazine에 속한 특정 ad 수정
DELETE /magazines/:magazine_id/ads/:id ads#destroy 특정 magazine에 속한 특정 ad 삭제

이는 또한 magazine_ads_urledit_magazine_ad_path와 같은 일반적인 path와 url 라우팅 헬퍼들을 생성할 것입니다. ads 리소스가 magazines 아래에 중첩되어 있기 때문에, ad URL들은 magazine을 필요로 합니다. 헬퍼들은 Magazine 인스턴스를 첫 번째 파라미터로 받을 수 있습니다(edit_magazine_ad_path(@magazine, @ad)).

2.7.1 중첩의 한계

원하는 경우 다른 중첩된 리소스 내에 리소스를 중첩할 수 있습니다. 예를 들어:

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

이는 publisher에 연결된 magazine에 연결된 photo의 nested resource를 정의합니다. 이 라우팅을 통해 publishers/1/magazines/2/photos/3와 같은 경로를 만들 수 있습니다.

위 예제에서, 애플리케이션은 다음과 같은 path를 인식할 것입니다:

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

이에 해당하는 route helper는 publisher_magazine_photo_url이 되며, 세 단계 모두에서 객체를 지정해야 합니다. 보시다시피, 깊이 중첩된 리소스는 지나치게 복잡해지고 유지보수하기가 어려워질 수 있습니다.

일반적인 경험칙은 리소스를 1단계 깊이로만 중첩하는 것입니다.

2.7.2 Shallow Nesting

깊은 중첩을 피하는 한 가지 방법(위에서 권장한 대로)은 부모 아래에 scoped된 collection 액션을 생성하는 것입니다. 이를 통해 계층 구조를 파악할 수 있으면서도 member 액션은 중첩하지 않습니다. 다시 말해, 리소스를 고유하게 식별하는 데 필요한 최소한의 정보로만 라우트를 구성하는 것입니다.

"member" 액션은 개별 리소스에 적용되며 특정 리소스를 식별하기 위한 ID가 필요한 show, edit 등과 같은 액션입니다. "collection" 액션은 index와 같이 리소스 전체 집합에 대해 동작하는 액션입니다.

예시:

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

이는 댓글이 article의 컨텍스트 안에서 생성되도록 하면서도, 댓글을 보거나 편집/삭제할 때는 article이 필요하지 않도록 합니다. 이렇게 하면 다음과 같은 더 짧은 URL과 경로를 사용할 수 있습니다:

위에서는 Rails에게 지정된 라우트만 생성하도록 지시하는 :only 옵션을 사용했습니다. 이는 설명적인 라우트와 깊은 중첩 사이의 균형을 맞춥니다. :shallow 옵션을 통해 이를 달성할 수 있는 간단한 문법이 있습니다:

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

shallow: true 옵션은 :comments에 대해 'shallow' 라우트를 생성합니다:

이는 첫 번째 예제와 동일한 routes를 생성합니다. 부모 resource에 :shallow 옵션을 지정할 수도 있으며, 이 경우 모든 중첩된 resource가 shallow로 처리됩니다:

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

이것은 위의 각 collection route를 정상적으로 생성하지만, member routes는 부모없이 생성됩니다:

/articles/1/comments
/articles/1/quotes
/comments/2
/quotes/2

위의 articles resource는 다음과 같은 라우트들을 생성할 것입니다:

HTTP Verb Path Controller#Action Named Route Helper
GET /articles/:article_id/comments(.:format) comments#index article_comments_path
POST /articles/:article_id/comments(.:format) comments#create article_comments_path
GET /articles/:article_id/comments/new(.:format) comments#new new_article_comment_path
GET /comments/:id/edit(.:format) comments#edit edit_comment_path
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 article_quotes_path
POST /articles/:article_id/quotes(.:format) quotes#create article_quotes_path
GET /articles/:article_id/quotes/new(.:format) quotes#new new_article_quote_path
GET /quotes/:id/edit(.:format) quotes#edit edit_quote_path
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(.:format) articles#index articles_path
POST /articles(.:format) articles#create articles_path
GET /articles/new(.:format) articles#new new_article_path
GET /articles/:id/edit(.:format) articles#edit edit_article_path
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 메소드는 모든 중첩이 shallow인 스코프를 생성합니다. 이는 이전 예제와 동일한 라우트를 생성합니다:

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

위의 코드는 다음과 동일합니다:

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

:shallow_path:shallow_prefix 이 두 가지 옵션을 scope와 함께 사용하여 shallow 라우트를 커스터마이징할 수 있습니다.

shallow_path 옵션은 주어진 파라미터를 member 경로에 접두사로 추가합니다:

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

위 코드는 "sekret" prefix를 모든 shallow route에 추가합니다.

comments 리소스는 다음과 같은 라우트들이 생성됩니다:

HTTP Verb Path Controller#Action Named Route Helper
GET /articles/:article_id/comments(.:format) comments#index article_comments_path
POST /articles/:article_id/comments(.:format) comments#create article_comments_path
GET /articles/:article_id/comments/new(.:format) comments#new new_article_comment_path
GET /sekret/comments/:id/edit(.:format) comments#edit edit_comment_path
GET /sekret/comments/:id(.:format) comments#show comment_path
PATCH/PUT /sekret/comments/:id(.:format) comments#update comment_path
DELETE /sekret/comments/:id(.:format) comments#destroy comment_path

:shallow_prefix 옵션은 지정된 파라미터를 _path_url 라우트 헬퍼에 추가합니다:

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

위 코드는 shallow URL 생성 시 지정한 prefix를 URL에 사용하게 됩니다. resources가 다음과 같은 경로를 생성합니다:

comments resource는 다음과 같은 routes를 생성합니다:

HTTP Verb Path Controller#Action Named Route Helper
GET /articles/:article_id/comments(.:format) comments#index article_comments_path
POST /articles/:article_id/comments(.:format) comments#create article_comments_path
GET /articles/:article_id/comments/new(.:format) comments#new new_article_comment_path
GET /comments/:id/edit(.:format) comments#edit edit_sekret_comment_path
GET /comments/:id(.:format) comments#show sekret_comment_path
PATCH/PUT /comments/:id(.:format) comments#update sekret_comment_path
DELETE /comments/:id(.:format) comments#destroy sekret_comment_path

2.8 Routing Concerns

Routing concerns를 사용하면 다른 resource들 안에서 재사용할 수 있는 공통 route들을 선언할 수 있습니다. concern을 정의하려면 concern 블록을 사용하세요:

concern :commentable do
  resources :comments
end

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

이 코드는 concern들을 정의합니다. concern은 재사용 가능한 route들의 모음입니다. 위의 코드는 두 개의 concern을 정의합니다 - :commentable과 :image_attachable 입니다. 각각은 comments와 images resources에 대한 route들을 정의합니다.

이러한 concern들은 코드 중복을 피하고 route들 간에 동작을 공유하기 위해 resource에서 사용될 수 있습니다.

resources :messages, concerns: :commentable

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

메시지에 대한 resource에 commentable concern을 적용하는 예시입니다.

articles에 대한 resource에는 commentable과 image_attachable이라는 두 개의 concern을 적용하는 예시입니다.

위는 다음과 동일합니다:

resources :messages do
  resources :comments
end

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

이것은 자동으로 Messages와 Comments 사이의 관계, 그리고 Articles와 Comments 및 Articles와 Images 사이의 관계를 인식하고 파악할 것입니다.

scope 또는 namespace 블록 내에서 concerns를 호출하여 위와 동일한 결과를 얻을 수도 있습니다. 예를 들어:

namespace :messages do
  concerns :commentable
end

namespace :articles do
  concerns :commentable
  concerns :image_attachable
end

2.9 객체로부터 Path와 URL 생성하기

라우팅 헬퍼를 사용하는 것 외에도, Rails는 파라미터 배열로부터 path와 URL을 생성할 수 있습니다. 예를 들어, 다음과 같은 라우트가 있다고 가정해봅시다:

resources :magazines do
  resources :ads
end

이는 magazine이 ads의 부모인 중첩된 라우트를 만듭니다.

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

<%= link_to '광고 세부정보', magazine_ad_path(@magazine, @ad) %>

생성된 path는 /magazines/5/ads/42 같은 형태가 됩니다.

위와 같은 path를 얻기 위해 url_for를 객체 배열과 함께 사용할 수도 있습니다:

<%= link_to '광고 상세정보', url_for([@magazine, @ad]) %>

이 경우 Rails는 @magazineMagazine이고 @adAd임을 인식하여 magazine_ad_path helper를 사용할 것입니다. link_to를 작성하는 더 짧은 방법은 전체 url_for 호출 대신 객체만 지정하는 것입니다:

<%= link_to '광고 상세정보', [@magazine, @ad] %>

단순히 magazine에 링크하고 싶다면:

<%= link_to '잡지 상세정보', @magazine %>

다른 action들의 경우, 당신은 edit_magazine_ad_path를 위해 배열의 첫 번째 요소로 action 이름을 삽입해야 합니다:

<%= link_to '광고 수정', [:edit, @magazine, @ad] %>

이를 통해 모델의 인스턴스를 URL처럼 다룰 수 있으며, 이는 resourceful 스타일을 사용하는 주요 장점입니다.

[@magazine, @ad]와 같은 객체로부터 자동으로 경로와 URL을 도출하기 위해, Rails는 ActiveModel::NamingActiveModel::Conversion 모듈의 메서드들을 사용합니다. 구체적으로, @magazine.model_name.route_keymagazines를 반환하고 @magazine.to_param은 모델의 id를 문자열로 반환합니다. 따라서 [@magazine, @ad] 객체에 대해 생성되는 경로는 /magazines/1/ads/42와 같은 형태가 될 수 있습니다.

2.10 RESTful 라우트 추가하기

기본적으로 RESTful 라우팅이 생성하는 7개의 라우트로만 제한되지는 않습니다. 컬렉션이나 컬렉션의 개별 멤버에 적용되는 추가 라우트를 설정할 수 있습니다.

아래 섹션에서는 member 라우트와 collection 라우트를 추가하는 방법을 설명합니다. member라는 용어는 show, update, destroy와 같이 단일 요소에 작용하는 라우트를 의미합니다. collection이라는 용어는 index 라우트처럼 여러 요소 또는 요소의 컬렉션에 작용하는 라우트를 의미합니다.

2.10.1 Member 라우트 추가하기

resource 블록 안에 member 블록을 다음과 같이 추가할 수 있습니다:

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

이렇게 하면 /photos/1/preview 같은 형태의 URL이 인식됩니다. preview action 내에서 params[:id]를 사용하여 photo record를 찾을 수 있습니다.

/photos/1/preview로 들어오는 GET 요청은 PhotosControllerpreview 액션으로 라우팅됩니다. 리소스 id 값은 params[:id]에서 사용할 수 있습니다. 또한 preview_photo_urlpreview_photo_path 헬퍼를 생성합니다.

member 블록 내에서 각 라우트 정의는 HTTP 동사를 지정합니다(위 예시에서는 get 'preview'와 같이 get을 사용). get 외에도 patch, put, post, 또는 delete를 사용할 수 있습니다.

여러 개의 member 라우트가 없는 경우, 블록을 없애고 :on을 라우트에 전달할 수도 있습니다:

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

:member modifier를 사용하면 아래와 같이 photos#preview를 취급하는 라우트가 생성됩니다:

:on 옵션을 생략할 수도 있습니다. 이렇게 하면 동일한 member 라우트가 생성되지만 리소스 id 값이 params[:id] 대신 params[:photo_id]로 사용 가능합니다. 라우트 헬퍼도 preview_photo_urlpreview_photo_path에서 photo_preview_urlphoto_preview_path로 이름이 변경됩니다.

2.10.2 Collection 라우트 추가하기

collection에 라우트를 추가하려면 collection 블록을 사용하세요:

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

이는 /photos/search URL을 post#search action으로 routing할 것입니다. GET 대신 collection를 통해 POST가 있는 경우, 일반적인 resourceful route를 정의하는 것과 동일한 방식으로 작동합니다.

이는 Rails가 GET 요청이 있는 /photos/search와 같은 경로를 인식하고 PhotosControllersearch 액션으로 라우팅할 수 있게 해줍니다. 또한 search_photos_urlsearch_photos_path 라우트 헬퍼를 생성합니다.

member 라우트와 마찬가지로, 라우트에 :on을 전달할 수 있습니다:

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

:collection 옵션을 사용하여 컬렉션 라우트를 만듭니다. 이 라우트는 컬렉션을 위한 actions를 위한 것입니다. id가 필요하지 않은 라우트입니다.

첫 번째 위치 인자로 심볼을 사용하여 추가적인 resource route를 정의할 때는, 문자열을 사용하는 것과 동일하지 않다는 점을 주의하세요. 심볼은 controller action을 추론하고 문자열은 경로를 추론합니다.

2.10.3 추가적인 New Action에 대한 Route 추가하기

:on 단축어를 사용하여 대체 new action을 추가하려면:

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

collection이나 member가 아닌 새로운 리소스 path에 액션을 추가합니다. 이는 /comments/new/preview와 같은 형태의 path를 생성합니다.

이를 통해 Rails는 GET을 사용한 /comments/new/preview와 같은 경로를 인식하고 CommentsControllerpreview 액션으로 라우팅할 수 있게 됩니다. 또한 preview_new_comment_urlpreview_new_comment_path 라우트 헬퍼를 생성합니다.

resourceful 라우트에 많은 추가 액션을 추가하고 있다면, 잠시 멈추고 다른 리소스의 존재를 감추고 있는 것은 아닌지 자문해볼 때입니다.

resources에 의해 생성되는 기본 라우트와 헬퍼를 커스터마이징하는 것이 가능합니다. 자세한 내용은 resourceful 라우트 커스터마이징 섹션을 참조하세요.

3 Non-Resourceful 라우트

resources를 사용한 resourceful 라우팅 외에도, Rails는 임의의 URL을 액션에 라우팅하기 위한 강력한 지원을 제공합니다. resourceful 라우팅에 의해 자동으로 생성되는 라우트 그룹을 얻지는 못합니다. 대신, 애플리케이션 내에서 각 라우트를 개별적으로 설정합니다.

일반적으로 resourceful 라우팅을 사용해야 하지만, non-resourceful 라우팅이 더 적절한 경우가 있습니다. 애플리케이션의 모든 부분을 무리하게 resourceful 프레임워크에 맞추려고 할 필요는 없습니다.

non-resourceful 라우팅의 한 가지 사용 사례는 기존 레거시 URL을 새로운 Rails 액션에 매핑하는 것입니다.

3.1 Bound Parameters

일반적인 라우트를 설정할 때, Rails가 들어오는 HTTP 요청의 일부에 매핑하는 일련의 심볼을 제공합니다. 예를 들어, 다음의 라우트를 살펴보세요:

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

id가 선택적 parameter인 경로를 생성합니다. 이 라우트는 /photos/12 또는 /photos 모두 매칭될 것입니다.

만약 들어오는 GET 요청인 /photos/1이 이 라우트에 의해 처리된다면, PhotosControllerdisplay 액션이 호출되고 최종 파라미터인 "1"params[:id]로 사용할 수 있게 됩니다. 이 라우트는 또한 /photos라는 들어오는 요청을 PhotosController#display로 라우팅할 것입니다. 왜냐하면 :id는 위 예제에서 괄호로 표시된 선택적 파라미터이기 때문입니다.

3.2 Dynamic Segments

일반적인 라우트 내에서 원하는 만큼의 dynamic segments를 설정할 수 있습니다. 모든 segment는 params의 일부로 액션에서 사용할 수 있습니다. 다음과 같은 라우트를 설정하면:

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

이 라우트는 /photos/1/2와 같은 경로에 응답할 것입니다. params 해시는 { controller: 'photos', action: 'show', id: '1', user_id: '2' }가 될 것입니다.

기본적으로 dynamic segments는 점(.)을 허용하지 않습니다 - 이는 점이 formatted routes의 구분자로 사용되기 때문입니다. dynamic segment 내에서 점을 사용해야 한다면, 이를 재정의하는 제약조건을 추가하세요 - 예를 들어, id: /[^\/]+/는 슬래시를 제외한 모든 것을 허용합니다.

3.3 Static Segments

Route를 생성할 때 세그먼트 앞에 콜론을 붙이지 않음으로써 static segment를 지정할 수 있습니다:

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' }가 됩니다.

3.4 쿼리 스트링

params는 쿼리 스트링의 모든 파라미터도 포함합니다. 예를 들어 다음 라우트에서:

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

"photos/:id"와 일치하는 요청에 라우팅합니다. 예를 들어, photos/1로의 요청은 PhotosController의 show 액션에 라우팅하며, { id: '1' } 을 params에 전달합니다.

들어오는 /photos/1?user_id=2에 대한 GET 요청은 일반적으로 PhotosController 클래스의 show action으로 전달되며, params hash는 { controller: 'photos', action: 'show', id: '1', user_id: '2' }가 됩니다.

3.5 기본 매개변수 정의하기

route에서는 :defaults 옵션에 hash를 제공하여 기본값을 정의할 수 있습니다. 이는 dynamic segments로 지정하지 않은 매개변수에도 적용됩니다. 예를 들어:

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

기본값으로 지정된 format이 있는 경우 요청하는 resource를 format 없이도 사용할 수 있습니다.

Rails는 photos/12PhotosControllershow 액션에 매칭시키고, params[:format]"jpg"로 설정할 것입니다.

또한 defaults 블록을 사용하여 여러 항목에 대한 기본값을 정의할 수 있습니다:

defaults format: :json do
  resources :photos
  resources :articles
end

format: :json을 기본 형식으로 하여 라우팅 블록을 정의합니다. 블록에 있는 모든 라우트는 JSON을 기본 형식으로 사용합니다. photos 리소스와 articles 리소스가 모두 JSON 형식을 사용하게 됩니다.

보안상의 이유로 query 파라미터를 통해 defaults를 재정의할 수 없습니다. 재정의할 수 있는 defaults는 URL 경로에서 대체를 통한 동적 세그먼트뿐입니다.

3.6 Routes 명명하기

어떤 route에 대해서도 :as 옵션을 사용해서 _path_url helper에서 사용될 이름을 지정할 수 있습니다:

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

"exit" 경로를 sessions#destroy action으로 라우팅하고 logout 이라는 이름을 지정합니다.

이렇게 하면 애플리케이션에서 route helper로 logout_pathlogout_url이 생성됩니다. logout_path를 호출하면 /exit을 반환합니다.

또한 아래와 같이 resource가 정의되기 전에 custom route 정의를 배치하여 resources로 정의된 routing helper 이름을 as로 덮어쓸 수 있습니다:

get ":username", to: "users#show", as: :user # 사용자명을 통해 사용자 프로필 표시
resources :users # 사용자를 위한 RESTful 라우트 생성

이는 /:username(예: /jane)과 매칭되는 user_path 헬퍼를 정의합니다. UsersControllershow 액션 내에서 params[:username]은 해당 사용자의 username을 포함하게 됩니다.

3.7 HTTP Verb 제약조건

일반적으로 라우트를 특정 HTTP verb로 제한하려면 get, post, put, patch, delete 메서드를 사용해야 합니다. 여러 개의 verb를 한 번에 매칭하려면 :via 옵션과 함께 match 메서드를 사용할 수 있습니다:

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

다음 HTTP 메서드들에 대해서만 라우팅을 수행합니다: GET와 POST.

위 route는 PhotosControllershow action에 대한 GET과 POST 요청을 매칭합니다.

via: :all을 사용하여 특정 route에 대한 모든 verb를 매칭할 수 있습니다:

"photos" 경로를 `:all` HTTP 메서드를 통해 `photos#show` 매칭합니다.

단일 action에 GETPOST 요청을 모두 라우팅하는 것은 보안상 영향이 있습니다. 예를 들어, GET action은 CSRF 토큰을 확인하지 않습니다(따라서 GET 요청으로 데이터베이스에 쓰는 것은 좋은 생각이 아닙니다. 자세한 내용은 보안 가이드를 참조하세요). 일반적으로 타당한 이유가 없다면 모든 HTTP 동사를 단일 action으로 라우팅하는 것을 피하세요.

3.8 Segment 제약사항

:constraints 옵션을 사용하여 동적 segment의 형식을 강제할 수 있습니다:

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

이 문장은 id가 대문자 하나와 5자리 숫자로만 이루어진 요청만을 매칭합니다.

위의 라우트 정의는 id가 5자리의 영숫자여야 합니다. 따라서 이 라우트는 /photos/A12345와 같은 경로와는 매칭되지만 /photos/893와는 매칭되지 않습니다. 동일한 라우트를 다음과 같이 더 간단하게 표현할 수 있습니다:

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

위 route는 대문자와 5자리 숫자로 구성된 ID(예: A12345)만 매칭됩니다.

:constraints 옵션은 정규표현식(또는 matches? 메소드에 응답하는 모든 객체)을 사용합니다. 단, regexp 앵커는 사용할 수 없다는 제약이 있습니다. 예를 들어, 다음 라우트는 작동하지 않습니다:

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

숫자로 시작하는 :id인 경우에만 route가 일치하도록 정의합니다.

그러나 모든 route가 시작과 끝에 정박되어 있으므로 앵커를 사용할 필요가 없다는 점에 유의하세요.

예를 들면:

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

첫 번째 route는 id 매개변수가 최소한 하나의 숫자(\d)로 시작하고 그 뒤에 임의의 문자(.+)가 오는 경우에만 일치하게 됩니다.

두 번째 route는 숫자로 시작하지 않는 모든 매개변수와 일치하게 됩니다. 이는 사용자 이름 기반 URL에 적합합니다.

위 routes는 root namespace를 공유하고 다음을 허용합니다:

  • /1-hello-world와 같이 항상 숫자로 시작하는 route paths는 id 값과 함께 articles로 라우팅됩니다.
  • /david와 같이 절대 숫자로 시작하지 않는 route paths는 username 값과 함께 users로 라우팅됩니다.

3.9 Request 기반 제약조건

Request 객체에서 String을 반환하는 모든 메소드를 기반으로 route를 제약할 수도 있습니다.

request 기반 제약조건은 segment 제약조건을 지정하는 것과 동일한 방식으로 지정합니다. 예를 들어:

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

subdomain이 "admin"인 경우에만 route가 매치됩니다.

경로가 admin 서브도메인과 일치하는 들어오는 요청과 매칭됩니다.

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

subdomain: "admin" 제약조건을 가진 경우에만 
  resources :photos
end

https://admin.example.com/photos와 같은 것과 매칭될 것입니다.

Request 제약조건은 해시 키와 동일한 이름의 메서드를 Request 객체에서 호출하고, 반환값을 해시 값과 비교하는 방식으로 동작합니다. 예를 들어: constraints: { subdomain: 'api' }는 예상대로 api 서브도메인과 매칭됩니다. 하지만 심볼 constraints: { subdomain: :api }을 사용하면 매칭되지 않습니다. request.subdomain이 문자열로 'api'를 반환하기 때문입니다.

제약조건 값은 해당하는 Request 객체 메서드의 반환 타입과 일치해야 합니다.

format 제약조건의 경우 예외가 있습니다. Request 객체의 메서드이긴 하지만, 모든 경로에서 암시적인 선택적 파라미터이기도 합니다. 세그먼트 제약조건이 우선순위를 가지며 format 제약조건은 해시를 통해 강제될 때만 적용됩니다. 예를 들어, get 'foo', constraints: { format: 'json' }GET /foo와 매칭됩니다. format이 기본적으로 선택사항이기 때문입니다.

get 'foo', constraints: lambda { |req| req.format == :json }와 같이 lambda를 사용하여 명시적인 JSON 요청에만 라우트를 매칭시킬 수 있습니다.

3.10 고급 Constraints

더 고급 수준의 constraint가 필요한 경우, Rails가 사용할 matches?에 응답하는 객체를 제공할 수 있습니다. 제한된 목록에 있는 모든 사용자를 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

위의 예제에서 RestrictedListConstraint 객체는 요청의 IP가 제한된 IP 목록에 있는지 검사하는 데 사용됩니다. *path는 루트의 모든 요청을 매칭합니다.

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

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

제약조건이 포함된 route가 처리되는 동안 특정 IP 목록을 포함하는 요청만을 받습니다. 이렇게 하면 차단된 IP 주소들이 application에 접근할 수 없습니다.

matches? 메소드와 lambda 모두 request 객체를 인자로 받습니다.

3.10.1 블록 형식의 Constraints

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

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

특정 IP 목록이 포함된 요청만 restricted_list#indexother_restricted_list#index로 라우팅되도록 제한합니다.

3.11 와일드카드 세그먼트

라우트 정의에는 와일드카드 세그먼트를 포함할 수 있습니다. 와일드카드 세그먼트는 별표로 시작하는 세그먼트입니다. 예를 들면 *other와 같습니다:

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

photos 이후의 모든 요청을 PhotosController의 unknown action으로 routing 합니다.

Wildcard segments는 "route globbing"이라고 불리는 것을 가능하게 하는데, 이는 특정 파라미터(위의 *other)가 라우트의 나머지 부분과 매칭되도록 지정하는 방법입니다.

따라서 위의 라우트는 photos/12 또는 /photos/long/path/to/12와 매칭되며, params[:other]"12" 또는 "long/path/to/12"로 설정합니다.

Wildcard segments는 라우트의 어느 위치에나 올 수 있습니다. 예를 들어:

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

books의 임의의 문자열 section과 title을 매칭시킵니다. section은 슬래시를 포함할 수 있어, "books/some/section/last-words-a-memoir/title"과 같은 요청이 { section: 'some/section/last-words-a-memoir', title: 'title' }라는 파라미터로 인식됩니다.

이것은 params[:section]'some/section'이고 params[:title]'last-words-a-memoir'books/some/section/last-words-a-memoir와 매칭됩니다.

기술적으로, 라우트는 하나 이상의 wildcard 세그먼트를 가질 수 있습니다. 매처는 세그먼트를 나타나는 순서대로 파라미터에 할당합니다. 예를 들어:

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

zoo/woo/foo/bar/baz를 매칭하며 params[:a]'zoo/woo'와 같고, params[:b]'bar/baz'와 같습니다.

3.12 세그먼트 포맷

다음과 같은 라우트 정의가 있다고 가정하면:

get "*pages", to: "pages#show"

이것은 URL의 모든 segments를 "pages" 파라미터에 저장하고 PagesController의 show action으로 라우팅합니다.

'/foo/bar.json'을 요청하면, params[:pages]'foo/bar'가 되고 요청 format은 params[:format]에 JSON으로 설정됩니다.

format의 기본 동작은 URL에 포함되어 있다면 Rails가 자동으로 이를 캡처하여 params[:format]에 포함시키지만, URL에 format이 반드시 필요한 것은 아닙니다.

명시적인 format이 없는 URL과 일치시키고 format 확장자가 포함된 URL을 무시하려면, 다음과 같이 format: false를 제공할 수 있습니다:

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

어떤 format 접미사도 처리하지 않고 페이지 URL의 모든 부분을 잡아내려면, 이런 route 설정을 사용하세요.

format 세그먼트를 필수로 만들어서 생략할 수 없게 하려면, 다음과 같이 format: true를 넣을 수 있습니다:

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

"*pages"와 매칭되는 모든 route를 pages#show action으로 보냅니다. format을 true로 설정하면 URL에 format 매개변수가 포함될 수 있습니다.

3.13 Redirection

라우터에서 redirect 헬퍼를 사용하여 어떤 경로든 다른 경로로 리다이렉트할 수 있습니다:

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

/stories로의 요청을 /articles로 리다이렉트합니다

리디렉션 경로 내에서 match의 동적 세그먼트를 재사용할 수도 있습니다:

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

"/stories/:name" 으로 들어온 request를 "/articles/%{name}" 으로 리디렉션합니다.

redirect에 block을 제공할 수도 있습니다. 이 block은 심볼화된 path 파라미터와 request 객체를 받습니다:

get "/stories/:name", to: redirect { |path_params, req| "/articles/#{path_params[:name].pluralize}" } # 객체의 복수형으로 stories 매개변수를 리다이렉트
get "/stories", to: redirect { |path_params, req| "/articles/#{req.subdomain}" } # 서브도메인으로 리다이렉트

기본 리다이렉션은 301 "Moved Permanently" 리다이렉트라는 점을 참고하세요. 일부 웹 브라우저나 프록시 서버가 이러한 유형의 리다이렉트를 캐시하여 이전 페이지에 접근할 수 없게 될 수 있다는 점에 유의하세요. :status 옵션을 사용하여 응답 상태를 변경할 수 있습니다.

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

:name parameter를 포함하는 URL path에서 다른 path로 redirect하는 예제입니다. redirect 메서드의 status 옵션으로 HTTP 상태 코드를 지정할 수 있습니다.

이러한 모든 경우에서 host(http://www.example.com)를 제공하지 않으면, Rails는 현재 request에서 해당 세부 정보를 가져갑니다.

3.14 Rack Application으로 라우팅하기

:toArticlesController 클래스의 index 메서드에 해당하는 'articles#index'와 같은 String으로 지정하는 대신, matcher의 endpoint로 어떤 Rack application이든 지정할 수 있습니다:

match "/application.js" MyRackApp으로 향하도록 하고, via: :all을 사용해 모든 HTTP 메소드에 대해 매칭합니다

MyRackAppcall에 응답하고 [status, headers, body]를 반환하는 한, 라우터는 Rack 애플리케이션과 컨트롤러 액션의 차이를 알 수 없습니다. 이는 Rack 애플리케이션이 모든 HTTP 동사를 처리하도록 허용하려는 경우 via: :all을 적절하게 사용하는 예시입니다.

흥미로운 점 - 'articles#index'ArticlesController.action(:index)로 확장되며, 이는 유효한 Rack 애플리케이션을 반환합니다.

proc/lambda는 call에 응답하는 객체이므로, 매우 간단한 라우트(예: 헬스 체크)를 인라인으로 구현할 수 있습니다. 예: get '/health', to: ->(env) { [204, {}, ['']] }

매처의 엔드포인트로 Rack 애플리케이션을 지정할 때, 수신 애플리케이션에서 라우트가 변경되지 않는다는 점을 기억하세요. 다음 라우트를 사용하는 경우 Rack 애플리케이션은 라우트가 /admin이 될 것으로 예상해야 합니다.

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

모든 HTTP method를 AdminApp으로 매칭합니다.

만약 Rack 애플리케이션이 루트 경로에서 요청을 받도록 하고 싶다면, mount를 사용하세요:

AdminApp을 "/admin" mount 합니다

3.15 root 사용하기

root 메서드를 사용하여 Rails가 '/'를 어디로 라우팅할지 지정할 수 있습니다:

root to: "pages#main"
root "pages#main" # 위의 단축 표현

일반적으로 root route는 파일 최상단에 위치시켜 첫번째로 매칭될 수 있도록 합니다.

root route는 기본적으로 GET 요청을 처리합니다. 하지만 다른 verb를 처리하도록 구성할 수도 있습니다 (예: root "posts#index", via: :post)

namespace와 scope 내부에서도 root를 사용할 수 있습니다:

root to: "home#index" # 루트 경로를 "home" 컨트롤러의 "index" 액션으로 연결합니다

namespace :admin do
  root to: "admin#index" # admin 네임스페이스의 루트 경로를 "admin" 컨트롤러의 "index" 액션으로 연결합니다
end

위 코드는 /adminAdminControllerindex action에 매칭하고, /HomeControllerindex action에 매칭합니다.

3.16 유니코드 문자 라우트

라우트에 유니코드 문자를 직접 지정할 수 있습니다. 예시:

get "안녕하세요", to: "welcome#index"

3.17 Direct Route들

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

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

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

위 예시는 direct를 이용하여 homepage라는 이름의 URL을 직접 생성하는 방법을 보여줍니다. 해당 URL 생성 결과로 homepage_url을 호출하면 "https://rubyonrails.org" 가 반환됩니다.

블록의 반환값은 url_for 메서드의 인자로 유효해야 합니다. 따라서 유효한 string URL, Hash, Array, Active Model 인스턴스 또는 Active Model 클래스를 전달할 수 있습니다.

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

주석을 달 수 있는 모델로 직접 연결합니다.

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

# >> main_url
# => "http://www.example.com/pages"

3.18 resolve 사용하기

resolve 메소드는 모델의 polymorphic 매핑을 커스터마이징할 수 있게 해줍니다. 예를 들면:

resource :basket

resolve("Basket") { [:basket] }

:basket resource는 단수형 리소스입니다. URL 헬퍼는 단수형(예: basket_path)을 사용하고 있지만, 실제 모델 인스턴스를 검색할 때 사용되는 라우트 해석은 복수형인 :baskets를 사용하게 되어 있습니다. resolve 호출은 리소스 이름 매칭을 단수형으로 지정해서 이것을 수정합니다.

<%= form_with model: @basket do |form| %>
  <!-- basket form -->
<% end %>

위 코드는 변경없이 그대로 유지해야 하므로 번역하지 않았습니다.

이는 일반적인 /baskets/:id 대신 단수형 URL /basket을 생성할 것입니다.

4 Resourceful 라우트 커스터마이징

resources에 의해 생성되는 기본 라우트와 헬퍼는 보통 잘 동작하지만, 어떤 방식으로든 이를 커스터마이징해야 할 수도 있습니다. Rails는 resourceful 라우트와 헬퍼를 커스터마이징하는 여러 가지 방법을 제공합니다. 이 섹션에서는 사용 가능한 옵션들을 자세히 설명합니다.

4.1 사용할 Controller를 지정하기

:controller 옵션을 사용하면 resource에 사용할 controller를 명시적으로 지정할 수 있습니다. 예를 들면:

resources :photos, controller: "images"

이것은 요청을 photos_controller.rb 대신 images_controller.rb로 라우팅하도록 지정합니다.

/photos로 시작하는 수신 경로를 인식하지만 Images controller로 라우팅합니다:

HTTP Verb Path Controller#Action Named Route Helper
GET /photos images#index photos_path
GET /photos/new images#new new_photo_path
POST /photos images#create photos_path
GET /photos/:id images#show photo_path(:id)
GET /photos/:id/edit images#edit edit_photo_path(:id)
PATCH/PUT /photos/:id images#update photo_path(:id)
DELETE /photos/:id images#destroy photo_path(:id)

namespace가 적용된 controller의 경우 디렉토리 표기법을 사용할 수 있습니다. 예를 들어:

resources :user_permissions, controller: "admin/user_permissions"

admin 디렉토리에 있는 user_permissions 컨트롤러를 사용하면서 URL helper는 그대로 유지됩니다.

이것은 Admin::UserPermissionsController 인스턴스로 라우팅됩니다.

디렉토리 표기법만 지원됩니다. Ruby constant 표기법(예: controller: 'Admin::UserPermissions')으로 controller를 지정하는 것은 지원되지 않습니다.

4.2 id에 대한 제약 조건 지정하기

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

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

id에 두 개의 대문자와 하나 이상의 숫자가 있어야 하는 패턴으로 제한하는 예입니다.

이 선언은 :id 파라미터가 주어진 regular expression과 일치하도록 제한합니다. 라우터는 더 이상 /photos/1을 이 라우트에 매칭하지 않습니다. 대신 /photos/RR27이 매칭될 것입니다.

블록 형식을 사용하여 여러 라우트에 적용할 단일 constraint를 지정할 수 있습니다:

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

이 블록 내의 모든 routes는 두 개의 대문자와 그 뒤에 숫자가 있어야 하는 id segment에 의해 제약됩니다.

이 컨텍스트에서도 non-resourceful 라우팅 섹션에서 제공되는 advanced constraints를 사용할 수 있습니다.

기본적으로 :id 파라미터는 점(dot)을 허용하지 않습니다 - 이는 점이 formatted 라우트의 구분자로 사용되기 때문입니다. :id 내에서 점을 사용해야 한다면 이를 재정의하는 constraint를 추가하세요 - 예를 들어 id: /[^\/]+/는 슬래시를 제외한 모든 것을 허용합니다.

4.3 Named Route Helpers 오버라이딩하기

:as 옵션을 사용하면 route helpers의 기본 명칭을 오버라이드할 수 있습니다. 예를 들어:

resources :photos, as: "images"

리소스의 URL helper를 다르게 지정할 수 있지만, path 자체는 그대로 유지합니다. URL helper를 photos_path 대신 images_path로 사용할 수 있게 됩니다.

이것은 /photos와 매칭되고 평소처럼 PhotosController로 요청을 라우팅하지만, :as 옵션의 값을 사용하여 아래와 같이 헬퍼를 images_path 등으로 이름 짓습니다:

HTTP Verb Path Controller#Action Named Route Helper
GET /photos photos#index images_path
GET /photos/new photos#new new_image_path
POST /photos photos#create images_path
GET /photos/:id photos#show image_path(:id)
GET /photos/:id/edit photos#edit edit_image_path(:id)
PATCH/PUT /photos/:id photos#update image_path(:id)
DELETE /photos/:id photos#destroy image_path(:id)

4.4 newedit 경로 이름 변경하기

:path_names 옵션을 사용하면 경로의 기본 newedit 세그먼트를 재정의할 수 있습니다. 예를 들어:

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

new나 edit와 같은 자동 생성되는 path 세그먼트를 수정합니다. 위 예제는 다음을 생성합니다:

이렇게 하면 /photos/new/photos/1/edit 대신 /photos/make/photos/1/change와 같은 경로를 사용할 수 있습니다.

route helper와 controller action 이름은 이 옵션에 의해 변경되지 않습니다. 위의 두 경로는 여전히 new_photo_pathedit_photo_path helper를 가지며 newedit action으로 라우팅됩니다.

scope 블록을 사용하여 모든 route에 대해 이 옵션을 일괄적으로 변경할 수도 있습니다:

scope path_names: { new: "make" } do
  # 나머지 route들
end

4.5 :as로 Named Route Helper에 접두사 붙이기

:as 옵션을 사용하여 Rails가 라우트에 대해 생성하는 named route helper에 접두사를 붙일 수 있습니다. 이 옵션은 path scope를 사용하는 라우트 간의 이름 충돌을 방지하기 위해 사용합니다. 예를 들어:

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

resources :photos

"admin" scope 내에서 photos를 admin_photos라는 이름으로 정의하면서도, scope 외부에서는 일반적인 photos 리소스를 따로 가질 수 있습니다.

이는 /admin/photos의 라우트 헬퍼를 photos_path, new_photos_path 등에서 admin_photos_path, new_admin_photo_path 등으로 변경합니다. scoped resources :photosas: 'admin_photos'를 추가하지 않으면, non-scoped resources :photos는 어떤 라우트 헬퍼도 가지지 않게 됩니다.

라우트 헬퍼 그룹에 접두사를 붙이려면, scope와 함께 :as를 사용하세요:

"admin" scope로, "admin"이라는 이름으로 스코프를 지정하고
내부에서 photos와 accounts 리소스를 정의합니다.  

photos와 accounts 리소스를 정의합니다.

이전과 마찬가지로 이는 /admin scope가 지정된 resource helper들을 admin_photos_pathadmin_accounts_path로 변경하고, scope가 지정되지 않은 resource들은 photos_pathaccounts_path를 사용할 수 있게 합니다.

namespace scope는 :module:path prefix뿐만 아니라 :as도 자동으로 추가합니다.

4.6 중첩된 Resource에서 :as 사용하기

:as 옵션은 중첩된 라우트에서도 resource의 라우팅 헬퍼 이름을 오버라이드할 수 있습니다. 예를 들어:

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

위 코드는 URL helper를 다시 명명할 수 있게 해줍니다. 이 경우에는 magazine_ads_url 경로 헬퍼 대신에 magazine_periodical_ads_url을 생성하게 됩니다.

이렇게 하면 기본값인 magazine_ads_urledit_magazine_ad_path 대신에 magazine_periodical_ads_urledit_magazine_periodical_ad_path 같은 routing helper가 생성됩니다.

4.7 매개변수적인 Scope들

named parameter로 routes에 접두사를 붙일 수 있습니다:

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

:account_id scope를 생성하며, :account_id는 숫자로만 구성되어야 합니다. scope는 resources :articles를 포함하고 있습니다.

이렇게 하면 /1/articles/9와 같은 path들이 제공되며, controllers, helpers, views에서 path의 account_id 부분을 params[:account_id]로 참조할 수 있습니다.

또한 account_로 시작하는 path와 URL helper들이 생성되어, 예상대로 객체들을 전달할 수 있습니다.

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" ...>

:as 옵션은 필수는 아니지만, 이것이 없으면 Rails는 url_for([@account, @article]) 또는 form_with와 같은 url_for에 의존하는 다른 헬퍼들을 평가할 때 에러를 발생시킵니다.

4.8 생성되는 라우트 제한하기

기본적으로 resources를 사용하면 7개의 기본 action(index, show, new, create, edit, update, destroy)에 대한 라우트가 생성됩니다. :only:except 옵션을 사용하여 생성되는 라우트를 제한할 수 있습니다.

:only 옵션은 Rails에게 지정된 라우트만 생성하도록 지시합니다:

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

인덱스와 쇼 액션만 포함한 RESTful한 라우트를 생성하고자 하는 경우에 사용할 수 있습니다.

이제 /photos 또는 /photos/:id에 대한 GET 요청은 성공하지만, /photos에 대한 POST 요청은 일치하지 않게 됩니다.

:except option은 Rails가 생성하지 않아야 할 route나 route 목록을 지정합니다:

resources :photos, except: :destroy

:destroy 액션을 제외한 모든 기본 라우팅을 생성합니다.

이 경우 Rails는 destroy 라우트(/photos/:id에 대한 DELETE 요청)를 제외한 모든 일반 라우트를 생성합니다.

애플리케이션에 많은 RESTful 라우트가 있다면 :only:except를 사용해 실제로 필요한 라우트만 생성하는 것이 사용되지 않는 라우트를 제거함으로써 메모리 사용량을 줄이고 라우팅 프로세스의 속도를 향상시킬 수 있습니다.

4.9 번역된 Path들

scope를 사용하면 resources로 생성된 path 이름을 변경할 수 있습니다:

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

routes를 scope로 감싸서 경로 이름을 다른 것으로 변경할 수 있습니다. 위 예시에서는 /categories/new/kategorien/neu가 되고 /categories/1/edit/kategorien/1/bearbeiten이 됩니다.

Rails는 이제 CategoriesController로 향하는 라우트들을 생성합니다.

HTTP Verb Path Controller#Action Named Route Helper
GET /kategorien categories#index categories_path
GET /kategorien/neu categories#new new_category_path
POST /kategorien categories#create categories_path
GET /kategorien/:id categories#show category_path(:id)
GET /kategorien/:id/bearbeiten categories#edit edit_category_path(:id)
PATCH/PUT /kategorien/:id categories#update category_path(:id)
DELETE /kategorien/:id categories#destroy category_path(:id)

4.10 Resource의 단수형 지정하기

Resource의 단수형을 재정의해야 하는 경우, inflections를 통해 Active Support Inflector에 규칙을 추가할 수 있습니다:

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

4.11 기본 라우트 파라미터 id 이름 변경하기

:param 옵션을 사용하여 기본 파라미터 이름 id를 변경할 수 있습니다. 예시:

resources :videos, param: :identifier

:identifier로 지정된 param을 사용하여 :videos resource를 정의합니다.

이제 params[:id] 대신 params[: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(id: params[:identifier])

# 다음과 같이 하는 대신
Video.find_by(id: params[:id])

연관된 모델의 URL을 생성하기 위해 ActiveRecord::Base#to_param을 오버라이드할 수 있습니다:

class Video < ApplicationRecord
  def to_param
    identifier
  end
end

한 모델에서 URL에 기본 id 대신 다른 속성을 사용하기를 원한다면, to_param 메서드를 오버라이드하세요.

irb> video = Video.find_by(identifier: "Roman-Holiday") 
irb> edit_video_path(video)
=> "/videos/Roman-Holiday/edit"

5 라우트 검사하기

Rails는 라우트를 검사하고 테스트할 수 있는 몇 가지 다른 방법을 제공합니다.

5.1 기존 라우트 나열하기

애플리케이션에서 사용 가능한 라우트의 전체 목록을 보려면, development 환경에서 http://localhost:3000/rails/info/routes를 방문하세요. 터미널에서 bin/rails routes 명령어를 실행하여 동일한 출력을 얻을 수도 있습니다.

두 방법 모두 config/routes.rb에 나타나는 순서대로 모든 라우트를 나열할 것입니다. 각 라우트에 대해 다음과 같은 정보를 볼 수 있습니다:

  • 라우트 이름(있는 경우)
  • 사용된 HTTP verb(라우트가 모든 verb에 응답하지 않는 경우)
  • 매칭할 URL 패턴
  • 해당 라우트의 라우팅 파라미터

예를 들어, 다음은 RESTful 라우트에 대한 bin/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

라우트 이름(예를 들어 위의 new_user)은 라우트 헬퍼를 생성하는 기본이 될 수 있습니다. 라우트 헬퍼의 이름을 얻으려면 라우트 이름에 _path 또는 _url 접미사를 추가하세요(예: new_user_path).

또한 --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

5.2 Routes 검색하기

grep 옵션 -g을 사용하여 routes를 검색할 수 있습니다. 이는 URL helper 메소드 이름, HTTP verb, URL 경로와 부분적으로 일치하는 모든 routes를 출력합니다.

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

Rails route를 검색할 때 pattern matching을 사용할 수 있습니다. pattern을 -g와 함께 지정하면 경로 이름, HTTP 메서드 또는 URL 경로와 매칭되는 route들만 표시됩니다.

특정 controller에 매핑되는 routes만 보고 싶다면, -c controller 옵션을 사용할 수 있습니다.

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

위 명령어들은 특정 controller의 route만 표시합니다.

터미널 창을 출력 라인이 줄바꿈되지 않을 때까지 넓히거나 --expanded 옵션을 사용하면 bin/rails routes 의 출력을 더 쉽게 읽을 수 있습니다.

5.3 사용되지 않는 Route 목록 보기

--unused 옵션을 사용하면 애플리케이션에서 사용되지 않는 route를 스캔할 수 있습니다. Rails에서 "사용되지 않는" route는 config/routes.rb 파일에 정의되어 있지만 애플리케이션의 어떤 controller action이나 view에서도 참조되지 않는 route를 말합니다. 예시:

$ bin/rails routes --unused
사용되지 않는 route 8개를 찾았습니다:

     Prefix Verb   URI Pattern                Controller#Action
     people GET    /people(.:format)          people#index
            POST   /people(.:format)          people#create
 new_person GET    /people/new(.:format)      people#new
edit_person GET    /people/:id/edit(.:format) people#edit
     person GET    /people/:id(.:format)      people#show
            PATCH  /people/:id(.:format)      people#update
            PUT    /people/:id(.:format)      people#update
            DELETE /people/:id(.:format)      people#destroy

5.4 Rails Console에서의 Routes

Rails Console 내에서 Rails.application.routes.url_helpers를 사용하여 route helper에 접근할 수 있습니다. 이들은 app 객체를 통해서도 사용할 수 있습니다. 예시:

irb> Rails.application.routes.url_helpers.users_path
=> "/users"

irb> user = User.first 
=> #<User:0x00007fc1eab81628
irb> app.edit_user_path(user) 
=> "/users/1/edit"

6 Routes 테스트하기

Rails는 routes 테스트를 더 간단하게 만들기 위해 3가지 내장된 assertion을 제공합니다:

6.1 assert_generates Assertion

assert_generates는 특정 옵션 세트가 특정 경로를 생성하는지 검증하며 기본 라우트나 커스텀 라우트에서 사용할 수 있습니다. 예시:

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

위 코드는 주어진 URL 경로가 올바른 route 매핑으로 생성되었는지를 검증합니다.

6.2 assert_recognizes Assertion

assert_recognizesassert_generates의 반대입니다. 주어진 경로가 인식되고 애플리케이션의 특정 위치로 라우팅되는지 검증합니다. 예를 들어:

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

이것은 요청 "/photos/1"이 지정된 controller, action, parameters를 인식하는지 확인합니다.

HTTP verb를 지정하기 위해 :method 인자를 제공할 수 있습니다:

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

path와 method가 주어진 controller와 action으로 인식되는지 검증합니다.

6.3 assert_routing Assertion

assert_routing assertion은 양방향으로 라우트를 체크합니다. assert_generatesassert_recognizes의 기능을 합친 것입니다. 경로가 옵션을 생성하는지, 그리고 옵션이 경로를 생성하는지 모두 테스트합니다:

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

주어진 path와 HTTP method가 올바른 controller와 action으로 routing되는지 assertion합니다.

7 draw로 큰 라우트 파일 분리하기

수천 개의 라우트가 있는 대규모 애플리케이션에서는 단일 config/routes.rb 파일이 다루기 어렵고 읽기 힘들어질 수 있습니다. Rails는 draw 매크로를 사용하여 하나의 routes.rb 파일을 여러 개의 작은 파일로 분리하는 방법을 제공합니다.

예를 들어, admin 영역과 관련된 모든 라우트를 포함하는 admin.rb 파일과 API 관련 리소스를 위한 api.rb 파일 등을 추가할 수 있습니다.

# config/routes.rb

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

  draw(:admin) # `config/routes/admin.rb`에 위치한 다른 route 파일을 로드할 것입니다
end
# config/routes/admin.rb 

namespace :admin do
  resources :comments 
end

Rails.application.routes.draw 블록 내에서 draw(:admin)를 호출하면 주어진 인자와 동일한 이름을 가진 route 파일(이 예시에서는 admin.rb)을 로드하려고 시도합니다. 이 파일은 config/routes 디렉토리나 하위 디렉토리(예: config/routes/admin.rb 또는 config/routes/external/admin.rb) 내에 위치해야 합니다.

admin.rb와 같은 보조 라우팅 파일 내에서 일반적인 라우팅 DSL을 사용할 수 있지만, Rails.application.routes.draw 블록으로 감싸지는 마세요. 이는 메인 config/routes.rb 파일에서만 사용되어야 합니다.

정말 필요한 경우가 아니라면 이 기능을 사용하지 마세요. 여러 개의 라우팅 파일을 사용하면 한 곳에서 route들을 발견하기가 더 어려워집니다. 대부분의 애플리케이션에서는 - 심지어 수백 개의 route가 있는 경우에도 - 개발자들에게는 단일 라우팅 파일을 가지는 것이 더 쉽습니다. Rails 라우팅 DSL은 이미 namespacescope를 통해 route들을 체계적으로 분리하는 방법을 제공합니다.



맨 위로