IO流在不同版本的ruby中的不一致

时间:2019-04-20 15:03:00

标签: ruby irb

我正在尝试创建一种将ruby程序的所有三个标准(输入,输出和错误)流镜像到不同文件的方法。
对于输出stdout和错误stderr流,我能够做到这一点。 但是,不同的ruby版本之间在如何处理IO流方面存在不一致之处。

底线是 如何处理旧版本的ruby中的流重复(第2点)?

问题摘要

  1. 旧的ruby版本不支持可变参数,而新版本则可以处理。

  2. 在相同的旧版本中,即使我尝试通过join输入参数来解决它,流内容也是重复的。


  1. 可变参数问题 在ruby 2.1.x和ruby 2.2.x中,$stdout仅接受单个参数。

所以对于那些红宝石

$stdout.write("Test") # works 

这不起作用

$stdout.write("Hello","Test")

ArgumentError: wrong number of arguments (2 for 1)
from (pry):6:in `write'

但是对于红宝石版本2.5.x2.6.x可变参数有效

$stdout.write("Hello")
$stdout.write("This","works", "as", "well") 
  1. 流内容重复,如果我添加了特定于版本的代码来处理流参数,则较旧的ruby版本最终将复制流内容。

    • 红宝石旧版本
driver.rb:4 in `puts` --> This is it driver.rb:4 in `puts` -->

  • 红宝石的新版本
driver.rb:4 in `puts` --> This is it

这是代码


  1. reox.rb
require_relative 'reox_io.rb'
require_relative 'reox_file.rb'

class Reox
    DEFAULT_RECORDING_PATH = "recordings" 

    def initialize(recording_path)
        @recording_paths = recording_path || DEFAULT_RECORDING_PATH  
    end

    def self.record 
        input_log,output_log,error_log = setup_files
        $stdout = ReoxIO.new(STDOUT,output_log)
        $stderr = ReoxIO.new(STDERR,error_log)
        yield
    end


    private 

    def self.setup_files
        ["input.log","output.log","error.log"].map do |file_name|
            self.setup_file(file_name)
        end 
    end

    def self.setup_file(file_name)
        file = ReoxFile.open(File.join(__dir__,file_name),"a")
        file.sync = true
        file
    end
end
  1. reox_file.rb
class ReoxFile < File 
end
  1. reox_io.rb
# Insipired from https://stackoverflow.com/a/6407200
require_relative 'reox_file.rb'
class ReoxIO
   $LOG_SEPARATOR = " --> ".freeze
   def initialize(*streams)
     @streams = streams
     @verbose = true
   end 

   def write(*content)
     @streams.each do |stream| 
      if @verbose and stream.is_a? ReoxFile
        stream.write([caller[2],$LOG_SEPARATOR,*content].join)
      else
        stream.write(*content)
      end    
     end 
   end

   def flush
    @streams.each(&:flush)
   end

   def close
    @streams.each(&:close) 
   end

end
  1. driver.rb
require_relative 'reox.rb'
Reox.record do 
  puts "This is it" 
end 

0 个答案:

没有答案