そんな今日この頃でして、、、

コード書いたり映画みたり。努力は苦手だから「楽しいこと」を探していきたい。

Ruby 第20章「ファイルを使った蔵書管理アプリケーションまとめ」

今週は割と仕事が忙し目だし体調もなんだか優れないのだが、かといって第四部のまとめだけ間を開けて残しておくのも気持ちが悪いので消化学習。

作りながら学ぶRuby入門 第2版

作りながら学ぶRuby入門 第2版


この章では第四部で学習してきたデータをファイルに保存すること全般についてのまとめが述べられている。



DBが使えるようになってしまうとファイル入出力というのは非効率だしなんとなく不恰好に思えてしまう場合もある。

※前職で使ってたPHPではこのあたりを全く使わなかったし・・・

でも、実際の業務なんかでも集計値をファイルに保存することによって何度も集計しないで済むようにしたり、一度にメモリにロードできないぐらい大きなデータを扱う処理なんかは中間ファイルを使わざるをえなかったりするわけで、おさえておく価値は大いにある。





そんなわけで以下が本章の課題。

課題1.18章では普通に文字列をファイル入出力してCSVファイルを操作していたが、RubyにはCSVクラスというものが用意されているため、そちらを使うように組み替える。

ググってみると色々と用法が有りそうだが、とりあえずは下記の一行ずつ読み込みループと

CSV.foreach([ファイル名], "r"){|row|
  col1, col2 , col3 = row
  print "#{col1},#{col2},#{col3}¥n"
}

配列からの一行ずつ書き込みを抑えておけば大丈夫そう。

CSV.open([ファイル名], "w"){|writer|
  witer << [col1, col2, col3]
}


以下が実際に作ったコード。

# -*- coding: utf-8 -*-
require 'date'
require 'csv'

class BookInfo
  def initialize( title, author, page, publish_date )
    @title = title
    @author = author
    @page = page
    @publish_date = publish_date
  end
  
  attr_accessor :title, :author, :page, :publish_date

  def to_array( key )
    [key, @title, @author, @page, @publish_date]
  end

  def to_s
    "#{@title},#{@author},#{@page},#{@publish_date}"
  end

  def toFormattedString( sep = "\n" )
    "書籍名: #{@title}#{sep}著者名: #{@author}#{sep}ページ数: #{@page}ページ#{sep}発刊日: #{@publish_date}#{sep}"
  end
end

class BookInfoManager
  def initialize( filename )
    @csv_fname = filename
    @book_infos = {}
  end

  def setUp
    CSV.foreach(@csv_fname, 'r:UTF-8'){|line|
      key, title, author, page, pdate = line
      @book_infos[ key ] = BookInfo.new(title, author, page.to_i, Date.strptime())
    }
  end

  def addBookInfo
    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.publish_date = Date.new( year, month, day )

    @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:UTF-8") {|witer|
      @book_infos.each { |key, info|
        witer << info.to_array(key)
      }
      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

book_info_manager = BookInfoManager.new("book_info.csv")
book_info_manager.setUp
book_info_manager.run

あえてこっちを使わなきゃいけないほど複雑な処理でもないが、すっきり分かりやすく書けるのは良い。



課題2.PStoreのメリット、CSV保存のメリット

PStoreがCSV保存より優れているのは、例えば入れ子式になっているような複雑なデータ構造をそのまま保存・再生できるからである。
これをCSVに保存したりパースしたりするのは大変だし、場合によってはファイルが複数になったりする。
作成も運用も大変になる可能性が高い。

また、後々保存するデータを追加したとしても、読み取る側では修正する必要が無いというのも実用上大きなメリットになる。(データにもよるけど)

一方でCSVは何と言っても人間がファイルを読めるというメリットが大きい。
例えば部分的な修正を行うことも容易だし、Excellで編集もできる。
また、そのCSVを他のプログラムにかませて何かやる、みたいなこともしやすい。




最近の話

秋アニメも終わり冬アニメが始まった時期であり、かく言う僕はといえば最近nasneを買ったので裏番組まで録画できたりiPadで布団の中からでも録画を消化できたりと、アニメ充な環境は整いつつかるけど、そんなに暇でもないしTorneで録った番組はPS3本体だから遠隔では見れなかったりで積みアニメは一向に消化しきれないまま更に溜まっていく今日このごろ。

nasne (ナスネ) (CECH-ZNR1J)

nasne (ナスネ) (CECH-ZNR1J)

iPad (Retinaディスプレイモデル 第3世代) 16GB Wi-Fiモデル ブラック MC705J/A

iPad (Retinaディスプレイモデル 第3世代) 16GB Wi-Fiモデル ブラック MC705J/A

もーちょいTwonky Beamの再生の精度が良くなって、対応する動画形式が増えればなー・・・