要素を動的に追加・削除できる手軽な構造体を提供するクラスです。
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
- でも、こういうのも便利ですよね〜(^^