私はRubyにかなり慣れていないので、これが明らかな質問である場合は申し訳ありません.
Struct をインスタンス化するときに名前付きパラメーターを使用したいと考えています。つまり、Struct 内のどのアイテムがどの値を取得するかを指定し、残りをデフォルトで nil に設定できるようにしたいと考えています。
たとえば、私はやりたい:
Movie = Struct.new :title, :length, :rating
m = Movie.new :title => 'Some Movie', :rating => 'R'
これはうまくいきません。
だから私は次のことを思いついた:
class MyStruct < Struct
# Override the initialize to handle hashes of named parameters
def initialize *args
if (args.length == 1 and args.first.instance_of? Hash) then
args.first.each_pair do |k, v|
if members.include? k then
self[k] = v
end
end
else
super *args
end
end
end
Movie = MyStruct.new :title, :length, :rating
m = Movie.new :title => 'Some Movie', :rating => 'R'
これは問題なく動作しているように見えますが、これを行うためのより良い方法があるかどうか、またはかなり非常識なことを行っているかどうかはわかりません。誰かがこのアプローチを検証/引き裂くことができれば、私は最も感謝しています.
アップデート
これを最初に 1.9.2 で実行しましたが、問題なく動作します。ただし、他のバージョンの Ruby で試してみたところ (rvm に感謝)、次のように機能する/機能しない:
- 1.8.7: 動かない
- 1.9.1: 作業中
- 1.9.2: 作業中
- JRuby (1.9.2 として実行するように設定): 動作しない
JRuby との互換性を維持したいので、JRuby は私にとって問題です。
さらに別の更新
このますます増え続けるとりとめのない質問で、私はさまざまなバージョンの Ruby で実験し、1.9.x の構造体はメンバーをシンボルとして格納することを発見しましたが、1.8.7 と JRuby ではそれらは文字列として格納されるため、コードを次のように更新しました。次のようになります(すでに親切に提供された提案を取り入れて):
class MyStruct < Struct
# Override the initialize to handle hashes of named parameters
def initialize *args
return super unless (args.length == 1 and args.first.instance_of? Hash)
args.first.each_pair do |k, v|
self[k] = v if members.map {|x| x.intern}.include? k
end
end
end
Movie = MyStruct.new :title, :length, :rating
m = Movie.new :title => 'Some Movie', :rating => 'R'
これは、私が試したすべての種類の Ruby で機能するようになりました。