RubyのYAMLとシンボルと私

Pocket

こんにちは、河野です。

近々勉強会での発表を控えているのですが、YAMLでアウトラインを書いてHTMLに変換したら良いんじゃね?と思いつき、rubyでスクリプトを書いていたんですがハマってしまいました。YAMLで書いたファイルを読み込んで、erbを使って出力しようとしてたんですが、どうもうまく行きません。

YAML

RUBY

出力

ppでは出力されていますが、erbでは出力されていません。なんでー!としばらく悩んでいたんですが、答えは単純でした。

YAMLで読み込んだハッシュのキーは文字列("hoge")になっているので、シンボル(:hoge)で参照しても対応する値が見つからないんですね。ppで出力した内容を良く見ると一目瞭然なんですけどね…気づくのに時間がかかってしまいました。

キーを文字列にすれば解決なんですけど、シンボルで書きたいので色々と模索してみました。

Rails由来のsymbolize_keys

RailsだとHashを拡張して、symbolize_keysというメソッドが使えるようになっています。名称の通り、キーをSymbolに変換してくれるメソッドです。今回みたいにRails使ってるわけじゃないんだけど…という時には、RailsのHashをコピペ参考にしてsymbolize_keysを実装して使うこともあるようなので、僕もやってみました。

RUBY

出力

当たり前ですが、ちゃんと出力されました!

YAML側にシンボルを書いてみた

とりあえず上手く行ったんですが、ちょっとYAML使いたいな~って度にHashを拡張するのも面倒です。もしかして、YAML側でシンボルのように書いてみたら、行けるんじゃないでしょうか?

YAML

RUBY(最初と同じです)

出力

で、でたーーーー!!!

ノリで書いてみたんで、てっきりパースエラーでも起きるかと思っていましたが、ちゃんと出力されました。
まさかと思って調べたところ、リファレンスにも載っていました。

library yamlより

標準添付の yaml 関連ライブラリには 1.8 系、1.9 系ともに以下のような Ruby 独自の拡張、制限があります。標準添付ライブラリ以外で yaml を扱うラ イブラリを使用する場合などに注意してください。

・ ":foo" のような文字列はそのまま Symbol として扱える

なるほど~。

Hashieというのがある

:hoge: booと書けるのは良いんですが、やっぱりこれってYAMLのRuby方言ですよね。YAMLは特定の言語に依存したフォーマットではないんで、他の言語で使うときに問題になりそうです。

そこで、さらにググってみると、Hashieというライブラリを発見しました。Hashieでは、キーをシンボルとして扱ったり、さらにプロパティとしてもアクセスできるようになります。

RUBY

出力

ppではキーは文字列のままですが、erbでもちゃんと出力できてますね。

追記:ActiveSupport使えば良いですよ

ActiveSupportを使ったらどう?という指摘をいただいたので、動作確認してみました。ライブラリ使っても良いんだったら、素直にActiveSupportを使うのがスムーズですね。

※確認用のYAMLに間違いがあったので、やり直しました。訂正してます。at 2012/11/09 13:00

RUBY

出力

ActiveSupportを使う場合はHashが拡張されますHashWithIndifferentAccessのインスタンスの引数にハッシュを渡します。それ以外は、特に何も気にせずキーをシンボルにしても値が取得されました。

まとめ

というわけで、RubyからYAMLを扱うときに、ハッシュのキーで悩んだら以下のどれかになりそうです。

  • キーは文字列がデフォルトなのでシンボルを使うのは諦める
  • symbolize_keysを自前で実装してシンボルに変換
  • YAML側にシンボルで書く
  • Hashieを使って自由に扱う
  • ActiveSupportのHashWithIndifferentAccessを使ってシンボルに変換

Hashie便利なので、今回はHashieを使ってみようと思います!

Pocket

Comments are closed, but you can leave a trackback: Trackback URL.