No, I don't want to repeat myself, either....

前に書いた写真取り込みスクリプトを案外便利に使っている。特に、さっと手元のカメラで何枚か写真を撮り、それをPCに取り込むという用途にはいい。「nikon -lcv」とかやると、ずばっと直近の写真をコピってくれる。この取り込みスクリプトWindowsRubyで使ってみたら、そのまま動いたので(当たり前か)仕事でもかなり使っている。

だいたい動作もオッケーみたいだし、copyだけじゃなくて、(恐ろしくて実装しなかった)moveもオプションに加えてみた。カメラ内にコピーし終わった写真が残ってるのは、実は管理面ではかなりウザい。どれとどれがコピー済みか、ワケが分からなくなりがちで、ついカメラ内の写真を不必要に残しがちになってしまうからだ。

ともあれ、move機能を加えるために、そのままcopyのとき使ったコードをコピペして、以下のように変更した。

Options = {
  :photo_dir => PHOTO_DIR,
  :hours     => HOURS,
  :copy      => false,
  :move      => false,
  :events    => (1..5),
  :verbose   => false,
}

:
:

def parse_option
  opts = OptionParser.new
  opts.on("-c", "--copy",
          "copy the photos, instead of just showing"){|val| Options[:copy] = true}
  opts.on("-m", "--move",
          "move the photos, instead of just showing"){|val| Options[:move] = true}
opts.parse!(ARGV)
end

:
:

if Options[:copy]
  Options[:events].each {|n|
    nikon.event(n).each {|photo|
      FileUtils.cp(photo[0],".",
                   {:verbose => Options[:verbose]})
    }
  }
elsif Options[:move]
  Options[:events].each {|n|
    nikon.event(n).each {|photo|
      FileUtils.mv(photo[0],".",
                   {:verbose => Options[:verbose]})
    }
  }
else
  Options[:events].each {|n|
    number = nikon.event(n).size
    print "Event",n, "(#{number}): "
    print nikon.event(n)[number-1][1].strftime("%m/%d %H:%M - ")
    print nikon.event(n)[0][1].strftime("%m/%d %H:%M")
    print "\n"
  }
end

これでちゃんと期待通りに動いているからいいのだけど、FileUtils.cpと、FileUtils.mvのところの重複感がひどい。「cp」と「mv」と、たった2文字、メソッド名が違うだけだ。これを、どうにかまとめたい。

で、すぐに頭に浮かんだのは、以下のようなまとめ方だけど、これってたいしてまとまってないよなぁ。

if (Options[:copy] || Option[:move])
  Options[:events].each {|n|
    nikon.event(n).each {|photo|
      if Option[:copy]
        FileUtils.cp(photo[0],".",
                     {:verbose => Options[:verbose]})
      elsif Option[:move]
        FileUtils.mv(photo[0],".",
                     {:verbose => Options[:verbose]})
      end
    }
  }
else
:
:

やりたいのは、以下のようなこと。

case Options[:copy]
  when "copy"
    f = FileUtils.cp
  when "move"
    f = FileUtils.mv
end

if (Options[:copy] != "")
  Options[:events].each {|n|
    nikon.event(n).each {|photo|
      f(photo[0],".",
              {:verbose => Options[:verbose]})
    }
  }
else
:
:

fという変数にcpやmvのメソッドを割り当てたい。

ふつうのクラスメソッドであれば、aliasを使って勝手に再定義すればいいだけのような気もするけど、FileUtilsはMix-inで読み込まれているモジュールのメソッドだ。

何をどうしていいのかよく分からない。うーん。