ruby on rails - How to show nested form validation errors after the validation errors for the parent model? -


using ruby on rails 4.2, have nested form. when testing validations entire form, noticed validation errors nested form appear @ top of validation errors list, validation errors main form appearing below.

this opposite order declared (since fields_for has appear within scope of parent form_for), looks this:

[name        ] [description ] [others      ] [nested #1   ] [nested #2   ] 

but validation errors appear (using blank example validation error):

  • nestedmodelname nested #1 can't blank.
  • nestedmodelname nested #2 can't blank.
  • name can't blank.
  • description can't blank.
  • others can't blank.

this confusing user, since errors appear out of order how appear on page. don't expect in correct position according appears in form, since validating each model in turn, since nested form model subordinate, should @ least added end instead of showing in beginning. there way nested form validation errors appear after parent form validation errors?

additional info:

errors being displayed in view using following:

application_helper.rb

def error_messages(resource)      return '' if resource.errors.empty?      messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join     sentence = i18n.t('errors.messages.not_saved',                       count: resource.errors.count,                       resource: resource.class.model_name.human.downcase)     html = <<-html     <div class="validation-error alert alert-danger alert-dismissable fade in alert-block">       <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>       <p>#{sentence}</p>       <ul>         #{messages}       </ul>     </div>     html    end 

and using in each view file containing form:

<%= error_messages(@model) %> 

update 1:

i discovered answer februaryink close correct if don't need worry i18n , translation of application text. if put has_many :child_model underneath validations, validations appear in correct order. however, full_messages doesn't appear translate model or attribute names using locale files, if require error messages translated (which do), answer still seems decent solution.

update 2:

just realized after posting first update simplify code generates messages list lot removing part ordering using discovery in update 1, , keep part translation. here new solution, combination of update 1 , original solution. other information config/locales/xx.yml , config/application.rb files still same updated solution original.

app/models/parent_model.rb

...  validates :name, # validations hash validates :description, # validations hash validates :others, # validations hash  has_many :child_models accepts_nested_attributes_for :child_models  ... 

app/models/child_model.rb

...  validates :nested_1, # validations hash validates :nested_2, # validations hash  ... 

app/helpers/application_helper.rb

messages = resource.errors.messages.keys.map {|value| error_message_attribute(resource, value) + i18n.t('space') + resource.errors.messages[value].first}.map { |msg| content_tag(:li, msg) }.join  private   def error_message_attribute(resource, symbol)     if symbol.to_s.split(".").length > 1       model_name, attribute_name = symbol.to_s.split(".")       model_class = model_name.singularize.camelize.constantize       model_class.model_name.human + i18n.t('space') + model_class.human_attribute_name(attribute_name).downcase     else       resource.class.human_attribute_name(symbol)     end   end 

end of update

i made few changes error_messages function in application_helper.rb , have working way wanted: main form validation errors on top, nested form validation errors under those, order of errors not change except moving nested form errors under main form errors.

my solution change messages = line in error_messages shown below , add private helper method. (this should broken down parts make easier read , understand, built in console wanted , pasted directly there).

app/helpers/application_helper.rb

messages = hash[resource.errors.messages.keys.map.with_index(1) { |attribute, index| [attribute, [index, attribute.match(/\./) ? 1 : 0]] }].sort_by {|attribute, data| [data[1], data[0]]}.collect { |attributes| attributes[0]}.map {|value| error_message_attribute_name(resource, value) + i18n.t('space') + resource.errors.messages[value].first}.map { |msg| content_tag(:li, msg) }.join  private     def error_message_attribute_name(resource, symbol)       if symbol.to_s.split(".").length > 1         model_name, attribute_name = symbol.to_s.split(".")         model_class = model_name.singularize.camelize.constantize         model_class.model_name.human + i18n.t('space') + model_class.human_attribute_name(attribute_name).downcase       else         resource.class.human_attribute_name(symbol)       end     end 

this solution should work other other locales, since used i18n names. have add following also:

config/locales/en.yml

en:   space: " " 

this model , attribute names handled correctly in languages either have or don't have spaces between words (the first locale need support chinese, doesn't have spaces between words). if did need support chinese, example, use this:

config/locales/zh.yml

zh:   space: "" 

if don't have support case, instances of i18n.t('space') can replaced " ". model , attribute names can translated as, again if don't need support locales beyond english don't need (although can use en.yml file change names of model or attributes displayed).

as example using en.yml change names displayed using common authors/books example:

config/locales/en.yml

en:   activerecord:     models:       author: "writer"       book: "manuscript"     attributes:       author:         name: "non de plume"       book:         name: "title"         published: "year" 

in example default, without above additions en.yml, be:

  • name can't blank.
  • book name can't blank.
  • book published can't blank.

but above additions en.yml be:

  • nom de plume can't blank.
  • manuscript title can't blank.
  • manuscript year can't blank.

and of course, if have zh.yml file appropriate translations, whatever have in show instead.

if need support multiple locales, don't forget add following config/application.rb (this part tested superficially, , may need additional configuration):

config/application.rb

config.i18n.available_locales = [:zh, :en] config.i18n.default_locale = :en 

Comments

Popular posts from this blog

android - MPAndroidChart - How to add Annotations or images to the chart -

javascript - Add class to another page attribute using URL id - Jquery -

firefox - Where is 'webgl.osmesalib' parameter? -