基本會員註冊登入沒問題後,剛開始大家可能會想先處理的,就是註冊的一些欄位新增與資料要寫入資料庫會碰到問題,以及個別通知訊息及標籤的 i18n 中文化等等,所以本篇會簡單提到關於 i18n 這個套件搭配 Devise 的用法

產生 controller

套件有指令可以幫忙生出對應的 controller,如果前面建立的 model 是 User 且也是放在 devise 之下,用以下的指令並且 [scope] 改為 users,可以產生對應的 controller,每個 controller 內容有許多註解為提示這些 controller 是對應那些功能相關

1
rails g devise:controllers [scope]

  • 也可以針對特定目標產生相關的 controller
1
rails generate devise:controllers [scope] -c=[controller's name]

注意有提示訊息提醒要確認在 routes.rb 中設定正確路徑

1
2
3
# 如果同上用 rails g devise:controllers user
# 想要用上其中的 sessions controller
devise_for :users, controllers: { sessions: "users/sessions" }

Controller filters 和 helper 使用

Devise 提供許多好用的 helper 方法,可以讓你套用在專案中。

controller filter

在 controller 內可以設定 before_action 加入預設認證使用者的方法,會讓該頁面跳轉到登入頁,且需要登入後才可以進入。

1
before_action :authenticate_user!

helper

判斷使用者是否已經登入?

1
user_signed_in?

當使用者登入後,指出目前使用者,這個指令應該會是大家用這個套件的一個主要亮點,你可以透過關聯來連結到其他的 model,去進行資料的撈取。

1
current_user

可以在登入對應的 scope 中使用的 session

1
user_session

當使用者登入時,devise 確認帳戶或更新密碼後,會去找 scope 的路徑。登入之後再把使用者導向設定好的地方。
如果自訂路徑使用 :user 的 resources,就會去 user_root_path,如果沒有設定這條路徑,就使用 root_path 為預設值,如同上一篇提到的。

客製新增資料欄位及驗證(強參數使用)

如同我們手刻的時候需要將資料透過強參數清洗,避免使用者在填入資料時,強制將一大包 params 惡意送入資料庫,需要經過 controller 的允許(permit)。

devise 預設註冊只有 email 和 password 可以通過,但我們通常會客製自己的欄位,例如使用者名稱、匿稱、生日、地址等等。

Devise 中有三個 action 可以允許設定的欄位通過傳到 model,
分別是:

  • sign_in ( Devise::SessionsController#create )
    只允許 authentication keys 通過(ex: email、account)
  • sign_up ( Devise::RegistrationsController#create )
    只允許 authentication keys、password、password_confirmation
  • account_update ( Devise::RegistrationsController#update )
    只允許 authentication keys、password、password_confirmation、 current_password

使用者註冊表單再額外多加其他欄位 如 username、birthday、address,必須在 ApplicationController 設定 before_action,並定義預設方法configure_permitted_parameters來執行,並且設定 before action 當用到 devise 的 controller 就會觸發。

以下為懶人的單行寫法:
ApplicationController.rb

1
2
3
4
5
6
7
8
9
10
11
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?

protected

def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :birthday, :address])
# ()內依序為 (action, 清洗的欄位1, 清洗的欄位2 ....)
# 注意欄位要用symbol
end
end

可以把這個部分寫到下層負責的 controller 嗎?

答案是可以,我一開始也覺得很奇怪,通常不該寫到最上層的地方,嘗試改動移到下面 registrations_controller 裡面,一直沒能成功,後來發現要使用到套件產生的 controller,或是其他你自己想用的 controller,需要先在路徑中指出你是用哪個 controller 來管理資料 (同前產生 controller 提示訊息提到),需要在 devise_for :users 後面加上你要使用的 controller

1
devise_for :users, controllers: { registrations: 'users/registrations'  }

再把相關的清洗設定移到裡面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
app/controller/users/registrations_controller.rb
module Users
class RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]

def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :birthday, :address])
end

def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:username, :birthday, :address])
end
end
end

I18N 套件使用

i18n 安裝

  1. 在 Gemfile 加上 gem “rails-i18n”,然後執行 bundle

  2. 修改 config/application.rb 的預設語系:
    預設應該是 en,就是英文語系,要使用中文可以改為 zh-TW

1
config.i18n.default_locale = "zh-TW"

調整訊息

github 上提供各語系 yml 原始碼

i18n 使用檔案 zh-TW.yml
devise 或 i18n-devise github 上已經有許多善心人士提供對應的翻譯檔案。
在 config/locale 中找到原本的 en 檔案,如果要中文翻譯,上面設定預設語系後加入zh-TW.yml檔案就可以。

調整密碼長度驗證

  1. 針對全區的會員密碼設定
    config/initializers/devise.rb 裡面有針對密碼寫入長度設定,可以設定為自己想要的,預設是 6~128 碼。
1
config.password_length = 6..128 # 可以自己調整

調整後包含前面註冊時預設的顯示都會變更,可以回去看一下 view 的檔案預設產生提示字樣的寫法,自行決定是否也要跟著顯示

  1. 針對個別 model 有需要密碼設定的設定驗證
    可以自行加入下面驗證設定
1
devise :database_authenticatable, :validatable, password_length: 10..128

關於註冊及忘記密碼頁面重新整理會出錯

似乎是這個套件存在的問題,主要是沒有/users 這個路徑。
目前根據找到的一些解法,是針對路徑修正,強制將路徑導回註冊或登入頁面

參考資料

路徑 config/routes.rb

1
2
3
4
devise_scope :user do
get '/users', to: 'devise/registrations#new'
get '/users/password', to: 'devise/passwords#new'
end

參考資料:

  1. devise - github
  2. Devise 快速上手