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

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

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

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

Q&A

解決済

1回答

1970閲覧

Ruby on rails 投稿したユーザーのみ編集 NameError|undefined local variable or method

ichigob

総合スコア27

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

0グッド

0クリップ

投稿2020/03/29 05:22

編集2020/03/29 08:27

環境

Ruby 2.6.3
Rails 5.2.4.1
初学者
ローカル
Mac

やろうとしていること

showのページで投稿したユーザーのみ編集のボタンを出したい

1つめのエラーは解決しました。

下部にあった2つ目のエラーはこちらに追記

<% if @post.user_id == @current_user.id %> エラーメッセージ NoMethodError in Posts#show undefined method `id' for nil:NilClass

エラーメッセージ

NameError in PostsController#show

undefined local variable or method `post' for #PostsController:0x00007fd3e1e1b380 Did you mean? @post

@user = post.userがエラー

def show @post = Post.find_by(id: params[:id]) @user = post.user end

show.thml.erb

<div class="post-preview"> <h2 class="post-title"> <%= @post.content %> </h2> <img src="<%="/user_images/#{@user.image_name}" %>"> <img src="<%=#"/user_images/#{post.user.image_name}" %>"> <%=# link_to(@post.user.name, "/users/#{@user.id})") %> <%= link_to(post.user.name, "/users/#{post.user.id}") %> <p class="post-subtitle"> 質問中身テキストテキストテキストテキストテキストテキスト... <p> show <p class="post-meta"> Posted by </p> <a href="#"> Start Bootstrap </a> <%= @user %> <p class="post-meta"><%= @post.created_at %></p> <% if @post.user_id == @current_user.id %> <div class="post-menus"> <%= link_to("編集", "/posts/#{@post.id}/edit") %> <%= link_to("削除", "/posts/#{@post.id}/destroy", {method: "post"}) %> </div> <!-- 以下の<% %>を使ってif文のendを追加してください --> <% end %> </div> <hr> <!-- Pager --> <div class="clearfix"> <a class="btn btn-primary btn-origin float-right" href="#">NEXT &rarr;</a> </div>

Posts_controoler.rb

class PostsController < ApplicationController #ログアウト時に表示しないページの設定 before_action :authenticate_user, {only: [:edit, :update, :new]} before_action :ensure_correct_user, {only: [:edit, :update, :destroy]} def index @posts = Post.all.order(created_at: :desc) end def show @post = Post.find_by(id: params[:id]) @user = post.user end # def new # if @current_user == nil # flash[:notice] = "ログインしてください" # redirect_to("/login") # end # end def new @post = Post.new end def create @post = Post.new( content: params[:content], user_id: @current_user.id ) if @post.save flash[:notice] = "質問が投稿されました。回答者にわかりやすい質問にするとよりよい回答がえ得られます!" redirect_to("/posts") else render("posts/new") end end def edit @post = Post.find_by(id: params[:id]) end def update @post = Post.find_by(id: params[:id]) @post.content = params[:content] if @post.save flash[:notice] = "変更されました。回答者にわかりやすい質問にするとよりよい回答がえ得られます!" render("/posts/edit") else render("/posts/edit") end end def destroy @post = Post.find_by(id: params[:id]) @post.destroy flash[:notice] = "質問が削除されました。" redirect_to("/posts") end # private # #paramsから欲しいデータのみ抽出 # def post_params # params.require(:post).permit(:name, :title, :content) # end def ensure_correct_user @post = Post.find_by(id:params[:id]) if @post.user_id != @current_user.id flash[:notice] = "権限がありません" redirect_to("/posts/index") end end end

Users_controoler.rb

class UsersController < ApplicationController #ログアウト時に表示しないページ設定 before_action :authenticate_user, {only: [:new, ]} #ログイン時に表示しないのページ設定 before_action :forbid_login_user, {only: [:new, :create, :login_form, :login]} #ログインユーザー before_action :ensure_correct_user,{only: [:edit, :update]} # before_action :correct_user, only: [:edit, :update, ] def index @users = User.all end def show @user = User.find_by(id: params[:id]) end def new @user = User.new end def create @user = User.new( name: params[:name], email: params[:email], image_name: "default_user.jpg", password_digest: params[:password_digest] ) if @user.save session[:user_id] = @user.id flash[:notice] = "ユーザー登録が完了しました" redirect_to("/users/#{@user.id}") else render("users/new") end end def edit @user = User.find_by(id: params[:id]) end def update @user = User.find_by(id: params[:id]) @user.name = params[:name] @user.email = params[:email] if params[:image] @user.image_name = "#{@user.id}.jpg" image = params[:image] File.binwrite("public/user_images/#{@user.image_name}" ,image.read) end if @user.save flash[:notice] = "ユーザー情報を編集しました" redirect_to("/users/#{@user.id}") else render("users/edit") end end def login_form end def login @user = User.find_by(email: params[:email], password_digest: params[:password_digest]) if @user session[:user_id] = @user.id flash[:notice] = "ログインしました" redirect_to("/") else @error_message = " メールアドレスまたはパスワードが間違っています。" @email = params[:email] @password_digest = params[:password_digest] render("users/login_form") end end def logout session[:user_id] = nil flash[:notice] = "ログアウト" redirect_to("/login") end def ensure_correct_user if @current_user.id != params[:id].to_i flash[:notice] = "権限がありません" redirect_to("/") end end # def correct_user # if @current_user.id != params[:id].to_i # flash[:notice] = "権限がありません" # redirect_to("/") # end # end # private # def correct_user # user = User.find(params[:id]) # if current_user != user # redirect_to root_path # end # end end

models/post.rb

class Post < ApplicationRecord # validates :content, {presence: true, length: {maximum: 14}} validates :content, {presence: true} validates :content, length: { maximum: 10, too_long: "入力は最大%{count}文字まで" } validates :user_id, {presence: :true} def user return User.find_by(id: self.user_id) end end

もう一箇所はまっている場所(現在上記のエラーが出ていて見れない)

<% if @post.user_id == @current_user.id %>
がエラー

user.idの idがnilのエラーだったと思います。

<% if @post.user_id == @current_user.id %> <div class="post-menus"> <%= link_to("編集", "/posts/#{@post.id}/edit") %> <%= link_to("削除", "/posts/#{@post.id}/destroy", {method: "post"}) %> </div> <!-- 以下の<% %>を使ってif文のendを追加してください --> <% end %>

試したこと。

はじめは、<% if @post.user_id == @current_user.id %>のエラーでした。

PostsController
UserController
を書き換えて試していうるうちに@user = post.userがエラーに。
@user = post.userを削除すると。

We're sorry, but something went wrong.

が出て進めなくなりました。
<% if @post.user_id == @current_user.id %>の部分は、
@post.user_id と @current_user.id をいろいろ書き換えましたがうまくいきません。
キータや参考になりそうなページも試しましたがうまくいきませんでした。

どこでハマってしまったかわからないので、記載漏れがあるかもしれません。
よろしくお願い致します。

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

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

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

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

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

guest

回答1

0

ベストアンサー

showアクション内で、postという変数が定義されていないいまま、@user = post.userとして使われています。
@user = @post.userにすればいいのではないでしょうか。

投稿2020/03/29 07:18

s_eric

総合スコア184

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

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

ichigob

2020/03/29 08:21

@user = User.find_by(id: @post.user_id) show.html <img src="<%= "/user_images/#{@user.image_name}" %>"> <%= link_to(@user.name, "/users/#{@user.id}")%> を直したところ1つ目のエラーが直ったかもしれません。
ichigob

2020/03/29 08:24

<% if @post.user_id == @current_user.id %> もう一つのエラーが見えました。 NoMethodError in Posts#show undefined method `id' for nil:NilClass
s_eric

2020/03/29 08:30

1つ目のエラーが直ったのならよかったです。 2つ目の方は、@current_userがnilになっているということです。どんなアプリを作っているのか存じませんが、ログインしていないユーザーでページを表示させているのではないでしょうか? deviseを使っているのなら、user_signed_in?などで分岐するか、単純にnilかどうかで分岐すれば解決できる気がします。
ichigob

2020/03/29 08:36

ありがとうございます。 Ruby on railsではじめて作っています。 アプリは、質問アプリです。 おっしゃる通り、ログインしていない状態でshowを見るとエラーです。 ログインしていないので@current_userがnilですね。ここは理解できました。 devise、user_signed_in?はどのようにしたらいいのでしょうか。 よくわかっていませんので調べてみます。
s_eric

2020/03/29 08:45

user_signed_in?では、ログインしている場合に、true、ログインしていない場合にfalseが返されます。 つまり、 if user_signed_in? (ログインしている場合の処理) end みたいに使えます。もちろん、unlessにしたり、elseをつけても使えます。
ichigob

2020/03/29 09:45

下記を試しましたがエラーでした。 contlollerにも何か必要でしょうか。 <% if user_signed_in? %> <div class="post-menus"> <%= link_to("編集", "/posts/#{@post.id}/edit") %> <%= link_to("削除", "/posts/#{@post.id}/destroy", {method: "post"}) %> </div> <!-- 以下の<% %>を使ってif文のendを追加してください --> <% end %> ーーーーーーーー エラー内容 ーーーーーーーー NoMethodError in Posts#show Showing /Users/ichigobranding/hikimy/app/views/posts/show.html.erb where line #20 raised: undefined method `user_signed_in?' for #<#<Class:0x00007fd3e6aa8f18>:0x00007fd3e27ce288> Did you mean? users_index_url
ichigob

2020/03/29 09:49

devise の設定も必要ということでしょうか?
s_eric

2020/03/29 09:54

確認してみましたが、deviseを導入していれば、追加の設定やコントローラー側での実装などはいらないはずです。参考までに私が見た記事を。 https://qiita.com/tobita0000/items/866de191635e6d74e392 もし、deviseのuser_signed_in?が機能しないのであれば、 unless @current_user.nil? (処理) end などでもいいかと思います。
ichigob

2020/03/29 11:54

<% unless @current_user.nil? %> で、ログインかどうかはできました。 ですが、ログインしたユーザー全て、どの投稿も編集できました。 やはり、ここのidをみてというパターンの方が良さそうです。 deviseを導入していれば、ということでしたので、deviseを入れてみます!
s_eric

2020/03/29 12:05

<% unless @current_user.nil? %>だけでは、ログイン状態の判定しかしていないので、そうなります。 ですので、&&で複数の条件をつないで、 if !@current_user.nil? && @post.user_id == @current_user.id のようにすれば解決できます。
ichigob

2020/03/29 13:00

deviseを導入したところ エラーになりました。 すでにuserを作っていて、deviseで同じuserという名前を作ったから? rails db:migrate ができずエラーに... 一度戻すか、このままエラーを直すか悩み中。 ActiveRecord::PendingMigrationError raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration? ーーーーーーーーーーーーーーーーー # Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending. def check_pending!(connection = Base.connection) raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration? end def load_schema_if_pending!
ichigob

2020/03/29 13:13

devise を一旦諦めてGitで戻して if !@current_user.nil? && @post.user_id == @current_user.id にしたところ解決いたしました! ありがとうございます。すごく助かりました。
s_eric

2020/03/29 13:56

それは良かったです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問