Any opinions on the best place (model, controller, decorator, presenter, etc.) to put validation messages that are specific to a given context? I.e., suppose you want to display a very detailed validation message with html tags, but even if the only current clients of the model validation can accept html_safe
strings, it somewhat doesn’t feel right to putting the html code in the model validator messages.
In a real project, I did the following:
- Started off with normal model validation.
- Moved the creation of the validation messages to a Draper decorator, as I needed various view (e.g., pluralize) and url helpers.
- Checked for the error situation before calling save or validate, and used the decorator’s message for the flash.
One issue I see with standard Rails validation is that there doesn’t seem to be some sort of error code along with the message. Sure, you know the attribute, but what if there’s different errors for that attribute. With an error code, the consumer of the Errors hash could use the error code. Without the error code, one could parse the resulting string, but thats seems incorrect (what if you later internationalize?).
Additionally, the documentation declares that the keys of the Errors hash should be symbols corresponding to the model’s attributes, or else :base
. So using additional keys also seems incorrect.
Suggestions? Anything better than working outside of normal validation?
Justin
From the docs:
Active Model Errors
Provides a modified Hash that you can include in your object for handling error messages and interacting with Action View helpers.
Changing the error message for rails validations or even providing messages for your own is a job for i18n. See: Rails Internationalization (I18n) API — Ruby on Rails Guides. This is the key → value store you are looking for.
1 Like
Thanks. Is it possible to get the key used for the translation rather than the actual translation, supposing that I want the view to alter the message based on the key?
Not that I know of. You could have i18n itself return you a key you could do something with, I suppose. Or set the message to a key directly?
If that’s the case, then it seems like the controller calling the same method doing the model validation before calling save is useful to know that a certain validation would fail and that you’d want a custom error message. It just seems wrong to have logic based on a human readable validation message which could inadvertently change. Maybe, being able to access the i18n key would be a super feature for Rails core for this use case.
I think I’d probably seriously reevaluate whether I needed anything more than the standard i18n approach of model validations. I18n supports pluralization but it will not have access to URL helpers.
The interesting thing is Rails models are responsible for validation messages, yet string messages are view context specific. When validation error messages occur, sometimes I want to give the user a URL to fix the issue.
In the past, I’ve had the model validation code call Draper Decorator methods to create the proper validation message. This works fine so long as there’s one consumer of the validation, the Rails web app. This is not ideal in the general case.