Ruby修行日記 カレンダープログラムを作る(とりあえず作成編)
いっぱしのプログラマーになるべく、プログラミングの修行をしています。(主にRuby) 今日はその修行のひとつ、カレンダープログラムを作る をやってみましたので試行錯誤の流れを残したいと思います。(日記です) この回は仕様を実直に(実直すぎるほど)プログラミングしたのでツッコミどころ満載プログラムとなります。(もちろんその後リファクタリングもします)
Rubyでカレンダープログラムを作る
●カレンダープログラムとは? 要件まとめ
<必須要件>
- Macのターミナルで動かすcalコマンドと同じような見た目にすること
こんなやつ
- コマンドのオプションとして
-m
、-y
を設定-mは月を指定でき、-yは年を指定できる - オプションを指定しない場合は、現在の月、年が表示される。
- 1970〜2100年まで正しく表示される。
<あるとなお良い>
- 今日の日付の部分の色が反転する
- どのような引数が与えられようが、cal コマンドと同じ表示結果になる
●カレンダープログラムってどんなものか仕様を細かく分けてみる
<基本仕様>
- 日曜日から土曜日まで数字が7つ順番に並ぶ
- 土曜日で次の行に改行する
- 月によって日数が変わる(30日、31日)
<オプション>
- 月と年を指定できるオプションを実装する
- 今日の日付の色を反転させてわかるようにする
●カレンダープログラムの仕様を作り込んでいく
1.日曜日から土曜日まで数字が7つ順番に並ぶ
これを作っていく。
まずはカレンダーもどきを作ってみる。
↓
カレンダーっぽいものが表示された(あたりまえ)
次に数字を自動で表示させたい。 プログラムを呼び出したときに入力したときの月のカレンダーとしたいので、 まずは入力時の月の日付を並べるプログラムを作ってみる。
ライブラリからDateクラスを呼び込み、メソッドを使って、year、month、dayに入力したときの年、月、日にちを代入する。 その月の最初の日と最後の日を指定したいので、month_start_dayとmonth_last_dayを作る。 とりあえず、ここでmonth_start_dayからmonth_last_dayを配列で表示させてみる。
年月日、その他情報が並んでしまった。
日付だけを並べるようにしないと。
.day
を使うとdateから日にちだけを抽出できるようなので、繰り返し処理で.day
をくっつけて出力させてみよう。
↓
横並びができた。
土曜日で改行してカレンダーっぽくする
横並びを土曜日で改行してカレンダーっぽい見た目にしたい。
Dataクラスにsaturday?
という、レシーバが土曜日だったらtrueを返すメソッドがあるようなので、これを条件分岐に入れてみる。
↓
おっ ちょっとカレンダーぽくなってきた 見た目が悪いので、日にちの間と、日にちが一桁だったときに数字の前にスペースを入れるプログラムを追加してみる。(ネスト深い?) あとついでに年月と曜日も表示させてみる。(putsで入れただけ)
↓
だいぶ見た目は良くなってきた。
あとは月の最初の週をうまく表示させたいところ。
2.月の最初の週の見た目を整える
しかし、どうやるんだこれ??🤔
1日の位置が重要だけど、1日をどうやって動かすか…。
理屈としては、1日の曜日ごとに位置を指定するイメージでいいのかな…。
であれば…。Dataクラスに.cwday
というレシーバの曜日を数字として返す(例:月曜の場合1を返す)メソッドがあったから、そのメソッドを使って1日の曜日ごとに位置を変更する条件分岐の構文を書いてみる。
こんな感じ
…。 なーんか、あまりかっこよくない感じ。。 とりあえず動きを見てみる。
ぐはっ! カレンダーを貫いた🤤 あー、土曜日以外はprintで横並びにしているから1日がちょうど土曜日だと折り返すプログラムにひっかからないのか…。 なら無理やりこうやって!😠
↓
修正はされた…が… だんだん、対処療法的なプログラムになってきている。やばいか…? ・・・ しかし、いいプログラムが思いつかないのでとりあえずこれで走ってみる。 他の年月でも動きを確認。 2021.10月
2020.4月
良さそう。
3.オプション機能をつけていく
月と年を指定できるオプションを実装する
-y 数字
の入力で年の指定を、-m 数字
の入力で月の指定をできるようにしたい。
optparseライブラリを使うとコマンドラインのオプションが実装できるとのこと。 リファレンスを読むと、
ARGV の機能 optparse を require すると ARGV に OptionParser::Arguable の機能が加わります。以下の書き方ができるようになります。 OptionParser::Arguable#getopts はオプションを保持した Hash を返します。
# sample.rb の内容 require 'optparse' params = ARGV.getopts("a:b:", "foo", "bar:") p params
この sample.rb を実行すると
$ ruby sample.rb -a 1 --foo --bar xxx {"a"=>"1", "b"=>nil, "foo"=>true, "bar"=>"xxx"}
とのことで、ARGV.getoptsにy:
とm:
を引数に設定すればオプションにできそう。
続きは次回!!