15

I have a contact info class defined like this:

class ContactInfo
  include Mongoid::Document

  validates_presence_of :name, :message => ' cannot be blank'

  field :name, :type => String
  field :address, :type => String
  field :city, :type => String
  field :state, :type => String
  field :zip, :type => String
  field :country, :type => String
  embedded_in :user
end

This contact info class is embedd as a nested attribute inside my user class:

class PortalUser
  include Mongoid::Document
  accepts_nested_attributes_for :contact_info
end

When I attempt to save a user without a name, I get an error message like this:

Contact info is invalid

However, this is not very useful to the end user, because he or she doesn't know what contact info is invalid. The REAL message should be 'Name cannot be blank'. However, this error is not being propagated upwards. Is there a way to get the 'Name cannot be blank' message inside the user.errors instead of the 'Contact info is invalid' error message?

Thanks

Richard
  • 1,146
  • 1
  • 13
  • 24
  • Mongo has this built in, with validates_associated. See http://stackoverflow.com/questions/5078661/field-for-and-nested-form-with-mongoid – Peter Ehrlich Sep 25 '12 at 21:59
  • 1
    validates_associated only validates the associated models but it still spits out the useless error message. – UrLicht Sep 16 '13 at 21:43

4 Answers4

14

Here's the solution I eventually came up with:

Added these lines to the user class

after_validation :handle_post_validation
def handle_post_validation
  if not self.errors[:contact_info].nil?
    self.contact_info.errors.each{ |attr,msg| self.errors.add(attr, msg)}
    self.errors.delete(:contact_info)
  end
end
Richard
  • 1,146
  • 1
  • 13
  • 24
  • Mongo has this built in, with `validates_associated`. See http://stackoverflow.com/questions/5078661/field-for-and-nested-form-with-mongoid – Peter Ehrlich Sep 25 '12 at 21:59
  • Note that this code will add the nested attributes to the end of the array of errors. – Nobu Feb 11 '14 at 22:35
1

Instead of returning the user.errors.full_messages create a specific error message method for your user model where you handle all your embedded document errors.

class PortalUser
  include Mongoid::Document
  accepts_nested_attributes_for :contact_info
  def associated_errors
    contact_info.errors.full_messages unless contact_infos.errors.empty?
  end
end

and in your controller

flash[:error] = user.associated_errors
Alexis Perrier
  • 683
  • 9
  • 13
0

My solution that covers each embedded document validation error is the following:

  after_validation :handle_post_validation
  def handle_post_validation
    sub_errors = ActiveModel::Errors.new(self)
    errors.each do |e|
      public_send(e).errors.each { |attr,msg| sub_errors.add(attr, msg)}
    end
    errors.merge!(sub_errors)
  end
Roman Savrulin
  • 183
  • 1
  • 6
-2

There might be a solution in the controller...

in the create action you can add something like

params[:portal_user][:contact_info_attributes] = {} if params[:portal_user] && params[:portal_user][:contact_info_attributes].nil?

This will force contact_info creation, and will trigger an error on the right field

If you don't add this, contact_info is not created

juco
  • 6,331
  • 3
  • 25
  • 42
koko
  • 1