I've got the following two (sanitized/stylized) models:
class DrivingExam < ActiveRecord::Base
belongs_to :dmv_rules
has_many :invigilator_assignments, as: :assignable
has_many :invigilator, through: :invigilator_assignments
validate do |record|
record.invigilator_assignments.each do |i|
next if i.valid?
i.errors.full_messages.each do |msg|
errors.add_to_base(msg)
end
end
end
end
class InvigilatorAssignment < ActiveRecord::Base
attr_accessible :invigilator_id
belongs_to :assignable, polymorphic: true
belongs_to :invigilator
validates :invigilator_id, presence: true
validates_each :invigilator do |record, attr, value|
if record.assignable.is_a?(DrivingExam) && !value.no_scheduling_conflicts?
record.errors.add attr, "This Invigilator has a scheduling conflict"
end
end
end
These get called from the DrivingExamController by way of:
if @driving_exam.save
The expected behaviour is that the model should return false on the validation and join the child messages into the parent errors hash and pass this up to the controller.
What happens instead is that the page fails to save (this is good) with a 422(this is weird) and does not pass the messages.
By adding puts statements throughout the above code, I have established that:
1) The if condition within validates_each is successful, and the record.errors array is thus set inside the InvigilatorAssignment model.
2) In the validate do loop the invigilator assignment is valid and has no errors
3) the validate do loop runs before the validates_each loop
So the question is: How do I ensure that the DrivingExam validates InvigilatorAssignment and merges its error messages onto its own error hash.
errors.add_to_basehas been dropped from Rails 3.0 and above and should be replaced with:errors[:base] << "Student Error: #{msg}"