先日、新しくgemを作ってリリースしました。
Hash#digの逆を行う、Hash#buryメソッドを定義したgemをリリースしたぞい。digは掘るなので、埋めるの意味のburyにした。https://t.co/6OQdcE22Q7
— パトラッシュ💉💉@リーダー業 (@patorash) 2022年1月26日
リポジトリはここ。
Hash#digの逆とは?
Hash#digは、引数に渡されたkeyの配列でHashを掘っていくメソッドです。
hash = { a: { b: { c: 1 } } } hash.dig(:a, :b, :c) # => 1
今回作ったやつは、それの逆を行います。引数で渡されたkeyの配列のところに値を埋め込みます。
require 'bury' hash = {} hash.bury([:a, :b, :c], 1) # => { a: { b: { c: 1 } } }
なお、digは「掘る」という意味なので、埋めるという意味のburyと名付けました。
途中のkeyが重複しても考慮される
途中のkeyが重複したらそれを検知してマージしてます。
require 'bury' hash = { a: { b: { d: 2 } } } hash.bury([:a, :b, :c], 1) # => { a: { b: { c: 1, d: 2 } } }
なんで作ったの?
Hashを動的に作りたかったのだけれど、Hashの深いネスト構造を作るのが大変だったので、作った次第です。今やっている作業を楽にするために作った完全に俺得なメソッドですが、もしかしたらこういう再帰的にHashをマージしたい需要はあるかもなぁと思ってgemにしました。
テストはminitestで書いてます。minitestは早くて簡単。
実装ポイント
Hashクラスへのメソッド追加のため、bury以外のメソッドを生やしたくなかったので、再帰的な処理をlambdaにしてメソッド内に閉じ込めました。
bury/bury.rb at 467750a62bc55959b03ad9ab680c109313105a11 · patorash/bury · GitHub
既に改善点が…
会社のTeamsで、こんなのを作ったと書いていたら、mergeメソッドにブロックを渡すとkeyが重複している際の処理が書けますよと教えてもらったので、それを使ってリファクタリングしたい所存。知らんかった…。めちゃ再帰でゴリ押ししてしまった。
しかし、公開するとフィードバックがあるのでありがたい😀
追記
リファクタリングを行い、かなりシンプルなコードになりました。これだけでよかったんか…😇
https://github.com/patorash/bury/blob/v2.0.0/lib/bury.rb
あと、元々のメソッドが破壊的メソッドなのに!マークのないメソッドだったので、非破壊的メソッドと破壊的メソッドを分けて定義しました。これで更に使いやすくなるはず。