LoginSignup
0
0

More than 3 years have passed since last update.

【Railsチュートリアル】第11章 アカウントの有効化①

Posted at

はじめに

アカウントを有効化するステップを新規登録の途中に差し込み、本当にそのメールアドレスの持ち主なのかどうかを確認できるようにする。

11.1 AccountActivationsリソース

セッション機能(8.1)を使って、アカウントの有効化という作業を「リソース」としてモデル化する。

11.1.1 AccountActivationsコントローラ

resources :account_activations, only: [:edit]

URL「/account_activation/トークン/edit」にGETがリクエストされたらeditアクションを呼び出す。

演習 1

現時点でテストスイートを実行すると green になることを確認してみましょう。
確認のみなので省略。

演習 2

表 11.2の名前付きルートでは、_pathではなく_urlを使うように記してあります。なぜでしょうか? 考えてみましょう。ヒント: 私達はこれからメールで名前付きルートを使います。
メール本文のURLからアクセスするから。

11.1.2 AccountActivationのデータモデル

仮想的な属性を使ってハッシュ化した文字列をデータベースに保存するようにする。

演習 1

本項での変更を加えた後、テストスイートが green のままになっていることを確認してみましょう。

GREEN

演習 2

コンソールからUserクラスのインスタンスを生成し、そのオブジェクトからcreate_activation_digestメソッドを呼び出そうとすると(Privateメソッドなので)NoMethodErrorが発生することを確認してみましょう。また、そのUserオブジェクトからダイジェストの値も確認してみましょう。

>> user = User.new
   (4.5ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil, password_digest: nil, remember_digest: nil, admin: nil, activation_digest: nil, activated: false, activated_at: nil>
>> user.create_activation_digest
Traceback (most recent call last):
        1: from (irb):2
NoMethodError (private method `create_activation_digest' called for #<User:0x00007f5eb1cd6088>)
Did you mean?  restore_activation_digest!

>> user.activation_digest
=> nil

演習 3

リスト 6.35で、メールアドレスの小文字化にはemail.downcase!という(代入せずに済む)メソッドがあることを知りました。このメソッドを使って、リスト 11.3のdowncase_emailメソッドを改良してみてください。また、うまく変更できれば、テストスイートは成功したままになっていることも確認してみてください。

app/models/user.rb

def downcase_email
  self.email.downcase!
end

GREEN

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

Action Mailerライブラリを使ってUserのメイラーを追加する。

11.2.1 送信メールのテンプレート

Userメイラーの生成
$ rails generate mailer UserMailer account_activation password_reset

$ rails generate [メイラー名][アクション名][アクション名]

app/views/user_mailer/account_activation.text.erb
app/views/user_mailer/account_activation.html.erb
ブラウザと違って、メールボックスによってHTMLを描画できないものもあるので、textも用意している。

app/mailers/application_mailer.rb

class ApplicationMailer < ActionMailer::Base
  default from: 'from@example.com'
    # どこから送るか
  layout 'mailer'
    # デフォルトではどんなレイアウトを使うのか。
end

application_mailer.rbではメイラー全体の設定をする。

app/mailers/user_mailer.rb

class UserMailer < ApplicationMailer

  # Subject can be set in your I18n file at config/locales/en.yml
  # with the following lookup:
  #
  #   en.user_mailer.account_activation.subject
  #
  def account_activation
    @greeting = "Hi"
      # インスタンス変数を展開

    mail to: "to@example.org"
  end

  # Subject can be set in your I18n file at config/locales/en.yml
  # with the following lookup:
  #
  #   en.user_mailer.password_reset.subject
  #
  def password_reset
    @greeting = "Hi"
      # インスタンス変数を展開

    mail to: "to@example.org"
  end
end

user_mailer.rbではメイラーでは何をするのかを設定する。

演習 1

コンソールを開き、CGIモジュールのescapeメソッド(リスト 11.15)でメールアドレスの文字列をエスケープできることを確認してみましょう。このメソッドで"Don't panic!"をエスケープすると、どんな結果になりますか?

>> CGI.escape("Don't panic!")
=> "Don%27t+panic%21"

エスケープ:使えない文字列を使える文字列に変換する。

11.2.2 送信メールのプレビュー

メールのメッセージをその場でプレビューすることができるメールプレビューを設定する。

development.rb: 開発環境用 / test.rb: テスト環境用 / production.rb : 本番環境用

host = 'localhost:3000' # ローカル環境用
config.action_mailer.default_url_options = { host: host, protocol: 'http' }

cloud9を使っていないので、上記を選択。
host〜をコピペすると、自分が開発しているhost(ドメイン名)にGETリクエストが送れないためにエラーが起きます。

演習 1

Railsのプレビュー機能を使って、ブラウザから先ほどのメールを表示してみてください。「Date」の欄にはどんな内容が表示されているでしょうか?

アクセスした日時が表示される。

11.2.3 送信メールのテスト

メールプレビューのテストも作成して、プレビューをダブルチェックできるようする。

リスト 11.21: テストのドメインホストを設定する

test/mailers/user_mailer_test.rb

require 'test_helper'

class UserMailerTest < ActionMailer::TestCase

  test "account_activation" do
    user = users(:Michael)
      # users(:Michael)をuserに代入
    user.activation_token = User.new_token
      # トークン情報を生成してuser.activation_tokenに代入
    mail = UserMailer.account_activation(user)
      # UserMailer.account_activation(user)をmail変数に代入

    # ここから確認のテスト
    assert_equal "Account activation", mail.subject
      # mail.subject(件名)を確認
    assert_equal [user.email], mail.to
      # mail.to(送り先)を確認
    assert_equal ["noreply@example.com"], mail.from
      # mail.from(送り元)を確認
    assert_match user.name,               mail.body.encoded
      # mail.body(本文)にuser.name(名前)が入っているか確認
    assert_match user.activation_token,   mail.body.encoded
      # mail.body(本文)にuser.activation_token(トークン)が入っているか確認
    assert_match CGI.escape(user.email),  mail.body.encoded
      # mail.body(本文)にuser.emailの「@」が
      # CGI.escape(エスケープ処理)されているものが入っているか確認
  end
end

演習 1

この時点で、テストスイートが green になっていることを確認してみましょう。
動作確認のみなので省略。

演習 2

リスト 11.20で使ったCGI.escapeの部分を削除すると、テストが red に変わることを確認してみましょう。
動作確認のみなので省略。

11.2.4 ユーザーのcreateアクションを更新

ユーザー登録を行うcreateアクションにコードを追加し、メイラーをアプリケーションで実際に使えるようにする。
signup直後のログインの廃止(本人確認前にログインできないようにする)して、メールチェックしてもらえるように促す。

app/controllers/users_controller.rb

class UsersController < ApplicationController
  .
  .
  .
  def create
    @user = User.new(user_params)
      # app/models/user.rb
      # attr_accessor :remember_token, :activation_token
      # before_save   :downcase_email

      # def create_activation_digest
      #  self.activation_token  = User.new_token
      #   self.activation_digest = User.digest(activation_token)
      # end

    if @user.save

      # app/models/user.rb
      # before_create :create_activation_digest

      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
  .
  .
  .
end

演習 1

新しいユーザーを登録したとき、リダイレクト先が適切なURLに変わったことを確認してみましょう。その後、Railsサーバーのログから送信メールの内容を確認してみてください。有効化トークンの値はどうなっていますか?

適切なURL: root_url

----==_mimepart_603da2dfbacd4_11ed2af75249ad6c294cd
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

Hi moutoon,

Welcome to the Sample App! Click on the link below to activate your account:

http://localhost:3000/account_activations/iXav_kpcTA4krSc-3LR3DA/edit?email=moutoonm342%40gamil.com

演習 2

コンソールを開き、データベース上にユーザーが作成されたことを確認してみましょう。また、このユーザーはデータベース上にはいますが、有効化のステータスがfalseのままになっていることを確認してください。

>> user = User.find_by(name: "moutoon")
   (0.1ms)  begin transaction
  User Load (5.8ms)  SELECT "users".* FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "moutoon"], ["LIMIT", 1]]
=> #<User id: 101, name: "moutoon", email: "moutoonm342@gamil.com", created_at: "2021-03-02 02:28:47", updated_at: "2021-03-02 02:28:47", password_digest: [FILTERED], remember_digest: nil, admin: nil, activation_digest: "$2a$12$9y5elJ64pu1EC1COuJfdU.95jcOd0TdqpDyHz7W5m1M...", activated: false, activated_at: nil>

activated: falseになっている。

0
0
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
0
0