Ruby on Rails: how to get error messages from a child resource displayed?
Add a validation block in the School
model to merge the errors:
class School < ActiveRecord::Base has_many :students validate do |school| school.students.each do |student| next if student.valid? student.errors.full_messages.each do |msg| # you can customize the error message here: errors.add_to_base("Student Error: #{msg}") end end endend
Now @school.errors
will contain the correct errors:
format.xml { render :xml => @school.errors, :status => :unprocessable_entity }
Note:
You don't need a separate method for adding a new student to school, use the following syntax:
school.students.build(:email => email)
Update for Rails 3.0+
errors.add_to_base
has been dropped from Rails 3.0 and above and should be replaced with:
errors[:base] << "Student Error: #{msg}"
Update Rails 5.0.1
You can use Active Record Autosave Association
class School < ActiveRecord::Base has_many :students, autosave: true validates_associated :studentsendclass Student < ActiveRecord::Base belongs_to :school validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :message => "You must supply a valid email"end@school = School.new@school.build_student(email: 'xyz')@school.save@school.errors.full_messages ==> ['You must supply a valid email']
reference: http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html
This is not a public API yet, but Rails 5 stable seems to have ActiveModel::Errors#copy!
to merge errors
between two models.
user = User.new(name: "foo", email: nil)other = User.new(name: nil, email:"foo@bar.com")user.errors.copy!(other.errors)user.full_messages #=> [ "name is blank", "email is blank" ]
Again, this is not officially published yet (I accidentally find this one before monkey-patching Errors
class), and I'm not sure it will be.
So it's up to you.