patorashのブログ

方向性はまだない

Hash#digの逆を行うHash#buryを定義するgem buryを作った

先日、新しくgemを作ってリリースしました。

リポジトリはここ。

github.com

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が重複している際の処理が書けますよと教えてもらったので、それを使ってリファクタリングしたい所存。知らんかった…。めちゃ再帰でゴリ押ししてしまった。

docs.ruby-lang.org

しかし、公開するとフィードバックがあるのでありがたい😀

追記

リファクタリングを行い、かなりシンプルなコードになりました。これだけでよかったんか…😇

https://github.com/patorash/bury/blob/v2.0.0/lib/bury.rb

あと、元々のメソッドが破壊的メソッドなのに!マークのないメソッドだったので、非破壊的メソッドと破壊的メソッドを分けて定義しました。これで更に使いやすくなるはず。