1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

OpenStructを再帰的に実行する

Last updated at Posted at 2016-11-14

ハッシュを渡すと構造体を返してくれるOpenStructが便利で使い始めたのですが、ネストしたハッシュに対して再帰的(recursive)には実行されないよう(オプションとかも無さそう)なので、この辺を参考にさせていただき「DeepOpenStruct」を書いてみました。

Code
lib/deep_open_struct.rb
class DeepOpenStruct < OpenStruct

  def initialize(hash = nil)
    @table = {}
    @hash_table = {}

    if hash
      hash.each do |key, value|
        @table[key.to_sym] =
          if value.is_a?(Array)
            value.map { |_value| (_value.is_a?(Array) || _value.is_a?(Hash)) ? self.class.new(_value) : _value }
          elsif value.is_a?(Hash)
            self.class.new(value)
          else
            value
          end
        @hash_table[key.to_sym] = value

        new_ostruct_member(key)
      end
    end
  end

  def to_h
    @hash_table
  end

end
RSpec
spec/libs/deep_open_struct_spec.rb
RSpec.describe DeepOpenStruct, type: :lib do

  let!(:strict) {
    DeepOpenStruct.new(
      foo: "abc",
      bar: %w(hoge, fuga, piyo),
      baz: {
        foobar: {
          hoge: :hoge,
          fuga: nil,
          piyo: [
            123,
            456,
            {
              z: {
                abc: "def",
                def: 999,
                ghi: [{ xyz: "xyz" }]
              }
            }
          ]
        }
      },
      qux: []
    )
  }

  it { expect(strict.foo).to eq "abc" }
  it { expect(strict.bar).to eq %w(hoge, fuga, piyo) }
  it { expect(strict.baz.foobar.hoge).to eq :hoge }
  it { expect(strict.baz.foobar.fuga).to be_nil }
  it { expect(strict.baz.foobar.piyo.size).to eq 3 }
  it { expect(strict.baz.foobar.piyo.first).to eq 123 }
  it { expect(strict.baz.foobar.piyo.second).to eq 456 }
  it { expect(strict.baz.foobar.piyo.third.z.abc).to eq "def" }
  it { expect(strict.baz.foobar.piyo.third.z.def).to eq 999 }
  it { expect(strict.baz.foobar.piyo.third.z.ghi.size).to eq 1 }
  it { expect(strict.baz.foobar.piyo.third.z.ghi.first.xyz).to eq "xyz" }
  it { expect(strict.qux).to eq [] }

end

補足

recursive-open-structというGemを使ったり、JSONに変換してから渡したりと、他にもやりようはありそうです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?