0
0

More than 3 years have passed since last update.

今が特定の時間範囲内かどうやって判断する?(システム運休期間とか)(リファクタリング)

Last updated at Posted at 2021-09-01

やりたいこと

現在時刻が特定の時間範囲内かどうかをスマートに判断したいです。
例えば、特定の時間帯、ユーザーグループごとシステムへのアクセスや一部機能を制限するのに使えるかと思います。

今日も弊社先輩のリファクタリングに息を呑んでしまったのでメモメモ。

Modelは例えばこんな感じ↓
「利用一時停止」をsuspensionとしてその期間を持たせています。

# == Schema Information
#
# Table name: user_groups
#
#  id                    :bigint           not null, primary key
#  name                  :text             not null
#  description           :text
#  created_at            :datetime         not null
#  updated_at            :datetime         not null
#  suspension_started_at :datetime
#  suspension_ended_at   :datetime

環境

ruby 3.0.0
Rails 6.0.3

実装!

Ruby歴8ヶ月の人の実装例

def suspension?
  return if suspension_started_at.nil? || suspension_ended_at.nil?

  current_time = Time.current
  current_time >= suspension_started_at && current_time < suspension_ended_at
end

:sweat_smile:

リファクタリング例

def suspension?
  return false if suspension_started_at.nil? || suspension_ended_at.nil?

  current_time = Time.current
  (suspension_started_at...suspension_ended_at).cover?(current_time)
end

最終行の可読性がグッと上がった印象です。
ポイントを以下に3つまとめておきます。

?で終わるメソッド

先輩から「?で終わるメソッドは毎回Booleanを返すべき」とレビューが返ってきました。それを読んだ僕は、「何をおっしゃいます。このメソッドの最終行はちゃんとtrue/falseを返しますよ?ふふ」と思ったら...あ、一行目が...!参りました!:bow:というわけで、return falseにしました。

範囲演算子...

...範囲演算子で、x以上y未満という範囲オブジェクトクラスのインスタンスを生成することができます。ちなみに今回はドット2つだけど..も見かけるような?:confused:と思ったら、そちらは未満ではなく以下の意味になるそうです。下記、Rubyのリファレンスマニュアルから引用です。

Rubyリファレンスマニュアル
Range.new(1, 5) # 1 以上 5 以下
1..5            # 同上
1...5           # 1 以上 5 未満

cover?メソッド

cover?は、include?と似ていますが、違いがあるようで、上のコードをRspecテストの中で単純に置き換えてみるとテストはパスしますが、下記のような注意を受けました。

DEPRECATION WARNING: Using Range#include? to check the inclusion of a value in a date time range is deprecated. It is recommended to use Range#cover? instead of Range#include? to check the inclusion of a value in a date time range. (called from suspension? at /Users/kakudaisuke/.../app/models/user_group.rb:83)

datetimeの範囲に値が含まれているかをチェックするにはinclude?は非推奨だよってことですね。ちなみに..にするとこのwarningは出現しませんでした。

cover?include?両者の違いは、ドキュメントに書いてありました↓

Range#include? と異なり <=> メソッドによる演算により範囲内かどうかを判定します。 Range#include? は原則として離散値を扱い、 Range#cover? は連続値を扱います。(数値については、例外として Range#include? も連続的に扱います。)
(Rubyリファレンスマニュアルより https://docs.ruby-lang.org/ja/latest/method/Range/i/cover=3f.html)

最後に

何かご指摘あれば、ぜひよろしくお願いします。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0