今年に入ってから,あるRubyスクリプトでエラーが発生していました.
先日久しぶりに動かしてみましたが,やはり途中でエラー終了となりました.
FileUtils.mkdir_pメソッドを呼び出した際に,「ArgumentError (wrong number of arguments (given 2, expected 1))」と出ます.後ろから前に訳していくと,このメソッドは本来(expected = 期待されるのは)引数が1個なんだけど,コードでは(given = 与えているのは)2個で,引数の数がおかしいよ,ということでArgumentErrorです.
実際のところ,mkdir_pには,ディレクトリ名を指定すればいいのだから,引数は1個でいいはずです.と思いながらhttps://docs.ruby-lang.org/ja/latest/class/FileUtils.html#M_MAKEDIRSを見ると,mkdir_pの引数は,作成するディレクトリ(文字列または配列)のlistと,「options = {}」というオプションです.オプションの説明は,https://docs.ruby-lang.org/ja/latest/class/FileUtils.htmlのはじめのほうに書かれています.
Emacsで,Rubyスクリプトを開いて見ました.エラーの行,第2引数はインスタンス変数@optでした.この変数は「@opt = {:verbose => true}」で代入していました.
irbコマンドを使って,動作確認してみますか….
$ irb
irb(main):001:0> require "fileutils"
=> false
irb(main):002:0> FileUtils.mkdir_p("a", {:verbose => true})
Traceback (most recent call last):
5: from /(略)/.rbenv/versions/3.0.0-dev/bin/irb:23:in `'
4: from /(略)/.rbenv/versions/3.0.0-dev/bin/irb:23:in `load'
3: from /(略)/.rbenv/versions/3.0.0-dev/lib/ruby/gems/3.0.0/gem
s/irb-1.2.7/exe/irb:11:in `'
2: from (irb):1
1: from /(略)/.rbenv/versions/3.0.0-dev/lib/ruby/3.0.0/fileutil
s.rb:206:in `mkdir_p'
ArgumentError (wrong number of arguments (given 2, expected 1))
やはり,エラーです.
ハッシュを使わない,キーワード引数だと…うまくいきました.
irb(main):003:0> FileUtils.mkdir_p("a", verbose: true})
mkdir -p a
=> ["a"]
irb(main):004:0> FileUtils.rmdir("a", verbose: true)
rmdir a
=> ["a"]
ブラウザで検索してみると,ハッシュオブジェクトからキーワード引数への自動変換が,Ruby 2.7で非推奨,そしてRuby 3ではできなくなるのを知りました.
- Ruby 2.7: ハッシュからキーワード引数への自動変換が非推奨に(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社
- サンプルコードでわかる!Ruby 2.7の主な新機能と変更点 Part 2 - キーワード引数に関する仕様変更 - Qiita
「今年に入ってから,エラー」の理由が,わかりました.rbenvを使って2.8.0-devをインストールし,このバージョンを使い始めたからです(ちなみに今は3.0.0-devです).
対応策は,double splat演算子(**)とのこと.irbに戻って,試してみると…うまくいきました.
irb(main):005:0> FileUtils.mkdir_p("a", **{:verbose => true})
mkdir -p a
=> ["a"]
irb(main):006:0> FileUtils.rmdir("a", verbose: true)
rmdir a
=> ["a"]
irb(main):007:0> exit
Emacsで編集です.FileUtilsのメソッドの最後の引数が,@optになっている箇所を,すべて「**@opt」に書き換えました.
それから実行すると,エラーが出なくなり,期待どおりの処理をしてくれました.