俺は Ruby について 1bit も理解していなかったので写経する 〜 添付ライブラリ 〜
これは
- Ruby Gold を受験するにあたって学んでいること等を写経したり, メモったりしています
- 「Ruby 技術者認定試験合格教本」を主に参考にしており, 今回は第六章「添付ライブラリ」を写経していきます
- 実行例では主に pry を利用していますが, 例外が発生した際の実行過程出力(from から始まる行)は省略しています...すいません
[12] pry(main)> Baz2.new.private_method1 NoMethodError: private method `private_method1' called for #<Baz2:0x005606f46e2778> from (pry):29:in `__pry__'
StringIO
- 文字列を IO クラスと同じインタフェースで取り扱うクラス
- IO クラスと同じインタフェースを持つが, 直接の継承関係は無い
- インスタンス生成時に与えられた文字列や puts 等のメソッドで文字列を StringIO 内のバッファに格納する
- gets や readline 等のメソッドでバッファから文字列を取り出すことが出来る
require 'stringio' sio = StringIO.new
open メソッドによる StringIO インスタンスの作成例.
[6] pry(main)> sio = StringIO.open "Hello World" do |io| [6] pry(main)* p io.read [6] pry(main)* nil [6] pry(main)* end "Hello World" => nil [7] pry(main)> p sio nil => nil
ファイルフォーマット
yaml
yaml とは
- YAML は, XML よりもさらに簡単な記法でデータ階層構造を表現出来るフォーマット
- ハッシュ・配列の組み合わせをスペース(タブは使用出来ない)によるインデントで表現したもの
- YAML の入出力に関するメソッドは全てクラスメソッドなので, インスタンスを生成しないで呼び出すことが出来る
yaml の読み込み
[7] pry(main)> YAML.load("---\n- foo\n- bar\n- baz\n") => ["foo", "bar", "baz"]
YAML.load メソッドは, YAML データが記録された文字列, IO インスタンスから Hash クラスのインスタンスを生成する. 複数の YAML が記録されていても, 最初の YAML のみが生成され, 残りは無視される.
$ cat sample.yml - foo - bar - baz $ ruby -r yaml -e 'p YAML.load_file("sample.yml")' ["foo", "bar", "baz"]
YAML.load_file メソッドは, 指定した YAML ファイルからオブジェクトを生成する.
yaml の書き込み
YAML.dump メソッドは, 単一のインスタンスを文字列又は IO インスタンスに出力することが出来る.
# 引数 io を省略すると YAML 形式に変換された文字列を返す [3] pry(main)> YAML.dump(['foo', 'bar', 'baz']) => "---\n- foo\n- bar\n- baz\n" # io を指定すると指定した出力先に YAML 形式のデータを書き込む [4] pry(main)> YAML.dump(['foo', 'bar', 'baz'], File.open("test.yml", "w+")) => #<File:test.yml> [5] pry(main)> exit $ cat test.yml --- - foo - bar - baz # YAML.dump_stream メソッドは, 複数のオブジェクトを文字列に出力することが出来る [1] pry(main)> require 'yaml' => true [2] pry(main)> YAML.dump_stream(['foo', 'bar'], ['hoge', 'fuga']) => "---\n- foo\n- bar\n---\n- hoge\n- fuga\n"
JSON
JSON とは
- Ruby 1.9 から標準添付ライブラリに JSON を扱うライブラリが追加された
- YAML 同様に簡単な記法でデータの階層構造を表現出来るフォーマット
- ブラウザとサーバー間でデータを交換する形式としてよく利用されている
JSON の読み込み
文字列から JSON を読み込む場合, JSON.parse 又は JSON.load メソッドを利用する.
[4] pry(main)> JSON.load('["foo", "bar", "baz"]') => ["foo", "bar", "baz"] # Proc には解釈されたオブジェクトから順番に渡されるので, 以下のように出力される [6] pry(main)> JSON.load('["foo", "bar", "baz"]', lambda{|x| p x}) "foo" "bar" "baz" ["foo", "bar", "baz"] => ["foo", "bar", "baz"] # JSON.parse は load と異なり, 引数には文字列しか渡すことが出来ない [7] pry(main)> JSON.parse('["foo", "bar", "baz"]') => ["foo", "bar", "baz"]
YAML と異なり, ファイルから直接読み込むメソッドは用意されていないが, load メソッドの引数に io オブジェクトを指定することで, io オブジェクト経由でデータを読み込むことが出来る.
$ cat sample.json ["foo", "bar", "baz"] $ ruby -r 'json' -e 'p JSON.load(File.open("sample.json"))' ["foo", "bar", "baz"]
JSON の書き込み
[1] pry(main)> require 'json' => true [2] pry(main)> JSON.dump(['foo', 'bar', 'baz']) => "[\"foo\",\"bar\",\"baz\"]"
ファイルに書き出す場合には, 第二引数に IO オブジェクトを指定する. 第三引数にはオブジェクトを参照する深さを指定する. limit 以上深くリンクしたオブジェクトをダンプしようとすると AregumentError が発生する.
[1] pry(main)> require 'json' => true [2] pry(main)> f = File.open('dump.json', "w") => #<File:dump.json> [3] pry(main)> JSON.dump(['foo', 'bar', 'baz'], f) => #<File:dump.json>
CSV
CSV とは
- 無く子も黙る...
読み書き可能なメソッド
CSV を mode で指定した形式でオープンし, ブロックで処理する.
[1] pry(main)> require 'csv' => true [2] pry(main)> CSV.open("sample.csv") do |csv| [2] pry(main)* csv.each do |row| [2] pry(main)* p row [2] pry(main)* end [2] pry(main)* end ["abc", "def", "ghi", "jkl"] ["123", "456", "789", "012"] ["ABCDEFG", nil, "HIJKLM", nil, nil] => nil
以下, 書き込み.
[3] pry(main)> CSV.open("sample2.csv", "w") do |row| [3] pry(main)* row << ["abc", "def", "ghi"] [3] pry(main)* row << ["jkl", "mno", "pqr"] [3] pry(main)* end => <#CSV io_type:File io_path:"sample2.csv" encoding:UTF-8 lineno:2 col_sep:"," row_sep:"\n" quote_char:"\""> [4] pry(main)> exit $ cat sample2.csv abc,def,ghi jkl,mno,pqr
読み込みのみ
以下のメソッドを利用する.
- foreach
- read
- realines
[1] pry(main)> require 'csv' => true [2] pry(main)> CSV.read("sample.csv") => [["abc", "def", "ghi", "jkl"], ["123", "456", "789", "012"], ["ABCDEFG", nil, "HIJKLM", nil, nil]] [3] pry(main)> CSV.readlines("sample.csv") => [["abc", "def", "ghi", "jkl"], ["123", "456", "789", "012"], ["ABCDEFG", nil, "HIJKLM", nil, nil]] [5] pry(main)> table = CSV.read("sample.csv", headers: true) => #<CSV::Table mode:col_or_row row_count:3> [6] pry(main)> table.to_a => [["abc", "def", "ghi", "jkl"], ["123", "456", "789", "012"], ["ABCDEFG", nil, "HIJKLM", nil, nil]]
以上
写経でした.