Hitsuji_monのブログ~ 村上春樹のあれ ~

文学好きな組み込み系エンジニア

【#100DaysOfCode】Day15「作りながら学ぶRuby入門」20章〜Ruby/DBI〜

今日で蔵書管理アプリケーション(データベース版)の完成
今日はあまり集中できなかった。

Day15


「作りながら学ぶRuby入門」
20章 Ruby/DBI:蔵書管理アプリケーション(データベース版)

今日のpoint

  • データベースからデータを取り出し格納する方法
    • データベースファイルを格納
    • 1行ずつeachメソッドで取り出し, row(適当) に入れる
    • .each_with_nameメソッド で値と項目名を取り出し、格納

考え方はこれまでと同じ

以下そのコード

# 「作りながら学ぶRuby入門」20章
require 'rubygems'  
require 'dbi'       

# データベース 'fruits01.db'に接続する
dbh = DBI.connect( 'DBI:SQLite3:fruits01.db' )

# テーブルからデータを読み込んで表示する
# select文の実行
sth = dbh.execute("select * from products")

# select文の結果を1件ずつrowに取り出し、繰り返し処理する
sth.each do |row|
  # rowは1件分のデータを保持しているので、
  # each_with_nameメソッドで、値と項目名を取り出して保持する
  row.each_with_name do |val, name|
    puts "#{name}: #{val.to_s}"
  end
  puts "----------"
end

# 実行結果を解放する
sth.finish

# データベースとの接続を終了する
dbh.disconnect





蔵書管理アプリケーション(データベース版)

Ruby/DBIの操作方法

  • 接続 : .connect
  • データベースの初期化(重要)
    • 既存のテーブルを削除: @dbh.do("drop table if exists bookinfos")
    • 新しくテーブルを作成: @dbh.do( "create table bookinfos (~~);" )
  • データベースへの登録: .insert
  • 実行結果の解放: .finish


今回学んだデータベースの作成方法、および中身のテーブルの作成方法はこんなところかな。
以下データベースを"蔵書管理アプリケーション"に取り込んだコード

蔵書データへのアクセスに「ハッシュの代わりにデータベースファイルへのアクセサ」を使っている

require 'rubygems'  
require 'dbi'       
require 'date'

class BookInfo
  # 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

  # BookInfoクラスのインスタンスの文字列表現を返す
  def to_s
    "#{@title}, #{@author}, #{@page}, #{@publish_date}"
  end

  # 蔵書データを書式をつけて出力する
  def toFormattedString( sep = "\n" )
    "書籍名: #{@title}#{sep}著者名: #{@author}#{sep}ページ数: #{@page}ページ#{sep}発刊日: #{@publish_date}#{sep}"
  end
end

# BookInfoManagerクラスを定義する
class BookInfoManager
  def initialize( sqlite_name )
    # SQLiteデータベースファイルに接続
    @db_name = sqlite_name
    @dbh = DBI.connect( "DBI:SQLite3:#{@db_name}" )
    
    # テーブル上の項目名を日本語に変える
    @item_name = {'id' => "キー", 'title' => "書籍名", 'author' => "著者名", 
      'page' => "ページ数", 'publish_date' => "発刊日" }
  end

  # 蔵書データベースを初期化する
  def initBookInfos
    puts "\n0. 蔵書データベースの初期化"
    print "初期化しますか?(Y/yなら削除を実行します)"
    # 読み込んだ文字を大文字に揃える
    yesno = gets.chomp.upcase
    if /^Y$/ =~ yesno
      # Yが1文字の時だけ、初期化する


      # もしすでにこのデータベースに、テーブル'book_infos'があれば、削除する
      @dbh.do("drop table if exists bookinfos")

      # 新しく'bookinfos'テーブルを作成する
      @dbh.do("create table bookinfos (
        id              varchar(50)   not null,
        title           varchar(100)  not null,
        author          varchar(100)  not null,
        page            int           not null,
        publish_date    datetime      not null,
        primary         key(id));")
      puts "データベースを初期化しました。"
    end
  end

  # 蔵書データを登録する
  def addBookInfo
    puts "\n1. 蔵書データの登録"
    print "蔵書データを登録します。"

    # 蔵書データ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.publish_date = Date.new( year, month, day )

    # 蔵書データ1件分を、データベースに登録する
    @dbh.do("insert into bookinfos values (
            '#{key}',
            '#{book_info.title}',
            '#{book_info.author}',
            #{book_info.page},
            '#{book_info.publish_date}');")
    puts "\n登録しました。"
  end

  # 蔵書データの一覧を表示する
  def listAllBookInfos
    puts "\n2. 蔵書データの表示"
    print "蔵書データを表示します"

    puts "\n---------------"

    # テーブルからデータを読み込んで表示する
    sth = @dbh.execute("select * from bookinfos")

    # select文の実行結果を、1件ずつ読み込んで表示する
    counts = 0
    sth.each do |row|
      # rowは1件分のデータを保持しているので、
      # each_with_nameメソッドで、値と項目名を取り出して保持する
      row.each_with_name do |val, name|
        # 項目名を日本語の項目名に変換して表示する
        print "#{@item_name[name]}:"
        # 項目の値を表示する(日付や数字もあるのでto_sを使う)
        print "#{val.to_s}\n"
        end
      puts "----------"
      counts = counts + 1
    end
    
    # 実行結果を解放する
    sth.finish

    puts "\n#{counts}件表示しました。"
  end

  # 処理の選択と選択後の処理を繰り返す
  def run
    while true
      # 機能選択画面を表示する
      print "
0. 蔵書データベースの初期化
1. 蔵書データの登録
2. 蔵書データの表示
9. 終了
番号を選んでください(0,1,2,9):"
      
      # 文字の入力を待つ
      num = gets.chomp
      case
      when '0' == num
        # 蔵書データベースの初期化
        initBookInfos
      when '1' == num
        # 蔵書データの登録
        addBookInfo
      when '2' == num
        # 蔵書データの表示
        listAllBookInfos
      when '9' == num
        # データベースとの接続を終了
        @dbh.disconnect
        # アプリケーションの終了
        puts "\n終了しました。"
        break;
      else
        # 処理選択待ち画面に戻る
      end
    end
  end

end


# ここからがアプリケーションを動かす本体

# アプリケーションのインスタンスを作る
# 蔵書データのSQLite3のデータベースを指定している
book_info_manager = BookInfoManager.new("bookinfo_sqlite.db")

# BookInfoManagerの処理の選択と選択後の処理を繰り返す
book_info_manager.run