shibaraku gem をリリースしました

暫

これは何?

ActiveRecord で期間を持つ model を扱う gem です。期間限定公開や、予約公開したいときなんかに使います。

作ったのは 1 年前なんですが、ずっと社内 gem として使用していたものを rubygems.org / github.com に上げました。

USAGE

基本的な使い方

start_at, end_at のあるモデルを用意します。

create_table :campaigns do |t|
  t.datetime :start_at
  t.datetime :end_at
end

shibaraku と 1 行書くと

class Campaign < ActiveRecord::Base
  shibaraku
end

以下の scope やメソッドが生えます。

# 開催中のキャンペーン一覧を取得する
Campaign.in_time
# Campaign Load (0.6ms)  SELECT `campaigns`.* FROM `campaigns`  WHERE ((start_at IS NULL OR start_at <= '2015-10-19 21:27:58') AND (end_at IS NULL OR '2015-10-19 21:27:58' < end_at))
#=> [#<Campaign id: 1>]
# キャンペーンレコードを
campaign = Campaign.create(start_at: 1.hour.ago, end_at: 1.hour.since)
# 開催中か判定する
campaign.in_time?
# => true

もっと詳しく

チェックするカラム名 start_at, end_at は変えられます

過去分詞形でも大丈夫!

create_table :events do |t|
  t.datetime :started_at
  t.datetime :ended_at
end

class Event < ActiveRecord::Base
  shibaraku start_at: :started_at,
            end_at:   :ended_at
end
Event.in_time
# Event Load (0.3ms)  SELECT `events`.* FROM `events` WHERE ((started_at IS NULL OR started_at <= '2015-10-19 22:09:49.411904') AND (ended_at IS NULL OR '2015-10-19 22:09:49.411904' < ended_at))
# => []

テストユーザにだけ公開することができます

「テストユーザのみ test_xxx_at を見るようにしたい」という要望がありそうなので、第一引数に super_user? に応答するオブジェクトを渡すことで切り替えられるようにしています。

change_table :campaigns, bulk: true do |t|
  t.datetime :test_start_at
  t.datetime :test_end_at
end
# 開催中のキャンペーン一覧を取得する
Campaign.in_time(user)
Campaign Load (0.6ms)  SELECT `campaigns`.* FROM `campaigns`  WHERE ((start_at IS NULL OR start_at <= '2015-10-19 21:27:58') AND (end_at IS NULL OR '2015-10-19 21:27:58' < end_at))
#=> [#<Campaign id: 1>]
# 運営ユーザで開催中のキャンペーン一覧を取得する
Campaign.in_time(super_user)
Campaign Load (0.6ms)  SELECT `campaigns`.* FROM `campaigns`  WHERE ((test_start_at IS NULL OR test_start_at <= '2015-10-19 21:30:13') AND (test_end_at IS NULL OR '2015-10-19 21:30:13' < test_end_at))
#=> [#<Campaign id: 1>, #<Campaign id: 2>]

読む人にやさしい表示にできます

「10/20 0:00 まで」と表示していた場合、10/20 の 0:00 なのか 24:00 なのか分かりづらいので 「23:59 まで」とすることができます。

campaign.end_at = "2015-10-20 00:00"
I18n.l(campaign.human_readable_end_at)
# => "2015/10/19 23:59:59"

作った経緯

社内のプロダクトのコミットログを見ていたら app/models/concerns/period_module.rb が追加されていることに気がつきました。

# start_at,end_atのあるActiveRecord用module

module PeriodModule
  extend ActiveSupport::Concern

  included do
    scope :in_time, ->(time = Time.current) do
      where("start_at IS NULL OR start_at <= ?", time).where("end_at IS NULL OR end_at >= ?", time)
    end
  end

  def in_time?(current_time: Time.current)
    return false if start_at && current_time < start_at
    return false if end_at && current_time > end_at
    true
  end
end

みたいな諸々のコメントを書きかけたんだけど、どう見ても頻出ロジック。

家に帰ってうちのカミさんに「何か時間に関係する良い名前ない?」と聞いたら 歌舞伎の暫 が出てきたので gem にしました。

なぜ公開してなかったのか

キラキラネームが気になって。。

なぜ公開したのか

「shibaraku って公開しないんですか?」って聞かれたからです。

他の gem と被らない方が重要だし、他の誰かが使いそうな名前でもないしと割り切った。