1
1

Rails Tutorial 第11章

Last updated at Posted at 2023-10-03

演習1

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

何も問題がなければGREENになるはずです

表 11.2の名前付きルーティングに_pathではなく_urlを使っている理由を考えてみましょう。(ヒント: 私たちはこれから名前付きルーティングをメールで使います。)

_path は例えば 
user_path
→'/user'
のようにrails 内で使用されているルートであれば_pathを使用できるという事です

_urlは
'http://www.example.com/user'
のように完全なURLを返してあげる必要があります。
それは_pathと違い外部からのアクセスとなるためです

まあ_pathは家では"花子ちゃん"でも良いけど
_urlは、外に出たら"山田花子さん"と呼びなさいって感じですかね(意味不明)

演習2

本節の変更を加えた後も、テストスイートが引き続き green になることを確認してみましょう。

rails testを行い、GREENになっていたらOKです

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

 user = User.first
  User Load (0.1ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> 
#<User:0x00007ff385e78c88
...
user.create_activation_digest
/usr/local/rvm/gems/default/gems/activemodel-7.0.4.3/lib/active_model/attribute_methods.rb:455:in `method_missing': private method `create_activation_digest' called for #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2023-10-01 08:28:59.861078000 +0000", updated_at: "2023-10-01 08:28:59.861078000 +0000", password_digest: [FILTERED], remember_digest: nil, admin: true, activation_digest: "$2a$12$pkJnv9FWgk753jd0oPM4TeV7y4P2q7fZNgfTXZH.D.A...", activated: true, activated_at: "2023-10-01 08:28:59.606888000 +0000"> (NoMethodError)
Did you mean?  restore_activation_digest!

この中の

activation_digest: "$2a$12$pkJnv9FWgk7・・・

がダイジェスト。
トークンが有効化されていますね。

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

app/models/user.rb

private

  # メールアドレスをすべて小文字にする
  def downcase_email
    self.email = email.downcase
  end

  # 有効化トークンとダイジェストを作成および代入する
  def create_activation_digest
    self.activation_token  = User.new_token
    self.activation_digest = User.digest(activation_token)
  end
end

のdowncase_emailメソッド内を以下に変更しましょう

  # メールアドレスをすべて小文字にする
  def downcase_email
    email.downcase!
  end

これでrails testを実行してみてGREENであることを確認してみましょう

演習3

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

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

演習4

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

その名の通り、現在の日付が入っています

スクリーンショット 2023-10-02 070407.png

演習5

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

GREENになればOKです

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

演習6

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

期待通りroot_urlにリダイレクトされています
スクリーンショット 2023-10-02 073955.png

下記のようにauthenticity_tokenがハッシュ化されています

Processing by UsersController#create as TURBO_STREAM
  Parameters: {"authenticity_token"=>"h1SQidx5juySt_ZX_7u9XT_bYE3BSFoJrLbeqfWY8nb0ufphkv0WVZPFUUY-w712CLnoDLxDptVaksFQM3ggQA", "user"=>{"name"=>"ryoryo", "email"=>"ryoryoryo@gmail.com", "password"=>"password", "password_confirmation"=>"password"}, "commit"=>"Create my account"}

補足
もしauthenticity_token"=>[FILTERD]となっている場合は

config/initializers/filter_parameter_logging.rb

の中にある

# Be sure to restart your server when you modify this file.

# Configure parameters to be filtered from the log file. Use this to limit dissemination of
# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported
# notations and behaviors.
#Rails.application.config.filter_parameters += [
  #:passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
#]

コメントアウトしてみてください。ハッシュ化されたauthenticity_tokenが表示されるはずです。
この中にある要素をフィルタリングしてくれます。今回はtokenという名前が付いているのでフィルタリングしてしまっているので、一時的にコメントアウトすれば表示されます。


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

最後に作成したユーザーを表示してみます。
activateがfalseであることを確認しましょう

 User.last
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> 
#<User:0x00007f71081be240
 id: 109,
 name: "ryoryo",
 email: "ryoryoryo@gmail.com",
 created_at: Mon, 02 Oct 2023 06:23:40.926093000 UTC +00:00,
 updated_at: Mon, 02 Oct 2023 06:23:40.926093000 UTC +00:00,
 password_digest: "[FILTERED]",
 remember_digest: nil,
 admin: false,
 activation_digest: "$2a$12$qOwZtLpGmyt4bQtr6cKShOuV7gUW4lNUp/xfPi21gKAnnzx01MAwK",
 activated: false,
 activated_at: nil>

演習7

コンソール内で新しいユーザーを作成してみてください。新しいユーザーの記憶トークンと有効化トークンはどのような値になっているでしょうか? また、各トークンに対応するダイジェストの値はどうなっているでしょうか?

 User.create(name: "ryouko", email: "ryouko@example.com", password: "password", password_confirmation: "password") 
(出力、略)

user = User.last

user.remember_token
=> nil
 user.remember_digest
=> nil
user.activation_token
=> "zg-CQQ4nTz60g0auoBff2Q"

user.activation_digest
=> "$2a$12$bzGtLdXEGenz8Umqzpt3huYm8RstXrztmDv3AwZJzf29Nh98Hr932"

リスト 11.26で抽象化したauthenticated?メソッドを使って、先ほどの各トークン/ダイジェストの組み合わせで認証が成功することを確認してみましょう。

user.authenticated?(:activation, user.activation_token)
=> true

演習8

11.2.4で生成したメールに含まれているURLをRailsコンソールで調べてみてください。URLのどの部分に有効化トークンが含まれているでしょうか?

新規ユーザーを登録した際に、ログでメールが確認できるはずです。それを調べてみましょう

<p>
Welcome to the Sample App! Click on the link below to activate your account:
</p>

<a href="https://&lt;hex string&gt;.app.github.dev/account_activations/7KnO69jec0OEOMCVrzO9aA/edit?email=hahaha%40gmail.com">Activate</a>

  </body>
</html>

ここの

account_activations/7KnO69jec0OEOMCVrzO9aA

の部分が有効化トークンとなっています

先ほど見つけたURLをブラウザに貼り付けて、そのユーザーの認証に成功し、有効化できることを確認してみましょう。また、有効化ステータスがtrueになっていることをコンソールから確認してみてください。

演習でやったURLを貼り付けてみましょう
私のURLは紛らわしいのですが、この部分です

/account_activations/7KnO69jec0OEOMCVrzO9aA/edit?email=hahaha%40gmail.com

ここをrailsのURLの後ろに貼り付けることでactivationに成功しました
スクリーンショット 2023-10-03 061816.png

続いて有効かステータスを調べてみましょう

user = User.last
 user.activated
=> true

演習9

リスト 11.36にあるactivateメソッドはupdate_attributeを2回呼び出していますが、これは各行で1回ずつデータベースへ問い合わせしていることになります。リスト 11.40に記したテンプレートを使って、update_attributeの呼び出しを1回のupdate_columns呼び出しにまとめてみましょう。これでデータベースへの問い合わせが1回で済むようになります。変更後にテストを実行し、 green になることも確認してください。(注: update_columnsはバリデーションが実行されない上、update_attributeと異なりモデルのコールバックも行われないため、本チュートリアル以外で使用する際は注意が必要です。)

単純にこのようにまとめてしまえばOKです

  def activate
    update_columns(activated: true, activated_at: Time.zone.now)
  end

現在は、/usersのユーザーindexページを開くとすべてのユーザーが表示され、/users/:idのようにIDを指定すると個別のユーザーを表示できます。しかし考えてみれば、有効でないユーザーは表示する意味がありません。そこで、リスト 11.41のテンプレートを使って、この動作を変更してみましょう10 。なお、このテンプレートで使っているActive Recordのwhereメソッドについては、13.3.3でもう少し詳しく説明します。

def index
    @users = User.where(activated: true).paginate(page: params[:page])
  end

  def show
    @user = User.find(params[:id])
    redirect_to root_url and return unless @user.activated?
  end

ここまでの演習課題で変更したコードをテストするために、/usersと/users/:idの両方に対する統合テストを作成してみましょう。/usersテストのテンプレートはリスト 11.42に示されています(本節の手法をリスト 10.63に適用した結果も示されています)。users/:idについては、rails generate integration_test user_showを実行してから、リスト 11.43に示すように無効なfixtureユーザを追加してください。対応するテストのテンプレートはリスト 11.44に示されています。

いろいろ検証してみましたが、ここはいったんパスします。また解答が分かり次第更新します。

演習10

実際に本番環境でユーザー登録をしてみましょう。ユーザー登録時に入力したメールアドレスにメールは届きましたか?

チュートリアルに従ってmailgunやrenderで設定をして、実際にユーザー登録してみましょう。
登録後入力したメールアドレスにactivationのメールが来るのでactiveすればログインできるはずです

メールを受信できたら、実際にメールをクリックしてアカウントを有効化してみましょう。また、Render上のログを調べてみて、有効化に関するログがどうなっているのか調べてみてください。

render上のログは下記の場所から見れるはずです。有効化されたログは恐らくここだと思われます
スクリーンショット 2023-10-03 161428.png

演習11

演習12

1
1
3

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