Alacritty というターミナルエミュレーターを試している

iTerm 2 が重いなぁ、と思って調べていたら、Alacritty というターミナルエミュレーターが爆速という記事をみかけたので試している。

github.com

Alacritty の特徴は GPU で描画するため高速、Rust で書かれたクロスプラットフォームなターミナルエミュレーターという認識。

Mac の場合、Homebrew でインストールできる。

brew cask install alacritty

感想

良いところ

  • とにかく描画が速い
  • iTerm 2 は CPU の使用率が高めだったのだが、Alacritty はあまり使っている様子がない。例えば Activity.app で確認すると Avg Energy Impact は iTerm 2 は 3.2 だが Alacritty は 0.27 と低い。
  • 設定を YAML で書ける

微妙なところ

  • 日本語が確定するまで表示されない (Google 日本語入力の問題かも?)
    • f:id:cho_co_by:20200108082537p:plain
  • マウスをダブルクリックした時の選択単位が Terminal.app や iTerm 2 と異なる
    • aaa@bbb という文字列があるとして、bbb 部分をダブルクリックすると iTerm 2 は bbb が選択されるが、Alacritty は aaa@bbb が選択される
    • (2020/01/15 追記) selectionsemantic_escape_chars@ を追加することで選択する単位を変更できた
  • ダブルクリックで文字列をコピーできない
    • (2020/01/15 追記) selectionsave_to_clipboardtrue に変更することでコピーできるようになった

とにかく描画が速いのが素晴らしく、微妙なところのほとんどは慣れれば気にならなさそう。 タブが無い件については tmux を使っているので問題にならなかった。

設定周り

設定を YAML で書けるところがよい。設定は以下に置いている。

dotfiles/.alacritty.yml at master · chocoby/dotfiles · GitHub

また、設定ファイルのサンプルは Alacritty の Releases にある。

今のところ、フォント以外で手をいれているのはショートカットくらい。

key_bindings:
  - { key: Return,  mods: Command,        action: ToggleFullscreen }
  - { key: N,       mods: Command,        action: SpawnNewInstance }
  • Command + Enter: フルスクリーンを切り替える
  • Command + N: 新しいウィンドウを開く
    • たまに tmux の session を複数開きたくなるので

何かあったら追記するかも。 しばらくは Alacritty を試してみようと思う。

Active Job の deserialize では default_scope は適用されない

Active Job の deserialize では、モデルの default_scope は適用されないという罠にハマったのでメモ。

バージョン情報

  • Rails v6.0.2.1
  • globalid v0.4.2

概要

例えば、以下のモデルがあるとします。 default_scope には、status:active のレコードのみ取得する条件を指定しています。

class Post < ApplicationRecord
  default_scope { where(status: :active) }
end

モデルのオブジェクトを Active Job のキューに追加します。オブジェクトは gid://foo-bar/Post/123 のような Global ID に serialize されて、キューに保存されます。

NotifyPostJob.perform_later(post)

そして、キューが実行されるまでに status:inactive など他の値が入ったものとします。

このキューが Active Job で実行されて、キューに含まれる Global ID からモデルのオブジェクトを deserialize する時に、default_scope は効きません。 僕は ActiveJob::DeserializationError が発生するものだと思っていました。

対応方法

deserialize 時に default_scope を考慮するパターンと、Job 内で考慮するパターンがあると思います。

deserialize 時に考慮するパターン

globalid gem のコードを確認すると、デフォルトでは Global ID からレコードを取得する際に UnscopedLocator という Locator が使用されます。 これは名前の通り、scope を解除してレコードを取得する処理になっています。

        def locate(gid)
          unscoped(gid.model_class) { super }
        end

        private
          # 省略

          def unscoped(model_class)
            if model_class.respond_to?(:unscoped)
              model_class.unscoped { yield }
            else
              yield
            end
          end

https://github.com/rails/globalid/blob/v0.4.2/lib/global_id/locator.rb#L153-L171

UnscopedLocatorBaseLocator を継承しています。

BaseLocator は、シンプルにモデルの find メソッドを呼び出す処理になっています。 この Locator では、default_scope が考慮されます。

        def locate(gid)
          gid.model_class.find gid.model_id
        end

https://github.com/rails/globalid/blob/v0.4.2/lib/global_id/locator.rb#L128-L151

従って、deserialize の挙動を変えるのであれば、UnscopedLocator ではなく BaseLocator を使用するように変更します。

config/initializers/globalid.rb:

# "foo-app" はアプリケーション名
GlobalID::Locator.use "foo-app", GlobalID::Locator::BaseLocator.new

Job で考慮するパターン

もう一つは default_scope を頼るのではなく、Job 内で処理するべきオブジェクトかを確認するパターンです。

  def perform(post)
    return unless post.active?

    # 処理
  end

どちらを採用するかは結構悩みましたが、特別なことがない限り default_scope は適用してほしいので、Locator を変更する方法で対応しました。

経緯

経緯を調べたところ、2015/08 時点では default_scope は考慮されていたようです。

github.com

2016/01 に UnscopedLocator がデフォルトの Locator になったようです。

github.com

github.com

なんだか副作用な気もしますが... 特に Issue が作られていないところを見ると、特に困っている人はいないのか、そもそも使っている人が少ないのか...

Apollon Audio NC800 SL の電源スイッチを取り替えた

Apollon Audio NC800 SL という Hypex NCore NC500 が載っているパワーアンプを購入しました。

www.apollonaudio.com

ところが、電源スイッチがオンのまま戻らないという、ちゃんと動作確認しているのかと不安になる問題が起きました。 メーカーに問い合わせたところ、新しい電源スイッチを送ってもらうことになったので、それを取り替えた記録です。

以下が問題のスイッチです。押したら電源がオンになり、もう一度押したら電源がオフになる方式のスイッチです。 初めて電源を入れた時に押し込めなくなり、それ以来電源がオフにならない、という状態になっています。(アンプ裏の主電源スイッチで電源を操作することは可能)

f:id:cho_co_by:20191006131457j:plain

送ってもらったスイッチ。

f:id:cho_co_by:20191006131705j:plain

天板のネジを外します。

f:id:cho_co_by:20191006131958j:plain

スイッチのコネクターを取り外します。

f:id:cho_co_by:20191006132442j:plain

ナットを緩めるとスイッチを取り外せます。

f:id:cho_co_by:20191006132600j:plain

左が新しいスイッチ、右が古いスイッチ。 どちらも電源をオンにした状態ですが、古いスイッチのほうが深くまで押し込まれています。

f:id:cho_co_by:20191006132806j:plain

新しいスイッチを取り付けました。取り付けは取り外しと逆の手順です。

f:id:cho_co_by:20191006133038j:plain

動作確認。電源オフの状態。

f:id:cho_co_by:20191006133216j:plain

電源オンの状態。良さそうです。

f:id:cho_co_by:20191006133228j:plain

まとめ

このアンプについての感想は後で書くかもしれないし書かないかもしれません。 一言でいうと、アンプモジュールに Hypex NCore NC500 を使っているので音質は問題なさそうだけど、品質やサポートについては期待できないな、という感じです。

このスイッチが届くまでにも色々あって、「スイッチを送ったよ!5 -7 日ぐらいで届くと思うから、届いたら詳しい手順を送るから教えてね」 → 届いたのが 20 日後。追跡番号を確認してみたら発送されたのはそのメールから 10 日後だった。届いてからも「スイッチが届いたよ」と送ったら「手順で分からないことがあったらメールしてね!」だけ返ってきた。手順が必要ないほど簡単だったのでいいのですが...

アンプ本体が送られてきたときも追跡番号が間違っていて、到着するまで追跡できなかった、ということもありました。 海外ガレージメーカーに期待するのが間違いな気もします。

ギャラリー

天板を開けたついでに色々撮ったのでアップ。

f:id:cho_co_by:20191006134530j:plain
中身は結構きれいに見えますがどうでしょう

f:id:cho_co_by:20191006134625j:plain
天板のネジのナットはレール上で動かせるようになっていました。

f:id:cho_co_by:20191006135005j:plain
Hypex NCore NC500 のアンプモジュール

f:id:cho_co_by:20191006135217j:plain
インプットバッファーボード。オペアンプには「Sparkos SS3602」か「Sonic Imagery 994」を選べます。温度感があるという「Sparkos SS3602」にしました。

RubyGems からメンテナンスしていない Gem を削除した

RubyGems からメンテナンスしていない、というか作ろうと思って放置していた Gem を削除しました。

Gem を削除する方法は以下のページに記載があり、gem yank コマンドで削除できます。*1

help.rubygems.org

OTP コードが入力できない

多要素認証を設定していると、gem yank コマンドを実行できない問題に遭遇しました。OTP コードを聞かれませんし otp オプションも通りません。

% gem yank fake_delete -v 0.0.1.alpha.1
Yanking gem from https://rubygems.org...
You have enabled multifactor authentication but no OTP code provided. Please fill it and retry.
% gem yank fake_delete -v 0.0.1.alpha.1 --otp 123456
ERROR:  While executing gem ... (OptionParser::InvalidOption)
    invalid option: --otp

調べてみると、コードベースに対応したコードはあるものの、まだリリースされていないそうです。

github.com

github.com

仕方がないので、RubyGems の「MFA Level」を一時的に「UI」に変更し、再度コマンドを実行すると無事に実行できました。

% gem yank fake_delete -v 0.0.1.alpha.1
Yanking gem from https://rubygems.org...
Successfully deleted gem: fake_delete (0.0.1.alpha.1)

削除すると、RubyGems のページが以下のようになりました。 100 日後にネームスペースが開放されるそうで、それまでは新たなバージョンを push したり、オーナーを変更することができるそうです。

f:id:cho_co_by:20190929143417p:plain

何の Gem を作っていたのか

いい機会なので、何の Gem を作っていたのかメモしておきます。

  • fake_delete: 論理削除を行う Gem で、deleted_at カラムの型を timestamp にする (未削除は 0, 削除はタイムスタンプ) ことでデータベースのユニーク制約を効かせようと考えたもの
  • haguruma: あまり覚えていないが、GitHub などから受け取った Webhook を整形して Slack など複数の送信先に通知することを考えていたもの

*1:サポートフォーラムで依頼して削除してもらう方式かなと思っていました

AirPods を新調した

1 世代目の調子が悪くなってきたので 2 世代目を購入した。2017/8 に購入したので 2 年間頑張ってくれた。

何が不調だったかというと、

  • バッテリーがヘタってきた。1 時間ぐらいで電池切れのアラートが鳴るようになってきた
  • iPhone や MacBook 間の切り替えに時間がかかったり、切り替えられなくなってきた

購入したのはワイヤレス充電できるタイプ。今のところ快調。また、遅延も改善されているようだ(ポケストップをタップした時とか)

AirPods は

  • iPhone, iPad, MacBook でシュッとソースを切り替えられる
  • とりあえず良い感じの音で聴ける

というところがよい。 使っている人増えましたね。

「第一回 Ruby で LT しちゃわナイト」に参加&LT した

昔の同僚が「Ruby で LT しちゃわナイト」というイベントを開催するということで、LT させてもらいました。

corundum.connpass.com

LT した

speakerdeck.com

僕が開発している jp_prefecture gem をどうやってメンテナンスしていくか、という話で LT させてもらいました(誰得な話題ですね、ごめんなさい)。 スライドを作っている間に考えが整理できたので良かったです。変更点については改めて記事にしようと思います。

とても緊張していましたが、2 番目の発表だったので、発表後はリラックスして他の方の発表を聞くことができました。

改善点としては、他の方が聞きたくなるような内容にするのはもちろんのこと、イベントが始まる前にプロジェクターのチェックをしておけばよかったです。 いざ発表という時にミラーリングになってしまい、手元のディスプレイでタイマーの確認ができなかったので。

各発表の感想

簡単に各発表の感想を。

  • kbaba1001 さん
    • レガシー Rails 改善ガイド」を書いた方で、いくつか改善パターンを説明されました。
    • Sonic Pi というライブコーディング環境について紹介されました。音楽制作は全然できませんが、コードなら何だかできそうな気がして、試したいなと思いました。
  • nobu417 さん
    • ガワアプリで使うための自作フレームワークを紹介されました。Haml, CoffeeScript, CSS で作られているらしく、UI を構築できたりとか、ネイティブな機能との橋渡しができるとのことでした。
  • なおう さん
    • とある大企業で社内システムの Rails アプリをメンテナンスしている話でした。懇親会でも少しお話しましたが、社内システムならではの辛みがあるようで、うまく共有できたら有益な情報が多そうな気がしました。
  • TakekiFujinami さん
    • どうやって Ruby についての情報を収集しているかの話でした。「週刊 Rails ウォッチ」は僕も読んでいて、参考になる情報が多いです。「ruby-jp Slack グループ」は存在は知っているのですがまだ入っていません。
    • 上の 2 つで時間切れでしたが、ブラウザのタブを見る感じ、あとは Ruby Weekly か何かのメールマガジンな気がしました。
  • iberianpig さん
    • Linux のノート PC で mac のようなマルチタッチジェスチャーを可能にする fusuma という Gem について紹介されました。
    • mac を使う理由の一つに高機能なトラックパッドが使える、というのがあるので、この Gem を使うと Linux に移行しやすくなるなと思いました。
  • miya_0436 さん
    • 日付オブジェクトを文字列に変換する方法で、複数のやり方が出てきて議論して最終的に落ち着いたものの、それを議論している時間はプロダクトの価値に寄与していないよね、本当に強制するメリットはあるのか、という話でした。
    • 個人的にはできるだけ規約で縛りたい派なのですが、機械的に指摘できないルールは、新人が入ってきたときもそうですし、そうでなくても何度レビューしても定着しなかったりするので、耳が痛かったですw
    • ちょうど最近 Google Engineering Practices Documentation のコードレビューについてのガイド を読んでいたので、色々と考えさせられました。

全体の感想

事前に発表する時間を指定できるものの、時間が過ぎたら強制的に終了だったので、ほどよい緊張感がありました。 各発表の終了後に主催の方が感想を一言くれたのもいいなと思いました。

イベントはとてもスムーズに運営されていました。事前に色々な準備があったのだと思います。 運営の皆様、会場や飲食物を提供してくださった ClipLine 株式会社様、ありがとうございました。

f:id:cho_co_by:20190915184104j:plain
プログラマーの日っぽく「エンジニアさんの歌〜納期前〜」という曲が流れていた

f:id:cho_co_by:20190915184043j:plain
謎の構図

追記: 主催のたけきさんの雑感エントリーが公開されました。

note.mu

9/13 はプログラマーの日

9/13 は 1/1 から 256 日目にあたる日で、ロシアの祝日とのことです。

ja.wikipedia.org

serverless-offline でサーバー起動時にエンドポイントをテストする

serverless-offline でサーバー起動時にスクリプトを実行する方法をメモ。 sls offline start コマンドに --exec オプションを指定する。

ヘルプから抜粋:

% yarn run sls offline --help
offline start ................. Simulates API Gateway to call your lambda functions offline using backward compatible initialization.
    --exec ............................. When provided, a shell script is executed when the server starts up, and the server will shut down after handling this command.

例えばサーバーを起動したあとに curl コマンドを叩くことができる。

yarn run sls offline start --exec "curl --fail 127.0.0.1:3000"

CircleCI の例ですが、こういう感じでエンドポイントにリクエストが通るかを雑にチェックすることができる。

- run:
    name: Check response
    command: yarn run sls offline start --exec "curl --fail 127.0.0.1:3000"
    when: always

Serverless Framework + TypeScript なプロジェクトを手っ取り早く始められるテンプレート的なプロジェクトでこの方法を使っています (宣伝)

github.com