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

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

ただいまの
回答率

90.12%

Railsで発生した「undefined local variable or method」エラーを直したいです。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 3,986

sugisakisaki

score 9

前提・実現したいこと

該当箇所とされるファイルを一通り確認しても問題箇所が見つからず、困っています。
rails初心者です。

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

Railsチュートリアル10章のリスト10.26より、
rails testを走らせた時に10errorが発生しました。

(直近テスト リスト10.22はエラー無し)

  1) Error:
UsersEditTest#test_successful_edit:
NoMethodError: undefined method `logged_in_user' for #<UsersController:0x007fa114dbe2e8>
Did you mean?  logged_in?
    test/integration/users_edit_test.rb:25:in `block in <class:UsersEditTest>'

  2) Error:
UsersEditTest#test_unsuccessful_edit:
NoMethodError: undefined method `logged_in_user' for #<UsersController:0x007fa114d6cfd8>
Did you mean?  logged_in?
    test/integration/users_edit_test.rb:12:in `block in <class:UsersEditTest>'

  3) Error:
UsersControllerTest#test_should_redirect_edit_when_logged_in_as_wrong_user:
NoMethodError: undefined method `logged_in_user' for #<UsersController:0x00000006b5e658>
Did you mean?  logged_in?
    test/controllers/users_controller_test.rb:33:in `block in <class:UsersControllerTest>'

  4) Error:
UsersControllerTest#test_should_redirect_update_when_logged_in_as_wrong_user:
AbstractController::ActionNotFound: The action 'update' could not be found for UsersController
    test/controllers/users_controller_test.rb:40:in `block in <class:UsersControllerTest>'

  5) Error:
UsersControllerTest#test_should_get_new:
ActionView::Template::Error: First argument in form cannot contain nil or be empty
    app/views/users/new.html.erb:5:in `_app_views_users_new_html_erb__4200017072968446905_56780960'
    test/controllers/users_controller_test.rb:11:in `block in <class:UsersControllerTest>'

  8) Error:
UsersLoginTest#test_login_with_valid_information_followed_by_:
ActionView::Template::Error: undefined method `name' for nil:NilClass
    app/views/users/show.html.erb:1:in `_app_views_users_show_html_erb__1377065752919381560_58665040'
    test/integration/users_login_test.rb:24:in `block in <class:UsersLoginTest>'

  9) Error:
UsersSignupTest#test_valid_signup_information:
ActionView::Template::Error: First argument in form cannot contain nil or be empty
    app/views/users/new.html.erb:5:in `_app_views_users_new_html_erb__4200017072968446905_56780960'
    test/integration/users_signup_test.rb:16:in `block in <class:UsersSignupTest>'

32 runs, 47 assertions, 0 failures, 10 errors, 0 skips

(字数制限により同じファイルからのエラーは一部省略してます)

該当のソースコード

テスト(10章で実装したもの)

①UsersEditTest

require 'test_helper'

class UsersEditTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  # 失敗時
  test "unsuccessful edit" do
    log_in_as(@user)
    get edit_user_path(@user)
    assert_template 'users/edit'
    patch user_path(@user), params: { user: { name:  "",
                                              email: "foo@invalid",
                                              password:              "foo",
                                              password_confirmation: "bar" } }

    assert_template 'users/edit'
  end

  # 成功時
  test "successful edit" do
    log_in_as(@user)
    get edit_user_path(@user)
    assert_template 'users/edit'
    name  = "Foo Bar"
    email = "foo@bar.com"
    patch user_path(@user), params: { user: { name:  name,
                                              email: email,
                                              password:              "",
                                              password_confirmation: "" } }
    assert_not flash.empty?
    assert_redirected_to @user
    @user.reload
    assert_equal name,  @user.name
    assert_equal email, @user.email
  end
end


②UsersControllerTest

require 'test_helper'

class UsersControllerTest < ActionDispatch::IntegrationTest

  def setup
    @user       = users(:michael)
    @other_user = users(:archer)
  end

  test "should get new" do
    get signup_path
    assert_response :success
  end

  test "should redirect edit when not logged in" do
    get edit_user_path(@user)
    assert_not flash.empty?
    assert_redirected_to login_url
  end

  test "should redirect update when not logged in" do
    patch user_path(@user), params: { user: { name: @user.name,
                                              email: @user.email } }
    assert_not flash.empty?
    assert_redirected_to login_url
  end


  # 他人が入った場合の失敗テスト

  test "should redirect edit when logged in as wrong user" do
    log_in_as(@other_user) # 例 archerさんが入った場合
    get edit_user_path(@user)
    assert flash.empty?
    assert_redirected_to root_url
  end

  test "should redirect update when logged in as wrong user" do
    log_in_as(@other_user) # 例 archerさんが入った場合
    patch user_path(@user), params: { user: { name: @user.name,
                                              email: @user.email } }
    assert flash.empty?
    assert_redirected_to root_url
  end

end

(③test_helper.rb)

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'

class ActiveSupport::TestCase
  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  fixtures :all

  # テストユーザーがログイン中の場合にtrueを返す
  def is_logged_in?
    !session[:user_id].nil?
  end

  # テストユーザーとしてログインする
  def log_in_as(user)
    session[:user_id] = user.id
  end
end

  class ActionDispatch::IntegrationTest

  # テストユーザーとしてログインする
  def log_in_as(user, password: 'password', remember_me: '1')
    post login_path, params: { session: { email: user.email,
                                          password: password,
                                          remember_me: remember_me } }
  end
end

ファイル(10章で実装したもの)

①UsersController

class UsersController < ApplicationController
  before_action :logged_in_user, only: [:edit, :update]
  before_action :correct_user,   only: [:edit, :update]
 # 上から順に行う

  def show
    @user = User.find(params[:id])
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      log_in @user
      flash[:success] = "Welcome to the Sample App!"
      redirect_to @user
      # GET => redirect_to "/user/#{@user.id}" => show
    else
      render "new"
    end
  end

  def edit
    @user = User.find(params[:id])
  end

  def update
    @user = User.find(params[:id])
    if @user.update_attributes(user_params) #下のバリデーション
      # Success
      flash[:success] = "Profile updated"
      redirect_to @user
    else
      # Failure
      # => @user.errors.full_messages()
      render 'edit'
    end
  end

  private

    def user_params
      params.require(:user).permit(
         :name, :email, :password,
         :password_confirmation)
    end

    # beforeアクション

    # ログイン済みユーザーかどうか確認
    def logged_in_user
      unless logged_in?
        flash[:danger] = "Please log in."
        redirect_to login_url
      end
    end

    # 正しいユーザーかどうか確認
    def correct_user
      # GET   edit
      # PATCH update
      @user = User.find(params[:id])
      redirect_to(root_url) unless @user == current_user
    end
  end


②edit.html.erb

<% provide(:title, "Edit user") %>
<h1>Update your profile</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_for(@user) do |f| %>
      <%= render 'shared/error_messages' %>

      <%= f.label :name %>
      <%= f.text_field :name, class: 'form-control' %>

      <%= f.label :email %>
      <%= f.email_field :email, class: 'form-control' %>

      <%= f.label :password %>
      <%= f.password_field :password, class: 'form-control' %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation, class: 'form-control' %>

      <%= f.submit "Save changes", class: "btn btn-primary" %>
    <% end %>

    <div class="gravatar_edit">
      <%= gravatar_for @user %>
      <a href="http://gravatar.com/emails" target="_blank">change</a>
    </div>
  </div>
</div>

試したこと

①ルーティング

実際にプレビューでブラウザに入り、

Homeから新規登録ページに行くと以下のエラーメッセージが出ました。

イメージ説明

エラーメッセージに「Routing Error」とあったので、

routesを確認しました。

Rails.application.routes.draw do

  get 'sessions/new'

  root 'static_pages#home'
  get  '/help',    to: 'static_pages#help'
  get  '/about',   to: 'static_pages#about'
  get  '/contact', to: 'static_pages#contact'
  get  '/signup',  to: 'users#new'

  get    '/login',   to: 'sessions#new'
  post   '/login',   to: 'sessions#create'
  delete '/logout',  to: 'sessions#destroy'

  resources :users

end


signup_pathとnew_user_pathがあることで、

これらのnewアクションへの重複によるものかと思いました。

signup GET    /signup(.:format)         users#new

new_user GET    /users/new(.:format)      users#new

ただ、home.html.erbを見るとsignup_pathへ送っていて、

またRailsチュートリアルでも特に問題ないとのことだったので、

違うと判断しました。

②誤字

リスト10.22〜10.26間でエラーが発生したため、

実装したチュートリアル内のコードを再度コピペし直しタイプミス等確認しましたが、エラーのままでした。

念のため10章の内容全てをコピペし直しましたが、変わりませんでした。

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

長文すみません。

1日調べましたが解決できず、先に進めなくて困っています。

ご協力お願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

恐らくUserControllerのどこかに全角の空白が含まれているのだと思います。
全角空欄がないか、検索をして調べてみてください。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/01/15 22:52

    " "はそういうことだったのですね!一瞬で解決しました!

    本当に助かりました!ありがとうございます!!!

    キャンセル

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

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