LoginSignup
65
62

More than 5 years have passed since last update.

手軽に構造体を使いたい時にOpenStruct

Posted at

要素を動的に追加・削除できる手軽な構造体を提供するクラスです。
OpenStruct のインスタンスに対して未定義なメソッド x= を呼ぶと、 OpenStruct クラスの BasicObject#method_missing で捕捉され、そのインスタンスに インスタンスメソッド x, x= が定義されます。 この挙動によって要素を動的に変更できる構造体として働きます。

手軽に使える

require "ostruct"

config = OpenStruct.new
config.level #=> nil
config.level = :debug
config.level #=> :debug

ぉー。確かに手軽かも。

初期値はハッシュ

require "ostruct"

config = OpenStruct.new(level: :debug, file: "log/test.log")
config.level #=> :debug
config.file  #=> "log/test.log"

初期値はハッシュ形式で渡せるそうです

OpenStructの子クラスを作る

何となく『初期値は最初から持っといてよ』って思ったので。
例を書くと下記のような感じかな?

def start(config = MyApp::Config.new)
  config.level
end

というわけで、次からサブクラスの初期化に含めてみます

require "ostruct"

module MyApp #他のアプリと当たらないように
  class Config < OpenStruct
    def initialize
      self.level = :debug #レシーバを指定しないとローカル変数になるので
    end
  end
end

def start(config = MyApp::Config.new)
  p config.level
end

start

実行

/ruby-1.9.3-p392/lib/ruby/1.9.1/ostruct.rb:172:in `method_missing': undefined method `[]=' for nil:NilClass (NoMethodError)
    from test.rb:6:in `initialize'
    from test.rb:11:in `new'
    from test.rb:11:in `start'
    from test.rb:15:in `<main>'

おや?

少し調べる

『何か初期化でしているのかな?』と思い、とりあえずインスタンス変数を出してみる

p OpenStruct.new.instance_variables #=> [:@table]

こいつで実際に管理しているっぽいですね。

親クラスの初期化を呼んでおく

require "ostruct"

module MyApp
  class Config < OpenStruct
    def initialize
      super
      self.level = :debug
    end
  end
end

def start(config = MyApp::Config.new)
  p config.level
end

start

そして実行

$ ruby test.rb 
:debug

ぁ。動きましたね。

まとめ

  • 手軽に構造体が利用出来る
  • オプション目的では、optparseやtrollopを使ったり、yamlを使っている事が多いと思うので、微妙かもしれないですねw
    • でも、こういうのも便利ですよね〜(^^
65
62
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
65
62