I’m working on a Rails app with Devise for user authentication. I want to add an ‘Enroll Now’ button that creates a record when a user views a lesson. Here’s my current setup:
class Student
has_many :completed_modules
has_many :enrolled_programs
end
class Module
belongs_to :program
end
class Program
has_many :modules
end
class CompletedModule
belongs_to :student
belongs_to :module
attribute :finished, :boolean
end
class EnrolledProgram
belongs_to :student
belongs_to :program
attribute :finished, :boolean
end
class ProgramsController < ApplicationController
def display
@program = Program.find(params[:id])
current_student.enrolled_programs.find_or_create_by(program: @program)
end
end
How can I modify this to add the ‘Enroll Now’ feature? Also, how do I prevent creating duplicate records when a student views the same program multiple times? Any help would be great. Thanks!
Hey there, GracefulDancer8!
Your project sounds super interesting! I’m curious about a few things though.
Have you considered using a service object for your enrollment logic? It might help keep your controller nice and lean. Something like:
class EnrollmentService
def self.enroll(student, program)
return false if student.enrolled_programs.exists?(program: program)
student.enrolled_programs.create(program: program)
true
end
end
Then in your controller, you could do:
def enroll
@program = Program.find(params[:id])
if EnrollmentService.enroll(current_student, @program)
flash[:notice] = 'Yay! You\'re enrolled! 🎉'
else
flash[:alert] = 'Oops! Already enrolled in this one.'
end
redirect_to @program
end
What do you think? Would that work for your use case?
Also, I’m wondering how you’re handling the UI for this. Are you using any JavaScript to make it more dynamic? It’d be cool to see the button change instantly when a user enrolls!
Let me know if you want to bounce around any other ideas. Always fun to chat about Rails projects! 
yo gracefuldancer8, here’s a quick fix for ur enroll button:
- add a route: post ‘/programs/:id/enroll’, to: ‘programs#enroll’
- in ProgramsController:
def enroll
@program = Program.find(params[:id])
current_student.enrolled_programs.find_or_create_by(program: @program)
redirect_to @program, notice: 'enrolled!'
end
this’ll handle duplicate enrollments too. lmk if u need anything else!
I’ve faced a similar challenge with enrollment systems. Here’s what worked for me:
Modify your ProgramsController to include an ‘enroll’ action:
def enroll
@program = Program.find(params[:id])
enrollment = current_student.enrolled_programs.find_or_create_by(program: @program)
if enrollment.persisted?
flash[:notice] = 'Successfully enrolled in the program.'
else
flash[:alert] = 'You are already enrolled in this program.'
end
redirect_to program_path(@program)
end
This approach uses find_or_create_by to prevent duplicate enrollments. It’s efficient and handles the logic in one go.
For the ‘Enroll Now’ button, add this to your view:
<%= button_to 'Enroll Now', enroll_program_path(@program), method: :post %>
Don’t forget to add the corresponding route in your routes.rb:
post '/programs/:id/enroll', to: 'programs#enroll', as: 'enroll_program'
This setup should give you a clean, functional enrollment system without duplicates.