Rails tutorial 11章 〜アカウントの有効化〜

おはようございます。

本日はrails tutorial 11章 アカウントの有効化についてまとめてみました。
ぜひ、最後まで見ていってください。

アカウント有効化の意義

アカウントの有効化を実装することで登録されたメールアドレスは本当にそのユーザーのものなのかが確認できるようになります。

実装するための大まかな手順

  1. 初期登録が行われた時に有効化トークンとそれに対応する有効化ダイジェストを作成する
  2. 有効化ダイジェストはDBに保存しておき、有効化トークンはユーザーに送信するメールに仕込んでおく
  3. ユーザーがメールアドレスのリンクをクリックしたら、メールアドレスをキーにトークンとダイジェストを比較し認証する

以上の流れになります。
順番に見ていきます。

有効化トークン、ダイジェストの作成

まず、最初にControllerの作成を行います。

rails g controller AccountActivation

これでControllerの作成は完了です。

ユーザーがメールアドレスのリンクをクリックして有効化をする際、次のurlが含まれます。

edit_account_activaton_url(activation_token)

ですので、先に名前付きルートを作成します。
routes.rb

・
・
・
resources :account_activations, only: [:edit]

次にUserモデルにカラムを追加していきますが、
仮想化した属性を使いハッシュ化した文字列をDBに保存していきます。
また、activated属性で論理値を取るようにします。

以上を踏まえて次のコマンドを実行します。

rails g migration add_activation_to_users \
activation_digest:string activated:boolean activated_at:datetime
rails db:migrate

これで変更が反映されました。

続いて、ユーザーが作成される前に有効化トークン、ダイジェストが作成されるようにbefore_createメソッドを設定します。
before_saveが保存される直前に実行されるのに対してこちらは作成される直前に実行されます。

User.rb

attr_accessor :activation_token
before_create :create_activation_digest
・
・
・
def create_activation_digest
self.activation_token = User.new_token
self.activation_digest = User.digest(activation_token)
end

アカウント有効化のメール送信

メイラーはrails gで簡単に作成できます。

rails g mailer UserMailer account_activation password_reset

password_resetは12章で使います。

次にテンプレートビューをカスタマイズします。

application_mailer.rb

class ApplicationMailer < ActionMailer::Base
default from: <u>"noreply@example.com"</u>
layout 'mailer'
end

user_mailer.rb

class UserMailer < ActionMailer::Base
<u>def account_activation
@user = user
mail to:user.email, subject: "Account activation"
end</u>
end

有効化トークンをメールに仕込む

パスワードだったら入力してそれをrailsがダイジェストに変換して認証を行なっていました。
しかし、今回はURLをクリックするだけです。
つまり、URLに何かしらの工夫をしなければなりません。

URLには認証のためのトークンとユーザーを見つけ出すためのメールアドレスを仕込みます。

<%= edit_account_activation_url(@user.activate_token, email:@user.email) %>

これによって発行されるURLは以下のようになります。

account_activations/q5lt38hQDc_959PVoo6b7A/edit?email=foo%40example.com

次にcreateアクションを変更して新規登録時にメールが送信されるようにします。

users_controller.rb

def create
@user = User.new(user_params)
if @user.save
UserMailer.account_activation(@user).deliver_now
flash[:info] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end

アカウントの有効化

これからaccount_activations_controllerのeditアクションを書いていきますが、その前にauthenticated?の文多少変更します。

現在のauthenticatedメソッドはこちらです。

User.rb

# トークンがダイジェストと一致したらtrueを返す
def authenticated?(remember_token)
return false if remember_digest.nil?
BCrypt::Password.new(remember_digest).is_password?(remember_token)
end

このままだとremember_tokennしか引数として受け取れませんのでここを変数に変える必要があります。
これにはsendメソッドを使います。
sendメソッドは渡されたオブジェクトにメッセージを送ることによって呼び出すメソッドを動的にすることができます。

def authenticated?(attribute, token)
digest = send("#{attribute}_digest")
return false if digest.nil?
BCrypt::Password.new(digest).is_password?(token)
end

これでeditアクションを呼び出す準備が整いました。
account_activations_controller.rb

def edit
user = User.find_by(email: params[:email])
if user && !user.activated? && user.authenticated?(:activation, params[:id])
user.update_attribute(:activated,    true)
user.update_attribute(:activated_at, Time.zone.now)
log_in user
flash[:success] = "Account activated!"
redirect_to user
else
flash[:danger] = "Invalid activation link"
redirect_to root_url
end
end
end

以上で、アカウント有効化の大まかな手順の説明は終わります。
ありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です