【#100DaysOfCode】Day13 「作りながら学ぶRuby入門」17章
オブジェクトを保存する方法として、今回は
- データベースとして保存
する方法を用いる。
Day13
「作りながら学ぶRuby入門」17章 PStore:データベースの扱い
蔵書データのファイル保存
- CSVファイルで保存 (前記事)
- PStoreでデータベースとして保存 (本記事)
これまでのハッシュの代わりみたいな振る舞い
ハッシュの場合 | データベースの場合 |
メモリ上のファイルをキーと値の組で管理 | メモリの外のファイルもキーと値で指定して管理 |
こんな感じ。
まずはデータベースへの書き込み・読み込みオブジェクト
# 「作りながら学ぶRuby入門」17章 # PStoreにデータを書き込んでから、読み込む require 'pstore' # 文字列を作成 juice = "orange juice" # 配列にデータを作成 fruits = ["apple", "banana", "cherry", "fig", "grape"] # PStoreデータベースを作成する db = PStore.new('fruitdb') # PStoreにデータを書き込む db.transaction do # 文字列をPStoreに保存する db["drink"] = juice # 配列をPStoreに保存する db["fruits"] = fruits end # PStoreに保存されるのは、transactionメソッドを抜ける時 # PStoreからデータを読み込んで表示する db.transaction(true) do puts "drink: #{db["drink"]}" puts "fruits: #{db["fruits"].join(",")}" end # PStoreが読み込みモードの時に書き込もうとすると、 # エラーになる db.transaction(true) do db["drink"] = "grape juice" end
データベース使用の流れ
- DBのインスタンスを作成する
- このとき、引数でDB名を指定しておく
- DBへの書き込み
- DBハッシュ.transaction do
- DBからの読み込み
- DBハッシュ.transaction(true) do
読み込みモード中に書き込もうとすると、ちゃんとエラーを出す
これが基本的なデータベースの扱い方。
まんまこれまでのハッシュの扱いと同じで助かる。
ライブラリのインポートが追加されただけ。
ということで、
【データベース機能を追加した蔵書管理アプリケーション】
のコードが以下。
# 「作りながら学ぶRuby入門」 17章 # PStoreを使って、データベースからの読み込み・書き込み・削除を行う require 'date' require 'pstore' class BookInfo # BookInfoクラスのインスタンスを初期化する def initialize (title, author, page, p_date ) @title = title @author = author @page = page @p_date = p_date end # 最初に検討する属性に対するアクセサを提供する attr_accessor :title, :author, :page, :p_date # BookInfoクラスのインスタンスの文字列表現を返す def to_s "#@title, #@author, #@page, #@p_date" end # 蔵書データを書式をつけて出力する def toFormattedString( sep = "\n") "書籍名: #{@title}#{sep}, 著者名: #{@author}#{sep}, ページ数: #{@page}ページ#{sep} 発刊日: #{@p_date}#{sep}" end end # BookInfoManagerクラスを定義する class BookInfoManager def initialize( pstore_name ) # PStoreデータベースファイルを指定して、初期化 @db = PStore.new(pstore_name) end # 蔵書データを登録する def addBookInfo # 蔵書データ1件分のインスタンスを作成する book_info = BookInfo.new( "", "", 0, Date.new ) # 登録するデータを項目ごとに入力する print "\n" print "キー: " key = gets.chomp print "書籍名: " book_info.title = gets.chomp print "著者名: " book_info.author = gets.chomp print "ページ数: " book_info.page = gets.chomp.to_i print "発刊年: " year = gets.chomp.to_i print "発刊月: " month = gets.chomp.to_i print "発刊日: " day = gets.chomp.to_i book_info.p_date = Date.new( year, month, day ) # 作成した蔵書データ1件分をPStoreデータベースに登録する @db.transaction do # 蔵書データをPStoreに保存する @db[key] = book_info end end # PStoreからデータベース情報を読み込み、一覧を表示 def listAllBookInfos puts "\n-----------------------------------------------" @db.transaction(true) do # rootsがキーの配列を返し、eachでそれを1件ずつ処理 @db.roots.each{ |key| # 得られたキーを使ってPStoreから蔵書データ(BookInfo)を取得 # それを書式をつけて出力する puts "キー: #{key}" print @db[key].toFormattedString puts "\n-----------------------------------------------" } end end # 蔵書データを1件ずつデータベースから削除する def delBookInfo # キーを指定してもらう print "\n" print "キーを指定してください: " key = gets.chomp # 削除対象データを確認してから、削除する @db.transaction do if @db.root?(key) print @db[key].toFormattedString print "\n削除しますか? (Y/yなら削除を実行します): " # 読み込んだ値を大文字に揃える yesno = gets.chomp.upcase if /^Y$/ =~ yesno # Yが1文字の時だけ,PStoreデータベースから削除する @db.delete(key) puts "\nデータベースから削除しました" end end end end # 処理の選択と選択後の処理を繰り返す def run while true # 機能選択画面を表示する print " 1. 蔵書データの登録 2. 蔵書データの表示 3. 蔵書データの削除 9. 終了 番号を選んでください (1, 2, 3, 9) :" # 文字の入力を待つ num = gets.chomp case when '1' == num # 蔵書データの登録 addBookInfo when '2' == num # 蔵書データの表示 listAllBookInfos when '3' == num # 蔵書データの削除 delBookInfo when '9' == num # アプリケーションの終了 break; else # 処理選択待ち画面に戻る end end end end # ここからがアプリケーションを動かす本体 # アプリケーションのインスタンスを作る # 蔵書データのPstoreデータベースを指定している book_info_manager = BookInfoManager.new("book_info.db") # BookInfoManager の処理の選択と、選択後の処理を繰り返す book_info_manager.run
データベースクラス関係のポイント
表示クラス listAllBookInfos
- 配列のキーを指定して、表示処理を1件ずつ行う
- 得られたキーを使って、PStoreからデータベース情報を取得
削除クラス delBookInfos
- データベースハッシュに (削除対象キー) が含まれているか判定
- 正規表現を使って、削除処理を選択
- /^Y$/ 文頭から文末に Y が含まれていれば処理を実行
今日はゴリゴリ進んでよかった