rubocop -a と rubocop -A オプション

RuboCop 0.87 がリリースされた。

github.com

今回の目玉は rubocop -a コマンドラインオプションへの非互換変更となる。

これまでは rubocop -a オプション (rubocop --auto-correct も同義) を使った場合に、自動修正を備えたすべての Cop が適用されたていた。そのため Safe でないと見なされる Cop の自動修正も適用されるというのがデフォルトの振る舞いだった。

今回のリリースからは rubocop -a は Safe とマークされている Cop のみが自動修正の対象となり、従来どおり自動修正を備えた Unsafe を含むすべての Cop を適用する場合は rubocop -A (rubocop --auto-correct-all) を実行することになる。つまり RuboCop 0.59 で導入された rubocop --safe-auto-correct が自動修正のデフォルトの振る舞いになる (そして rubocop --safe-auto-correct オプション自体は非推奨になりました) 。

RuboCop に導入されている Safe というメタデータについては過去の日記を参照してください。

koic.hatenablog.com

GitHubの新デザインを先取りして使う

GitHub がユーザー全体のデザインを変えるより前に、Feature preview を使うと先駆けで新デザインを使うことができる。

先行して新デザインが使えるときは、以下の Feature preview に通知がきているので、それを有効にする。

f:id:koic:20200624175208p:plain:w400

過去に自分が見たプレビュー機能には、"Design updates" と "Repository refresh" があった。

"Design updates" はユーザープロフィールページを新デザインにするものだった。

"Repository refresh" はリポジトリのトップページを新デザインにするものだった。

それぞれ "Give feedback" のリンクからフィードバックできるようになっている。

"Repository refresh" について、リポジトリのトップに表示されている最新のコミットで CI の結果 (✔︎or❌) が分からくなっていて不便だったのを以下の画像添付と一緒に GitHub にフィードバックしていた (たしか昨日 (2020年6月23日) か一昨日くらいのこと) 。

f:id:koic:20200624174907p:plain:w400

この日記を書いている 2020年6月24日現在、リポジトリのトップで master ブランチへのマージ後の最新のコミットへの CI の結果がわかるようになっていた。GitHub への自分のフィードバックか、誰か他の人も同一のフィードバックをしていたかは分からないが、便利になって良かった (というかもともとのデザインで見れていたものなので、ないと不便だった) 。

いまは "Feature preview" が空になっているので、また次のプレビューが楽しみですね。

GitHub が落ちた時に復旧情報を受け取る

Twitter のタイムラインが賑わう GitHub のサービスダウンに関する tip です。

f:id:koic:20200619184749p:plain:w400

GItHub のサービスの状態については https://status.github.com/ で確認できます。

f:id:koic:20200619184810p:plain:w400

さらに右上の Subscribe から復旧状態をメールなどで通知を受け取ることができます。

f:id:koic:20200619184827p:plain:w400

たとえばメール通知にすると、復旧したらこんな感じでメールが来ます。

f:id:koic:20200619185820p:plain:w400

実践的には GitHub に繋がらなければ繋がらないでできる仕事にスイッチして進めている間にだいたい復旧しているので、UX 最高とまではいかなかったりですが参考までに。

pluck.uniqをdistinct.pluckに置換する

先日リリースした RuboCop Rails 2.6.0 でバグフィックスされた Rails/UniqBeforePluck についての話。

この Cop は RuboCop Rails に細かな部署があるなら、スタイルではなくパフォーマンスに属するもの。RDBMS から結果を取得したあとに Rubyuniq で一意にするのではなく、DISTINCT を使ったクエリを RDBMS に発行してあらかじめ一意になっている結果を得るもの。

デフォルトで以下のような検出を行う。

# bad
Model.pluck(:foo).uniq

# good
Model.distinct.pluck(:foo)

なお、この Rails/UniqBeforePluck cop はバグ修正された RuboCop Rails 2.6 以上でないと distinct に置換すべきところ Rails 5.0 で非推奨にされた uniq にオートコレクトしてしまう問題がある。

github.com

いまメンテナンスされている Rails 5.2, Rails 6.0 なんかでは NoMethodError: undefined methoduniq'` エラーになるので自動修正を使うときは RuboCop Rails を最新の 2.6.0 に更新してください。

なお Rails/UniqBeforePluckEnforcedStyle のオプションを持っていて、デフォルトの EnforcedStyle: conservative偽陰性が起きえて、EnforcedStyle: aggressive偽陽性が起きうるという。常時はデフォルトの EnforcedStyle: conservative のままとしている。パッチ会あたりでも聞いてみたいところ。

github.com あとは悲しいかな、誤検知をもちうる Cop のため git grep 'pluck.*uniq' なんかで置き換えが可能かどうかを見て判定というのが最初の導入として確実。まずは grep で対応した後に EnforcedStyle: conservative あたりで検出を行うというのが、まさに consavative なやり方になるだろう。型があれば誤検知なく EnforcedStyle: conservative が使えそうで未来の処理系に期待される。

そして、Rails/UniqBeforePluck cop は歴史的経緯ですでに名前が実体にあっていないので、RuboCop Rails 3.0 あたりでリネームされる予定です。

追記

同僚の kunitoo より例えば MySQL の collation によって、RDBMS によっては非互換が生まれる可能性があるかもという指摘があった。たしかに現状の実装だとオートコレクトの unsafe を検討できるかもしれない。

SSDが擦り切れる前にルーターとHDDを導入した

2013 年モデルの MacBook Pro を開発機に使っていて、一説によると寿命の目安が5年くらいとも言われている SSDアディショナルタイムに突入して数年経過している。多くの作業中ブランチを含む手元の OSS リポジトリやら環境が飛ぶと立ち直るのがつらい状況に対し、重い腰をあげて Time Machine でバックアップをとるための機材を購入した。

ちょっと前までであれば Time Capsule を使えば無線 LAN ルーター + NAS を兼ねて便利そうだったけれど、すでに生産終了のアイテムになっているため寿命がある前提の外部ストレージとしては選択肢から外した。

結果的には ASUS の無線 LAN ルーターと BUFFALO の外付け HDD の組み合わせにした。バックアップのため有線で外付け HDD を繋げたりする面倒はしたくない性格なのと今後の拡張性から無線 LAN ルーターを合わせて導入している。

信頼できる筋の人たちによる ASUS RT-AC68U への絶賛帯はルーター選定への後押しになっている。この場を借りて感謝。

最終的に、この無線 LAN ルーターは Time Machine の USB アプリが入っているので今回の目的と相性が良いだろうというのが決め手となった。

外部ストレージについては、第一の用途が保険的なバックアップストレージなので今回は速度より価格面をとって SSD ではなく安価な HDD としたが、SSD の体験を知っていると HDD の IO は結構ストレスになったりもする。いずれも寿命のあるものながら、日常の体験を考えて SSD にしておくべきだったかもしれない。

また保険的にはクラウドストレージが一番なんだろうけれど、現在 COVID-19 の社会的影響で滅多に外出していない状態で、その買い物にも PC を持って行くことなんか絶無なので今回の構成にしている。例えば iCould 2TB でも現在の状況での保険用途に限れば支出がペイしないかもという判断は断念した要因のひとつ。

一方でそうそうあることではないとは思っているが、MBP の内蔵 SSD と外付けの HDD が同時になくなると目も当てられないので、物理デバイスだとしてもデュアル HDD あるいは SSD にそのうち装備を強化したいところ。いずれにせよ保険にいくら掛けられるかということになる。

そして手元に届いた後はさっそくバックアップを行なったわけだが、Power Nap を ON にしていなかったのが原因か sparsebundle が壊れているらしく「信頼性を向上するために、Time Machineは新規バックアップを作成する必要があります」で何度か半日は掛かる初期バックアップ削除からやり直しの憂き目に遭った。キーワードとして書き記しておく。


無限にやることがある OSS への活動に対して、土台となるこういったインフラ機材についても GitHub Sponsors でまかなったり選択肢を増やせるようシフトできると良いなと思っていて OSS 活動へのスポンサーを募集しています。

github.com

もちろん心意気にあわせてモチベーションもブーストされます :-)

`Layout/LineLength` のデフォルトを 120 にした

RuboCop の LineLength のデフォルトが 80 ではつらいという声はずっと聞いていて、そもそも RuboCop にパッチを送り始めた頃は、いつかこの変更をするのが目標のひとつだった。

今回 3年半越しに実現することができた。現在の最新版の RuboCop 0.84.0 に適用済み。

github.com

OSS で年月をかけた粘り強い振る舞いは kamipo さんから学んだことで、RangeError にまつわる rails/rails#30000 もそこに到るまでを含めてコントリビュータ時代から何年か掛けていると聞いている。

RuboCop リポジトリ自体の方では、その後にコアメンバーからエディタを縦分割した際に 120 だと厳しいという声があり、RuboCop リポジトリ自体の設定は 100 になったというエピソードがある (デフォルトの設定は 120 で維持されています) 。RuboCop 自体も無数にあるリポジトリのひとつなので、アクティブメンテナーが過ごしやすい設定に歩み寄った形。

実際のところ 80 から 120 になると、本来名付けたかった名前への省略や、本質的に不必要な行の折り返しなんかを考える yak shaving な手間が減るという効能を実感しているので、80 では厳しいと思っていた人には良いのではと思う。従来の 80 がお気に入りの場合は Layout/LineLength を 80 にセットしてください。

Rails 6.0で不要なArel.sqlを減らす

Rails 5.2 で以下のように Arel.sql を使ってセキュアな文字列であることを明示するという警告が出るようになっていたのは、多くの Rails アプリケーション開発者が通ってきているように思える。

DEPRECATION WARNING: Dangerous query method (method whose arguments are used as
raw SQL) called with non-attribute argument(s): "対象のSQL文字列".
Non-attribute arguments will be disallowed in Rails 6.0. This method should not
be called with user-provided values, such as request parameters or model
attributes. Known-safe values can be passed by wrapping them in Arel.sql().

新しい Rails であれば、不必要な Arel.sql (いわゆる false alarm) を抑制できるという話を思い出したので、rails/rails のコミットを調べて Oracle も同様の対応をした。 余談だが OracleNULLS FIRST, NULLS LAST をサポートしているのでその対応も入っている。

github.com

新しい Rails と言っているのは、この Oracle 向けパッチを書いた時点では Arel.sql の false alarm への抑制に次の Rails 6.1 が必要だと思っていたところ kamipo さんから Rails 6.0 にも入っているというコメントをもらった (なんといういい仕事!) 。

なので Rails 6.0 にして不要な Arel.sql を除去すれば、いきなり Arel という文字列を見てなんぞという初見でちょっとビビらせる機会が減るのではと思う。

Oracle enhanced adapter の 6.0 ブランチの方にもバックポートしておいたので、そちらは次のリリースで対応される見込みです。

Rails 5.2が出る頃に Arel.sql について日記を書いていたので、今回 2年半越しに良い話を書けたのだった。

koic.hatenablog.com