From: djo.went@hotmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:91308] [Ruby trunk Feature#15563] #dig that throws an exception if an key doesn't exist
Date: Mon, 28 Jan 2019 17:06:05 +0000 (UTC) [thread overview]
Message-ID: <redmine.journal-76554.20190128170603.003f52057fce27f2@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-15563.20190125170732@ruby-lang.org
Issue #15563 has been updated by 3limin4t0r (Johan Wentholt).
My scenario would be the similar as described by k0kubun.
```Ruby
# The connection translates the request to JSON and parses the response
# from JSON into the correct objects. In this case a nested hash structure.
response = connection.send(request)
# assign shortcuts
report = response
.fetch('Era.Common.NetworkMessage.ConsoleApi.Reports.RpcGenerateReportResponse')
.fetch('report')
column_data = report.fetch('data').fetch('columns')
column_labels = report.fetch('rendering').fetch('table').fetch('columns')
# build report
report_data = column_data.each_with_object({}) do |column, data|
column_id = column.fetch('header').fetch('column_id')
data[column_id] = column.fetch('values')
end
report = column_labels.each_with_object({}) do |column, data|
label = column.fetch('label').fetch('literal')
column_id = column.fetch('column_id')
data[label] = report_data.fetch(column_id)
end
```
From the above scenario you can see that having this new functionality would help out a lot.
The reason I use `#fetch` here is because the API to which I'm talking might change it's structure. Getting an error as soon as possible reduces debug time, since the code won't move on with a `nil` value (that probably raises an exception somewhere later).
----------------------------------------
Feature #15563: #dig that throws an exception if an key doesn't exist
https://bugs.ruby-lang.org/issues/15563#change-76554
* Author: 3limin4t0r (Johan Wentholt)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
----------------------------------------
Ruby 2.3.0 introduced `#dig` for *Array*, *Hash* and *Struct*. Both *Array* and *Hash* have `#fetch` which does the same as `#[]`, but instead of returning the default value an exception is raised (unless a second argument or block is given). *Hash* also has `#fetch_values` which does the same as `#values_at`, raising an exception if an key is missing. For `#dig` there is no such option.
My proposal is to add a method which does the same as `#dig`, but instead of using the `#[]` accessor it uses `#fetch`.
This method would look something like this:
```Ruby
module DigWithException
def dig_e(key, *others)
value = fetch(key)
return value if value.nil? || others.empty?
if value.respond_to?(__method__, true)
value.send(__method__, *others)
else
raise TypeError, "#{value.class} does not have ##{__method__} method"
end
end
end
Array.include(DigWithException)
Hash.include(DigWithException)
```
The exception raised is also taken from `#dig` (`[1].dig(0, 1) #=> TypeError: Integer does not have #dig method`). I personally have my issues with the name `#dig_e`, but I haven't found a better name yet.
There are also a few other things that I haven't thought out yet.
1. Should this method be able to accept a block which, will be passed to the `#fetch` call and recursive `#dig_e` calls?
```Ruby
module DigWithException
def dig_e(key, *others, &block)
value = fetch(key, &block)
return value if value.nil? || others.empty?
if value.respond_to?(__method__, true)
value.send(__method__, *others, &block)
else
raise TypeError, "#{value.class} does not have ##{__method__} method"
end
end
end
Array.include(DigWithException)
Hash.include(DigWithException)
```
2. I currently kept the code compatible with the `#dig` description.
> Extracts the nested value specified by the sequence of *key* objects by calling `dig` at each step, returning `nil` if any intermediate step is `nil`.
However, with this new version of the method one could consider dropping the *"returning `nil` if any intermediate step is `nil`"* part, since this would be the more strict version.
```Ruby
module DigWithException
def dig_e(key, *others)
value = fetch(key)
return value if others.empty?
if value.respond_to?(__method__, true)
value.send(__method__, *others)
else
raise TypeError, "#{value.class} does not have ##{__method__} method"
end
end
end
Array.include(DigWithException)
Hash.include(DigWithException)
```
I'm curious to hear what you guys think about the idea as a whole, the method name and the two points described above.
--
https://bugs.ruby-lang.org/
next prev parent reply other threads:[~2019-01-28 17:06 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <redmine.issue-15563.20190125170732@ruby-lang.org>
2019-01-25 17:07 ` [ruby-core:91265] [Ruby trunk Feature#15563] #dig that throws an exception if an key doesn't exist djo.went
2019-01-25 17:48 ` [ruby-core:91266] " djo.went
2019-01-25 19:35 ` [ruby-core:91267] " shevegen
2019-01-26 13:14 ` [ruby-core:91284] " Ruby-Lang
2019-01-26 13:54 ` [ruby-core:91285] " matz
2019-01-26 14:35 ` [ruby-core:91286] " takashikkbn
2019-01-28 17:06 ` djo.went [this message]
2019-03-12 21:56 ` [ruby-core:91795] " walerian.sobczak
2019-06-13 8:08 ` [ruby-core:93096] " knu
2019-11-18 13:08 ` [ruby-core:95876] [Ruby master " djo.went
2019-11-18 13:16 ` [ruby-core:95877] " djo.went
2019-12-01 8:43 ` [ruby-core:96044] " ariel.caplan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.ruby-lang.org/en/community/mailing-lists/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=redmine.journal-76554.20190128170603.003f52057fce27f2@ruby-lang.org \
--to=ruby-core@ruby-lang.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).