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

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

ただいまの
回答率

89.55%

rails tutorial 第9章 remember_token アトリビュートアクセッサーが上手くいかない

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 401

前提・実現したいこと

rails tutorial第9章でremember me機能をつける為に
アトリビュートアクセッサーを使ってremember_tokenという
アクセッサーを定義したのですがエラーが出てしまいます。

発生している問題・エラーメッセージ

ERROR["test_current_user_returns_right_user_when_session_is_nil", SessionsHelperTest, 1.2696126079999885]
 test_current_user_returns_right_user_when_session_is_nil#SessionsHelperTest (1.27s)
NoMethodError:         NoMethodError: undefined method `remember_token=' for #<User:0x00000000076326d8>
        Did you mean?  remember_token       =
            app/models/user.rb:27:in `remember'
            app/helpers/sessions_helper.rb:9:in `remember'
            test/helpers/sessions_helper_test.rb:7:in `setup'

ちなみにテストを走らせるとこのようなエラーになります。

該当のソースコード

class User < ApplicationRecord
  attr_accessor :remember_token       # アトリビュートアクセッサー を使ってセッターメソッドとゲッターメソッドを実装することができる (データベースには反映されないけどメソッドとして使えるデータを保持する場所)
  has_many :microposts, dependent: :destroy
  before_save {email.downcase!}
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: {case_sensitive: false}
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }, allow_nil: true

  # 渡された文字列のハッシュ値を返す
  def self.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end

  # ランダムなトークンを返す
  def User.new_token
    SecureRandom.urlsafe_base64
  end

    # 永続セッションのためにユーザーをデータベースに記憶する
  def remember
    self.remember_token = User.new_token
    update_attribute(:remember_digest, User.digest(remember_token))   
  end

  # 渡されたトークンがダイジェストと一致したらtrueを返す
  def authenticated?(remember_token)
    return false if remember_digest.nil?
    BCrypt::Password.new(remember_digest).is_password?(remember_token)
  end

  # ユーザーのログイン情報を破棄する
  def forget
    update_attribute(:remember_digest, nil)
  end

end

試したこと

rails consoleを使って rememberを実行すると

2.6.3 :017 > user = User.first
User Load (0.1ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2019-07-17 09:41:35", updated_at: "2019-07-17 09:41:35", password_digest: "$2a$10$JDI8PEk25zNy8PIuJLqLVevU9jblPNaZ/sZN8AMjwNT...", remember_digest: nil, admin: true> 
2.6.3 :018 > user.remember                                                    
Traceback (most recent call last):
2: from (irb):18
1: from app/models/user.rb:27:in remember' NoMethodError (undefined method remember_token=' for #<User:0x0000000002e40910>)
Did you mean?  remember_token       =
2.6.3 :019 > 

と、remember_tokenでnomethoderrorが出てしまいます。

補足情報(FW/ツールのバージョンなど)

ruby 2.6.3, rails 5.1.6 を使用しています。
ここにより詳細な情報を記載してください。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+1

  attr_accessor :remember_token       # アトリビュートアクセッサー を使ってセッターメソッドとゲッターメソッドを実装することができる (データベースには反映されないけどメソッドとして使えるデータを保持する場所)

remember_tokenのあとに全角空白が混入しています。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/22 19:21

    コメントありがとうございます!
    アトリビュートアクセッサーの後ろのコメントアウトがエラーの原因だったようです。
    ありがとうございました。

    キャンセル

  • 2019/07/22 19:23

    コメントアウトの前の全角空白が問題なのでお間違えのないように
    半角空白と全角空白の識別ができるテキストエディタを使った方がよいですよ

    キャンセル

checkベストアンサー

0

ここですが、User.new_tokenではなくself.new_tokenではないでしょうか?

def self.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end
# ランダムなトークンを返す
  def User.new_token
    SecureRandom.urlsafe_base64
  end

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/19 19:47

    すみません。まだまだrails を始めたばかりでUserモデルではなく、Userクラスだという指摘が良く理解できません。自分でも少し調べては見たのですが良くわかりませんでした。
    もう少し詳しく教えていただけますでしょうか。
    もしくは理解しやすいサイトなどがあればお教えできないでしょうか。

    キャンセル

  • 2019/07/19 21:34

    class User < ApplicationRecord
    ここの部分です。このクラスそのものがselfになっているのではないでしょうか。

    通常は、selfがモデルそのものを意味するのですが、このモデルメソッドのプログラムでのselfは先述したクラスそのものとして解釈されているのだと思います

    キャンセル

  • 2019/07/22 19:22

    コメントありがとうございます!
    アトリビュートアクセッサの後ろのコメントアウトがまずかったようです。
    返信遅れて申し訳ありませんでした。

    キャンセル

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

  • ただいまの回答率 89.55%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る