[Rails] Bitwise Operator(ビット演算)を用いた曜日の管理

Cronのように曜日を指定してジョブを発動するスケジューラを作成していて、外部にこれを保持するテーブルを作るのはセンスがないし、mondayからsundayのカラムを作るのも無駄に感じたので、ビットを使って曜日を表現し、これを用いて曜日の判別をしようと思いました。 Railsでビット演算を用いたチェックボックスのフラグ管理をしてみたを多いに参考にさせていただきました。

具体的には下記のように表現します。

  • 月曜日 0b1
  • 火曜日 0b10
  • 水曜日 0b100
  • 木曜日 0b1000
  • 金曜日 0b10000
  • 土曜日 0b100000
  • 日曜日 0b1000000

1100101の場合、月曜日、水曜日、土曜日、日曜日が選択されている状態です。 1バイト以下の7bitで表現できるのでメモリにもストレージにも優しいですね。

Migrationファイルを作り、DBカラムwday作成。

$ rails g migration AddWdayToTimer wday:integer
$ vi db/migrate/20180818*
# limitを追加し、最小限1バイトのtinyint(dbによりますが)を作成
 t.integer :wday, limit: 1

View/Controllerは下記のようになりDBには整数で保存されます。

  <div class="field">
  <% %w(Mon Tue Wed Thu Fri Sat Sun).each_with_index do |v, i| %>
    <%= form.label :wday  do %>
      <%= form.check_box :wday, {multiple: true, checked: !form.object.wday.nil? && (form.object.wday & 2**i != 0)}, 2**i %>
      <%= v %>
      &nbsp
    <% end %>
  <% end %>
  </div>
  def create
    @timer = Timer.new(timer_params)
    @timer.wday = timer_params[:wday].map(&:to_i).inject(&:+)

これを使う時に、&し判定します。 0でない場合は、曜日フラグが立っているということです。  僕の遠い昔のアセンブリ言語の記憶が正しければbitのAND計算は鬼早いはずです。

[2] pry(main)> Timer.last.wday
  Timer Load (0.2ms)  SELECT  "timers".* FROM "timers" ORDER BY "timers"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> 21
[3] pry(main)> Timer.last.wday & 0b1 #月曜日
  Timer Load (0.1ms)  SELECT  "timers".* FROM "timers" ORDER BY "timers"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> 1
[4] pry(main)> Timer.last.wday & 0b10 #火曜日
  Timer Load (0.1ms)  SELECT  "timers".* FROM "timers" ORDER BY "timers"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> 0
[5] pry(main)> Timer.last.wday & 0b100 #水曜日
  Timer Load (0.1ms)  SELECT  "timers".* FROM "timers" ORDER BY "timers"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> 4

DBに対しては、月曜日にフラグがたってるRowを取り出すには、

Timer.where('wday & ? > 0', 0b0000001)

ビットフラグの管理はアプリケーション側にその管理を要求するのしっかりドキュメントしておく必要がありますので、忘れずにコメントを書いておきましょう。

google-api-ruby-clientを使ってG Suiteのユーザを作る方法

ドキュメントがなくていつもかなり悩むのでメモしておく。

セムラーイズムを読んで

MAVERICKというのが原著のタイトル。@dhhがオススメしていたこともあり読んでみました。

要点を言えば、硬直化した官僚体質な組織を民主化したという話。 響いたことを箇条書きにすると

  • 偉くなっても特権をなくす(社長室、社用車など)
  • 小さな組織にする
  • 委員会に権限移譲
  • 同僚による常識を用いた評価
  • 必要のない仕事をなくす(秘書など)
  • 同心円状の組織体制

今の会社は官僚体制にもならない小さな組織。それでもピラミッドを作ってしまう。 ピラミッド構造自体は運用しやすい。それ自体が悪なのではなくて、階級があるような雰囲気がいけないのかもしれない。 フラットな雰囲気な会社のままでいれたらなって思う。

Delegation(権限移譲)も難しい課題。 Delegationすることで若いものが育つのは頭でわかっていてもなかなかできない。 自分でなくてもできることは多いけど、やはり心配になってしまう。 権威移譲のせいでシステムが落ちたら、復旧するのは自分だからか。 そこまで任せられるような人がいればいいだけなのかもしれない。

会社とはなんだろう。

収入を得るだけのものだとつまらない。

会社への貢献と自分の将来の積集合がゴールになるような組織にしたいね。

javascriptでTabキーを無効にする方法

メモ。

window.onkeydown = function(e) {
  if (e.keyCode == 9)
    return false; // Disable Tab!
}