Ruby のエイプリルフール新構文 2021

Downward assignments という名前で Ruby に提案された機能 (mame さん今年もありがとうございます) 。

p(2 * 3 * 7)  #=> 42
  ^^^^^var

p var         #=> 6

bugs.ruby-lang.org

エイプリルフールということを失念していて「これは!」とおもしろく思った一方で思ったのが、以下のような RuboCop のテスト機構とぶつかった場合に、テストの仕組みを考える必要があるかもしれないという点だった (がんばりましょう) 。

expect_offense(<<~RUBY)
  def func
    some_preceding_statements
    x = something
    ^^^^^^^^^^^^^ Redundant assignment before returning detected.
    x
  end
RUBY

github.com

また他の機能提案として、mrkn さんからはこんな提案が開かれていました。

irb(main):001:0> x = 3
=> 3
irb(main):002:0> 2x
=> 6
irb(main):003:0> def pi = Math::PI
=> :pi
irb(main):004:0> 2pi
=> 6.283185307179586

bugs.ruby-lang.org

エイプリルフールネタでいうと、Ruby 3.0 で正式採用された Endless Method Definition の例もあるので、気になる人はウォッチしてみましょう。

2021年4月5日追記

いずれの提案もエイプリルフール終了ということでクローズされたようです。

`String#split`と`String#chars`の小咄

最近、String#splitString#chars まわりの Cop をメンテナンスしたり実装した際の、それらメソッドに関する知見を書き残しておきます。

String#split の小咄

RuboCop Performance に string.split(/re/) より string.split('re') の方が速いので、Cop にどうかという提案があったのがはじまり。

split の引数が文字列で済む場合は、正規表現ではなく文字列を渡すのは良いとして、正規表現と文字列で振る舞いが異なるものがある。

たとえば split の引数が空白なしの // である場合は '' と結果は同じなので、安全に置換できる。

'a    b    c'.split(//)
#=> ["a", " ", " ", " ", " ", "b", " ", " ", " ", " ", "c"]
'a    b    c'.split('')
#=> ["a", " ", " ", " ", " ", "b", " ", " ", " ", " ", "c"]

しかし split の引数が空白一つの / / である場合は ' ' と結果が異なり、戻り値に互換性がなくなる。

'a    b    c'.split(/ /)
#=> ["a", "", "", "", "b", "", "", "", "c"]
'a    b    c'.split(' ')
#=> ["a", "b", "c"]

なお、空白2つ以上は、互換性があるため安全に置換できる。

'a    b    c'.split(/  /)
#=> ["a", "", "b", "", "c"]
'a    b    c'.split('  ')
#=> ["a", "", "b", "", "c"]

このあたり戻り値の違いへの考慮に関して、つい今しがたリリースした RuboCop Performance 1.10.2Performance/RedundantSplitRegexpArgument の既知の誤検知については修正しておいた。

github.com

String#chars の小咄

たとえば split の引数が空白なしの // である場合は '' と結果は同じなので、安全に置換できると前述した続き。Twitter での @onk のツイート。

Ruby 1.9 以前は戻り値に違いがあった。

% ruby -v
ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-darwin13.0.2]

% ruby -e "p 'foo'.split(//)"
["f", "o", "o"]
% ruby -e "p 'foo'.chars"
#<Enumerator: "foo":chars>

Ruby 2.0 以降は戻り値に差異がなくなったため、String#chars を使った方が明確な名前になると思う。

% ruby -v
ruby 2.0.0p648 (2015-12-16 revision 53162) [x86_64-darwin13.0.2]

% ruby -e "p 'foo'.split(//)"
["f", "o", "o"]
% ruby -e "p 'foo'.chars"
["f", "o", "o"]

こういった歴史的経緯があるとき、アンラーニングしきれず手癖で split の方を使ってしまったりするケースもあると思う。

このあたり次の RuboCop のリリース (たぶん 1.12.0) で、Style/StringChars cop として追加される予定です。

社内向けに「Rails Doctrine勉強会」を行った

Rails のテクニカルな話は、新機能がリリースされたり業務で困ったら調べたりなどで日頃から触れている一方で、そもそもの Rails の理念やコミュニティなどを焦点に触れるというのはあまりないのではと以前から思っていたので、勉強会という形で開催してみた。

本家の Rails Doctrine は以下。

rubyonrails.org

勉強会では、ちょうど takahashim さんRails Doctrine を新訳されていたので、そちらを使わせていただきました。ありがとうございます。

qiita.com

本筋の流れを踏みつつ、『設定より規約』がなぜ嬉しいのか Rails 以前の世界との対比の補完や、美しいコードそれ自体の価値、ゼロサムが難しいときは大体の人が嬉しいような決定を選ぶという考え方などを Rails Doctrine ベースで話したりしていた。

RubyRails の歴史を思い出しながら話している中で、Rubyオープンクラスを活用した Symbol#to_proc による items.map(&:to_s) という書き方は、当時 Rails から Ruby にポーティングされたすごい発明だったのを思い出したので、ひとつの事例として話したりしていた。これはわずかな変更で世界を変えたすごいパッチなので、ぜひ読んでもらいたい。

github.com

『大きな傘を広げる Push up a big tent』の締め括りのあとに話したこととして、オープンなアクティビティ以外でも、1日を過ごす仕事の時間で新しい RubyRails を使える環境にアップグレードすることはとても価値があり、新しく迎え入れる人に新しい環境を用意していけると良いですねという話で締め括った (古い Ruby, Rails を使うことになるより、新しい Ruby, Rails の方がわくわくしますよね?) 。

なお、「Rails Doctrine 勉強会」というタイトルは「DHH 勉強会」という名前でも良かったかもしれないというのが、開催してみての感想でした。もし未読であれば一読してみると面白いと思います。

ちなみに私の勤務先に入社すると、同僚の ima1zumi メンバーがまとめてくれている勉強会の esa 記事を読むことができます。

agile.esm.co.jp

CircleCIのビルドがトリガーされない誤制限について問い合わせた

ここ数日 CircleCI でトリガーが効かなくなって困っていたので問合せをサポートにリクエストをした。 今後、似た問題に当たった人が現れたとき自力解決は難しいと思うのと "CircleCI Maintenance" と検索しても、当然 CircleCI のメンテナンス情報しか出てこず良く分からないと思うので書き残しておく。

当初ビルド上限に引っかかったかと思ったけれど、見てみたらそんなことはなく、自分のアカウント以外ではビルドが動いているので疑問に思っていた。ちなみにここ数日は CircleCI について、OSS 活動のみで使っているというコンテキストだった。気になったのは以下の画面の文言。

f:id:koic:20210318104554p:plain

"⚠️We have detected an anomaly that violates the CircleCI Terms of Service." とスクリーンに表示されているが、心当たりがないのでもしかするとこれは誤制限では、、、と思い以下の窓口から問合せを送ってみた。

support.circleci.com

問合せは以下のようなもの。カテゴリに関しては "Build Failure / Configuration Help" というカテゴリも選択肢にあって悩んだけれど、気持ちとしては失敗より前段の CI がトリガーされないことから "Service Issue" にした。

Please choose your issue below

"Service Issue"

Subject

Unable to trigger CircleCI on my account

Description

I'm developing RuboCop (https://github.com/rubocop) , an open source software and CircleCI hasn't run for the last few days.

  • Side navigation "Status" remains "Maintenance".
  • "We have detected an anomaly that violates the CircleCI Terms of Service." is displayed on the screen.

(I have attached a screenshot.)

I have no idea about violations, could you please confirm it? In addition, it seems that CircleCI can be triggered except for my account (https://github.com/koic) .

Thank you for your support.

 Is this ticket about CircleCI hosted on your own infrastructure?

No

 GitHub and/or Bitbucket organization name(optional)

https://github.com/rubocop

 GitHub/Bitbucket Username(optional)

https://github.com/koic

 URL(s) of Issue on CircleCI

問題になっている管理画面の URL を貼って、スクリーンショットを添付した。

シュッと辿った先が英語だったので、URL に en-us が入っているので日本語もあるかもと思いながら問い合わせを出したが、実際日本語でも問合せできるようだった。このあたりはおまけ情報として。

support.circleci.com

真夜中の JST に送ったイシューだったのが幸いしてか、タイムゾーンとしては海の向こうのサポートエンジニアの方が即対応してくれてビルドできるようになった。感謝。

結果としては CircleCI が誤って制限をかけてしまっていたようで、それを解除してもらったというもの。自力での解決は難しいものだったので、今回の問題はサポートに問い合わせるのが正攻法で良かったっぽい。

ディレクトリの一括作成とブレース展開に関する豆知識

RuboCop で直した「おっ」と思ったバグ。シェルのブレース展開 {...} を使って複数ディレクトリを一括で作成する手法がある。業務で連番でのディレクトリ作成とか必要だったりするときに使えたりする。

% mkdir {a,z}
% ls 
a z

% mkdir {a..c}
% ls 
a b c 

% mkdir {1..10}
% ls 
1 10 2 3 4 5 6 7 8 9

% mkdir {01..10}
% ls
01 02 03 04 05 06 07 08 09 10

ではディレクトリ名の指定なしで {} とするとどうなるか?

% mkdir {}

{} という名前のディレクトリができる (なるほど?) 。

% ls
{}

で、この {} という名前のディレクトリについて RuboCop が処理をしようとしたら、エラーになったという問題が報告されたので直しておいた。

% rubocop
(snip)

File name too long - /tmp////////////////////////////////////////////// (続く)

github.com

Windows でも禁則文字に入っていなさそうなので、同様かもしれない (持っていないのでよくわからない) 。 docs.microsoft.com

移行アシスタントでMacBook Proを移行後に画面共有できない問題の解決

先日、移行アシスタントを使って MacBook Pro を移行したのだが、Web 会議や勉強会でオンライン画面共有できない問題が起きていた。

具体的に問題になった Web 会議ツールとしては Zoom アプリケーションと Google Chrome を使った Google Meet のふたつ。

Web 会議で画面共有をしようとすると、警告ダイアログが表示されて「セキュリティとプライバシー」の「画面収録」に導かれる。しかし、本来は画面共有したいアプリケーションが一覧になっているべき領域がどうみても空。アプリケーションを再起動して、再び画面共有を試みても結果変わらずだった。

f:id:koic:20210307133955p:plain:w320

念のため「アクセシビリティ」でアプリケーションにチェックが入っていることを確認したり、NVRAM / PRAM のリセットをしたり、Google Chrome を最新版にしても依然として解決しない。

f:id:koic:20210307140031p:plain:w320

インターネットを見てもいまいちだったので、Apple の電話サポートにコンタクトして聞いてみた。結果としてはアプリケーションの再インストールで解決した。

Google Chrome の再インストールは不要で、Zoom アプリケーションのみ再インストールすれば解決した (Zoom の再インストールの方が手間が少なそうだったので、先に試しでやってみたらすべて解決した) 。

f:id:koic:20210307134027p:plain:w320

蓋を開けてみれば何て事のない解決方法ではあったが、なまじ他の操作が期待しているとおり動いている環境だと盲点で忘れたりもあるかもなので、今後誰か現象にあたった人への参考まで。Apple のサポートに感謝。

社内向けに「ソフトウェアの契約と見積り勉強会」を行った

5年くらい前に XP 祭りで登壇した内容を、当時と組織メンバーの顔ぶれも変わっていることもあり社内向けに話した。

www.slideshare.net

参加メンバーからは「3秒見積りは良くないのを知れた」「ハイブリッド契約という手法を知った」など、見積りや契約まわりに関する知見を伝えることができて良かったのではと思う。あと『誰と重要』

スライド中にも引用しているスティーブ・マコネルの『ソフトウェア見積り』は、後半はともかく前半は「見積りとは、何であり、何ではないのか?」を知る意味でも読んでおいた方が良い。これは受託開発とかサービス開発とか一切関係なくオススメどころか、ソフトウェアの開発に掛かる見積りの基礎的な考え方を語る上で必読だと思っている。

時間がない人は、最初は要所要所にある箱書きのポイントだけ流してみても関心を引く構成になっていると思う。

f:id:koic:20210304200807p:plain

『達人プログラマー』然り、『時を超えた建設への道』然りの良書構成、おすすめ。