🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby on Rails

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

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

Q&A

解決済

1回答

2597閲覧

バリデーション機能の実装

kur

総合スコア3

Ruby on Rails

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

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

0グッド

0クリップ

投稿2020/12/04 07:56

編集2020/12/04 10:19

前提・実現したいこと

プログラミング初学者です。
現在、Ruby on Railsで本の投稿ができるアプリケーションを作成しております。
RailsのバージョンはRails 5.2.4で、ログイン機能にはdeviseを利用し、2つのモデルを用意して作成しています。
また、一部、部分テンプレートも使っています。
・ユーザに関するモデル名は、User
Userモデルのカラム名は、
name:名前
introduction:自己紹介文
profile_image_id:「refile」による画像保存用

・投稿データに関するモデル名は、Book
Bookモデルのカラム名は、
title:本のタイトル
body:感想
user_id

実現したいことは、バリデーションチェックが働き、有効でない場合はバリデーションエラーが返るようにすることです。
Userモデルのカラムのバリデーションは
name:一意性を持たせ、かつ2~20文字の範囲で設定
introduction:最大50文字までに設定

Bookモデルのカラムのバリデーションは
title:空でないように設定
body:空でない、かつ最大200文字までに設定

このバリデーション機能を現在はBookモデルのカラムのコードを書いて実装中です。
下記のようなエラーが出てしまい、解決策が分からないため、ご教授いただけると幸いです。

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

コード NoMethodError in Books#create Showing /home/ec2-user/environment/Bookers2/app/views/users/_user_show.html.erb where line #7 raised: undefined method `name' for nil:NilClass Extracted source (around line #7): 5 <tbody> 6  <tr> 7 <th>name</th><th><%= user.name %></th> 8 </tr> 9 <tr> 10 <th>introduction</th><th><%= user.introduction %></th>

該当のソースコード

ソースコード [ブックモデル] class Book < ApplicationRecord belongs_to :user validates :title, presence: true validates :body, presence: true validates :body, length: { maximum: 200 } end [ユーザーモデル] class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :books, dependent: :destroy attachment :profile_image validates :name, uniqueness: true validates :name, length: { in: 2..20 } validates :introduction, length: { maximum: 50 } end [ブックコントローラー] class BooksController < ApplicationController before_action :authenticate_user! before_action :ensure_correct_user, only:[:edit] def new @book = Book.new end def create @book = Book.new(book_params) @book.user_id = current_user.id if @book.save flash[:notice] = "You have created book successfully." redirect_to book_path(@book) else render :index end end def index @books = Book.all @user = current_user @book = Book.new end def show @book = Book.find(params[:id]) @book_new = Book.new end def edit @book = Book.find(params[:id]) end def update @book = Book.find(params[:id]) @book.user_id = current_user.id if @book.update(book_params) flash[:notice] = "You have updated book successfully." redirect_to book_path(@book) else render :edit end end def destroy @book = Book.find(params[:id]) @book.destroy redirect_to books_path end private def book_params params.require(:book).permit(:title, :body) end def ensure_correct_user @book = Book.find(params[:id]) unless @book.user == current_user redirect_to user_path end end end [ユーザーコントローラー] class UsersController < ApplicationController before_action :authenticate_user! before_action :ensure_correct_user, only:[:edit, :show] def show @user = User.find(params[:id]) @book = Book.new @books = @user.books end def new @book = Book.new end def create @book = Book.new(book_params) @book.user_id = current_user.id if @book.save redirect_to book_path(@book) else render :index end end def index @users = User.all end def edit @user = User.find(params[:id]) end def update @user = User.find(params[:id]) @user = current_user if @user.update(user_params) flash[:notice] = "You have updated user succeessfully." redirect_to user_path(@user) else render :edit end end private def user_params params.require(:user).permit(:name, :introduction, :profile_image_id) end def ensure_correct_user @user = User.find(params[:id]) unless @user == current_user redirect_to user_path(current_user.id) end end end [部分テンプレート、_book_new.html] <h2>New book</h2> <%= form_with model: book, local:true do |f| %> <div class="form-group"> <%= f.label :title, 'Title' %> <%= f.text_field :title, class: 'form-control' %> </div> <div class="form-group"> <%= f.label :body, 'Opinion' %> <%= f.text_area :body, class: 'form-control' %> </div> <div><%= f.submit 'Create Book', class: 'btn btn-success' %></div> <% end %> [部分テンプレート、_user_show.html] <h2>User info</h2> <%= attachment_image_tag user, :profile_image, size: "60x60", farmat: 'jpg', fallback: "no_image.jpg" %> <table class="table"> <tbody> <tr> <th>name</th><th><%= user.name %></th> </tr> <tr> <th>introduction</th><th><%= user.introduction %></th> </tr> </tbody> </table> <div class="row"> <%= link_to edit_user_path(user), class: "btn btn-outline-dark btn-block" do %> <span class="fas fa-user-cog"></span> <% end %> </div> [books/index.html(投稿に失敗した時は本の一覧画面に返るようにしたいので、ここに<% if @book.errors.any? %>を書きました)] <div class="container"> <div class="row"> <% if @book.errors.any? %> <%= @book.errors.count %>error prohibited this book from being saved:<br> <% @book.errors.full_messages.each do |message| %> <%= message %> <% end %> <% end %> <div class="col-md-3"> <%= render 'users/user_show', user: @user %> <%= render 'books/book_new', book: @book %> </div> <div class="col-md-8 offset-md-1 pt-3"> <%= render 'books/book_index', books: @books %> </div> </div>

試したこと

コントローラなど見返したのですが、どのように直せば良いか分からなかったです。
1:Nの関係なども復習下のですがはっきりできませんでした。

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

ここにより詳細な情報を記載してください。
ご指摘ありがとうございます。
コピペして訂正しました、
初めての質問で見辛い点もあるかと思いますが、よろしくお願いいたします。

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

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

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

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

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

no1knows

2020/12/04 09:41

コードは画像ではなく、<code>タグを利用してコピペしてください。
kur

2020/12/04 10:24

ご指摘ありがとうございました。 初めてこちらのサイトを利用したので拙い点も多いかと思いますが、ご教授いただけると幸いです。
no1knows

2020/12/04 11:51

あとコードは、それぞれのモデルや、コントローラー、ビューなどでわけていただけると、回答しようかなーと考えている人は見やすくて嬉しいです。
kur

2020/12/04 12:34

<code>の中にソースコード以外を書くとややこしいですね、、 基本的な質問の仕方も分かっていなかったのでご指摘いただきありがとうございます。
no1knows

2020/12/04 12:37

説明が悪かったようでごめんなさい。 例えばhttps://teratail.com/questions/308183のような形で、それぞれを独立して記載いただくと見たいものがすぐ見れて嬉しいのです・・・
no1knows

2020/12/04 12:41

あと_user_show.htmlってどうやってよびだされているのでしょうか?
kur

2020/12/04 12:57

すみません、正しくは_user_show.html.erbです。 Railsの規則によって呼び出されていると認識しています。
guest

回答1

0

ベストアンサー

BooksController#create で@book.saveに失敗した場合にrender :indexが呼ばれます。

books/index.html で<%= render 'users/user_show', user: @user %>としていますが、
この@usernilです。なぜなら、BooksController#create のどこにも@userがありません。

パーシャル(_user_show.html)に渡されたuserも当然nilです。
_user_show.html でuser.nameとしているので、

undefined method `name' for nil:NilClass Extracted source (around line #7):

このエラーを回避するには、render :indexの前に@user(と@books)を用意します。

@user = current_user @books = @user.books render :index

@book.saveに失敗するのは(多分)validationですが、このエラーはvalidationとは関係ありません。

投稿2020/12/04 10:47

neko_daisuki

総合スコア2090

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

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

kur

2020/12/04 12:46

ありがとうございます! ご教授いただいた通りにするとうまくいきました。 elseにおいても定義が必要だったのですね、、 引っかかっていたので本当に助かりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問