16
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rubocopに怒られないように0埋めした桁揃え文字列を作る

Posted at

TL;DR

1〜3桁の整数sizeがあり、そこから例えばL064.datみたいなファイル名を作りたい時、Rubocopに怒られないようにするには

filename = format("L%<size>03d.dat", size: size)

とすれば良い。これだけなんだけど、ここまで来るのに妙に苦労したのでRubocopの文句からこの記事にたどり着けるように詳細を書いておきます。

Rubocopに怒られる

C言語っぽく

1〜3桁の整数sizeがあり、そこから例えばL064.datみたいなファイル名を作りたい。C言語から入った人ならsprintf使ってこんな感じに書くと思う。

format1.rb
size = 10
puts sprintf("L%03d.dat", size)

これはRubocopに以下のように怒られる。

$ rubocop format1.rb
Inspecting 1 file
C

Offenses:

format1.rb:2:6: C: Style/FormatString: Favor format over sprintf.
puts sprintf("L%03d.dat", size)
     ^^^^^^^
format1.rb:2:16: C: Style/FormatStringToken: Prefer annotated tokens (like %<foo>s) over unannotated tokens (like %s).
puts sprintf("L%03d.dat", size)
               ^^^^

1 file inspected, 2 offenses detected

とりあえずsprintfを使うな、formatを使え、と言ってるようですね。Rubyには書式付き文字列の作成方法が複数あるため、フォーマットを統一するため、RubocopのStyle/FormatStringでどれを使うか指定できますが、デフォルトではEnforcedStyleformatとなっています。

formatを使う

というわけでformatを使いましょう。sprintfの代わりにformatって書いただけ。

format2.rb
size = 10
puts format("L%03d.dat", size)

これはまたRubocopに怒られる。

$ rubocop format2.rb
Inspecting 1 file
C

Offenses:

format2.rb:2:15: C: Style/FormatStringToken: Prefer annotated tokens (like %<foo>s) over unannotated tokens (like %s).
puts format("L%03d.dat", size)
              ^^^^

1 file inspected, 1 offense detected

Unannotated tokensを使うなと言ってるようですね。

Template tokensを使う

さて、ここで渡しは先の文句ではannotated tokensを使え、と書いてありますが、それに気づかずに(annotated tokenとtemplate tokenの違いを理解せずに)template tokenを使いました。

Template tokensというのは、formatの文字列に引数としてハッシュを渡すと、%{name}などで、キーを参照してそのまま代入してくれる機能です。ただし、%{name}を使うとフォーマットできないので、フォーマットしたい場合はフォーマット済み文字列を渡す必要があります。こんな感じでしょうか。

format3.rb
size = 10
puts format("L%{size}.dat", size: size.to_s.rjust(3, "0"))

なんか不必要に複雑になった上に、まだRubocopに怒られますね。

$ rubocop format3.rb
Inspecting 1 file
C

Offenses:

format3.rb:2:15: C: Style/FormatStringToken: Prefer annotated tokens (like %<foo>s) over template tokens (like %{foo}).
puts format("L%{size}.dat", size: size.to_s.rjust(3, "0"))
              ^^^^^^^

1 file inspected, 1 offense detected

Template tokens %{foo}ではなく、annotated tokens%<foo>sを使え、と言ってますね。ここで初めてannotated tokenというものがあることを知りました。

Annotated tokensを使う

Annotated tokensは、templated tokensと同様に引数にハッシュを与えますが、%<name>dのようにフォーマット指定できます。これを使うとこうなりますかね。

format4.rb
size = 10
puts format("L%<size>d.dat", size: size)

上記はRubocopは文句を言いませんが、出力結果が0埋めされません。

Annotated tokensを使って、かつ桁指定して0埋めする

Annotated tokensでは、printfと同様にフォーマット指定子が使えます。例えば、3桁の整数で左を0埋めしたければ、%<name>03dと書けます。

format5.rb
size = 10
puts format("L%<size>03d.dat", size: size)

ようやくRubocopに文句を言われずに、0埋めした桁揃え文字列を作ることができました。

まとめというか・・・

普段VSCodeを使ってますが、ちょっとしたスクリプトはVimで書いてます。で、VimでRubocopで確認するようにしてみたらRubocopのうるさいことうるさいこと。自動的に直せるところは直すauto-correctもあるのですが、保存時にこれが走るようにしたらかえって鬱陶しかったので、今のところ手でなおしています。

「自由に、好きなように書ける」のがRubyの良いところだと思っているのですが、その思想とLinterはどうも相性が悪いような気がしますね・・・

参考

16
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?