2017/11/29

Ruby - 使用 Devise confirmable

markdown ## Devise confirmable 當你想要認證註冊者的信箱時可以使用 confirmable 安裝方式請參考:[https://github.com/plataformatec/devise/wiki/How-To:-Add-:confirmable-to-Users](https://github.com/plataformatec/devise/wiki/How-To:-Add-:confirmable-to-Users) 以下說明一些實務上的可能會遇到的細節調整方式。 ## 什麼時候會寄出信? ### 建立 user 時 在建立 user 時,會在呼叫 user.save 後寄信給 user。 ``` user = User.create user.save ``` ### user email 更新時 在編輯 user 時,若 email 有修改,會在呼叫 user.save 後寄信給 user。 ``` user = User.find(params[:id]) user.email = 'QQ@QQ' user.save ``` 此時寫入的 email 會被保存到 unconfirmed_email,而原先的 email 欄位在 user 完成認證之前不會改變。 ## 開發時測試寄信的方法 在開發時可能會希望不要真的寄出信件,此時可以使用 letter_opener,他會在需要寄信時,只將信件內容印在 console log 上。 設定方法是在 `config/environments/development.rb` 加入以下程式碼: ``` config.action_mailer.delivery_method = :letter_opener config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } ``` ## confirmable 自動測試 加入了 confirmable 之後可能會導致 test fail,因為 devise 嘗試 send mail 但是 test 環境下可能無法正確寄信。 #### 避免寄出信件的方法 如果你希望在測試時不要寄信,如果你使用 FactoryBot 這個套件來生成 user,以下是跳過 email 驗證的方法: ``` FactoryBot.define do factory :user do after(:build) { |u| u.skip_confirmation! } end end ``` 在不使用 FactoryBot 的情況下,跳過 email 驗證的方法: ``` user = User.new user.skip_confirmation! user.save ``` #### 成功寄出信件的方法 如果你希望寄信,但是你沒有設定 host 值,那麼你會看見這個: ``` ActionView::Template::Error: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true ``` 此時你需要加入以下內容至 `config/environments/test.rb`: ``` config.action_mailer.delivery_method = :test config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } ``` ### 測試寄件內容 使用 ActionMailer::Base.deliveries.last 可以取得最後一次寄出的信件內容: ``` user = User.new user.save mail = ActionMailer::Base.deliveries.last mail.from mail.to mail.subject mail.body.to_s ``` 因此可以對信件內容做測試。 ### 模擬使用者完成認證 用 code 完成認證的方法 ``` user = User.find(params[:id]) user.confirm ``` ## 同一個認證連結被點擊第二次會發生什麼事? 當 user 點擊第二次認證信連結時,預設是會顯示「 Email was already confirmed, please try signing in. 」字樣。可以透過自訂 controller 去修改預設行為 ## 怎麼修改認證信內容? 改 template 改 template 路徑 ## 自定義寄信路徑 ``` class DeviseMailer < Devise::Mailer helper :application # gives access to all helpers defined within `application_helper`. include Devise::Controllers::UrlHelpers # Optional. eg. `confirmation_url` def headers_for(action, opts) super.merge!({template_path: '/users/mailer'}) # this moves the Devise template path from /views/devise/mailer to /views/users/mailer end # def confirmation_instructions(record, token, opts={}) # headers["Custom-header"] = "Bar" # opts[:from] = 'my_custom_from@domain.com' # opts[:reply_to] = 'my_custom_from@domain.com' # super # end end ``` ## 參考資料: 測試寄信的方法 [http://guides.rubyonrails.org/testing.html#testing-your-mailers](http://guides.rubyonrails.org/testing.html#testing-your-mailers) 阻止修改mail時的認證:[https://coderwall.com/p/7_yh8q/skip-devise-email-confirmation-on-update](https://coderwall.com/p/7_yh8q/skip-devise-email-confirmation-on-update)

沒有留言: