Hatena::Grouprubyist

雲雀は高く空を舞い RSSフィード

 | 

2007-06-14

SAKURAエディタRubyのSyntax Highlightをする。 17:27  SAKURAエディタでRubyのSyntax Highlightをする。 - 雲雀は高く空を舞い を含むブックマーク はてなブックマーク -  SAKURAエディタでRubyのSyntax Highlightをする。 - 雲雀は高く空を舞い  SAKURAエディタでRubyのSyntax Highlightをする。 - 雲雀は高く空を舞い のブックマークコメント

こちら>

no title

からRubyDef.lzhを落としてきて、後はReadMeを参考に。

YAML::Store (1) 17:58 YAML::Store (1) - 雲雀は高く空を舞い を含むブックマーク はてなブックマーク - YAML::Store (1) - 雲雀は高く空を舞い YAML::Store (1) - 雲雀は高く空を舞い のブックマークコメント

目的

YAML形式でデータファイルに残したい。

背景


ではどうもうまく書き込みがなされなかった。YAML::Storeがあるとか。YAML::StorePStoreYAML版。

というわけでまずはPStoreから調べてみる。

PStore

Rubyオブジェクトを外部ファイルに格納するためのクラス内部Marshalを使ってバイナリ化したデータを保存する、とか。

参考になるところ


以下「Rubyist Magazine - 標準添付ライブラリ紹介 【第 9 回】 PStore」を写経。正確な情報はそちらを参照のこと。

基本的な使い方

使い方は基本的には Hashと類似。

PStore#[]= で値を保存して、PStore#[] を使って値を取り出す。

また、Hash#keysHash#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>

続く!

つぎこそYAML::Store

YAML::Store (2) 19:51  YAML::Store (2) - 雲雀は高く空を舞い を含むブックマーク はてなブックマーク -  YAML::Store (2) - 雲雀は高く空を舞い  YAML::Store (2) - 雲雀は高く空を舞い のブックマークコメント

PStoreで書いたことでほとんど全部だったのかも。

Method

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


YAMLドキュメントからRubyオブジェクトへの変換 19:51  YAMLドキュメントからRubyオブジェクトへの変換 - 雲雀は高く空を舞い を含むブックマーク はてなブックマーク -  YAMLドキュメントからRubyオブジェクトへの変換 - 雲雀は高く空を舞い  YAMLドキュメントからRubyオブジェクトへの変換 - 雲雀は高く空を舞い のブックマークコメント


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

YAML ストリーム 19:51  YAML ストリーム - 雲雀は高く空を舞い を含むブックマーク はてなブックマーク -  YAML ストリーム - 雲雀は高く空を舞い  YAML ストリーム - 雲雀は高く空を舞い のブックマークコメント

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 19:51 sqlite - 雲雀は高く空を舞い を含むブックマーク はてなブックマーク - sqlite - 雲雀は高く空を舞い sqlite - 雲雀は高く空を舞い のブックマークコメント

データの格納・検索・処理をしたいのだったらデータベース仕様を検討してもいいのかも?ということでsqliteについて後で調べてみようかしら。。」


SQLiteMySQLやPostgreSQLと同じDBMSデータベース管理ソフト)であるが、サーバとしてではなくアプリケーションに組み込まれて利用される軽量データベースである。

SQLite - Wikipedia

後で読む


今日のまとめ的な例 19:51 今日のまとめ的な例 - 雲雀は高く空を舞い を含むブックマーク はてなブックマーク - 今日のまとめ的な例 - 雲雀は高く空を舞い 今日のまとめ的な例 - 雲雀は高く空を舞い のブックマークコメント

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