Rubyで演算子を再定義したメソッドを使う
Rubyでこんな感じのクラスを作りたかった。
基準となる時間で初期化をしておいて、基準の時間に分数を追加するとその追加した分数分加算された時間が取得できる、というもの。
$ time = TodoTime.new('20:30')
$ time + 30
# 分を加算した時間が返ってくる
=> '21:00'
普通にやるとadd
みたいな名前のメソッドを用意してtime.add(30)
みたく実行することになるんだけど、より直感的にわかりやすくかけるようにしたいと思ってプラスマークを使えないかと思った。
以下のようにクラスの中で演算子を再定義するとできました。
def +(minutes)
とすると、右辺の値を引数として受け取ることができます。(この記事の下に改良版があります)
class TodoTime
def initialize(start_at_string)
s = start_at_string.split(':')
@hour = s[0].to_i
@minute = s[1].to_i
end
def +(minutes)
h = minutes / 60
m = minutes % 60
"#{(@hour + h).to_s.rjust(2, '0')}:#{(@minute + m).to_s.rjust(2, '0')}"
end
end
実行してみると以下のようになりました。素晴らしい。
irb(main):001:0> t = TodoTime.new('09:15')
=> #<TodoTime:0x0000000108a34310 @hour=9, @minute=15>
irb(main):002:0> t + 30
=> "09:45"
irb(main):003:0> t + 60
=> "10:15"
irb(main):004:0> t + 61
=> "10:16"
TodoTime
というのは今作っているサービスで必要になるクラス名です。
そこらへんはお好きなものをご利用ください。
改良版
上のサンプルだと、TodoTime.new('10:30') + 30
とかしたときに10:60
になってしまうので、改良したコードも置いておきます。
もっとスマートなやり方もあると思います。思いついた人は教えてください。
class TodoTime
def initialize(start_at_string)
s = start_at_string.split(':')
@hour = s[0].to_i
@minute = s[1].to_i
end
def +(minutes)
added_minutes = base_minutes + minutes
h = added_minutes / 60
m = added_minutes % 60
"#{(h).to_s.rjust(2, '0')}:#{(m).to_s.rjust(2, '0')}"
end
private
def base_minutes
@hour * 60 + @minute
end
end
この記事の環境情報
- Ruby 3.1.2
- 焼き鳥を食べた次の日の朝
Rubyに関する他の記事を読む
- slimでtype='application/ld+json'のscriptタグを書く
- Slack APIによる自動メッセージでユーザーグループにメンションする方法
- RubyでUnixtimeからTimeオブジェクトを生成する
- gemインストール時にUndefined symbols for architecture arm64と出たときの対応
- RubyでUTCの時刻情報をJST基準に変換する
最近の記事を読む
- Flutterでcontextを使わずにlocale情報を取得する
- Cloud RunでIAPを有効にしようとしてハマったこと
- slimでtype='application/ld+json'のscriptタグを書く
- タグマネージャーでjsのloadイベントを発火させたいとき
- mysqlコマンドを実行してERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)と言われたら