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

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

ただいまの
回答率

90.53%

  • Ruby on Rails 4

    2535questions

    Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Rails バリデーション>elseの場合、render template メソッドでのエラー undefined method `◯◯' for nil:NilClass

解決済

回答 1

投稿

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

yy-ymsht

score 2

概要

Rails で顧客管理システムをつくっています。
customer#indexに顧客一覧が表示され、詳細に進むと、
customer#showで顧客詳細ページが表示されます。

cusutomer_controller.rb


class CustomersController < ApplicationController

  before_action :authenticate_user!, only: [:new, :create, :edit, :update, :destroy]
  before_action :set_customer, only: [:show, :edit, :destroy, :update]

〜省略〜

  def show
    @comment = Comment.new
    #@comments = Comment.where(customer_id: params[:id].to_i)
    @comments = @customer.comments
  end

〜省略〜

  private

  def set_customer
    @customer = Customer.find(params[:id])
  end

  def customer_params
    params.require(:customer).permit(
      :family_name,
      :given_name,
      :email,
      :company_id,
      :post_id
      )
  end
end

今回やりたいこと:顧客詳細ページ(show)、対応履歴の管理を追加。

対応履歴の追加は、詳細ページ内にform_forメソッドを埋め込み
@commentモデルオブジェクトに追加し、comment#createに投げています。

詳細ページ内、<h2>対応履歴</h2>以下にeachメソッドで、
@commentからデータを受け取り、追加したコメントを表示しています。

ここまでは問題ありません。

customer/show.html.erb

<div class="row">
    <div class="col-lg-12">
        <h1>顧客詳細</h1>
        <dl>
            <dt>お名前</dt>
            <dd style="margin:0px 0px 10px 20px"><%= @customer.full_name %></dd>
~省略~

        <hr />

        <h2>対応履歴</h2>
        <% @comments.each do |comment| %>
            <div class="media">
                <div class="media-body">
                    <%= simple_format(comment.body) %>
                    <p class="text-muted">
                         投稿記事:<%= comment.created_at.strftime('%Y%m%d %H:%M') %>
                         <%= link_to "削除する", comment_path(comment), method: :delete %>
                    </p>
                </div>
            </div>
        <% end %>

        <%= form_for(@comment, url: { controller: :comments, action: :create}) do |f| %>
            <div class="form-group">
                <%= f.label :body, '対応内容' %>
                <%= f.text_area :body, class: "form-control" %>
            </div>
            <%= f.hidden_field :customer_id, value: @customer.id %>
            <%= f.submit class: "btn btn-default" %>
        <% end %>
    </div>
</div>
routes.rb

Rails.application.routes.draw do
〜省略〜
  resources :comments, only: [:create, :destroy]
  post '/comments' => 'comments#create'

end
comments_controller.rb

class CommentsController < ApplicationController
~省略~
    def create
        @comment = Comment.new(comment_params)
        if @comment.save
            redirect_to customer_path(@comment.customer_id)
        else
            render template: "customers/show"
        end
    end
~省略~
end

エラーと再現手順

今回、対応履歴の追加の際に、200文字上限のバリデーションを追加しました。

comment.rb

class Comment < ActiveRecord::Base
    belongs_to :customer

    validates :body,        presence: true, length: { maximum: 200 }
    validates :customer_id, presence: true

end

文字数超過の場合には、エラーメッセージを詳細ページで表示したかったため、
comments#createで、elesにrender templateメソッドを使い、
遷移先をcustomers/showとしています。

この状態で、Webサーバを立ち上げ、ブラウザから、詳細ページにて
対応履歴を200文字以上入力し、登録すると以下のエラー画面が表示され、
手詰まりとなっています。。

<エラー画面>

Showing /home/ubuntu/workspace/elites-crm02/app/views/customers/show.html.erb where line #6 raised:

undefined method `full_name' for nil:NilClass
Extracted source (around line #6):

<dt>お名前</dt>
<dd style="margin:0px 0px 10px 20px"><%= @customer.full_name %></dd>
<dt>電子メール</dt>
<dd style="margin:0px 0px 10px 20px"><%=  @customer.email %></dd>
<dt>会社名</dt>

Rails.root: /home/ubuntu/workspace/elites-crm02

Application Trace | Framework Trace | Full Trace
app/views/customers/show.html.erb:6:in `_app_views_customers_show_html_erb___3504510312829596345_37028060'
app/controllers/comments_controller.rb:16:in `create'

該当のfull_nameメソッドは、customerモデルで定義しており、
通常のcustomers#showで表示する際には問題ありません。

customer.rb

class Customer < ActiveRecord::Base
        belongs_to :company
        belongs_to :post
        has_many :comments
〜省略〜

        def full_name
          family_name + given_name
        end
end

試したこと

NilClassというものについて、ネットで調べ、comments#showで、
@customerが定義されていないことが原因かと思い、
@cutomer = Customer.all などをcomment#showに入れてみましたがうまく行きませんでした。

commentsコントローラーで@customerを定義できていないのが原因な気がしますが、
自力では解決できず、ご教示いただけますと幸いです。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

@customerが定義されていないことが原因かと思い

だと思いますし、Customer.all じゃなくて Customer.find 的なインスタンスが必要かと。
CommentsControllerがどうなってるか分かりませんが、
Customerに対してのコメントなら @customer を取得しておくべきかと。

before_action :set_customer

def set_customer
  @customer = Customer.find params[:customer_id] # ?
end

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/12/18 06:12

    tanyzz様 遅くなりすみません!
    やはりコントローラーで@customerが取得できていないんですね!
    やってみます。

    キャンセル

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

  • Ruby on Rails 4

    2535questions

    Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。