質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.53%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

763閲覧

Remenber me機能において,わざわざ仮想の属性を作る理由がわからない

OHASI

総合スコア96

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2022/11/17 09:39

 現在,ruby on railsでユーザのログイン状態をブラウザを閉じた後でも有効にする「Remenber me機能」を実装しようとしていて,記憶トークンと記憶ダイジェストの部分でつまづいています.

ちなみに,使用している教材は「Ruby on Railsチュートリアル」というもので,その中でわからない部分があったため質問させていただきました.

前提

まず,記憶ダイジェスト用のマイグレーションを生成しました.
なお,記憶ダイジェストを保存する場所のカラム名は「remember_digest」にしました.
出来上がったUserモデルは以下の通りです.

idinteger
namestring
emailstring
created_atdatetime
updated_atdatetime
password_digeststring
remember_digeststring

教材でわからない部分

rememberメソッドの説明

 ユーザーを記憶するには、記憶トークンを作成して、そのトークンをダイジェストに変換したものをデータベースに保存します。

 さしあたっての実装計画としては、user.rememberメソッドを作成することにします。

 user.rememberメソッドは記憶トークンをユーザーと関連付け、トークンに対応する記憶ダイジェストをデータベースに保存します。Userモデルには既にremember_digest属性が追加されていますが、remember_token属性はまだ追加されていません。このためuser.remember_tokenメソッドを使ってトークンにアクセスできるようにし、かつ、トークンをデータベースに保存せずに実装する必要があります。

---------------------- ここからが分からない -------------------------

rememberメソッドの1行目の代入にご注目ください。selfというキーワードを使わないと、Rubyによってremember_tokenという名前のローカル変数が作成されてしまいます。この動作は、Rubyにおけるオブジェクト内部への要素代入の仕様によるものです。今欲しいのはローカル変数ではありません。selfキーワードを与えると、この代入によってユーザーのremember_token属性が期待どおりに設定されます。

なぜローカル変数ではだめなのですか?
コードを見る限りただ値を移行しているだけのように見えるのですが?
でもそうじゃないから,わざわざ仮想の属性を作ってまで,こんなことをしているのだろうと思うのですが,,,

まとめると

  • 質問1: わざわざ仮想の属性を作る理由はなんですか?
  • 質問2:値をただ移動しているだけではないのなら,何をしている(何が行われている)のかご教授ください.

コード(下から3,4行目が分かりません)

ruby

1// ファイルの場所 2app/models/user.rb 3 4class User < ApplicationRecord 5 attr_accessor :remember_token // ← 新しいトークンを作成するためのnew_tokenメソッドを作成 6 before_save { self.email = email.downcase } 7 validates :name, presence: true, length: { maximum: 50 } 8 VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i 9 validates :email, presence: true, length: { maximum: 255 }, 10 format: { with: VALID_EMAIL_REGEX }, 11 uniqueness: { case_sensitive: false } 12 has_secure_password 13 validates :password, presence: true, length: { minimum: 6 } 14 15 # 渡された文字列のハッシュ値を返す 16 def User.digest(string) 17 cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : 18 BCrypt::Engine.cost 19 BCrypt::Password.create(string, cost: cost) 20 end 21 22 # ランダムなトークンを返す 23 def User.new_token 24 SecureRandom.urlsafe_base64 25 end 26 27 # 永続セッションのためにユーザーをデータベースに記憶する 28 def remember 29 self.remember_token = User.new_token               // ← この部分(なぜローカル変数ではだめなのですか?) 30 update_attribute(:remember_digest, User.digest(remember_token)) // ← この部分 31 end 32end

長くなって申し訳ありません.
以上,よろしくお願いいたします.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

質問1: わざわざ仮想の属性を作る理由はなんですか?

あとでremember_tokenを使う必要があるためです。ダイジェスト化した後のremember_digestからremember_tokenを復元することはできません。

投稿2022/11/17 09:48

maisumakun

総合スコア145021

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

OHASI

2022/11/17 12:03

なるほど! 分かりやすい解説ありがとうございました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.53%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問