これまでのあらすじ
前回の記事よりActionMailerの機能でメールを飛ばせることを検証しました。
今回は、メールアドレスを認証させるために仮ユーザ登録させてからユーザ登録させるための仮ユーザ登録機能を作ってみます。
ユーザ認証に関しては、deviseなどのGemの利用がRailsでは、一般的(というか便利)らしいですが、Ruby・Railsの勉強をするために純粋にRuby・Railsで構築してきたいと思います。
Top画面の作成
まずトップ画面を作成します。
top_cotroller.rb
を作成します。
$ rails g cotroller top
class TopController < ApplicationController
def index
end
end
indexアクションを作成し、/views/top/index.html.erb
を作成します。
config/routes.rb
にルートを追加する。
rootパスにtop#indexアクションを指定します。
Rails.application.routes.draw do
root 'top#index'
# top_controller
get 'top', to: 'top#index'
end
TOP画面はこんな感じにBootstrapを駆使して作りました。
(管理者とかあるのはご愛嬌で...)
背景に動画を埋め込んで「イマドキ」っぽいおしゃれなWebサイトっぽくしました。
仮ユーザのModel作成
仮ユーザ(temp_user)のModel(DBのテーブル)を作成します。
create_table "temp_users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
t.string "mail_address", null: false
t.string "last_name", null: false
t.string "first_name", null: false
t.string "token", limit: 64, null: false
t.datetime "expired_at", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["mail_address"], name: "index_temp_users_on_mail_address", unique: true
t.index ["token"], name: "index_temp_users_on_token", unique: true
end
仮ユーザ情報として、ログインに使用するmail_addressとユーザの氏名、仮ユーザを認証するためのtoken、仮ユーザ情報の有効期限のためのexpired_atで構成されています。
仮ユーザ登録までの流れ
- TOP画面のsign onボタンを押下し、仮登録画面を表示。
- 仮登録画面で氏名・メールアドレスを入力。
- メールアドレス登録完了と同時に、本登録画面のurlを記載したメール送信。
- 仮登録が完了した旨のメッセージ表示。
1. TOP画面のsign onボタンを押下し、仮登録画面を表示。
以前の記事で紹介したモーダルウィンドウを起動し、仮登録画面を表示しました。
top_controller#sign_onで表示しています。
form_with用の@temp_userをnewしている以外は特別なことはしていません。
class TopController < ApplicationController
def sign_on
@temp_user= TempUser.new
end
end
2. 仮登録画面で氏名・メールアドレスを入力。
temp_user.rbにバリデーションを追加しました。
class TempUser < ApplicationRecord
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :last_name, presence: true
validates :first_name, presence: true
validates :mail_address, presence: true
validates :mail_address, format: { with: VALID_EMAIL_REGEX }
end
氏名は必須。
メールアドレスは必須とメールアドレス正規表現によるフォーマットチェックをしています。
3. メールアドレス登録完了と同時に、本登録画面のurlを記載したメール送信。
top#sign_onでformを表示し、formのsubmitでtop#createを読んでいます。
本処理は
- mail_addressがすでに使用されている(temp_userに登録済み)の場合は、UPDATE、未使用の場合は、INSERTをする。(UPSERT処理)
- UPDATE時、入力された姓・名・有効期限は後勝ちとする。
- tokenはランダム文字列で生成。
find_or_initialize_byで条件にformで入力されたmail_addressを指定しています。
find_or_initialize_byは取得できた場合、取得結果をModelに詰め、できない場合は、ただ単純にnewします。
その後、姓・名をセットします。
tokenですが、SecureRandom.urlsafe_base64でランダム文字列を作成しました。なお、重複登録を防ぐために、token = 生成文字列でtemp_userを検索し、存在した場合、再度生成しています。
有効期限はとりあえず現在日時をセットし、saveしています。
find_or_initialize_byで生成しているため、すでに存在している場合は、UPDATE・新規の場合はINSERTをrailsで判断しています。(便利ですね!!)
def create
# 入力されたメールアドレスは登録済みか
@temp_user = TempUser.find_or_initialize_by(mail_address: temp_users_params[:mail_address])
# 入力された姓・名をセット
@temp_user.last_name = temp_users_params[:last_name]
@temp_user.first_name = temp_users_params[:first_name]
# トークンを生成
@temp_user.token = create_token
# 有効期限に現在日時をセットする
@temp_user.expired_at = DateTime.now
respond_to do |format|
# UPSERT実行
if @temp_user.save
format.js { @status = "success" }
else
format.js { @status = "fail" }
end
end
end
private
def create_token
token = nil
loop do
token = SecureRandom.urlsafe_base64
break if TempUser.find_by(token: token).nil?
end
return token
end
4. 仮登録が完了した旨のメッセージ表示。
成功した場合は、完了した旨のメッセージを表示しました。
これもModalで表示していますが、formのモーダルを消してから、完了のモーダルをshowするため
遅延実行しています。
<% if @status == 'success' %>
$('#top_modal').modal('hide');
setTimeout(function(){
$('#top_modal').html('<%= j(render 'completed_sign_on') %>');
$('#top_modal').modal('show');
}, 500);
<% elsif @status == 'fail' %>
$('#sign_on_errors').html('<%= j(render 'layouts/error_messages', model: @temp_user) %>');
<% end %>
こんな感じ...
今後は…
これで仮登録までできました。
とりあえず、前回の記事の検証と合わせて、メールを飛ばすところまではつくりたいですね。
(こうしたほうがいいとか、ご意見あったらぜひぜひいただけると嬉しいです。)