Add ActionController::Parameters#dig to grab values out of nested params, failing gracefully

Hi folks,

For better or worse, this is a pattern you see pretty often in real-world Rails code [0]:

params[:order] && params[:order][:shipping_info] && params[:order][:shipping_info][:country]

or

params[:order][:shipping_info][:country] rescue nil

or

params.fetch(:order, {}).fetch(:shipping_info, {}).fetch(:country, nil)

What if we had a method to accomplish this more concisely?

Eg.

params.traverse_nested_params_and_return_nil_if_a_key_isnt_found(:order, :shipping_info, :country)

Or to take a nice method name suggestion [1]:

params.dig(:order, :shipping_info, :country)

Another example solution is https://github.com/intridea/hashie#deepfetch (Although I don’t like “fetch” in this method name since it doesn’t and can’t take a default value as an argument like Hash#fetch does)

Would a method like this possibly belong in ActionController::Parameters? Or maybe even in Active Support extensions on Hash (gasp!)? Or is it just an all-around terrible idea?

Thanks,

Gabe

[0] Sources:

https://groups.google.com/d/msg/rubyonrails-core/bOkvcvS3t_A/QXLEXwt9ivAJ

https://stackoverflow.com/questions/1820451/ruby-style-how-to-check-whether-a-nested-hash-element-exists

https://stackoverflow.com/questions/19115838/how-do-i-use-the-fetch-method-for-nested-hash

https://stackoverflow.com/questions/10130726/ruby-access-multidimensional-hash-and-avoid-access-nil-object

[1] http://stackoverflow.com/a/1820492/283398

Adding stuff to AS core extensions has to be done carefully, the criteria
is that it has to be clearly useful either for Rails internals (the main
design driver of AS core extensions), or solve a common need in web
development.

While the quoted questions wonder about nested hashes in Ruby, that doesn't
seem like a strong point for the criteria above.

Also, if the intermediate key has an integer value, should it raise? Would
it create expectations in users about the rest of the API? What about
nested deletion? Nested has_key? Should AC::Parameters respond to all that
as well?

Hesitant to add it to AS.

Hi Gabe,

I’d recommend the small and very versatile andand gem for the use case that you mention. In that case, the use case becomes:

params[:order].andand[:shipping_info].andand[:country]

loosing very little expressiveness, not having to revert to rescuing exceptions, etc.

Best,