Firebase Weekly 第3号をまとめました

www.getrevue.co

週に1度のブログ更新です。 Firebase Weekly 3号をまとめました。個人的には、メルカリさんがメルカリチャンネルで Realtime Database 使ってるよ。ってお話が、これからの自分の仕事の仕方を早めに変えてくれて嬉しいなと思いました。ちょっと説得力が違います。

個人的には、 jQueryRails のときのような……、食器洗い洗浄機のような……、ルンバのような……、そういう種類の、業界だけでなく自分のライフスタイルや考え方への強い変化を感じています。

Firebase Weekly 第2号をまとめました

www.getrevue.co

ちゃんと2号も出しました。 Firestore と DevFest Tokyo のおかげです。

DevFest Tokyo は招待いただいてたのに( Firebase の話が全然ねえ)と思って申し込みすらしなかったんですが、結構トークがあったみたいで…。ないと思った僕は何を見ていたんだろうか。何も見ていなかったんでしょう。

まとめてて思ったことは、みんな iOS かブラウザだなってことです。

Firebase Weekly を作ってみました

Firebase の日本語の情報ってなかなか集めるの大変だなーと思っていたので、 iOSAndroid や Swift や Kotlin みたいに Firebase Weekly みたいなのないかなあと検索したら、なかったので、えーって思って作りました。

www.getrevue.co

サービスは Swift Weekly の使ってるところですが、中身は日本語のものを集めました。とりあえず1週間分。

次回は英語と動画の追加を予定してます。自分以外に一人でもお求めの方がいれば…と思ってます。誰もみてなくても3号までは必ずやります! よろしくお願いいたします。

近況

最後の記事からほぼ3年経ちまして、その間にすっかりインフラや Rails には縁が遠くなり、今は Firebase と Android アプリと iOS アプリを同時に全部やって作るというこれまた楽しいお仕事をさせていただいています。

その辺りのことは、試験的に Medium に書いてみているのですが、いやーこれが自分が SNS に投げた URL 以外からの流入がびっくりするほどない! Google.co.jp のランクなんかびっくりするほど上がらないです。クロール間隔もすごくゆっくり。

medium.com

日本におけるはてなと Qiita のエコシステムは素晴らしいものであるなあと実感する日々です。乗っかるだけである程度の流入があります。

Medium も英語で書けばかなりいいんですよね。ということは逆もまた然りなのか……。

自分で検索していても、日本語の Firebase Database の話とか、自分みたいなふわっとしたレイヤーからリーチする Rx の話とか、もうちょっとあってもいいなと思うので、ある程度やってダメならまたここに戻ってこようと思います。

stop したり init スクリプトを削除したりすると apache2 cookbook なんかが仕込む delayed な reload アクションがこけて converge 全体が失敗する

また Chef のしょうもない話で恐縮なのですが、表題のようなことに悩んでおりました。

実はこれ、単に次の起動時に立ち上がってきて欲しくないという要求から始まったもので、それだけなら stop も削除もせず、立ち上げたまま chkconfig off でも service リソースで止めるでもしておくだけでいいわけですが、なんかこー…勝手に上がって欲しくないときって、あらかじめ明示的に止めたいじゃないですか、私の手で。特に docker なんかだと supervisord 使いたいじゃないですか。使わない(使って欲しくない)のが明らかなら upstart の config ファイルや init ファイルも消したい……はやり過ぎかもしれませんが、そういうときにどうするかっていうのを

delayed されたものをキャンセルしてえー

とか結構長いこと悩んで放置していたのですが、どこだったか誰かのレシピ見てて

あ…… web_app リソースの後に stop する delayed なアクションをセットするんだ……

という学びがあった次第です。

web_app 'oogatta' do
  docroot   /var/www/oogatta
  server_name    'oogatta'
end

bash 'cleanup_services' do
  code <<-EOH
    if [[ -e /etc/init.d/httpd ]]; then
      service httpd stop
      chkconfig httpd off
      pkill httpd
    fi
  EOH
  action :nothing
end

log 'set cleanup timer' do
  level    :info
  notifies :run, 'bash[cleanup_services]', :delayed
end

気がついてみると実に当たり前ですね。

EC2 の Amazon Linux を launch するとき authorized_keys に公開鍵が注入されるユーザを変更したい

変更したくないですか? 私はしたかった。いい加減 recipe 作り込んだし、 ec2-user じゃねえだろって思ってた。例えば oogatta とかにしたかった。でもわからなかった。

今日、 @ainame と話してたら「それは CloudInit です」と教わった。 CloudInit …!

その通りだった。 /etc/cloud/cloud.cfg.d/00_defaults.cfg を開くと

# A set of users which may be applied and/or used by various modules
# when a 'default' entry is found it will reference the 'default_user'
# from the distro configuration specified below
users:
  - default

と書いてあり、その通り system_info の中を見ると default_user がいた。

# System and/or distro specific settings
# (not accessible to handlers/transforms)
system_info:
  # This will affect which distro class gets used
  distro: amazon
  distro_short: amzn
  # Default user name + that default users groups (if added/used)
  default_user:
    name: ec2-user
    lock_passwd: true
    gecos: EC2 Default User
    groups: [ wheel ]
    sudo: [ "ALL=(ALL) NOPASSWD:ALL" ]
    shell: /bin/bash

めっちゃ ec2-user って書いてある……。

さっそくこの一歩前の recipe で

if platform?('amazon')
  bash 'switch default user' do
    code <<-EOH
  sed -i -e '{s/name: ec2-user/name: oogatta/;}' /etc/cloud/cloud.cfg.d/00_defaults.cfg
    EOH
  end
end

ぶち込んでやりましたら、望んでいたとおりになった……。 lock_passwd とか passwordless sudo とかそのままでいいのかってのはあとで調整として、これで packer とか test-kitchen とか ssh 接続をラップするツールを横断している時に(今はどのユーザとどの鍵で入れるんだっけ……?)といちいち認知負荷を強いられることがなくなり、今夜は健やかな夜を過ごせそうです。 @ainame サンタさん、ありがとう。

これでミッチェル先生が packer の ssh 鍵交換周りで本気出してない理由わかったす。

Rails の n.months って Date の加減演算の引数になると月ごとの日数考慮するんだなあ

知らなかったというか、それについて真面目に考えたことが無かった。

コード

class HogeTest < Test::Unit::TestCase
  def test_hoge
    Timecop.freeze Date.new(2014, 11, 1) do
      assert_equal Date.new(2014, 11, 1), Date.today
      assert_equal Date.new(2014, 12, 1), Date.today >> 1
      assert_equal Date.today + 1.months, Date.today >> 1
      assert_equal Date.today, Date.today + 1.months - 30.days
      assert_equal 30.days, 1.months
    end

    Timecop.travel Date.new(2014, 12, 1) do
      assert_equal Date.new(2014, 12, 1), Date.today
      assert_equal Date.new(2015, 1, 1),  Date.today >> 1
      assert_equal Date.today + 1.months, Date.today >> 1
      assert_equal Date.today, Date.today + 1.months - 31.days
      assert_equal 30.days, 1.months
    end

    assert_equal Date.new(2015, 1, 1),  Date.new(2015, 1, 1) + 2.months - 59.days
    assert_equal Date.new(2015, 2, 1),  Date.new(2015, 2, 1) + 3.months - 89.days
  end
end
$ RAILS_ENV=test rbbe rails r hoge.rb

ぽてっと 1.months って書いた場合はいつも固定で30日が来るんですが、加算の左辺が11月の場合30日になって、12月の場合31日になる。2015年の1-2月の2ヶ月だと59日で、2-4月の3ヶ月だと89日。

いつも定数的に使ってるけど、同じスコープ内で同じ表記して違う値が戻ってくるんだなあ。31日から1ヶ月後とやって次の月に31日が無い場合30日に戻るので、「次の月の同じ日に行く!(その日が無かったら有効なとこまで戻る!)」指向なのでありました。

ActiveSupport::Duration 同士の加減算では年月日の情報が保持されている

ちなみに 1.month + 1.days こんな感じに左辺としても使うと呼ばれるのは Duration#+ でこれはもちろん30日固定…なんだけど、この加算で生成された Durationインスタンスは内部的に「月が1で日が1です」って情報を抱えていて、これを Date に対して加算しようとするとやっぱり30日になったり31日になったり28日になったりする。

    duration = 1.months + 1.days
    assert_equal Date.new(2014,11,1) + duration, Date.new(2014,11,1) + 31.days
    assert_equal Date.new(2014,12,1) + duration, Date.new(2014,12,1) + 32.days

これは、自分アホなんで、間違いなく定数として使ってバグらすパターンですね。

実装

Date#+ はその実 Rails が拡張した Date#plus_with_duration で、これが最終的にネイティブの Date>> を使っておられる。

TimeDate はいかにも Ruby ネイティブの少女っぽいふりして Rails によってすっかり女に変えられているので、裏表あって怖い。