Gần đây, khi phải tạo Breadcrumb cho 1 trang web được viết bằng Rails, mình có sử dụng gem breadcrumbs_on_rails
, và thấy nó khá hiệu quả, dễ dàng cài đặt, nên muốn giới thiệu cho mọi người.
I. Breadcrumb là gì?
Breadcrumb là một tập các đường link phân cấp, được sử dụng để trợ giúp điều hướng trong giao diện web, giúp người dùng biết mình đang ở đâu, và dễ dàng di chuyển sang các trang khác. Với những trang web có cấu trúc phức tạp, việc có breadcrumb giúp người dùng dễ dàng tìm kiếm và truy cập những thông tin họ cần, giảm đi các thao tác quay lại trang cũ.
Breadcrumb thường được đặt đầu trang và có cấu trúc như sau
- Dựa trên lịch sử xem
Page viewed > Page viewed > Page viewed > Page viewed > Page currently being viewed
- Dựa trên cấu trúc phân cấp của trang
Home page > Section page > Subsection page
Về phía người dùng, Breadcrumb giúp người dùng tương tác với trang web thuận tiện hơn.
Về phía người chủ trang web, Breadcrumb là 1 phần quan trọng giúp tối ưu SEO. Google Search sử dụng Breadcrumb để phân loại và hiển thị kết quả tìm kiếm. Do đó những trang web có Breadcrumb cũng sẽ được Google Search đánh giá cao hơn.
- Trang web không có Breadcrumb
- Trang web có Breadcrumb
Breadcrumb được chia làm 3 loại chính
- Location breadcrumb: Hiển thị vị trí trang trong hệ thống phân cấp trang. Đây là loại phổ biến nhất
- Attribute breadcrumb: Cung cấp thuộc tính phân loại trang hiện tại
- Path breadcrumb: Hiển thị cho người dùng các bước mà họ đã thực hiện để đến trang hiện tại
II. Breadcrumbs On Rails
Breadcrumbs On Rails cho phép tạo và quản lý Breadcrumb trong Rails đơn giản, và mình có thể thay đổi thiết kế Breadcrumb linh hoạt.
Với phiên bản mới nhất hiện nay (3.0.1) thì Breadcrumbs On Rails yêu cầu Rails 4 hoặc Rails 5
1. Cài đặt
Thêm dòng sau vào Gemfile
gem "breadcrumbs_on_rails"
Và thực hiện dòng lệnh
bundle
để cài đặt dependencies
2. Hướng dẫn cơ bản
Để tạo 1 Breadcrumb ở Rails app bằng cách sử dụng Breadcrumbs On Rails thì khá đơn giản.
2.1 Controller
Ở controller, dùng add_breadcrumb
để thêm element vào breadcrumb stack. add_breadcrumb
cần có 2 tham số: tên của Breadcrumb và đường dẫn của nó
class MyController
add_breadcrumb "home", :root_path
add_breadcrumb "my", :my_path
def index
add_breadcrumb "index", index_path
# ...
end
end
Ngoài ra, add_breadcrumb
có tham số thứ 3 để customize đường dẫn của breadcrumb.
2.1 View
Ở view, render Breadcrumb bằng cách dùng render_breadcrumbs
<body>
<%= render_breadcrumbs %>
</body>
Mình có thể thay đổi dấu phân cách mặc định bằng cách sử dụng option :separator
<body>
<%= render_breadcrumbs :separator => ' / ' %>
</body>
Hiện tại thì mới chỉ support 2 options sau:
:separator
:tag
3. Chi tiết về add_breadcrumb
3.1 HTML Escaping
Breadcrumb text mặc định sẽ được html-escaped để tránh bị tấn công XSS
class MyController
add_breadcrumb "This is the <b>Main</b> page".html_safe
def profile
add_breadcrumb "#{@user_name} Profile", users_profile
end
end
Nếu @user_name
là <script>
thì kết quả hiển thị nó sẽ như sau
This is the <b>Main</b> page > <script> Profile
3.2 Breadcrumb Element
Bằng cách sử dụng add_breadcrumb
mình sẽ thêm các Element
vào danh sách Breadcrumb. Mỗi Element bao gồm: tên Breadcrumb và đường dẫn của nó
Ta có thể sử dụng các Ruby type sau cho tên và đường dẫn của Element
- Symbol
Ví dụ ở đây ta set tên của Element bằng Symbol:root_name
và sẽ kết quả tên của Element sẽ có giá trị trả về của phương thức đã được định nghĩa ở dưới
class MyController
add_breadcrumb :root_name, "/"
protected
def root_name
"the name"
end
end
- Proc
Proc là 1 cách hiệu quả để truy cập vào 1 phương thức hoặc biến đặc biệt được tạo trong controller
class MyController
add_breadcrumb Proc.new { |c| c.my_helper_method }, "/"
end
- String
Là cách đơn giản nhất, tuy nhiên thực tế ít dùng hơn type kia
class MyController
add_breadcrumb "homepage", "/"
end
3.3 Phạm vi của breadcrumb
Ta có thể sử dụng các Rails filter option để giới hạn phạm vi của Breadcrumb như sau
class PostsController < ApplicationController
add_breadcrumb "admin", :admin_path
# Chỉ hiển thị với các action index và show
add_breadcrumb "posts", :posts_path, :only => %w(index show)
end
class ApplicationController < ActionController::Base
# Chỉ hiển thị với điều kiện là admin controller
add_breadcrumb "admin", :admin_path, :if => :admin_controller?
def admin_controller?
self.class.name =~ /^Admin(::|Controller)/
end
end
3.4 Đa ngôn ngữ
Breadcrumbs On Rails tương thích với đa ngôn ngữ của Rails
Nếu muốn ta có thể định nghĩ tên breadcrumb ở file .yml
như sau
# config/locales/en.yml
en:
breadcrumbs:
homepage: Homepage
first: First
second: Second
third: Third
# config/locales/it.yml
it:
breadcrumbs:
homepage: Homepage
first: Primo
second: Secondo
third: Terzo
Và ở controller, ta dùng phương thức I18n.t
class PostsController < ApplicationController
add_breadcrumb I18n.t("breadcrumbs.first"), :first_path
add_breadcrumb I18n.t("breadcrumbs.second"), :second_path, :only => %w(second)
add_breadcrumb I18n.t("breadcrumbs.third"), :third_path, :only => %w(third)
end
class ApplicationController < ActionController::Base
add_breadcrumb I18n.t("breadcrumbs.homepage"), :root_path
end
III. Một vài case study
Tùy vào yêu cầu của từng trang web, ta có thể cần 1 số xử lý đặc biệt cho Breadcrumb. Dưới đây là 1 số trường hợp mình đã gặp trong dự án. Ngoài ra có thể tham khảo Issues của Breadcrumbs On Rails để biết thêm 1 sô trường hợp khác mà người khác đã gặp.
1. Truyền tham số cho path của Rails
Bình thường ta có thể cài đặt Breadcrumb đơn giản như sau
class MyController
add_breadcrumb I18n.t('home.title'), :root_path
add_breadcrumb I18n.t('my.title'), :my_path
def index
add_breadcrumb I18n.t('my.index.title'), :my_index_path
# ...
end
end
Tuy nhiên với trường hợp path cần truyền tham số thì sao? Ở đây ta có thể dùng Proc để truyền tham số cho path
def edit
add_breadcrumb(I18n.t('my.edit.title'), proc { edit_my_path(id: @my_id) })
# ...
end
2. Breadcrumb phụ thuộc vào giá trị thay đổi
Ví dụ trường hợp user bình thường và admin sẽ hiển thị Breadcrumb khác nhau khi vào trang index, ta có thể dùng before_action để xử lý như sau
class MyController
add_breadcrumb I18n.t('home.title'), :root_path
before_action only: [:index] do
@user = User.find(params[:user_id])
case @user[:type]
when Settings.user[:admin]
add_breadcrumb I18n.t('my.admin.title'), :my_admin_path
when Settings.user[:normal_user]
add_breadcrumb I18n.t('my.normal_user.title'), :my_user_path
end
end
def index
add_breadcrumb I18n.t('my.index.title'), :my_index_path
# ...
end
end
Hoặc có thể cho xử lý đó vào 1 hàm như sau
class MyController
add_breadcrumb I18n.t('home.title'), :root_path
before_action only: [:index] :add_breadcrumb_user_base
def index
add_breadcrumb I18n.t('my.index.title'), :my_index_path
# ...
end
private
def add_breadcrumb_user_base
@user = User.find(params[:user_id])
case @user[:type]
when Settings.user[:admin]
add_breadcrumb I18n.t('my.admin.title'), :my_admin_path
when Settings.user[:normal_user]
add_breadcrumb I18n.t('my.normal_user.title'), :my_user_path
end
end
end
3. Breadcrumb Top/Home cho tất cả các trang
Thường thì ở đầu Breadcrumb ta sẽ muốn set Top/Home cho tất cả các trang web. Ta chỉ cần add Breadcrumb 1 lần ở ApplicationController và tất cả các trang sẽ được hiển thị.
Tuy nhiên, với trường hợp muốn Top/Home khác nhau với từng đối tượng user khác nhau (như admin và user bình thường), hoặc không muốn add Top/Home ở 1 số màn hình đặc biệt (như login, logout) ta có thể cài đặt như sau
class ApplicationController < ActionController::Base
# Chỉ add breadcrumb ngoại trừ devise_controller (Gem Devise là 1 gem phổ biến để xác thực người dùng)
before_action unless: :devise_controller? do
@home_path = home_path
add_breadcrumb I18n.t('home.title'), @home_path
end
private
# Set home path khác nhau với những đối tượng user khác nhau
def home_path
if current_login_account.admin? && params[:controller].include?('admins')
admin_home_path
else
user_home_path
end
end
end
Hi vọng những case study này sẽ hữu ích với mọi người!