ではどうもうまく書き込みがなされなかった。YAML::Store
があるとか。YAML::Store
はPStoreのYAML版。
というわけでまずはPStoreから調べてみる。
Rubyのオブジェクトを外部ファイルに格納するためのクラス。内部でMarshalを使ってバイナリ化したデータを保存する、とか。
参考になるところ
以下「Rubyist Magazine - 標準添付ライブラリ紹介 【第 9 回】 PStore」を写経。正確な情報はそちらを参照のこと。
使い方は基本的には Hashと類似。
PStore#[]= 値
で値を保存して、PStore#[]
を使って値を取り出す。
また、Hash#keysとHash#key?に相当するのはそれぞれPstore#rootsとPStore#root?。
データ操作はtransaction中のみ。データを参照するのみの場合は引数にtrueを指定することで、読み込み専用のtransactionとなる。
require 'pstore' db = PStore.new('PStoretest') db.transaction do p db.roots ary = db['root'] = [1,2,3,4] # 配列を db に設定 ary[0] = [1,1.5] # 破壊的に変更 end # 保存は transaction を抜けるときなので変更された結果が保存される db.transaction(true) do # 読み込み専用モード p db.root?('root') p db['root'] end begin db.transaction(true) do db['root'] = 'hoge' # 書き込もうとすると PStore::Error end rescue PStore::Error p $! end
実行結果 (1回目)
[] true [[1, 1.5], 2, 3, 4] #<PStore::Error: in read-only transaction>
実行結果 (2 回目以降):
["root"] true [[1, 1.5], 2, 3, 4] #<PStore::Error: in read-only transaction>
続く!
「Rubyist Magazine - プログラマーのための YAML 入門 (中級編)」より
require 'yaml' require 'yaml/store' ## YAML::Store オブジェクトを作成 filename = "store.yaml" store = YAML::Store.new(filename) ## データの読み出しと格納 store.transaction do |hash| ## データの読み出し count = hash["count"] count = 0 if count == nil puts "count = #{count}" ## データの格納 hash["count"] = count + 1 end
require 'yaml' hashlist = [ { 'name' => 'Shiina', 'age' => 6, 'birth' => Date.new(1999, 1, 1), 'favorite' => ['Thomas', 'Pokemon'], }, { 'name' => 'Sumire', 'age' => 4, 'birth' => Date.new(2001, 2, 2), 'smoker' => false, }, ] hashyaml = hashlist.to_yaml yamlhash = YAML.load(hashyaml) p hashyaml p yamlhash
「Rubyist Magazine - プログラマーのための YAML 入門 (中級編)」より
複数のYAMLドキュメントを含むデータを、YAMLではストリームという。個々のYAMLドキュメントは「---」で区切る。
ストリームの読み込みには以下を用いる。引数 input には文字列または IO オブジェクト(File オブジェクトを含む)が指定できる。
## YAML データ (「---」で区切って複数のデータを記述している) str = <<END --- name: Ruby url: http://www.ruby-lang.org --- name: Python url: http://www.python.org --- name: PHP url: http://www.php.net END ## YAML ドキュメントをひとつずつ読み込む require 'yaml' YAML.load_documents(str) do |doc| p doc end ## または複数の YAML ドキュメントをまとめて読み込む stream = YAML.load_stream(str) ## stream は YAML::Stream オブジェクト stream.documents.each do |doc| p doc end
実行結果
{"name"=>"Ruby", "url"=>"http://www.ruby-lang.org"} {"name"=>"Python", "url"=>"http://www.python.org"} {"name"=>"PHP", "url"=>"http://www.php.net"}
ひとつのファイルに複数の YAML ドキュメントを書き込むには、YAML.dump_stream() または YAML::Stream#emit() を用いる。
例
## 複数のデータ hash_list = [ { "lang"=>"Ruby", "url"=>"http://www.ruby-lang.org" }, { "lang"=>"Python", "url"=>"http://www.python.org" }, { "lang"=>"PHP", "url"=>"http://www.php.net" }, ] ## ひとつのファイルに複数の YAML ドキュメントを出力する require 'yaml' str = YAML.dump_stream(*hash_list) print str ## または YAML::Stream を使って次のようにする stream = YAML::Stream.new() hash_list.each { |hash| stream.add(hash) } str = stream.emit() print str
実行結果
--- url: http://www.ruby-lang.org lang: Ruby --- url: http://www.python.org lang: Python --- url: http://www.php.net lang: PHP
データの格納・検索・処理をしたいのだったらデータベースの仕様を検討してもいいのかも?ということでsqliteについて後で調べてみようかしら。。」
SQLite はMySQLやPostgreSQLと同じDBMS(データベース管理ソフト)であるが、サーバとしてではなくアプリケーションに組み込まれて利用される軽量データベースである。
SQLite - Wikipedia
後で読む
require 'time' class Person def initialize( name, mail, objective ) # @id = Guid.new.to_s @name = name @mail = mail @update = Time.now # @objective = objective end # attr_reader :id, :update # attr_accessor :name, :mail attr_accessor :name, :mail, :update def to_s "person[ @id=#{@id}, @name=#{@name}, @mail=#{@mail}, @update=#{@update.xmlschema} ]" end def to_h {"name"=>@name, "mail"=>@mail, "update"=>@update} end end
p1 = Person.new('person1','person1@ruby.org') p2 = Person.new('person2','person2@ruby.org') h = [p1.to_h,p2.to_h] h.to_yaml
--- - name: person1 mail: person1@ruby.org update: 2007-06-14 19:44:35.120682 +09:00 - name: person2 mail: person2@ruby.org update: 2007-06-14 19:26:20.372198 +09:00