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

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

ただいまの
回答率

88.92%

Railsチュートリアル11章エラー

解決済

回答 1

投稿

  • 評価
  • クリップ 4
  • VIEW 522

takuo5

score 44

前提・実現したいこと

Railsチュートリアル学習中のものです。
11章のアカウント認証のところまで進めましたがここでrails testコマンド入力をすると下記エラーが出ました。
リンク内容
このエラーの解消方法がわからず詰まっております。
該当されると思われるファイルのコードは下記に貼り付けております。

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

ERROR["test_current_user_returns_nil_when_remember_digest_is_wrong", SessionsHelperTest, 2.259955172000005]
 test_current_user_returns_nil_when_remember_digest_is_wrong#SessionsHelperTest (2.26s)
ArgumentError:         ArgumentError: wrong number of arguments (given 1, expected 2)
            app/models/user.rb:32:in `authenticated?'
            app/helpers/sessions_helper.rb:60:in `current_user'
            test/helpers/sessions_helper_test.rb:17:in `block in <class:SessionsHelperTest>'

ERROR["test_current_user_returns_right_user_when_session_is_nil", SessionsHelperTest, 2.2706089260000084]
 test_current_user_returns_right_user_when_session_is_nil#SessionsHelperTest (2.27s)
ArgumentError:         ArgumentError: wrong number of arguments (given 1, expected 2)
            app/models/user.rb:32:in `authenticated?'
            app/helpers/sessions_helper.rb:60:in `current_user'
            test/helpers/sessions_helper_test.rb:11:in `block in <class:SessionsHelperTest>'

該当のソースコード

app/models/user.rb

class User < ApplicationRecord
  attr_accessor :remember_token, :activation_token
  before_save   :downcase_email
  before_create :create_activation_digest
  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 User.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?(attribute, token)
    digest = send("#{attribute}_digest")
    return false if digest.nil?
    BCrypt::Password.new(digest).is_password?(token)
  end

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

  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
app/helpers/sessions_helper.rb

module SessionsHelper

  # 渡されたユーザーでログインする
  def log_in(user)
    session[:user_id] = user.id
  end

  # ユーザーのセッションを永続的にする
  def remember(user)
    user.remember
    cookies.permanent.signed[:user_id] = user.id
    cookies.permanent[:remember_token] = user.remember_token
  end

  # 渡されたユーザーがログイン済みユーザーであればtrueを返す
  def current_user?(user)
    user == current_user
  end

  # 現在ログイン中のユーザーを返す (いる場合)
  def current_user
    if (user_id = session[:user_id])
      @current_user ||= User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id])
      raise       # テストがパスすれば、この部分がテストされていないことがわかる
      user = User.find_by(id: user_id)
      if user && user.authenticated?(:remember, cookies[:remember_token])
        log_in user
        @current_user = user
      end
    end
  end

  # ユーザーがログインしていればtrue、その他ならfalseを返す
  def logged_in?
    !current_user.nil?
  end

  # 永続的セッションを破棄する
  def forget(user)
    user.forget
    cookies.delete(:user_id)
    cookies.delete(:remember_token)
  end

   # 現在のユーザーをログアウトする
  def log_out
    forget(current_user)
    session.delete(:user_id)
    @current_user = nil
  end
test/helpers/sessions_helper_test.rb

require 'test_helper'

class SessionsHelperTest < ActionView::TestCase

  def setup
    @user = users(:michael)
    remember(@user)
  end

  test "current_user returns right user when session is nil" do
    assert_equal @user, current_user
    assert is_logged_in?
  end

  test "current_user returns nil when remember digest is wrong" do
    @user.update_attribute(:remember_digest, User.digest(User.new_token))
    assert_nil current_user
  end
end

試したこと

ネットで検索すると引数の数が違うということでエラーが出ていますと書かれていますが、どこをどのように直せばよいのかわかりません。

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

AWS : Cloud9

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

こんばんは。
もし解決済みとかでしたら、ご容赦くださいませ。
質問的なところもありますが、コメントしてみますね。

メッセージの件

引数の数が違うということでエラーが出ています

というので合っていますので、ログを丁寧に見ていくと良いです。

「sessions_helper.rbのcurrent_userのところで、user.rbのauthenticated?を呼び出してる。でも、引数が合わないよ」というメッセージになります。

一見すると問題なさそうな気がするのですが、ちょっと気になったのが、エラーで出ている行番号です。

app/models/user.rb:32:in authenticated?'             app/helpers/sessions_helper.rb:60:in current_user'
test/helpers/sessions_helper_test.rb:11:in `block in <class:SessionsHelperTest>'

sessions_helper.rbのソースコードを貼っていただいていますが、実際は、本当に60行までありますか?

また、60行目のcurrent_userのところで、user.rbのauthenticated?を呼び出している、という処理が書かれていますか?

もしかしたら編集の際のインデントやendの抜け漏れがあったりするかもしれません。ファイルの末尾までチェックするといいのでは。

チュートリアルの補足

Railsチュートリアルの各章、すこしずつ変えて進めていくと、抜粋だけだとわかりにくい点があるかもしれません。
チュートリアルのサイトを運用してくださっているYassLabさまのリポジトリで、各章の状態を追えるようになっているリポジトリがあります。

困ったらこちらを参考にされると良いと思います。

https://github.com/yasslab/sample_apps

今回話題にしている11章の課題が終わった段階だと、こちらになりますね。

https://github.com/yasslab/sample_apps/tree/master/5_1_2/ch11

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/09/27 23:37

    suamaさん、コメント頂きましてありがとうございます。
    とてもわかりやすいご解説をしていただいて本当にありがとうございます。

    YassLabさまのソースコードと自分のコードを見比べてみると下記のようにケアレスミスがありました。

    ①def current_userが2つ定義されていました。
    ⇛ 1つ削除しました。
    ②def current_userの中のコメントアウト部分がコメントアウトされていなかった。 ⇛ コメントアウトしました。

    上記2点を修正したところエラーが無くなりました。

    誠にお恥ずかしい間違えで申し訳ありません。
    Railsチュートリアル進めるにあたって今後は下記のことに気をつけていこうと思います。

    ①エラーメッセージのしっかりと読んで理解する。
    ②エラーメッセージにある箇所を確認。
    ③調べてわからない場合は完成版のソースコードと見比べて見る。

    非常に助かりました。
    ありがとうございました。

    キャンセル

  • 2019/09/28 06:18

    エラーが解消されたようで何よりです!
    エラーの読み取り方、原因の探り方も、ご自身の中でだいぶ理解されているかと思います。がんばってください!

    キャンセル

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

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

関連した質問

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