Home > front end >  Shallow Nesting in Rails - RecordNotFound Error
Shallow Nesting in Rails - RecordNotFound Error

Time:03-07

I'm trying to figure out shallow nesting in Rails but I get RecordNotFound for certain actions. A student has many checklists, a checklist belongs to a student, and I made sure routes.rb was setup correctly and form_with partials were getting both the student and checklist passed in.

I think something in my controller is messed up:

class ChecklistsController < ApplicationController
  before_action :get_student
  before_action :set_checklist, only: %i[show edit update destroy]

  def index
    @checklists = @student.checklists
  end
  def show
    @student = @checklist.student
  end
  def new
    @checklist = @student.checklists.build
  end
  def edit
    @student = @checklist.student
  end
  def create
    @checklist = @student.checklists.build(checklist_params)

    if @checklist.save
      redirect_to @checklist, notice: 'Checklist was successfully created.'
    else
      render :new, status: :unprocessable_entity
    end
  end
  def update
    @student = @checklist.student

    if @checklist.update(checklist_params)
      redirect_to @checklist, notice: 'Checklist was successfully updated.'
    else
      render :edit, status: :unprocessable_entity
    end
  end
  def destroy
    @student = @checklist.student

    @checklist.destroy
    redirect_to student_checklists_url(@student), notice: 'Checklist was successfully destroyed.'
  end

  private

  def set_checklist
    @checklist = @student.checklists.find(params[:id])
  end

  def get_student
    @student = Student.find(params[:student_id])
  end

  # Only allow a list of trusted parameters through.
  def checklist_params
    params.require(:checklist).permit(:title, :date, :setting)
  end
end

CodePudding user response:

When using shallow nesting you need to separate the callbacks for the collection actions (new, create, index) which are nested from the member actions (show, edit, update, destroy) which are not:

class ChecklistsController < ApplicationController
  before_action :set_student, only: %i[new, index, create]
  before_action :set_checklist, only: %i[show edit update destroy]

  def index
    @checklists = @student.checklists
  end

  # Defining this empty method is actually optional - Rails will implicitly render `show.html.erb` anyways
  def show
  end

  def new
    @checklist = @student.checklists.build
  end

  def create
    @checklist = @student.checklists.build(checklist_params)
    if @checklist.save
      redirect_to @checklist, notice: 'Checklist was successfully created.'
    else
      render :new, status: :unprocessable_entity
    end
  end

  def edit
  end

  def update
    if @checklist.update(checklist_params)
      redirect_to @checklist, notice: 'Checklist was successfully updated.'
    else
      render :edit, status: :unprocessable_entity
    end
  end

  def destroy
    @checklist.destroy
    redirect_to student_checklists_url(@student), notice: 'Checklist was successfully destroyed.'
  end


  private

  def set_student
    @student = Student.find(params[:student_id])
  end

  def set_checklist
    # this lookup will never be based off a student record
    # since the route is not nested 
    @checklist = Checklist.eager_load(:student)
                          .find(params[:id])
    @student = @checklist.student
  end

  # Only allow a list of trusted parameters through.
  def checklist_params
    params.require(:checklist)
          .permit(:title, :date, :setting)
  end
end
  • Related