ActiveRecord: can objects be added to has_many: through a single batch operation?
Take the following simple object model, for example:
class Course
has_many :enrollments
has_many :students, :through => :enrollments, :after_add => :send_email
def send_email(student)
puts "Email Sent"
end
end
class Enrollment
belongs_to :course
belongs_to :student
end
class Student
has_many :enrollments
has_many :courses, :through => :enrollments
end
I would like to execute send_email
after adding one or more students to the course, however after_add is triggered after each item is added to the students collection.
bill = Student.first carl = Student.last Course.first.students << [bill, carl]
Will output
Email Sent
Email Sent
How can I catch the SINGLE event after all items have been added to the collection?
Can I insert records into a table enrollments
in a single query for all students, rather than one student?
Does Rails have some kind of built-in mechanism, or do I need to write my own logic to catch the batch cleanup calls before send_email
?
Thanks for any information!
source to share
Adding the after_create callback in the registration model will result in the desired behavior.
With batch assignments in has_many:, entries are created in the registration table through relations if necessary. For every new entry, Rails will apply all the validations and callbacks in the connection model. If student enrollment in the course is marked in an entry in the application pooling table. This will then work regardless of how you add a student to the course.
This is the code to change the registration class
class Enrollment < ActiveRecord::Base
belongs_to :course
belongs_to :student
after_create :send_email
protected
def send_email
course.send_email(student)
end
end
It will call the course send_email procedure while you create a registration record using Rails.
The following will send emails.
@student.courses << @course
@course.students << @student
Enrollment.create :student => @student, :course => @course
source to share
I have checked and it doesn't seem like any of the built-in callbacks will do what you need to do. You might want to experiment with custom callback classes to make sure you can achieve what you need.
http://guides.rubyonrails.org/activerecord_validations_callbacks.html#callback-classes
Good luck :)
source to share