Enhancement: improved ActiveModal::Errors enumeration

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Enhancement: improved ActiveModal::Errors enumeration

Evan Prothro

I love the concept and usability of an ActiveModel::Errors paradigm. However, I and others often find it frustrating to work with the implementation.


I'd love to see a proper ActiveModel::Error object, where the errors attribute of a model including ActiveModel::Errors was an Enumerator of these objects.


There are various implied benefits and added flexibility that could be introduced in a backwards compatible way later, and immedate benefits. Would love to know what y'all think about this. Happy to implement if desired.


Immediate Benefits


The error type could be retained

APIs we build prefer to return Error objects to clients with the following schema:

{
  attribute:  "The model attribute to which the error applies. If blank, the error applies generically to the base model.",
  type:       "The type of error encountered with the model attribute or model."
  messsage:   "An internationalized message that can be displayed to a user.",
}

In particular, the type attribute allows clients to couple any logic they need on the error attribute and type, not themessage, which should be able to change with business/product needs.

With a proper ActiveModel::Error object, this is easily done. With the current enumerable design, this is not a clean extension to make.


The error message can be lazily looked up

Currently, the message interpolation is looked up when the error is added to the model. This isn't necessarry, and is easily lazily evaluated when a derived attribute on an Error object.


Other Enhancements easily enabled


Accessing the attribute value more cleanly

error = model.errors.first
error.attribute
=> :username
error.attribute_value
=> 'eprothro'


Easier custom interpolation parameters

# en.yml
errors:
      models:
        user:
          attributes:
            username:
              taken: "%{value} has already been taken."

--
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 [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Enhancement: improved ActiveModal::Errors enumeration

Rafael Mendonça França
I'm positive for this enhancement. The type information is already retained in Rails 5 but having real object could be real handy.

On Mon, Feb 29, 2016 at 12:47 PM Evan Prothro <[hidden email]> wrote:

I love the concept and usability of an ActiveModel::Errors paradigm. However, I and others often find it frustrating to work with the implementation.


I'd love to see a proper ActiveModel::Error object, where the errors attribute of a model including ActiveModel::Errors was an Enumerator of these objects.


There are various implied benefits and added flexibility that could be introduced in a backwards compatible way later, and immedate benefits. Would love to know what y'all think about this. Happy to implement if desired.


Immediate Benefits


The error type could be retained

APIs we build prefer to return Error objects to clients with the following schema:

{
  attribute:  "The model attribute to which the error applies. If blank, the error applies generically to the base model.",
  type:       "The type of error encountered with the model attribute or model."
  messsage:   "An internationalized message that can be displayed to a user.",
}

In particular, the type attribute allows clients to couple any logic they need on the error attribute and type, not themessage, which should be able to change with business/product needs.

With a proper ActiveModel::Error object, this is easily done. With the current enumerable design, this is not a clean extension to make.


The error message can be lazily looked up

Currently, the message interpolation is looked up when the error is added to the model. This isn't necessarry, and is easily lazily evaluated when a derived attribute on an Error object.


Other Enhancements easily enabled


Accessing the attribute value more cleanly

error = model.errors.first
error.attribute
=> :username
error.attribute_value
=> 'eprothro'


Easier custom interpolation parameters

# en.yml
errors:
      models:
        user:
          attributes:
            username:
              taken: "%{value} has already been taken."

--
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 [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.

--
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 [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Enhancement: improved ActiveModal::Errors enumeration

mark-3
I happen to implemented a gem for this, and only now realized someone having the same issue as me.

Repo: https://github.com/lulalala/adequate_errors
Blog post: http://lulalala.logdown.com/posts/2909828-adequate-errors

Would it be possible to take some of these to Rails 6 (with the intention to break compatibility?)

Rafael Mendonça França於 2016年2月29日星期一 UTC+8下午11時58分01秒寫道:
I'm positive for this enhancement. The type information is already retained in Rails 5 but having real object could be real handy.

On Mon, Feb 29, 2016 at 12:47 PM Evan Prothro <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="ufVXEBLWBgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">evan.p...@...> wrote:

I love the concept and usability of an ActiveModel::Errors paradigm. However, I and others often find it frustrating to work with the implementation.


I'd love to see a proper ActiveModel::Error object, where the errors attribute of a model including ActiveModel::Errors was an Enumerator of these objects.


There are various implied benefits and added flexibility that could be introduced in a backwards compatible way later, and immedate benefits. Would love to know what y'all think about this. Happy to implement if desired.


<a href="https://gist.github.com/eprothro/5ea12fd2b0527baf0090#immediate-benefits" style="color:rgb(64,120,192);display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2F5ea12fd2b0527baf0090%23immediate-benefits\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEcaKrMNc_kp8ZfAjClppjFCpl05w&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2F5ea12fd2b0527baf0090%23immediate-benefits\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEcaKrMNc_kp8ZfAjClppjFCpl05w&#39;;return true;">Immediate Benefits


<a href="https://gist.github.com/eprothro/5ea12fd2b0527baf0090#the-error-type-could-be-retained" style="color:rgb(64,120,192);display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2F5ea12fd2b0527baf0090%23the-error-type-could-be-retained\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFtrBDs97riecOvUe8HxQwhtqD3xg&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2F5ea12fd2b0527baf0090%23the-error-type-could-be-retained\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFtrBDs97riecOvUe8HxQwhtqD3xg&#39;;return true;">The error type could be retained

APIs we build prefer to return Error objects to clients with the following schema:

{
  attribute:  "The model attribute to which the error applies. If blank, the error applies generically to the base model.",
  type:       "The type of error encountered with the model attribute or model."
  messsage:   "An internationalized message that can be displayed to a user.",
}

In particular, the type attribute allows clients to couple any logic they need on the error attribute and type, not themessage, which should be able to change with business/product needs.

With a proper ActiveModel::Error object, this is easily done. With the current enumerable design, this is <a href="https://gist.github.com/eprothro/d58d143729987c6c8834" style="color:rgb(64,120,192);background-color:transparent" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2Fd58d143729987c6c8834\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGmHE-sEaRsikhMmgJ1AZD7wbXihw&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2Fd58d143729987c6c8834\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGmHE-sEaRsikhMmgJ1AZD7wbXihw&#39;;return true;">not a clean extension to make.


<a href="https://gist.github.com/eprothro/5ea12fd2b0527baf0090#the-error-message-can-be-lazily-looked-up" style="color:rgb(64,120,192);display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2F5ea12fd2b0527baf0090%23the-error-message-can-be-lazily-looked-up\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEIIvkxYChGggwvHRzdaOyTUQATUQ&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2F5ea12fd2b0527baf0090%23the-error-message-can-be-lazily-looked-up\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEIIvkxYChGggwvHRzdaOyTUQATUQ&#39;;return true;">The error message can be lazily looked up

Currently, the message interpolation is looked up when the error is added to the model. This isn't necessarry, and is easily lazily evaluated when a derived attribute on an Error object.


<a href="https://gist.github.com/eprothro/5ea12fd2b0527baf0090#other-enhancements-easily-enabled" style="color:rgb(64,120,192);display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2F5ea12fd2b0527baf0090%23other-enhancements-easily-enabled\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFZ25lEDHjLHGfNBeIOTBmAXTX3yA&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2F5ea12fd2b0527baf0090%23other-enhancements-easily-enabled\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFZ25lEDHjLHGfNBeIOTBmAXTX3yA&#39;;return true;">Other Enhancements easily enabled


<a href="https://gist.github.com/eprothro/5ea12fd2b0527baf0090#accessing-the-attribute-value-more-cleanly" style="color:rgb(64,120,192);display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2F5ea12fd2b0527baf0090%23accessing-the-attribute-value-more-cleanly\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEKypWwb1W0D4K-y4HqD4fNrCpNog&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2F5ea12fd2b0527baf0090%23accessing-the-attribute-value-more-cleanly\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEKypWwb1W0D4K-y4HqD4fNrCpNog&#39;;return true;">Accessing the attribute value more cleanly

error = model.errors.first
error.attribute
=> :username
error.attribute_value
=> 'eprothro'


<a href="https://gist.github.com/eprothro/5ea12fd2b0527baf0090#easier-custom-interpolation-parameters" style="color:rgb(64,120,192);display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2F5ea12fd2b0527baf0090%23easier-custom-interpolation-parameters\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFMIeni3R6CCh0W_dj4l_EEfDXILQ&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgist.github.com%2Feprothro%2F5ea12fd2b0527baf0090%23easier-custom-interpolation-parameters\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFMIeni3R6CCh0W_dj4l_EEfDXILQ&#39;;return true;">Easier custom interpolation parameters

# en.yml
errors:
      models:
        user:
          attributes:
            username:
              taken: "%{value} has already been taken."

--
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 <a href="javascript:" target="_blank" gdf-obfuscated-mailto="ufVXEBLWBgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">rubyonrails-co...@googlegroups.com.
To post to this group, send email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="ufVXEBLWBgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">rubyonra...@googlegroups.com.
Visit this group at <a href="https://groups.google.com/group/rubyonrails-core" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/group/rubyonrails-core&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/rubyonrails-core&#39;;return true;">https://groups.google.com/group/rubyonrails-core.
For more options, visit <a href="https://groups.google.com/d/optout" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
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 [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.