From: TAKAHASHI Masayoshi Date: 2001-12-21T07:22:44+09:00 Subject: [ruby-dev:15512] Re: fileutils (2) 高橋征義です。 すみません、つっこみを入れてしまいます。しかも長いです。 Minero Aoki wrote: > 長いあいだ放りだしていたファイル操作モジュール fileutils ですが、 > ようやくまとまりました。最新は > > http://www.loveruby.net/archive/fileutils.tar.gz > > です。入ってるテストスクリプトは 1.7 じゃないと動きません。 あ、互換性はいったん捨てることにしたんですね。 では、改めて考えてみましょう。 このファイル操作モジュールは、 * ファイルやディレクトリの作成・移動・削除などを行う * 主にインストールの時などに使われる というものですよね。確かにこういうのがあると、install.rb とかは書きやすくなって便利そうです。 ここで要求されるモジュールの特徴としては、 * オプションがいろいろある というのが第一に挙げられると思います。青木さんの最新版では、 verbose/noop/force/preserveの4つ(さらにrecursiveがメソッド名と 統合されている)が使われています。 fileutilsの最新版ではこれをどう解決しているかというと、 FileUtils#cd( [options,] dir ) というように、オプションを最初の引数に持ってきてます。ここで cd(:verbose, :noop, some_dir) とかという感じで指定するわけ ですね。 このため、dirが何番目の引数になるかは決まってはいない ようになっています。……うーん、これはちょっとRuby的には 不自然な気が。 なんでこうなっているかというと、 FileUtils#ln_s( [options,] file1, file2 ..., dir ) というように、任意の数の引数を取るメソッドがあるのと、 Unixのコマンドがオプションを前に持ってくる習慣があるから だろうと思います(あってます?)。 なお、このようなことをするための実装の方はといえば、 def newest?( *args ) (new,*fnames), (verbose,) = fu_parseargs( args, 1..INF, :verbose ) というように、引数は配列で受けて、fu_parseargsでparseしてから、 多重代入で受ける、という感じになっているようです。ちなみにこのINFは、 INF = 1/0.0 という定義になってますね。うむむむ。 ところで、上のln_sのように、file1,file2,...とたくさん並べる 必要はあるのでしょうか? shell上でその都度コマンドを入力する ならいざしらず、Rubyのスクリプトならメソッドを並べるなり、 eachで回すなりすればいいような。 それよりも問題はオプションですね。やっぱりシンボルで引数の 前にオプションを置く(ために、引数の絶対位置に意味がなくなる) のはRubyっぽくないので、なんだか抵抗があります。 では、どういうのがRubyっぽいのか? というのを考えると、やはり verbose/noop/force/preserveみたいな属性は、オブジェクトの プロパティとして持たせておく、というのがRubyっぽいような気が します。そもそもverboseなんてのは、それぞれのメソッドについて 出力してほしいなら全部verbose、そうじゃないなら全部verboseじゃ ないように指定する方が一般的かと思います。 というわけで、発想を少し(かなり)転換させて、cpやln_sやmkdirと いった一連のメソッドは、FileUtilsモジュールのモジュール関数 ではなく、FileUtilsクラスのインスタンスメソッドにする、と いうのはどうでしょうか。 # あるいは名前を変えてFileManagerとかにした方がいいのかもしれ # ませんが。 こうすると、 fu = FileUtils.new() fu.verbose = true fu.noop = true dirs.each{|d| fu.mkdir(...) fu.cp(...) ... } という感じに書けるようになります(verboseなどはinitializeの 引数でも指定できるようにした方がいいかも)。 んー、なんか別物っぽくなってしまいますけど、どうでしょうか? 高橋征義 (TAKAHASHI Masayoshi) E-mail: maki@rubycolor.org