2
2

More than 5 years have passed since last update.

Rubyでファイルを同期コピーしたいとき

Posted at

Rubyでファイルをコピーするとき、あまり同期/非同期を意識していなくて、テストでハマった時のお話。
あるテストを実行するときに設定ファイルのspec/necessaryが必要で、なければspec/exampleからコピーして使うという状況でした。
Rakefileで書くとこんな感じ、

RSpec::Core::RakeTask.new('spec') do |t|
    t.verbose = true
end

file 'spec/necessary' => 'spec/example' do |task|
  CLEAN.exclude task.name
  src_path = File.expand_path("../../#{task.prerequisites.first}", __FILE__)
  dst_path = File.expand_path("../../#{task.name}", __FILE__)

  dst_file = File.open(dst_path, 'w')
  File.open(src_path) do |f|
    f.each_line do |line|
      dst_file.write line
    end
  end
end

Rake::Task[:spec].prerequisites << :'spec/necessary'

この書き方でテストが通らないので調べてみると、specタスクの実行時に'spec/necessary'が空の状態で存在していました。同期モードにしていなかったのが原因で、書き込みが終わる前にspecタスクが実行されていると。

同期モードになるように修正したところ

file 'spec/necessary' => 'spec/example' do |task|
  CLEAN.exclude task.name
  src_path = File.expand_path("../../#{task.prerequisites.first}", __FILE__)
  dst_path = File.expand_path("../../#{task.name}", __FILE__)

  dst_file = File.open(dst_path, 'w')
+ dst_file.sync = true

  File.open(src_path) do |f|
    f.each_line do |line|
      dst_file.write line
    end
  end
end
file 'spec/necessary' => 'spec/example' do |task|
  CLEAN.exclude task.name
  src_path = File.expand_path("../../#{task.prerequisites.first}", __FILE__)
  dst_path = File.expand_path("../../#{task.name}", __FILE__)

+  File.open(dst_path, 'w') do |dest|
+    File.open(src_path).each do |source|
+      dest.write source
    end
  end
end

というレビューをもらいました。ブロックを渡せば、すぐに実行されるんだったなぁ。
時間を見つけて、Rubyのコードを読まないと・・・・

2
2
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
2
2