Feature #20769
closedAdd `Hash#transform_value`
Description
Add Hash#transform_value
as a specialized, key-specific version of Hash#transform_values.
hash = { image: "https://example.com/image.jpg" }
mutated_hash = hash.transform_value(:image) { |url| download(url) }
hash # => { image: "https://example.com/image.jpg" }
mutated_hash # => { image: File<...> }
hash.transform_value!(:image) { |url| download(url) }
hash # => { image: File<...> }
Similar value transformation can be achieved through variable assignment and direct mutation:
hash = { image: "https://example.com/image.jpg" }
hash.merge(image: download(hash[:image]))
hash[:image] = download(hash[:image])
While simple and currently supported, it requires a local variable (and therefore poses some challenges when chaining other methods) and repeats the Hash key in both the reading and writing portions of the code.
Updated by nobu (Nobuyoshi Nakada) about 2 months ago
hash.merge(image: nil) {|_, url| download(url)}
hash.merge!(image: nil) {|_, url| download(url)}
Updated by seanpdoyle (Sean Doyle) about 2 months ago
Thank you for sharing that code sample. It demonstrates an interesting way to use Hash#merge
with a block argument.
When the key argument is absent from the Hash, a call to Hash#transform_value
would be a no-operation. I apologize for not including this in the original example:
hash = { foo: "value" }
transformed_hash = hash.transform_key(:bar) { |value| fail "This block is never yielded" }
transformed_hash # => { foo: "value" }
nobu (Nobuyoshi Nakada) wrote in #note-1:
hash.merge(image: nil) {|_, url| download(url)} hash.merge!(image: nil) {|_, url| download(url)}
Using Hash#merge
in the way you have shared does reduce the number times the key name is repeated.
However, without a guarding conditional call to hash.key?(:image)
, the returned Hash
would include image: nil
when an :image
key was not initially present:
hash = {}
transformed_hash = hash.merge(image: nil) { |_, url| download(url) }
transformed_hash # => { image: nil }
hash = {}
transformed_hash = hash.merge(image: nil) { |_, url| download(url) } if hash.key?(:image)
transformed_hash # => {}
Updated by matz (Yukihiro Matsumoto) about 2 months ago
- Status changed from Open to Feedback
I don't see the real-world use-case for the proposed method.
Matz.