Currently it’s impossible to figure out which validations actually failed for a given field, as AM::Errors provides only field name and translated error message. We’ve got a simple workaround for this issue:
module ActiveModel
class Errors
def error_types
@_error_types ||= Hash.new{|hash,k| hash[k] = []}
end
def add_with_save_names(attribute, message = nil, options = {})
message ||= :invalid
message = message.call if message.is_a?(Proc)
error_types[attribute] << message
add_without_save_names(attribute, message, options)
end
alias_method_chain :add, :save_names
end
end
This solution is far from perfect, but it's relatively simple and so far works for us.
The best solution would be to actually build a structure similar to GitHub response - from that structure it would be trivial to build #full_messages and similar methods and it would provide a lot of additional info which would be extremely useful for creating APIs.
Cheers,
Szymon
I’ll make all current methods to return the same result as they do now (even #to_json and similar methods) and use new structure only internally. The only question is how this new structure should be accessed via ActiveModel object - object.errors.errors?
It’s been a while, but once again I’m working on an API-only Rails app and I have the same problem again
Now that Rails 4.2 has been released and work on 5.0 has started, maybe it would be a good time to change ActiveModel::Errors API, so that it would allow to return translated error messages (like it does right now) or error codes (e.g. :invalid, :missing) that can be translated to any language by the app that’s using the API?
My friend just created a pull request that adds error codes to AM:Errors - https://github.com/rails/rails/pull/18322. It’s backward compatible, but methods like “<<”, “=” etc. don’t add errors to “codes” hash (however, they never actually did work correctly, as error messages added this way are not translated).
It might be possible to refactor AM::Errors completely and build “messages” based on “codes” instead of managing both of them.