티스토리 뷰

프로그래밍 공부/TIL : Rails Tutorial

Chapter 9 : Rails Routing from the Outside In

마음 따뜻한 개발자, 나른한 하루 2020. 7. 13. 01:00
이 글은 Rails 5.0 Guide 기준으로 작성됩니다.
https://guides.rubyonrails.org/v5.0/routing.html

 

 

  • Rails Routing from the Outside In Intro

Rails 라우팅을 사용하면서 다루게 될 대면 기능을 서술합니다.

 

 

  • The Purpose of the Rails Router

Rails 라우터는 URL을 인식하고, 이를 컨트롤러의 동작으로 발송합니다. 또한 View에서 문자열을 하드 코딩 할 필요없이 path와 URL을 생성 할 수 있습니다.

 

1. Connecting URLs to Code

만약 외부로부터 아래와 같은 URL에 접속 시(혹은 request 할 경우)

GET /patients/17

아래 요청과 매칭됩니다.

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

요청은 patients controller 내 show Action으로 dispatch가 이루어지고, { id: '17' } 라는 parameters가 생성됩니다.

 

2. Generating Paths and URLs from Code

일부 라우터 규칙에 있어 path 이름을 따로 설정하고 싶을 때가 있습니다.

그럴 경우에는 아래와 같이 as 문법을 입력하면 됩니다.

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

 

그리고 View 코드에 표현에 있어, 아래와 같이 patient_path(@patient) 를 써주면 됩니다.

아래 코드는 @patient 객체가 가진 정보 중, ID값을 참고하여 이동됩니다. (link_to는 HTML의 a 태그와 같은 역할)

## Controller
@patient = Patient.find(17)

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

 

 

  • Resource Routing: the Rails Default

Resources 라우팅을 통해 index, show, new, edit, create, update, destroy Action(Restful API)에 대해 별도의 Route 규칙을 선언하는 대신 한 줄의 코드로 Restful API 규칙을 빠르게 선언할 수 있습니다.

 

1. Resources on the Web

브라우저는 GET, POST, PATCH, PUT 및 DELETE와 같은 특정 HTTP 메소드를 통해 URL을 요청하여 페이지를 요청합니다. 각 방법은 resources에 대한 작업을 수행하기 위한 요청입니다. resources 경로는 여러 관련 요청을 단일 컨트롤러의 작업에 매핑합니다.

 

예를들어, 아래의 요청에 대해서는

DELETE /photos/17

 

라우터의 아래 줄에 명시된 한 줄의 코드에 위의 DELETE Method에 대한 정의가 포함되어 있습니다. 

resources :photos

Rails는 위 요청을 parameters: {id : '17'} 을 가지고 photos controller의 destroy Action으로 전달합니다.

 

2. CRUD, Verbs, and Actions

Rails에서 resourceful route는 HTTP 동사와 URL을 컨트롤러 Action에 매핑합니다. 일반적으로 각 작업은 데이터베이스의 특정 CRUD 작업에 매핑됩니다.

 

다음은 Rails route의 resources 문법이 CRUD작업과 매핑이 되는것을 보여주는 도표입니다.

(기본적으로 resources 맵핑은 Restful API 규칙을 따릅니다.)

HTTP Verb Path Controller#Action 목적
GET /photos photos#index photos의 목록을 보여줍니다.
GET /photos/new photos#new photo 데이터 생성을 위한 form 페이지로 이동됩니다.
POST /photos photos#create photo 데이터를 생성합니다.
GET /photos/:id photos#show 특정 photo의 id값 데이터를 보여줍니다.
GET /photos/:id/edit photos#edit 기존의 photo 데이터를 수정하기 위한 form 페이지로 이동합니다.
PATCH/PUT /photos/:id photos#update photo 데이터 수정 처리가 이루어집니다.
DELETE /photos/:id photos#destroy photo 데이터 삭제 처리가 이루어집니다.

 

3. Path and URL Helpers

resourceful route를 생성 시, application 내의 많은 controller 및 헬퍼들이 노출됩니다.

  • 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) returns /photos/:id (예를 들어, photo_path(10) = /photos/10)

 

4. Defining Multiple Resources at the Same Time

하나 이상의 resources에 대한 경로를 만들어야 함에 있어, 아래와 같이 resources를 한번만 호출 후 추가하고자 하는 resources에 대해 아래와 같이 작성하면 됩니다.

resources :photos, :books, :videos

이를테면 위 코드는 아래와 동일하게 작업이 이루어집니다.

resources :photos
resources :books
resources :videos

 

5. Singular Resources

때로는 resource 문법에 있어 ID값이 필요가 없을 수도 있습니다. (예를들어 마이페이지 기능) 그렇다보니 하나의 자원(resource)에 대해선 ID값이 표기되지 않습니다.

만약 아래와 같이 현재 로그인된 유저의 정보를 열람해야 한다면 아래와 같이 라우터에서 정의내릴 수 있습니다.

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

이를테면, 본래 resources 에서라면 show 기능에는 :id 정보가 있어야 했으나, resource에는 :id 정보 없이 열람이 가능합니다.

 

위 코드와 같이 String을 전달하면 controller#action 형식이 필요하지만,

아래와 같이 Symbol을 전달하면 아래와 같이 컨트롤러도 지정해줘야 합니다.

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

 

Route 내에서 resource 문법이 정의될 경우

resource :profile

 

resource 문법은 다음 도표의 6가지 경로와 맵핑이 됩니다.

 참고  resources와 차이가 있다면, edit, update, show에는 id값을 받지 않는다는 점, index Action이 없다는 점입니다.

HTTP Verb Path Controller#Action 목적
GET /profile/new profile#new profile 데이터 생성을 위한 form 페이지로 이동됩니다.
POST /profile profile#create profile 데이터를 생성합니다.
GET /profile profile#show 특정 profile의 id값 데이터를 보여줍니다.
GET /profile/edit profile#edit 기존의 profile 데이터를 수정하기 위한 form 페이지로 이동합니다.
PATCH/PUT /profile profile#update profile 데이터 수정 처리가 이루어집니다.
DELETE /profile profile#destroy profile 데이터 삭제 처리가 이루어집니다.

 

singular resourceful route는 아래 Path helper와 같은 이름이 정의됩니다.

  • new_geocoder_path = /geocoder/new
  • edit_geocoder_path = /geocoder/edit
  • geocoder_path = /geocoder

 참고  오랜 버그로 인해 form_for helper 에서는 단일 리소스를 자동으로 사용할 수 없습니다. 이 문제를 해결하려면 다음과 같이 URL을 직접 지정해야 합니다.

form_for @geocoder, url: geocoder_path do |f|

 

6. Controller Namespaces and Routing

1) Namespace

네임 스페이스 아래에서 컨트롤러 그룹을 구성 할 수 있습니다. 가장 일반적으로 Admin::namespace 아래에 여러 관리 컨트롤러를 그룹화 할 수 있습니다 .

namespace :admin do
  resources :articles, :comments
end

위 코드를 토대로 컨트롤러는 app/controllers/admin 디렉토리 아래 에 놓고 라우터에서 그룹화 할 수 있습니다.

Admin::ArticlesControllerRails는 articles및 comments컨트롤러에 대해 아래와 같은 URI 패턴을 생성합니다.

 

2) Module

Controller은 namespace 방식으로 가리키되, Path는 기존의 resource(s) 방식으로 가리키고 싶을 경우, module 문법을 활용하면 됩니다.

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

## 위 표현과 동일한 문법
resources :articles, module: 'admin'
HTTP Verb Path Controller#Action Named Helper
GET /articles admin/articles#index articles_path
GET /articles/new admin/articles#new new_article_path
POST /articles admin/articles#create articles_path
GET /articles/:id admin/articles#show article_path(:id)
GET /articles/:id/edit admin/articles#edit edit_article_path(:id)
PATCH/PUT /articles/:id admin/articles#update article_path(:id)
DELETE /articles/:id admin/articles#destroy article_path(:id)

 

3) Scope

Controller은 기존의 resource(s) 방식으로 가리키되, Path는 namespace 방식으로 변경하고 싶을 경우, scope 문법을 활용하면 됩니다.

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

## 위 표현과 동일한 문법
resources :articles, path: '/admin/articles'
HTTP Verb Path Controller#Action Named 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)

 

7. Nested Resources

만약 resource(s) 안에 자식 resource(s)가 있는 경우, 라우터에서 block 형태로 다음과 같이 정의할 수 있습니다.

class Magazine < ApplicationRecord
  has_many :ads
end
 
class Ad < ApplicationRecord
  belongs_to :magazine
end
## config/routes.rb

resources :magazines do
  resources :ads
end
HTTP Verb Path Controller#Action Named Helper
megazine resources들... (생략), 아래는 megazine resources에 종속된 ads의 양식들입니다.
GET /magazines/:magazine_id/ads ads#index magazine ID에 종속된 모든 ads를 보여줍니다.
GET /magazines/:magazine_id/ads/new ads#new magazine ID에 종속된 ad 생성을 위한 form 페이지로 이동합니다.
POST /magazines/:magazine_id/ads ads#create magazine ID에 종속된 ad 데이터를 생성합니다.
GET /magazines/:magazine_id/ads/:id ads#show magazine ID에 종속된 ad의 id값 데이터를 보여줍니다.
GET /magazines/:magazine_id/ads/:id/edit ads#edit 기존의 magazine ID에 종속된 ad 데이터를 수정하기 위한 form 페이지로 이동합니다.
PATCH/PUT /magazines/:magazine_id/ads/:id ads#update 기존의 magazine ID에 종속된 ad 데이터 수정 처리가 이루어집니다.
DELETE /magazines/:magazine_id/ads/:id ads#destroy 기존의 magazine ID에 종속된 ad 데이터 삭제 처리가 이루어집니다.

 

1) Limits to Nesting

원하는 경우 resource(s) 중첩 내에 또 중첩을 할 수 있습니다. 예를 들면 아래와 같습니다.

## config/routes.rb

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

#=> /publishers/1/magazines/2/photos/3

 

2) Shallow Nesting

상위 계층의 Controller 내 Action들에 대해 대해서는 가만히 냅두나, 하위 resource(s)에서는 아래와 같이 특정 Action에 대해서만 URI를 열어두는 방법이 있습니다. 

 

필요하지 않은 상위 ​​수집 URL 규칙을 버려내는 작업으로서, :index , :create, :new Action만을 생성합니다.

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

하지만 위 방법을 좀 더 간결히 표현할 수 있는 방법이 있습니다.

## 방법 1 : 블록 내 resources 중, 일부에 대해 shallow 옵션 적용
resources :articles do
  resources :comments, shallow: true
end


## 방법 2 : 블록 내 resources 전체에 shallow 옵션 적용
resources :articles, shallow: true do
  resources :comments
end

 

scope에도 다음과 같이 :shallow_path 옵션 통해 루트 ID에 종속된 자식 resources가 없는 URI를 생성할 수 있습니다.

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

좌측 : shallow_path 옵션이 있는 scope, 우측 : 일반적인 scope

 

:shallow_prefix 옵션을 통해서도 아래와 같이 적용할 수 있습니다.

Path Helper에 변화를 줍니다.

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

 

8. Routing concerns

만약 아래와 같은 라우터 정의 예제가 있다고 합시다. :

## config/routes.rb

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

위 라우터에서 보면 comments에 대해 공통적으로 중첩이 되어있는게 확인할 수 있습니다.

이러한 중복 문제를 해결할 수 있는 문법 중 하나가 concerns 로서, 다른 리소스 및 경로 내에서 문법을 재사용할 수 있게 해줍니다.

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]

 

scope, namespace에서도 다음과 같이 concern 문법을 활용할 수 있습니다.

namespace :articles do
  concerns :commentable
end

 

9. Creating Paths and URLs From Objects

Rails는 라우팅 헬퍼를 사용하는 것 외에도 다양한 파라미터로부터 경로와 URL을 생성 할 수 있습니다. 예를 들어 다음과 같은 경로 집합이 있다고 가정합니다.

resources :magazines do
  resources :ads
end

# [ad#show] magazine_ad_path
# /magazines/:magazine_id/ads/:id

 

magazine_ad_path를 사용하는 경우 숫자 ID 대신 Magazine 및 Ad 인스턴스를 전달할 수 있습니다.

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

 

url_for 문법을 통해 다음과 같이 자동으로 URI 경로위치가 지정되게 할 수 있습니다.

 참고  url_for 내 대괄호 안에는 단순히 id값 만을 가진게 아닌, 객체 정보를 가진 변수 자체를 넣어줘야 합니다.

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

 

이 외에도 아래와 같이 다양하게 link_to 문법을 쓸 수 있습니다.

<%= link_to 'Ad details', [@magazine, @ad] %>
# /magazines/:magazine_id/ads/:id

<%= link_to 'Magazine details', @magazine %>
# /magazines/:id

<%= link_to 'Edit Ad', [:edit, @magazine, @ad] %>
# /magazines/:magazine_id/ads/:id/edit

 

10. Adding More RESTful Actions

1) member

RESTful API 외의 URI 생성에 있어, 복수(resources) URI를 생성하고 싶을 경우, 아래와 같이 collection 문법을 통해 URI 규칙을 생성해낼 수 있습니다.

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

위의 라우트 코드를 아래와 같이 표현을 해낼 수도 있습니다.

resources :photos do
  get 'preview', on: :member
end
HTTP Verb Path Controller#Action
GET /photos/:id/preview photos#preview
그 외 photos 관련 resources (index, show, new, edit, create, update, destroy)

 

2) collection

RESTful API 외의 URI 생성에 있어, 단일(resource) URI를 생성하고 싶을 경우, 아래와 같이 collection 문법을 통해 URI 규칙을 생성해낼 수 있습니다.

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

 

위의 라우트 코드를 아래와 같이 표현을 해낼 수도 있습니다.

resources :photos do
  get 'search', on: :collection
end
HTTP Verb Path Controller#Action
GET /photos/search photos#search
그 외 photos 관련 resources (index, show, new, edit, create, update, destroy)

 

3) Adding Routes for Additional New Actions

Controller의 새로운 Action 추가 및 URI에 대한 경로를 재정의 하고싶을 경우, 다음과 같이도 정의할 수 있습니다. 

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

이를 통해 Rails는 [GET] /comments/new/preview 와 같은 경로를 인식하고 CommentsController의 preview Action으로 라우팅 할 수 있습니다. 또한 preview_new_comment_url 및 preview_new_comment_path 2가지의 path helper를 생성합니다.

 

 

  • Non-Resourceful Routes

Rails는 resource(s) 라우팅 외에도 임의의 URL을 Controller의 Action으로 라우팅하는 기능을 지원합니다.

resource(s)가 많은 라우팅에 의해 자동으로 생성 된 경로 그룹을 얻지 못하나, 대신 application 내에서 각 경로를 별도로 설정해낼 수 있습니다.

 

일반적으로 resource(s) 문법을 통해 라우팅 정의를 많이 한다곤 하나, 때론 간단한 라우팅이 더 적합한 곳도 있으며, 특히 간단한 라우팅을 통해 레거시 URL에 대해 새로운 Action으로 쉽게 매핑 할 수 있습니다.

 

1. Bound Parameters

get ':controller(/:action(/:id))'

일반 경로를 설정할 때 Rails가 들어오는 HTTP 요청의 일부에 자동으로 라우터 규칙에 매핑하는 일련의 symbole을 제공합니다.

이러한 symbol에 있어 두 가지 특징이 있습니다.

  1) :controller는 응용 프로그램의 컨트롤러 이름에 매핑

  2) :action은 해당 컨트롤러 내의 작업 이름에 매핑

 

예를들어 /photos/show/1 로 홈페이지에 접속 시, Parameters: {"action"=>"show", "controller"=>"photos", "id"=>"1"} 로 맵핑됩니다.

 

2. Dynamic Segments

:controller 또는 :action 이외의 것은 매개 변수의 일부로 작업에 사용할 수 있습니다.

get ':controller/:action/:id/:user_id'

예를들어 /photos/show/1/2 로 홈페이지 접속 시, Parameters: {"action"=>"show", "controller"=>"photos", "id"=>"1", "user_id"=>"2"} 로 맵핑됩니다.

 참고  namespace 및 module에는 :controller symbol 표현을 못합니다.

만약 namespace에서 :controller symbol을 표현하고 싶다면 아래와 같이 regex(정규식) 설정을 해줘야 합니다.

get ':controller(/:action(/:id))', controller: /admin\/[^\/]+/

 

3. Static Segments

get ':controller/:action/:id/with_user/:user_id'

콜론(:)을 조각 앞에 추가하지 않고 라우트를 작성할 때 정적 세그먼트를 지정할 수 있습니다.

 

4. The Query String

get ':controller/:action/:id'

위 URI 문법을 기반으로, params에는 query string으로 부터 Parameters도 가지고 있습니다.

예를들어 /photos/show/1?user_id=2 홈페이지 접속 시, Parameters: { controller: 'photos', action: 'show', id: '1', user_id: '2' }

 

5. Defining Defaults

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

Route 내에서 :controller:action symbol을 명시 적으로 사용할 필요는 없습니다.

위와같이 to 옵션을 통해 기본값으로 설정할 수 있습니다.

 

또한 아래 문법과 같이, 해시 문법을 통해 :defaults 옵션을 설정해서 경로에 다른 기본값을 정의 할 수도 있습니다. 이는 동적 세그먼트로 지정하지 않은 parameters에도 적용됩니다.

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

위 라우터 예시를 기반으로 홈페이지에 접근 시, params 중 params[:format] = "jpg" 로 parameter가 전송됩니다.

 

6. Naming Routes

:as 옵션을 사용하여 path helper 이름을 지정할 수 있습니다.

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

 

7. HTTP Verb Constraints

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

일반적으로 get, post, put, patch, delete 메소드를 사용하여 특정 동사(verb; URI 행위 이름)에 대한 경로를 제한해야합니다.

match 메소드를 :via 옵션과 함께 사용하여 여러 동사를 한 번에 일치시킬 수 있습니다.

 

또한 아래와 같이 모든 Method에 대해 허용시킬 수도 있습니다.

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

 참고 1  GET 및 POST 요청을 single Action으로 라우팅시 보안에 영향을 미칩니다. 일반적으로 적절한 이유가없는 한 모든 동사를 동작으로 라우팅하지 않아야합니다. 

 참고 2  GET Method는 CSRF 취약점을 검사하지 않습니다. 만약 Database 접근(쓰기/삭제)을 행위하는 URI일 경우 GET 메소드를 써선 안됩니다.

 

8. Segment Constraints

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

 

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

또한 정규식 표현을 통해 문자열 매칭을 시킬 수 있습니다.

 

예를들어 위 :constraints 에 명시된 정규식을 토대로 /photos/A12345 에 대해선 웹사이트 접근을 할 수 있으나, /photos/893 경로는 정규식 규칙과 비일치하므로 접근이 안됩니다.

 

9. Request-Based Constraints

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

String을 반환하는 Request 객체의 모든 Method를 기반으로 경로를 제한할 수 있습니다. Request 기반 제한 조건을 정합니다.

위 코드를 예를들어, http://admin.domain.com/photos 를 통해선 접근이 허용되나, http://domain.com/photos 와 같은 경로로 접근은 제한됩니다.

 

또한, 위의 표현을 아래와 같이 정의내릴 수 있습니다.

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

 참고 1  subdomain에 있어 string을 통한 표현('admin')에 대해선 허용이 되나, symbold 표현(:admin)은 허용이 안됩니다.

 참고 2  format 설정에 있어 라우터에 get 'foo', constraints: { format: 'json' } 정의 후, request에 있어 format: json 을 주지 않아도 접속이 잘 됩니다. 이는 constraints: { format: 'json' } 는 단순히 선택사항(option)이기 때문입니다.

하지만 get 'foo', constraints: lambda { |req| req.format == :json } 을 정의할 경우, 이 때는 request에 있어 json 이어야지만 결과값이 return 됩니다. 

 

10. Advanced Constraints

class BlacklistConstraint
  def initialize
    @ips = Blacklist.retrieve_ips
  end
 
  def matches?(request)
    @ips.include?(request.remote_ip)
  end
end
 
Rails.application.routes.draw do
  get '*path', to: 'blacklist#index',
    constraints: BlacklistConstraint.new
end

만약 타 class를 통해 constraints 검증을 해야할 경우, 위와같이 코드를 짜낼 수 있습니다.

위 코드는 Blacklist Model 내 retrive_ips 컬럼을 기반으로 접속된 유저(request)의 IP와 blacklists 테이블 내에 등록되어있는 블랙리스트 IP에 대해 검사하는 코드입니다.

 

Lambda를 통해서도 아래와 같이 constraints 옵션을 줄 수 있습니다. 

## config/routes.rb

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

 

11. Route Globbing and Wildcard Segments

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

 

글로빙(globbing) Route는 특정 parameter가 나머지 모든 부분과 일치하도록 지정하는 방법입니다.

여기서 other 앞에 붙은 *은 "wildcard segments" 라고 합니다.

 

1) /photos/12 로 접속 시, Parameters: {"other"=>"12"}

2) /photos/long/path/to/12 로 접속 시, Parameters: {"other"=>"long/path/to/12"}

 

 참고  '/foo/bar.json'을 요청하면 params[:pages]는 요청 형식이 JSON 인 'foo/bar'와 같습니다.

 

12. Redirection

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

라우터의 Redirect helper을 통해 다른 경로로 리디렉션 할 수 있습니다.

 

 참고  redirect helper은 기본적으로 301(Moved Permanently) 응답을 합니다.

만약 status code를 바꾸고 싶을 경우, 아래와 같이 :status 옵션을 줄 수 있습니다.

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

 

13. Routing to Rack Applications

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

ArticlesController의 index Action에 해당하는 'articles#index'와 같은 문자열 표현 대신, 모든 Rack Application을 macher의 endpoint로 지정할 수 있습니다.

 

MyRackApp이 응답하고 [status, headers, body]을 return하는 한, router는 Rack Application과 Action의 사이의 차이점을 모릅니다. Rack Application이 적절하다고 간주되는 모든 동사를 처리 할 수 ​​있도록하려면 via: :all 을 적절하게 사용합니다.

 

 참고  'articles#index'가 실제로 ArticlesControlle의 action(:index)로 확장되어 유효한 Rack Application을 반환한다는 것입니다.

 

Rack Application이 루트 경로에서 요청을 받게 하려면. mount를 사용하면 됩니다.

mount AdminApp, at: '/admin'

 

 

14. Using root

## config/routes.rb

Rails.application.routes.draw do
  root to: 'pages#main'
  root 'pages#main' # 위 root to: 의 축약 표현
end

메인 페이지('/') 접근에 있어, 보여질 페이지에 대해 설정할 수 있습니다.

root 설정은  config/routes.rb  블록 내의 최상단에 표현되어야 합니다.

 참고  root path 설정은 GET Method에 대해서만 설정 가능

 

다음과 같이 개별 URI 공간을 생성하는 namespace 내에서도 root 설정이 가능합니다.

Rails.application.routes.draw do
  namespace :admin do
    root to: "admin#index"
  end

  root to: "home#index"
end

 

15. Unicode character routes

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

라우터 경로설정에 있어, 단순히 unicode 문자에 대해서도 설정할 수 있습니다.

 

 

  • Customizing Resourceful Routes

resources :articles 에 의해 생성되는 URI와 Path helper은 일반적으로 잘 작동하지만, 사용자 임의대로 설정할 수도 있습니다.

Rails를 사용하면 리소스가 많은 헬퍼의 거의 모든 부분을 사용자 정의 할 수 있습니다.

 

1. Specifying a Controller to Use

resources :photos, controller: 'images'

:controller 옵션을 사용하면 리소스에 사용할 컨트롤러를 정할 수 있습니다.

resources와 :controller 옵션을 사용한 Router 규칙은 아래와 같습니다.

HTTP Verb Path Controller#Action Named 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)

 

다음과 같은 표기로도 작성할 수 있습니다.

resources :user_permissions, controller: 'admin/user_permissions'

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

 

2. Specifying Constraints

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

 

:constraints 옵션을 통해 params[:id] 에 정규식 형식을 지정할 수 있습니다.

아래와 같이 block 형식으로도 정의내릴 수 있습니다.

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

 

3. Overriding the Named Helpers

resources :photos, as: 'images'

:as 옵션을 통해 Path Helper 이름을 재정의 할 수 있습니다.

HTTP Verb Path Controller#Action Named 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. Overriding the new and edit Segments

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

 

:path_names 옵션을 통해 Path 이름이 override 됩니다.

photos 에서 new 및 edit Path를 보면 명칭이 다른게 보임.

 참고 1  실제 Controller 내 Action 이름은 변경되지 않습니다.

 참고 2  모든 경로에 대해이 옵션을 균일하게 변경하려는 경우 scope 문법을 활용할 수 있습니다. (7번 째 : Translated Paths 참고)

scope path_names: { new: 'make' } do
  # rest of your routes
end

 

5. Prefixing the Named Route Helpers

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

:as 옵션을 사용하여 기존의 Path Helper를 as 이름에 맞추어 접두어로 사용할 수 있습니다. 경로 간의 이름 충돌을 방지하려면이 옵션을 사용하세요. (사용 예시는 위와 같음.)

 

아래와 같이 scope 블록 전체에도 적용해낼 수 있습니다.

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

 

prefix router에 대해선 아래와 같이도 작성할 수 있습니다.

scope ':username' do
  resources :articles
end

 참고  만약 /kcm/articles 로 접속 시, parameters: {"controller"=>"articles", "action"=>"index", "username"=>"kcm"}

 

6. Restricting the Routes Created

## [GET] photos, [GET] photos/:id 만 생성
resources :photos, only: [:index, :show]

## 전체 RESTful API에서 [DELETE] photos/:id 만 제거
resources :photos, except: :destroy

기본적으로 Rails는 애플리케이션의 모든 RESTful 경로에 대해 7 가지 기본 작업(index, show, new, create, edit, update, destroy; resources 기준)에 대한 경로를 만듭니다.

:only:except 옵션을 사용하여 라우터 경로를 설정합니다.

  1) :only  Resftul API에서 지정된 Action에 대해서만 생성합니다.

  2) :except  Resftul API에서 지정된 Action에 대해 제거합니다.

 

 참고  Application에 많은 RESTful 경로가 있는 경우, :only, :except 옵션을 통해 실제 필요한 URI만 생성 시, 메모리 사용을 줄이고 라우팅 프로세스 속도를 높일 수 있습니다.

 

 

7. Translated Paths

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

scope 문법을 통해 resources에서 생성 된 Path 이름을 변경할 수 있습니다.

HTTP Verb Path Controller#Action Named 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)

 

8. Overriding the Singular Form

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

 

singular form of resource(단일 형태의 resource)을 정의하려면 Inflector에 규칙을 추가해야합니다.

라우터에서 Path Helper 네이밍 표현에 있어, URI의 역할에 따라 단수/복수 구분을 하여 네이밍을 하곤 합니다.

resources :mice 설정 시, Path Helper에서 역할에 맞게 단수/복수 이름이 쓰임

이는 ActiveSupport::Inflector.inflections 에서 이름에 대한 교정을 자동으로 해주기 때문입니다.

이 기능을 이용해서 개발자가 임의의 단수-복수 네이밍을 설정해줘야 할 경우 아래과 같이 해낼 수 있습니다.

ActiveSupport::Inflector.inflections do |inflect|
  # inflect.irregular '(singular; 단수)', '(plural; 복수)'
  inflect.irregular 'ping', 'pong'
end

 

 Dash (Rails API)  ActiveSupport::Inflector

class의 singleton instance는 ActiveSupport::Inflector#inflections에 의해 생성되며, 추가 inflection 규칙을 지정하는 데 사용할 수 있습니다. locale(Application 언어설정)을 전달하면 다른 언어에 대한 규칙을 지정할 수 있습니다. 기본 locale은 :en (영어)로서, 영어 규칙만 제공됩니다.

 

9. Using :as in Nested Resources

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

:as 옵션은 resources를 통해 정의된 Path Helper 이름을 재정의 합니다.

위 예시를 보면 Path Helper 이름이 ads 에서 periodical_ads 로 재정의 되어있는걸 볼 수 있습니다.

 

10. Overriding Named Route Parameters

resources :videos, param: :identifier

 

:param 옵션은 기본 resource 식별자인 :id (라우트를 생성하는 데 사용되는 동적 세그먼트의 이름)를 재정의합니다.

params[<:param>]을 사용하여 컨트롤러에서 해당 세그먼트에 액세스 할 수 있습니다.

기존에 URI에서 ID를 받는 인자가 params[:id] 이었지만, :params 옵션으로 인해 params[:identifier] 로 바뀌어져 있음.

 

ActiveRecord::Base#to_param 에서 아래와 같이 override를 해낼 수 있습니다.

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

 

 

  • Inspecting and Testing Routes

Rails에서는 경로 검사 및 테스트를 위한 기능을 제공합니다.

 

1. Listing Existing Routes

1) Route의 전체 URI 목록을 보려면 서버가 켜진 상태에서 http://localhost:3000/rails/info/routes 를 방문하면 됩니다.

2) 혹은 터미널에서 rails routes 명령을 실행하여 동일한 결과를 볼 수 있습니다.

 

홈페이지 접속 혹은 명령어 방법 모두  config/routes.rb  에 작성된 순서대로 모든 라우터 경로가 보여집니다.

 

 

grep 옵션을 사용하여 경로를 검색 할 수 있습니다 : [옵션] -g

URL의 Path Helper 이름, HTTP 동사, URL 경로와 부분적으로 일치하는 경로를 출력합니다.

grep -g option을 이용한 라우터 탐색

만약 특정 Controller를 가리키는 라우터를 탐색하고 싶을 경우, -c 옵션을 활용하면 됩니다.

grep -c option을 이용한 라우터 탐색

 

2. Testing Routes

Rails는 route를 간단하게 테스트 하기 위해 3가지 built-in assertion을 제공합니다.

  • assert_generates
  • assert_recognizes
  • assert_routing

1) The assert_generates Assertion

assert_generates 은 특정 옵션 설정이 경로(path)를 생성하고 기본 routes 또는 사용자 정의 routes와 함께 사용될 수 있습니다.

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

 

2) The assert_recognizes Assertion

assert_recognizes는 assert_generates의 반대적인 특징을 가집니다.

주어진 경로를 인식하고 Application의 특정 지점으로 경로를 지정합니다.

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

 

HTTP 동사를 지정하기 위해 Method을 설정할 수 있습니다.

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

 

3) The assert_routing Assertion

assert_routing assertion은 route를 두 가지 방법으로 경로를 확인합니다. :

Path가 Option을 생성하는지, Option이 Path를 생성하는지 테스트

 

또한, The assert_routing Assertion은 위에 언급됐던 assert_generates와 assert_recognizes 두 기능의 특징을 가지고 있습니다.

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

 

 

  • 자료 참고

1. riptutorial : 경로 범위 지정

 

댓글
댓글쓰기 폼
공지사항
Total
44,670
Today
11
Yesterday
141
링크
«   2020/09   »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30      
글 보관함