Daniel Thomas
Daniel Thomas

Reputation: 43

Ruby on Rails Undefined method 'course_name' for nil:NilClass

I am creating a simple student planner app. If I try to view the course (course#show) assignments before adding an assignment to the course I get an error thrown instead of an empty list with just the course_name printed at the top.

The error reads: "undefined method `course_name' for nil:NilClass"

My course#show page is where the error is being thrown on line 2:

<div class='container text-center'>
 <h2> <%= @course.course_name %> </h2>
 <% @course.assignments.all.each do |assignment| %>
  <%= assignment.title %>, <%= assignment.course.course_name %>, <%= assignment.due_date %> 
  <br>
 <% end %>
</div>

My courses_controller:

class CoursesController < ApplicationController
 def new
  @course = Course.new
 end
 def create
  @course = Course.create(course_params)
  if @course.save
   redirect_to student_courses_path(@student)
  else
   render :new
  end
 end
def index
  student = Student.find_by(id: params[:student_id])
  @courses = Course.all
end
def show
  student = Student.find_by(id: params[:student_id])
  @course = student.courses.find_by(id: params[:id])
end
def edit
end
def update
end
private
  def course_params
    params.require(:course).permit(:course_name)
  end
end

Course model:

class Course < ActiveRecord::Base
 has_many :assignments
 has_many :students, through: :assignments
 validates :course_name, presence: true
end

Any thoughts on what's going on? Any advice is much appreciated!

Upvotes: 0

Views: 75

Answers (2)

Akash Kinwad
Akash Kinwad

Reputation: 815

Also modify your html code as below and show assignments only if they are present.

Also no need to write .all on associated objects.

<% if @course %>
  <div class='container text-center'>
    <h2><%= @course.course_name %></h2>
    <% if @course.assignment.any? %>
      <% @course.assignments.each do |assignment| %>
        <%= assignment.title %>, <%= assignment.course.course_name %>, <%= assignment.due_date %> 
        <br>
      <% end %>
    <% end %>
  </div>
<% else %>
  <div class='container text-center'>
    <p>This student has no course yet.</p>
  </div>
<% end %>

Upvotes: 1

ZedTuX
ZedTuX

Reputation: 3027

@course come from your show controller action, where you're trying to find it by its ID, but you're not checking if you found it or not.

In the case a Course is mandatory for a Student, add a presence validation on :course_id on the Student model, and when you create the student, you'll get an error when no course is assigned.

In the case Course is not mandatory for a Student, you could add a <% if @course %> block in your view file, and in the <% else %> part showing a message. For example:

<% if @course %>
  <div class='container text-center'>
    <h2><%= @course.course_name %></h2>
    <% @course.assignments.all.each do |assignment| %>
      <%= assignment.title %>, <%= assignment.course.course_name %>, <%= assignment.due_date %> 
      <br>
    <% end %>
  </div>
<% else %>
  <div class='container text-center'>
    <p>This student has no course yet.</p>
  </div>
<% end %>

Upvotes: 1

Related Questions