Tìm hiểu về routing trong Rails

Giới thiệu

Routing là tính năng điều hướng một URL vào một phương thức nhất định, tính năng routing có trong hầu hết các web framework phổ biến. Trong Ruby on Rails, routing được định nghĩa trong file config/routes.rb, được viết bằng ruby thuần và có thể hoạt động vơi mọi web server. Vì thế, việc tạo các router sẽ trở nên đơn giản, có thể coi như vẽ bản đồ cho các HTTP request biết đi đến đâu. Trong bài viết này mình sẽ giới thiệu một vài cách sử dụng routing cơ bản trong framework Ruby on Rails.

Tổng quan

Thay vì dựa vào web server để điều hướng url. Rails xử lý routing thông qua file config/routes.rb

#config/routes.rb
#các method thường sử dụng
Rails.application.routes.draw do
  root "users#index"
  get "/logout", to: "sessions#destroy", as: "logout"
  resources :users
  get "/stories", to: redirect("/photos")
end

Khi Rails app khởi động, file này sẽ được đọc. Công việc tiếp theo là Rails sẽ chuẩn hóa, biến từng câu lệnh trên thành 5 biến chứa thông tin của route được định nghĩa.

Đây là một ví dụ cụ thể:

Rails.application.routes.draw do
  get 'photos/:id' => 'photos#show', :defaults => { :format => 'jpg' }
end

sẽ được chuẩn hóa thành:

app: #<ActionDispatch::Routing::RouteSet::Dispatcher:0x007fd05e0cf7e8
           @defaults={:format=>"jpg", :controller=>"photos", :action=>"show"},
           @glob_param=nil,
           @controller_class_names=#<ThreadSafe::Cache:0x007fd05e0cf7c0
           @backend={},
           @default_proc=nil>>
conditions: {:path_info=>"/photos/:id(.:format)", :required_defaults=>[:controller, :action], :request_method=>["GET"]}
requirements: {}
defaults: {:format=>"jpg", :controller=>"photos", :action=>"show"}
as: nil
anchor: true

Trong đó:

  • app lưu thông tin về controller, action sẽ chạy nếu điều kiện thỏa mãn.

  • conditions lưu thông tin các điều kiện, trong đó path_info chính là phần để xác định route nào sẽ được sử dụng, bằng cách so sánh url với path_info (cùng với request_method).

  • requirements lưu thông tin các ràng buộc.

  • defaults lưu thông tin các mặc định.

  • as lưu tên được đặt cho route, mặc định là nil.

Chịu trách nhiệm cho việc chuẩn hóa này là class ActionDispatch::Routing::Mapper.

module ActionDispatch
  module Routing
    class Mapper
      include Base
      include HttpHelpers
      include Redirection
      include Scoping
      include Concerns
      include Resources
    end
  end
end

Các method như root, get, post, delete, resources,... được định nghĩa trong các module được include. Ví dụ:

module HttpHelpers
  def get(*args, &block)
  end

  def post(*args, &block)
  end

  def patch(*args, &block)
  end

  def put(*args, &block)
  end

  def delete(*args, &block)
  end
end

Root Route

Root route là route được sử dụng nhiều nhất, thường là trang chủ của app. Trong ví dụ:

root "users#index"

Khi nhập URL "/" thì Rails sẽ gọi tới action index của User controller. Ngoài ra đoạn code trên còn sinh ra các helper.

root_url   # => 'http://www.example.com/'
root_path  # => '/'

Lưu ý: root route chỉ điều hướng GET request.

HTTP Verb Route

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

đoạn code trên điều hướng GET request có URL "/logout" tới action destroy của Session controller. Option as dùng để khai báo tên cho route, từ đó ta có thể sử dụng helper logout_path hoặc logout_url. Ngoài ra còn một số option khác như constraints khai báo các ràng buộc cho route, defaults khai báo các params có giá trị mặc định được truyền vào controller cùng với request.

Resources Route

resources :users

Rails giúp việc tạo các route phổ biến theo chuẩn RESTful một cách nhanh chóng. Cụ thể là 7 route khác nhau tương ứng với các action trong User controller.

HTTP Verb Path Controller#Action Mục đích sử dụng Helper sinh ra
GET /users users#index hiển thị tất cả các users users_path
GET /users/new users#new trả về HTML form để tạo mới một user new_user_path
POST /users users#create tạo mới user users_path
GET /users/:id users#show hiển thị một user cụ thể user_path(:id)
GET /users/:id/edit users#edit trả về HTML form để thay đổi một user edit_user_path(:id)
PATCH/PUT /users/:id users#update thay đổi một user cụ thể user_path(:id)
DELETE /users/:id users#destroy xóa một user cụ thể user_path(:id)

Nếu chỉ muốn sử dụng một vài route thì ta có thể thêm option except hoặc only.

resources :users, only: :new    # => tương đương với get "/users/new", to: "users#new", as: "new_user"

Redirect Route

Sử dụng helper redirect để chuyển hướng sang một route khác. Thường sử dụng khi app thay đổi các đường dẫn.

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

Trong ví dụ trên, khi người dùng nhập url "/stories", Rails app sẽ tự động chuyển hướng về url "/photos".

Kết luận

Đó là một số kiến thức cơ bản để xây dựng một router hoàn chỉnh cho Rails app. Ngoài ra còn có một số method hay option giúp bạn xây dựng router hiệu quả hơn theo mục đích của mình. Hi vọng bài viết sẽ giúp ích được cho các bạn.

Nguồn tham khảo

http://blog.bigbinary.com/2013/01/29/journey-into-rails-routing.html

http://api.rubyonrails.org/classes/ActionDispatch/Routing.html

http://guides.rubyonrails.org/routing.html