【#100DaysOfCode】Day13 「作りながら学ぶRuby入門」16章
取り組み方を変えたおかげで、今日はスタコラ進んだ。
ファイルアクセスとかやりだすと、「オブジェクト指向的言語」クッソ便利だなあと実感。
指定・修正・更新 がオブジェクトへのアクセスだけで、済むんだもんあ
Day13
蔵書データのファイル保存
- CSVファイルで保存 (本記事)
- PStoreでデータベースとして保存 (別)
このようなやり方がある。
本記事では、csvファイルで保存する 場合のコードを書く。
以下コード
読み込みモジュールのみ (単体では動かない)
# csvファイルから蔵書データを読み込む class BookInfoManager def initialize ( filename ) # 初期化でcsvファイルを指定する @csv_fname = filename # 蔵書データのハッシュ @book_infos = {} end #(中略) # 蔵書データをセットアップする def setUp # csvファイルを読み込みモードでオープンする open(@csv_fname){ |file| # ファイルの1行ずつを取り出して、lineに読み込む file.each{ |line| # lineからchompで改行を除き、splitでカンマ区切りに分割し、 # 左辺のそれぞれの項目へ多重代入する key, title, page, pdate = line.chomp.split(',') # strptimeは、文字列からDateクラスのインスタンスを作成するメソッド @book_infos[key] = BookInfo.new(title, author, page.to_i, Date.strptime(pdate)) } # 1行ずつの処理の終わり } #このブロックを抜けると、ファイルを閉じる end # (以下略) end
これを用いて、
【csv形式で読み込み・書き込みを追加した蔵書管理アプリケーション】
のコードが以下のようになる。
※このコードにcsvファイルの新規作成機能はない
# 「作りながら学ぶRuby入門」 16章 # csvファイル保存版 の蔵書管理アプリケーション # 【準備】:新規ファイルの作成昨日はないので、 # 予め「空のcsvファイル」を作っておくこと require 'date' 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クラスのインスタンスをcsv形式に変換する def to_csv(key) "#{key},#{@title},#{author},#{page},#{p_date}\n" end # 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( filename ) # 初期化でcsvファイルを指定する @csv_fname = filename # 蔵書データのハッシュ @book_infos = {} end # 蔵書データをセットアップする def setUp # csvファイルを読み込みモードでオープンする open( @csv_fname ){ |file| # ファイルの行を1行ずつ取り出して、lineに読み込む file.each { |line| # lineからchompで改行を除き、splitでカンマ区切りに分割し、 # 左辺のそれぞれの項目へ、多重代入する key, title, author, page, p_date = line.chomp.split(',') # 蔵書データ1件分のインスタンスを作成して、ハッシュに登録する # strptimeは、文字列からDateクラスのインスタンスを作成するメソッド @book_infos [key] = BookInfo.new(title, author, page.to_i, Date.strptime(p_date)) } # 1行ずつの処理のおわり } # ファイルを閉じている 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件分をハッシュに登録する @book_infos[key] = book_info end # 蔵書データの一覧を表示する def listAllBookInfos puts "\n---------------------------" @book_infos.each { |key, info| print info.toFormattedString puts "\n---------------------------" } end # 蔵書データを全件ファイルに書き込んで保存する def saveAllBookInfos # csvファイルを書き込みモードでオープンする open(@csv_fname, 'w'){ |file| @book_infos.each{ |key, info| file.print( info.to_csv( key ) ) } # 1行ずつの処理のおわり puts "\nファイルへ保存しました" } # ファイルを閉じている end # 処理の選択と選択後の処理を繰り返す def run while true # 機能選択画面を表示する print " 1. 蔵書データの登録 2. 蔵書データの表示 8. 蔵書データをファイルへ保存 9. 終了 番号を選んでください (1, 2, 8, 9) :" # 文字の入力を待つ num = gets.chomp case when '1' == num # 蔵書データの登録 addBookInfo when '2' == num # 蔵書データの表示 listAllBookInfos when '8' == num # 蔵書データをファイルに保存 saveAllBookInfos when '9' == num # アプリケーションの終了 break; else # 処理選択待ち画面に戻る end end end end ################### main ################################ # ここからがアプリケーションを動かす本体 # アプリケーションのインスタンスを作る # 蔵書データのcsvファイルを指定している book_info_manager = BookInfoManager.new("book_info.csv") # BookInfoMnager の蔵書データをセットアップする book_info_manager.setUp # BookInfoManagerの処理の選択と、選択後の処理を繰り返す book_info_manager.run