いよいよレビューアプリの最後の項目である。
ここでは以下2点を習得する。
- 配列に対して繰り返し処理を行えるようになる
- 配列から要素を取り出せるようになる
配列から要素を取り出す
既に前回レビューを配列で管理することを行った。
ここではその配列から選んだ順番の要素を取得できるようにする。
配列は順番でオブジェクトを管理していることは前回行った通り。
配列は順番を指定することでオブジェクトを取得することができる。
以下の書き方で配列オブジェクトから指定した順番の要素を取得できる。
配列オブジェクト[順番(数値)]
配列オブジェクトに続けて[](大括弧)とその中に取得したいオブジェクトの順番を指定する。
以下の配列オブジェクトplayersから「山田」を取り出してputsメソッドで表示してみる。
players = ["山田", "青木", "村上"]
配列の順番は0から始まる。
つまりplayers[1]は配列playersの2番目のオブジェクトを取得しているということになる。
よって「山田」を取得する正解はplayers[0]となる。
players = ["山田", "青木", "村上"] puts players[0] # => "山田"
指定した順番のレビューを表示させるようにする
では、実際に「レビューを読む」を実装していく。
レビューを読むのメソッドread_reviewsに書き足していく。ここで作る機能は以下の通り。
- 見たいレビューの番号を入力させる
メニューで[1]:レビューを読むを入力後
1 2
見たいレビューの番号を入力してください: # 入力待ち
- その番号のレビューのジャンル、タイトル、感想を表示する
レビューの番号を入力後
1 2 3 4 5 6
ジャンル : マンガ --------------------------- タイトル : るろうに剣心 --------------------------- 感想 : 映画もいいけどやっぱりマンガが最高! ---------------------------
レビューの一覧の表示をするには配列オブジェクトpostsの要素すべてに表示の処理を行う必要がある。
配列オブジェクトの要素すべてに共通の処理を行う
配列の要素すべてに対して共通の処理を行うには配列の繰り返しを使う。
繰り返しのためのメソッドはeachメソッドである。
eachメソッド
配列オブジェクトに対してeachメソッドを実行すると、配列に含まれる要素を順に取り出して繰り返し処理が行われる。
すなわち、配列の要素の数だけ処理が行われる。
eachメソッドの使い方は以下のように配列オブジェクトに使う。
配列オブジェクト.each do |変数| # 処理 end
変数には繰り返しごとに配列の要素が代入されていく。
試しに以下のソースコードを実行してみよう。
players = ["山田", "青木", "村上"] players.each do |player| puts player end
上のコードでは配列オブジェクトの要素を1つずつ変数playerに入れてputs playerの処理を行っている。
配列の要素は選手の名前なので、その共通項をとって変数名をplayerにしている。
配列の要素["山田", "青木", "村上"]のすべてが出力されていることが確認できる。
きちんと要素の数だけ繰り返されているかも、以下のプログラムで確認してみよう。
players = ["山田", "青木", "村上"] number = 0 players.each do |player| puts player number = number + 1 end puts "#{number}回繰り返しました"
解説動画1
https://www.youtube.com/watch?v=x-ADKbjaE-I&feature=youtu.be
解説動画2
https://www.youtube.com/watch?v=wXKBBhGx1Ts&feature=youtu.be
「レビューを読む」を入力したらレビューの一覧を表示させよう
メニューで"[1]レビューを読む"を入力したらレビューの一覧を表示させてから見たいレビューの番号を入力させるようにしてみよう。
レビューの一覧は以下のように
[順番]:"タイトル"のレビュー
というフォーマットで表示させる。
1 2 3 4 5 6 |
⇒
問題17:メニューで"[1]レビューを読む"を入力したら「レビューの一覧を表示させてから」見たいレビューの番号を入力させるようにしましょう
作業ファイル:reviewApp.rb
ヒント:配列オブジェクトpostsにeachメソッドを使って繰り返し処理を行い、全ての要素を表示させましょう
完成ソースコード
# メソッドの定義 def post_review(posts) # 変数の定義 post = {} puts "ジャンルを入力してください:" post[:genre] = gets.chomp puts "タイトルを入力してください:" post[:title] = gets.chomp puts "感想を入力してください:" post[:review] = gets.chomp line = "---------------------------" # レビューの描画 puts "ジャンル : #{post[:genre]}\n#{line}" puts "タイトル : #{post[:title]}\n#{line}" puts "感想 :\n#{post[:review]}\n#{line}" # 配列オブジェクトに追加 posts << post # postsをメソッドの呼び出し元に返す return posts end def read_reviews(posts) # リストの表示 number = 0 posts.each do |post| puts "[#{number}]:#{post[:title]}のレビュー" number += 1 end puts "\n見たいレビューの番号を入力してください:" input = gets.to_i # レビューの取得 post = posts[input] # レビューの描画 line = "---------------------------" puts "ジャンル : #{post[:genre]}\n#{line}" puts "タイトル : #{post[:title]}\n#{line}" puts "感想 :\n#{post[:review]}\n#{line}" end def end_program exit end def exception puts "入力された値は無効な値です" end posts = [] # 配列オブジェクトpostsの生成 while true do # メニューの表示 puts "レビュー数:#{posts.length}" puts "[0]レビューを書く" puts "[1]レビューを読む" puts "[2]アプリを終了する" input = gets.to_i if input == 0 then posts = post_review(posts) # post_reviewメソッドの呼び出し elsif input == 1 then read_reviews(posts) # read_reviewsメソッドの呼び出し elsif input == 2 then end_program # end_programメソッドの呼び出し else exception # exceptionメソッドの呼び出し end end
処理の流れ
最後に全体の処理の流れをおさらいする。
- まず2行目から52行目
ソースコードの開始である、2行目から52行目まででプログラムで使用するメソッドをすべて定義する。
これで52行目以降で、いま定義したメソッドを自由に使うことができる。
- 54行目
54 |
posts = []
|
メニューの表示やレビューの投稿、表示といったメインの処理があるwhile文より前で、複数のレビューを管理するための配列オブジェクトpostsを定義する。
- 56行目
56 |
while true do
|
- 58行目から61行目
アプリケーションのメインの処理である
「メニューの表示」 → 「ターミナルからの入力」 → 「入力に応じた処理」 という流れは「プログラムを終了」するまで繰り返し続ける。
そのためこれらの処理のかたまりをwhile文で囲み、条件式をtrueにすることでexitメソッドが呼ばれるまで繰り返し続けるようにする。
exitメソッドはメニューで「2」を入力(プログラムの終了を選択)すると呼ばれる。
reviewApp.rb
58 59 60 61 |
puts "レビュー数:#{posts.length}"
puts "[0]レビューを書く"
puts "[1]レビューを読む"
puts "[2]アプリを終了する"
|
メニューの表示を行う。また、今まで投稿したレビューの数を配列のlengthメソッドを使って表示する。
- 62行目
62 |
input = gets.to_i
|
メニューのうち、どれを選択するかをgetsメソッドを使ってターミナルから入力させる。
- 64行目から72行目
ターミナルから入力した値によって処理を分岐させる。処理の分岐にはif文を使う。
2を入力したときはend_programメソッドを呼び出し、その中でexitメソッドを使いプログラムを終了させる。
46 47 48 |
def end_program
exit
end
|
無効な値の場合はexceptionメソッドを呼び出し、無効な値であることを知らせる。
50 51 52 |
def exception
puts "入力された値は無効な値です"
end
|
- 65行目
65 |
posts = post_review(posts)
|
ターミナルで「0」を入力した場合、レビューを書くためのメソッドpost_reviewを呼び出す。
このとき引数としてレビューを管理する配列オブジェクトpostsを渡す。
- 2行目から23行目
post_reviewメソッドが呼ばれた場合、ターミナルからユーザーに対して新しくレビューを書くように促す。
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
def post_review(posts)
# 変数の定義
post = {}
puts "ジャンルを入力してください:"
post[:genre] = gets.chomp
puts "タイトルを入力してください:"
post[:title] = gets.chomp
puts "感想を入力してください:"
post[:review] = gets.chomp
line = "---------------------------"
# レビューの描画
puts "ジャンル : #{post[:genre]}\n#{line}"
puts "タイトル : #{post[:title]}\n#{line}"
puts "感想 :\n#{post[:review]}\n#{line}"
|
作成されたレビューは引数として渡された配列オブジェクトの最後に追加される。
19 |
posts << post
|
新しく書いたレビューが追加された配列オブジェクトをメソッドの呼び出し元に返す。
メソッドの呼び出し元では変数postsにこの返り値を代入する。
これにより新しいレビューが追加された配列オブジェクトをpostsに代入することができる。
22 |
return posts
|
65 |
posts = post_review(posts)
|
- 67行目
67 |
read_reviews(posts)
|
ターミナルで「1」を入力した場合、レビューを閲覧するためのメソッドread_reviewsを呼び出す。
このとき引数としてレビューを管理する配列オブジェクトpostsを渡す。
- 25行目から44行目
read_reviewsメソッドが呼び出されると、まず引数として渡した配列オブジェクトに入っているすべてのレビューを一覧で表示する。
25 26 27 28 29 30 31 |
def read_reviews(posts)
# リストの表示
number = 0
posts.each do |post|
puts "[#{number}]:#{post[:title]}のレビュー"
number += 1
end
|
何番目に書いたレビューかわかるように番号用の変数numberを定義する。
配列オブジェクトのすべての要素に対して繰り返し処理を行うにはeachメソッドを使う。
1 2 3 |
配列オブジェクト.each do |要素|
# 要素を一つずつ取り出して処理を行う
end
|
次に、詳細を見たいレビューの番号をターミナルから入力させる。
33 34 |
puts "\n見たいレビューの番号を入力してください:"
input = gets.to_i
|
入力された値の順番のレビューを配列オブジェクトから取り出す。
配列オブジェクトから特定の順番の要素を取り出すのは配列オブジェクト[順番]という書き方をする。
38 |
post = posts[input]
|
これで変数postには指定した番号のレビューのハッシュオブジェクトが代入されている。あとは詳細を表示させるだけ。
40 41 42 43 |
line = "---------------------------"
puts "ジャンル : #{post[:genre]}\n#{line}"
puts "タイトル : #{post[:title]}\n#{line}"
puts "感想 :\n#{post[:review]}\n#{line}"
|
これですべての処理の流れは終了である。
以上ですべての実装が完了。
70行程度のソースコードの量で立派にアプリケーションとして機能している。
アプリケーションが完成した後
これで一応は完成しましたが、まだまだこのアプリケーションには改善の余地がある。
例を挙げると以下のような部分である。
- 入力する項目を増やす。
- レビューが1つも書かれていないときに「レビューを読む」を選べなくする。
- 「見たいレビューの番号を入力してください:」で書いたレビュー数より大きい番号を入力したら再入力させる。
- レビューの描画を別メソッドとして分ける。
もちろんこれらの改善をすべて行う必要はない。
しかし自分で考えてプログラムを組むことは非常にレベルアップに繋がるため今後挑戦していきたい。