8
11

More than 5 years have passed since last update.

Rails ~会員登録までの道のり~

Posted at

これまでのあらすじ

前回の記事よりActionMailerの機能でメールを飛ばせることを検証しました。
今回は、メールアドレスを認証させるために仮ユーザ登録させてからユーザ登録させるための仮ユーザ登録機能を作ってみます。
ユーザ認証に関しては、deviseなどのGemの利用がRailsでは、一般的(というか便利)らしいですが、Ruby・Railsの勉強をするために純粋にRuby・Railsで構築してきたいと思います。

Top画面の作成

まずトップ画面を作成します。
top_cotroller.rbを作成します。

terminal
$ rails g cotroller top
top_controller.rb
class TopController < ApplicationController
    def index
    end
end

indexアクションを作成し、/views/top/index.html.erbを作成します。
config/routes.rbにルートを追加する。

rootパスにtop#indexアクションを指定します。

routes.rb
Rails.application.routes.draw do
    root 'top#index'

    # top_controller
    get 'top', to: 'top#index'
end

TOP画面はこんな感じにBootstrapを駆使して作りました。

ezgif.com-video-to-gif.gif

(管理者とかあるのはご愛嬌で...)

背景に動画を埋め込んで「イマドキ」っぽいおしゃれなWebサイトっぽくしました。

仮ユーザのModel作成

仮ユーザ(temp_user)のModel(DBのテーブル)を作成します。

schema.rb
  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で構成されています。

仮ユーザ登録までの流れ

  1. TOP画面のsign onボタンを押下し、仮登録画面を表示。
  2. 仮登録画面で氏名・メールアドレスを入力。
  3. メールアドレス登録完了と同時に、本登録画面のurlを記載したメール送信。
  4. 仮登録が完了した旨のメッセージ表示。

1. TOP画面のsign onボタンを押下し、仮登録画面を表示。

以前の記事で紹介したモーダルウィンドウを起動し、仮登録画面を表示しました。

ezgif.com-video-to-gif.gif

top_controller#sign_onで表示しています。
form_with用の@temp_userをnewしている以外は特別なことはしていません。

top_controller.rb
class TopController < ApplicationController
    def sign_on
        @temp_user= TempUser.new
    end
end

2. 仮登録画面で氏名・メールアドレスを入力。

temp_user.rbにバリデーションを追加しました。

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で判断しています。(便利ですね!!)

top_controller.rb
    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するため
遅延実行しています。

create.js.erb
<% 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 %>

こんな感じ...

ezgif.com-video-to-gif.gif

今後は…

これで仮登録までできました。
とりあえず、前回の記事の検証と合わせて、メールを飛ばすところまではつくりたいですね。
(こうしたほうがいいとか、ご意見あったらぜひぜひいただけると嬉しいです。)

8
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
11