###AccountActivationのデータモデル
ubuntu:~/environment/sample_app (account-activation) $ rails generate migration add_activation_to_users activation_digest:string activated:boolean activated_at:datetime
Running via Spring preloader in process 4751
invoke active_record
create db/migrate/20211017043743_add_activation_to_users.rb
####Activationトークンのコールバック
####アカウント有効化用の属性とインデックスを追加するマイグレーション
db/migrate/[timestamp]_add_activation_to_users.rb
class AddActivationToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :activation_digest, :string
add_column :users, :activated, :boolean, default: false
# activated属性のデフォルトの論理値をfalseにしておきます
# 仮想属性の有効化トークンにアクセス
add_column :users, :activated_at, :datetime
end
end
###Userモデルにアカウント有効化のコードを追加する
app/models/user.rb
class User < ApplicationRecord
attr_accessor :remember_token, :activation_token
before_save :downcase_email
before_create :create_activation_digest
# トークンとそれに対応するダイジェストを割り当てる
.
.
.
private
# メールアドレスをすべて小文字にする
def downcase_email
self.email = email.downcase
end
# 有効化トークンとダイジェストを作成および代入する
def create_activation_digest
# Userモデル内でしか使わないので、外部に公開する必要ない。
self.activation_token = User.new_token
self.activation_digest = User.digest(activation_token)
end
end
####サンプルユーザーの生成とテスト
サンプルデータとfixtureも更新し、テスト時のサンプルとユーザーを事前に有効化する
####サンプルユーザーを最初から有効にしておく
db/seeds.rb
# メインのサンプルユーザーを1人作成する
User.create!(name: "Example User",
email: "example@railstutorial.org",
password: "foobar",
password_confirmation: "foobar",
admin: true,
activated: true,
activated_at: Time.zone.now)
# create!は基本的にcreateメソッドと同じものですが、
# ユーザーが無効な場合にfalseを返すのではなく例外を発生させる
# admin:trueにして管理者にする
# サーバーのタイムゾーンに応じたタイムスタンプ
# 追加のユーザーをまとめて生成する
# メイン以外のユーザー99人を作成
99.times do |n|
name = Faker::Name.name
email = "example-#{n+1}@railstutorial.org"
# 数ごとにメアドが変更される
password = "password"
# パスワードは変わらない
User.create!(name: name,
email: email,
password: password,
password_confirmation: password,
activated: true,
activated_at: Time.zone.now)
# 許可された属性リストにadminが含まれていない
# 任意のユーザーが自分自身にアプリケーションの
# 管理者権限を与えることを防止
end
####fixtureのユーザーを有効にしておく
test/fixtures/users.yml
michael:
name: Michael Example
email: michael@example.com
password_digest: <%= User.digest('password') %>
admin: true
activated: true
activated_at: <%= Time.zone.now %>
# サーバーのタイムゾーンに応じたタイムスタンプ
archer:
name: Sterling Archer
email: duchess@example.gov
password_digest: <%= User.digest('password') %>
activated: true
activated_at: <%= Time.zone.now %>
lana:
name: Lana Kane
email: hands@example.gov
password_digest: <%= User.digest('password') %>
activated: true
activated_at: <%= Time.zone.now %>
malory:
name: Malory Archer
email: boss@example.gov
password_digest: <%= User.digest('password') %>
activated: true
activated_at: <%= Time.zone.now %>
<% 30.times do |n| %>
# さらに30人のユーザーを追加
user_<%= n %>:
name: <%= "User #{n}" %>
email: <%= "user-#{n}@example.com" %>
password_digest: <%= User.digest('password') %>
activated: true
activated_at: <%= Time.zone.now %>
<% end %>
###演習
1.
本項での変更を加えた後、テストスイートが green のままになっていることを確認してみましょう。
ubuntu:~/environment/sample_app (account-activation) $ rails t
Running via Spring preloader in process 9538
Started with run options --seed 13465
43/43: [============================] 100% Time: 00:00:03, Time: 00:00:03
Finished in 3.52011s
43 tests, 168 assertions, 0 failures, 0 errors, 0 skips
コンソールからUserクラスのインスタンスを生成し、そのオブジェクトからcreate_activation_digestメソッドを呼び出そうとすると(Privateメソッドなので)NoMethodErrorが発生することを確認してみましょう。また、そのUserオブジェクトからダイジェストの値も確認してみましょう。
ubuntu:~/environment/sample_app (account-activation) $ rails console
Running via Spring preloader in process 9590
Loading development environment (Rails 6.0.3)
>> User.create_activate_digest
Traceback (most recent call last):
1: from (irb):1
NoMethodError (undefined method `create_activate_digest' for User (call 'User.connection' to establish a connection):Class)
リスト 6.34で、メールアドレスの小文字化にはemail.downcase!という(代入せずに済む)メソッドがあることを知りました。このメソッドを使って、リスト 11.3のdowncase_emailメソッドを改良してみてください。また、うまく変更できれば、テストスイートは成功したままになっていることも確認してみてください。
class User < ApplicationRecord
.
.
.
#private
# メールアドレスをすべて小文字にする
def downcase_email
email.downcase!
end
.
.
.
end
ubuntu:~/environment/sample_app (account-activation) $ rails t
Running via Spring preloader in process 11264
Started with run options --seed 11907
43/43: [============================] 100% Time: 00:00:02, Time: 00:00:02
Finished in 2.14029s
43 tests, 168 assertions, 0 failures, 0 errors, 0 skips