tags:

views:

25

answers:

1

This code installs gems into your project based on a gem manifest. Why does it need to spawn threads for this?

module Gemifest
  class Installer
    def initialize(gem)
      @gem = gem
    end

    def perform!
      begin
        $stdout = StringIO.new('')
        $stderr = StringIO.new('')
        with_progress 'Installing ' + @gem.name do
          `#{@gem_command} install --no-ri --no-rdoc #{@gem.line}`
        end
      ensure
        $stderr = STDERR
        $stdout = STDOUT
      end
    end

    private

    def with_progress(label)
      STDERR.print label
      begin
        t = Thread.new do
          loop do
            STDERR.print('.')
            STDERR.flush
            sleep 0.8
          end
        end
        yield
        STDERR.puts ' done!' unless $?.exitstatus > 0
      rescue => e
        STDOUT.puts "Error:"
        STDOUT.puts e.message
      ensure
        t.kill
      end
    end
  end
end
+2  A: 

If you would remove the Thread.new the yield would execute after the loop do ... end has finished (i.e. never).

The purpose of having the loop in a seperate thread is that it's supposed to execute at the same time as the block and then be killed once the block is finished.

sepp2k
ok. so it just prints ............ while the gem installation is happening. so the with_progress method just prints the progress dots to standard error and the block does the installation at the same time: with_progress 'Installing ' + @gem.name do `#{@gem_command} install --no-ri --no-rdoc #{@gem.line}` end
uzo
Right, exactly.
sepp2k