Proposal for a new ActiveModel::Errors structure

243 views
Skip to first unread message

Szymon Nowak

unread,
Sep 25, 2012, 9:39:58 AM9/25/12
to rubyonra...@googlegroups.com
There are few issues with the current ActiveModel::Errors class.

Firstly, when an error is added to ActiveModel::Errors class via #add method (https://github.com/rails/rails/blob/master/activemodel/lib/active_model/errors.rb#L294) its translation is added. It should not be translated when being added, but only when being read.

The second issue is a bit bigger. We'd like to create error responses in our API similar to GitHub: 

{
   "message": "Validation Failed",
   "errors": [
     {
       "resource": "Issue",
       "field": "title",
       "code": "missing_field"
     }
   ]
 }

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

Piotr Sarnacki

unread,
Sep 25, 2012, 9:52:35 AM9/25/12
to rubyonra...@googlegroups.com
I would really love to see such changes in AM::Errors. +1 from me.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-core/-/FSdTDr6g6CwJ.
To post to this group, send email to rubyonra...@googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-co...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.



--
Piotr Sarnacki
http://piotrsarnacki.com

Aaron Patterson

unread,
Sep 25, 2012, 1:26:30 PM9/25/12
to rubyonra...@googlegroups.com
Seems good. Can you work on a patch and send a PR? If we can maintain
backwards compat, I am happy.

--
Aaron Patterson
http://tenderlovemaking.com/

Szymon Nowak

unread,
Sep 26, 2012, 8:00:26 AM9/26/12
to rubyonra...@googlegroups.com, tende...@ruby-lang.org
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? :)

BTW. Aaron, if you have a while could you check PR about ActionDispatch::ParamsParser (https://github.com/rails/rails/pull/7444)?

Szymon Nowak

unread,
Jan 1, 2015, 5:26:17 PM1/1/15
to rubyonra...@googlegroups.com, tende...@ruby-lang.org
Hey, 

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?

Jason Fleetwood-Boldt

unread,
Jan 2, 2015, 4:54:35 PM1/2/15
to rubyonra...@googlegroups.com, tende...@ruby-lang.org

+1 for separation of concerns



--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-co...@googlegroups.com.

To post to this group, send email to rubyonra...@googlegroups.com.

----

Jason Fleetwood-Boldt

All material © Jason Fleetwood-Boldt 2014. Public conversations may be turned into blog posts (original poster information will be made anonymous). Email ja...@datatravels.com with questions/concerns about this.

pathé Sene

unread,
Jan 3, 2015, 8:24:11 PM1/3/15
to rubyonra...@googlegroups.com, tende...@ruby-lang.org
+1

Almas Sapargali

unread,
Jan 3, 2015, 11:48:26 PM1/3/15
to rubyonra...@googlegroups.com, tende...@ruby-lang.org
What do you think about using numbers for error codes? For example on ios side errors may have message (description) and code (among other things).

Szymon Nowak

unread,
Jan 4, 2015, 4:31:42 AM1/4/15
to rubyonra...@googlegroups.com, tende...@ruby-lang.org
I don't think numbers are a good idea in this case, as symbols map nicely to existing error codes in Rails (http://guides.rubyonrails.org/i18n.html#error-message-interpolation).

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.

Tsyren Ochirov

unread,
Jan 8, 2015, 10:59:37 AM1/8/15
to rubyonra...@googlegroups.com
Seems nice, +1 vote for that.

Thanks
Tsyren

Wojciech Wnętrzak

unread,
Jan 22, 2015, 6:21:17 AM1/22/15
to rubyonra...@googlegroups.com
Finally, it was merged.
Reply all
Reply to author
Forward
0 new messages