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