Support nested attribute names for validation error messages
Hello,
I'm trying to override a nested attribute's name that gets show in the validation message, but it doesn't seem possible for nested params
I want to override registration[total_capacity] attribute name:
my params:
params :sessions_params do
optional :registration_allowed, type: Boolean, desc: 'registration allowed for session?'
optional :registration, type: Hash, desc: 'session registration settings' do
requires :total_capacity, type: Integer, desc: 'session registration total capacity', message: :name_required
requires :waiting_list_enabled, type: Boolean, desc: 'is session registration waiting list enabled?'
end
end
en.yml
en:
grape:
errors:
format: ! '%{attributes} %{message}'
messages:
name_required: 'must be present'
attributes:
registration:
total_capacity: 'Total capacity'
expected error message if total capacity is not sent:
"Total capacity must be present"
actual error message:
"registration[total_capacity] must be present"
is this not possible or is there a problem with my code?
using grape 0.16.2, ruby 2.3.3, rails 4.2
thanks
If you put a project up that reproduces this I can try to help.
Hi @dblock
here's a project with steps to reproduce in the README:
https://github.com/amrrbakry/grape-nested-params-validation
:+1:
@amrrbakry I tried it. Looked like a bug at first, but is more like a non-feature. Looking at https://github.com/ruby-grape/grape/blob/master/lib/grape/exceptions/base.rb#L73 is getting called with registration[total_capacity], so the following en.yml yields what you expect:
attributes:
registration[total_capacity]: '...'
This is pretty annoying and we should be supporting the syntax that you were trying to use above with nested attributes, and hopefully preserving backwards compatibility.
Would you care to write some specs and maybe implement this?
Thank you, @dblock. I'd be happy to help with this. I'll take a look and see what I can do :+1:
Hey @dblock, I need some help/opinion for the ideal way to tackle this. it seems that ParamsScope class constructs the full name of the param as a string (e.g. "registration[total_capacity]") here: https://github.com/ruby-grape/grape/blob/512d4e3494dbd9804a87247f07e2cdd9c3629aef/lib/grape/validations/params_scope.rb#L76 before passing it to the Validation class for translation.
do you suggest a change to the full_name method or is it better to try to extract the names of the nested attributes from the string before the translation?
Without digging how it's used I think full_name could return a structure (array?) and that's what we would be passing around until we need a string representation of it.