Ruby on Rails
라우팅
수색…
소개
비고
일반적으로 "라우팅"은 앱에서 URL을 "처리"하는 방법입니다. Rails의 경우 일반적으로 어떤 컨트롤러인지, 컨트롤러의 어떤 액션이 특정 들어오는 URL을 처리 할 것인가입니다. Rails 응용 프로그램에서 경로는 대개 config/routes.rb
파일에 있습니다.
리소스 라우팅 (기본)
경로는 config/routes.rb
정의됩니다. 이들은 종종 resources
또는 resource
방법을 사용하여 관련된 라우트 그룹으로 정의됩니다.
resources :users
는 다음 7 개의 경로를 만들고 UsersController
모든 작업에 매핑합니다.
get '/users', to: 'users#index'
post '/users', to: 'users#create'
get '/users/new', to: 'users#new'
get '/users/:id/edit', to: 'users#edit'
get '/users/:id', to: 'users#show'
patch/put '/users/:id', to: 'users#update'
delete '/users/:id', to: 'users#destroy'
액션 이름은 위의 to
매개 변수의 #
뒤에 표시됩니다. 같은 이름의 메소드는 다음과 같이 app/controllers/users_controller.rb
정의되어야합니다.
class UsersController < ApplicationController
def index
end
def create
end
# continue with all the other methods…
end
다음 only
생성되거나 except
된 동작을 제한 할 수 있습니다.
resources :users, only: [:show]
resources :users, except: [:show, :index]
주어진 시간에 다음을 실행하여 애플리케이션의 모든 경로를 볼 수 있습니다.
$ rake routes
$ rake routes
# OR
$ 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
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
특정 컨트롤러에 매핑되는 경로 만 보려면 :
$ rake routes -c static_pages
static_pages_home GET /static_pages/home(.:format) static_pages#home
static_pages_help GET /static_pages/help(.:format) static_pages#help
$ rake routes -c static_pages
static_pages_home GET /static_pages/home(.:format) static_pages#home
static_pages_help GET /static_pages/help(.:format) static_pages#help
# OR
$ rails routes -c static_pages
static_pages_home GET /static_pages/home(.:format) static_pages#home
static_pages_help GET /static_pages/help(.:format) static_pages#help
-g
옵션을 사용하여 경로를 검색 할 수 있습니다. helper 메소드 이름, URL 경로 또는 HTTP 동사와 부분적으로 일치하는 경로를 보여줍니다.
$ rake routes -g new_user # Matches helper method
$ rake routes -g POST # Matches HTTP Verb POST
$ rake routes -g new_user # Matches helper method
$ rake routes -g POST # Matches HTTP Verb POST
# OR
$ rails routes -g new_user # Matches helper method
$ rails routes -g POST # Matches HTTP Verb POST
또한 개발 모드에서 rails
서버를 실행할 때 <hostname>/rails/info/routes
에서 우선 순위가 일치하는 검색 필터로 모든 경로를 표시하는 웹 페이지에 액세스 할 수 있습니다. 다음과 같이 보입니다.
돕는 사람 | HTTP 동사 | 통로 | 컨트롤러 # 액션 |
---|---|---|---|
경로 / URL | [경로 일치] | ||
users_path | 도망 | /users(.:format) | users # index |
우편 | /users(.:format) | users # create | |
new_user_path | 도망 | /users/new(.:format) | 사용자 # 명 |
edit_user_path | 도망 | /users/ : id / edit(.:format) | 사용자 # 편집 |
user_path | 도망 | /users/:id(.:format) | 사용자 # 명 |
반점 | /users/:id(.:format) | 사용자 # 업데이트 | |
놓다 | /users/:id(.:format) | 사용자 # 업데이트 | |
지우다 | /users/:id(.:format) | 사용자 # 명 삭제 |
라우트는 routes.rb
의 resources
대신 메서드 resource
를 사용하여 멤버 (콜렉션이 아님)에서만 사용할 수 있습니다. resource
사용하면 명시 적으로 다음과 같이 요청할 때만 index
경로가 기본적으로 만들어지지 않습니다.
resource :orders, only: [:index, :create, :show]
제약 조건
제약 조건을 사용하여 사용 가능한 경로를 필터링 할 수 있습니다.
다음과 같은 제약 조건을 사용하는 몇 가지 방법이 있습니다.
예를 들어 특정 IP 주소로만 경로에 액세스 할 수 있도록 요청 된 기반 제약 조건 :
constraints(ip: /127\.0\.0\.1$/) do
get 'route', to: "controller#action"
end
비슷한 다른 예를 봅니다. ActionDispatch :: Routing :: Mapper :: Scoping .
좀 더 복잡한 작업을 원한다면 고급 제한 조건을 사용하고 논리를 래핑 할 클래스를 생성 할 수 있습니다.
# lib/api_version_constraint.rb
class ApiVersionConstraint
def initialize(version:, default:)
@version = version
@default = default
end
def version_header
"application/vnd.my-app.v#{@version}"
end
def matches?(request)
@default || request.headers["Accept"].include?(version_header)
end
end
# config/routes.rb
require "api_version_constraint"
Rails.application.routes.draw do
namespace :v1, constraints: ApiVersionConstraint.new(version: 1, default: true) do
resources :users # Will route to app/controllers/v1/users_controller.rb
end
namespace :v2, constraints: ApiVersionConstraint.new(version: 2) do
resources :users # Will route to app/controllers/v2/users_controller.rb
end
end
하나의 양식, 여러 제출 버튼
양식의 제출 태그 값을 제약 조건으로 사용하여 다른 작업으로 라우팅 할 수도 있습니다. 여러 개의 제출 버튼이있는 양식 (예 : '미리보기'및 '제출')이있는 경우 javascript를 사용하여 양식 도착 URL을 변경하는 대신 routes.rb
에서이 제약 조건을 직접 캡처 할 수 있습니다. 예를 들어, commit_param_routing gem을 사용하면 레일즈 submit_tag
Rails submit_tag
첫 번째 매개 변수를 사용하면 양식 커밋 매개 변수의 값을 변경할 수 있습니다.
# app/views/orders/mass_order.html.erb
<%= form_for(@orders, url: mass_create_order_path do |f| %>
<!-- Big form here -->
<%= submit_tag "Preview" %>
<%= submit_tag "Submit" %>
# => <input name="commit" type="submit" value="Preview" />
# => <input name="commit" type="submit" value="Submit" />
...
<% end %>
# config/routes.rb
resources :orders do
# Both routes below describe the same POST URL, but route to different actions
post 'mass_order', on: :collection, as: 'mass_order',
constraints: CommitParamRouting.new('Submit'), action: 'mass_create' # when the user presses "submit"
post 'mass_order', on: :collection,
constraints: CommitParamRouting.new('Preview'), action: 'mass_create_preview' # when the user presses "preview"
# Note the `as:` is defined only once, since the path helper is mass_create_order_path for the form url
# CommitParamRouting is just a class like ApiVersionContraint
end
경로 범위 지정
Rails는 경로를 구성하는 몇 가지 방법을 제공합니다.
URL 별 범위 :
scope 'admin' do
get 'dashboard', to: 'administration#dashboard'
resources 'employees'
end
이렇게하면 다음 경로가 생성됩니다.
get '/admin/dashboard', to: 'administration#dashboard'
post '/admin/employees', to: 'employees#create'
get '/admin/employees/new', to: 'employees#new'
get '/admin/employees/:id/edit', to: 'employees#edit'
get '/admin/employees/:id', to: 'employees#show'
patch/put '/admin/employees/:id', to: 'employees#update'
delete '/admin/employees/:id', to: 'employees#destroy'
서버 측에서 다른보기를 다른 하위 폴더에 유지하고 관리자보기와 사용자보기를 분리하는 것이 더 적절할 수 있습니다.
모듈 별 범위
scope module: :admin do
get 'dashboard', to: 'administration#dashboard'
end
module
은 주어진 이름의 하위 폴더 아래에있는 컨트롤러 파일을 찾습니다.
get '/dashboard', to: 'admin/administration#dashboard'
as
매개 변수를 추가하여 경로 헬퍼 접두어의 이름을 바꿀 수 있습니다
scope 'admin', as: :administration do
get 'dashboard'
end
# => administration_dashboard_path
Rails는 namespace
메소드를 사용하여 위의 모든 작업을 수행하는 편리한 방법을 제공합니다. 다음 선언문은 동등한 내용입니다.
namespace :admin do
end
scope 'admin', module: :admin, as: :admin
컨트롤러 별 범위
scope controller: :management do
get 'dashboard'
get 'performance'
end
이 경로를 생성합니다.
get '/dashboard', to: 'management#dashboard'
get '/performance', to: 'management#performance'
얕은 둥지
리소스 경로는 가능한 경우 URL을 줄이는 데 도움이되는 :shallow
옵션을 허용합니다. 리소스를 한 단계 이상 중첩해서는 안됩니다. 이것을 방지하는 한 가지 방법은 얕은 경로를 만드는 것입니다. 목표는 필요하지 않은 상위 수집 URL 세그먼트를 떠나 버리는 것입니다. 결과적으로 생성 된 중첩 된 경로는 :index
, :create
및 :new
작업에만 해당됩니다. 나머지는 자신의 얕은 URL 컨텍스트에 보관됩니다. 사용자 정의 얕은 경로의 범위에는 두 가지 옵션이 있습니다.
: shallow_path : 멤버 경로에 지정된 매개 변수를 접두사로 붙입니다 .
scope shallow_path: "sekret" do resources :articles do resources :comments, shallow: true end end
: shallow_prefix : 명명 된 헬퍼에 지정된 매개 변수 추가
scope shallow_prefix: "sekret" do resources :articles do resources :comments, shallow: true end end
우리는 또한 다음과 같이 shallow
경로를 설명 할 수 있습니다.
resources :auctions, shallow: true do
resources :bids do
resources :comments
end
end
또는 다음과 같이 코드화됩니다 (차단 된 경우).
resources :auctions do
shallow do
resources :bids do
resources :comments
end
end
end
결과 경로는 다음과 같습니다.
접두사 | 동사 | URI 패턴 |
---|---|---|
bid_comments | 도망 | /bids/:bid_id/comments(.:format) |
우편 | /bids/:bid_id/comments(.:format) | |
new_bid_comment | 도망 | /bids/:bid_id/comments/new(.:format) |
edit_comment | 도망 | /comments/ : id/edit(.:format) |
논평 | 도망 | /comments/ : id(.:format) |
반점 | /comments/ : id(.:format) | |
놓다 | /comments/ : id(.:format) | |
지우다 | /comments/ : id(.:format) | |
auction_bids | 도망 | /auctions/:auction_id/bids(.:format) |
우편 | /auctions/:auction_id/bids(.:format) | |
new_auction_bid | 도망 | /auctions/:auction_id/bids/new(.:format) |
edit_bid | 도망 | /bids/ : id / edit(.:format) |
매기다 | 도망 | /bids/:id(.:format) |
반점 | /bids/:id(.:format) | |
놓다 | /bids/:id(.:format) | |
지우다 | /bids/:id(.:format) | |
경매 | 도망 | /auctions(.:format) |
우편 | /auctions(.:format) | |
new_auction | 도망 | /auctions/new(.:format) |
edit_auction | 도망 | /auctions/ : id/edit(.:format) |
경매 | 도망 | /auctions/:id(.:format) |
반점 | /auctions/:id(.:format) | |
놓다 | /auctions/:id(.:format) | |
지우다 | /auctions/:id(.:format) |
주의 깊게 생성 된 경로를 분석하면 표시 할 데이터를 결정할 때 URL의 중첩 된 부분 만 포함된다는 것을 알 수 있습니다.
우려 사항
중첩 된 경로에서 반복을 피하기 위해 문제는 재사용 가능한 공통 리소스를 공유하는 좋은 방법을 제공합니다. 관심사를 생성하려면 routes.rb
파일 내의 메소드 concern
문제를 사용하십시오. 이 메서드는 심볼과 블록을 기대합니다.
concern :commentable do
resources :comments
end
경로 자체를 작성하지 않는 동안이 코드는 자원에 :concerns
속성을 사용할 수있게합니다. 가장 간단한 예는 다음과 같습니다.
resource :page, concerns: :commentable
동일한 중첩 리소스는 다음과 같습니다.
resource :page do
resource :comments
end
이것은 예를 들어 다음 경로를 구축합니다.
/pages/#{page_id}/comments
/pages/#{page_id}/comments/#{comment_id}
의미있는 관심사를 위해서는 우려를 활용하는 여러 리소스가 있어야합니다. 추가 리소스는 다음 문법 중 하나를 사용하여 문제를 호출 할 수 있습니다.
resource :post, concerns: %i(commentable)
resource :blog do
concerns :commentable
end
리디렉션
Rails 경로에서 다음과 같이 리디렉션을 수행 할 수 있습니다.
get '/stories', to: redirect('/posts')
match "/abc" => redirect("http://example.com/abc")
알 수없는 모든 경로를 지정된 경로로 리디렉션 할 수도 있습니다.
match '*path' => redirect('/'), via: :get
# or
get '*path' => redirect('/')
match '*path' => redirect('/')
멤버 및 컬렉션 경로
리소스 내에서 멤버 블록을 정의하면 해당 리소스 기반 라우트의 개별 멤버에서 작동 할 수있는 경로가 만들어집니다.
resources :posts do
member do
get 'preview'
end
end
그러면 다음과 같은 구성원 경로가 생성됩니다.
get '/posts/:id/preview', to: 'posts#preview'
# preview_post_path
콜렉션 라우트는 자원 오브젝트 콜렉션에서 작동 할 수있는 라우트를 작성할 수있게합니다.
resources :posts do
collection do
get 'search'
end
end
다음과 같은 수집 경로가 생성됩니다.
get '/posts/search', to: 'posts#search'
# search_posts_path
대체 구문 :
resources :posts do
get 'preview', on: :member
get 'search', on: :collection
end
마침표가있는 URL 매개 변수
ID 번호보다 복잡한 url 매개 변수를 지원하려면 값에 마침표가 포함되어 있으면 파서에 문제가 발생할 수 있습니다. 마침표 다음에 오는 것은 형식 (즉, json, xml)으로 가정됩니다.
허용 된 입력을 확장 하기 위해 제약 조건을 사용하여이 제한을 해결할 수 있습니다.
예를 들어, url의 전자 메일 주소로 사용자 레코드를 참조하려는 경우 :
resources :users, constraints: { id: /.*/ }
루트 경로
root
메소드를 사용하여 홈 페이지 경로를 앱에 추가 할 수 있습니다.
# config/routes.rb
Rails.application.routes.draw do
root "application#index"
# equivalent to:
# get "/", "application#index"
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def index
render "homepage"
end
end
그리고 터미널에서 rake routes
(Rails 5의 rails routes
)는 다음을 생성합니다.
root GET / application#index
일반적으로 홈페이지가 가장 중요한 경로이므로 경로가 표시된 순서대로 우선 순위가 지정되므로 root
경로는 일반적으로 경로 파일의 첫 번째 경로 여야합니다.
추가 RESTful 액션
resources :photos do member do get 'preview' end collection do get 'dashboard' end end
이렇게하면 기본 7 RESTful 경로 외에도 다음 경로 가 만들어집니다.
get '/photos/:id/preview', to: 'photos#preview'
get '/photos/dashboards', to: 'photos#dashboard'
단일 행에서이 작업을 수행하려면 다음을 사용할 수 있습니다.
resources :photos do get 'preview', on: :member get 'dashboard', on: :collection end
/new
경로에 작업을 추가 할 수도 있습니다.
resources :photos do get 'preview', on: :new end
어느 것이 만들 것인가?
get '/photos/new/preview', to: 'photos#preview'
RESTful 경로에 작업을 추가 할 때주의하십시오. 아마도 다른 리소스가 누락되었을 것입니다.
사용 가능한 로캘 범위
응용 프로그램이 다른 언어로 제공되는 경우 일반적으로 현재 로켈을 URL에 표시합니다.
scope '/(:locale)', locale: /#{I18n.available_locales.join('|')}/ do
root 'example#root'
# other routes
end
루트는 I18n.available_locales
정의 된 로케일을 통해 액세스 할 수 있습니다.
다른 응용 프로그램 탑재
mount는 다른 응용 프로그램 (기본적으로 랙 응용 프로그램) 또는 현재 응용 프로그램 내에서 사용될 레일 엔진을 탑재하는 데 사용됩니다
통사론:
mount SomeRackApp, at: "some_route"
이제 route helper some_rack_app_path
또는 some_rack_app_url
사용하여 위에 마운트 된 응용 프로그램에 액세스 할 수 있습니다.
그러나이 도우미 이름의 이름을 바꾸려면 다음과 같이 할 수 있습니다.
mount SomeRackApp, at: "some_route", as: :myapp
이렇게하면이 마운트 된 응용 프로그램을 탐색하는 데 사용할 수있는 myapp_path
및 myapp_url
도우미가 생성됩니다.
리디렉션 및 와일드 카드 경로
사용자의 편의를 위해 URL을 제공하려는 경우 이미 사용중인 다른 URL로 직접 매핑하십시오. 리디렉션 사용 :
# config/routes.rb
TestApp::Application.routes.draw do
get 'courses/:course_name' => redirect('/courses/%{course_name}/lessons'), :as => "course"
end
글쎄, 그 재미있는 빠른 있어요. 여기서 기본 원칙은 #redirect
메소드를 사용하여 하나의 경로를 다른 경로로 보내는 것입니다. 경로가 간단하다면 정말 간단합니다. 그러나 원래 매개 변수를 보내려면 %{here}
안의 매개 변수를 캡처하여 체조를 약간 수행해야합니다. 모든 것을 둘러싼 작은 따옴표를 주목하십시오.
위의 예제에서 : as 매개 변수와 함께 별칭을 사용하여 편의를 위해 경로의 이름을 변경했습니다. 이렇게하면 #_ 경로 도우미와 같은 메소드에서 해당 이름을 사용할 수 있습니다. 다시, 질문이있는 $ rake routes
를 테스트하십시오.
여러 파일로 경로 분할
라우트 파일이 압도적으로 클 경우 라우트를 여러 파일에 넣고 Ruby의 require_relative
메소드를 사용하여 각 파일을 포함시킬 수 있습니다.
config/routes.rb
: YourAppName::Application.routes.draw do
require_relative 'routes/admin_routes'
require_relative 'routes/sidekiq_routes'
require_relative 'routes/api_routes'
require_relative 'routes/your_app_routes'
end
config/routes/api_routes.rb
: YourAppName::Application.routes.draw do
namespace :api do
# ...
end
end
중첩 된 경로
중첩 된 경로를 추가하려면 routes.rb
파일에 다음 코드를 작성하면됩니다.
resources :admins do
resources :employees
end
그러면 다음 경로가 생성됩니다.
admin_employees GET /admins/:admin_id/employees(.:format) employees#index
POST /admins/:admin_id/employees(.:format) employees#create
new_admin_employee GET /admins/:admin_id/employees/new(.:format) employees#new
edit_admin_employee GET /admins/:admin_id/employees/:id/edit(.:format) employees#edit
admin_employee GET /admins/:admin_id/employees/:id(.:format) employees#show
PATCH /admins/:admin_id/employees/:id(.:format) employees#update
PUT /admins/:admin_id/employees/:id(.:format) employees#update
DELETE /admins/:admin_id/employees/:id(.:format) employees#destroy
admins GET /admins(.:format) admins#index
POST /admins(.:format) admins#create
new_admin GET /admins/new(.:format) admins#new
edit_admin GET /admins/:id/edit(.:format) admins#edit
admin GET /admins/:id(.:format) admins#show
PATCH /admins/:id(.:format) admins#update
PUT /admins/:id(.:format) admins#update
DELETE /admins/:id(.:format) admins#destroy