素のRubyを用いてちょっとした業務カイゼンアプリを作ってたのだが、そのときにほんの少しだけ当たった問題
※ 鬼基本的な内容です
while
はnil
を返します
※単一ファイルで書かれたスクリプトを想定しています
「渡ってきた日付(date
オブジェクト)が土日祝のいずれかに当てはまるかを判定し、当てはまる場合は平日になるまで1日ずつ日付を加算する」という処理を作っていた
- 日付を加算するには
date
オブジェクトに+ 1
をしていけばよい - 土日の判定はDateクラスにある
saturday?
やsunday?
が、日付が土日の場合にtrue
を返す - 日本の祝日判定は
HolidayJp
というGemのメソッドを使えば同じように祝日に当てはまるときtrue
を返す - 上記が
true
のときに日付を1日加算したい
→ 条件がtrue
のときに処理をループさせることができるwhile
使えばいいのでは? と思い以下のような処理を書いた
while day.saturday? ||
day.sunday? ||
HolidayJp.holiday?(day)
day += 1
end
実際に試してみる
# 日曜日
day = Date.new(2024, 8, 11)
=> #<Date: 2024-08-11 ((2460534j,0s,0n),+0s,2299161j)>
while day.saturday? ||
day.sunday? ||
HolidayJp.holiday?(day)
day += 1
end
p day
=> #<Date: 2024-08-12 ((2460535j,0s,0n),+0s,2299161j)>
# ちゃんと平日である8月12日㈪が返ってきた!
期待した値が返ってきたのでOK
ただこの処理はスクリプト内のいたるところで使用していたので、メソッドにしたいと思いメソッド化した
# 日曜日
day = Date.new(2024, 8, 11)
def check_weekend_return_weekday(day)
while day.saturday? ||
day.sunday? ||
HolidayJp.holiday?(day)
day += 1
end
end
weekday = check_weekend_return_weekday(day)
p weekday
「ま、ふつうになんも問題ないやろ」と思ってたら。。。。。。。。。
nil
ohhhhhhhhhhhhhhhhhhhhhhhhh
なぜだ、、、と思ってリファレンス見てみたら普通に答え書いてあった
while は nil を返します
公式: 制御構造 (Ruby 3.3 リファレンスマニュアル)
Rubyはメソッドの最後に評価された式が戻り値になるのでwhile
自体がnil
を返すならnil
が返ってくるのは当たり前だ。。。。
メソッド内でwhileで処理した値を返したい場合はbreak
か戻り値を明示させよう
なので修正
公式には以下のように書いてある
また、引数を伴った break により while 式の戻り値をその値にすることもできます。
公式: 制御構造 (Ruby 3.3 リファレンスマニュアル)
というわけで返したい値にbreak
を明示させておこう
# 日曜日
day = Date.new(2024, 8, 11)
def check_weekend_return_weekday(day)
while day.saturday? ||
day.sunday? ||
HolidayJp.holiday?(day)
break day += 1 # breakを明示
end
end
weekday = check_weekend_return_weekday(day)
p weekday
=> #<Date: 2024-08-12 ((2460535j,0s,0n),+0s,2299161j)>
ちゃんと返ってきた!
当然だがbreak
使わないでメソッドの最後に戻り値を明示させるだけでもOK
# 日曜日
day = Date.new(2024, 8, 11)
def check_weekend_return_weekday(day)
while day.saturday? ||
day.sunday? ||
HolidayJp.holiday?(day)
day += 1
end
day # メソッドの最後に戻り値を明示
end
weekday = check_weekend_return_weekday(day)
p weekday
=> #<Date: 2024-08-12 ((2460535j,0s,0n),+0s,2299161j)>
基本的なことだが忘れないようにしよう