Ruby IO - file input / output indirectly

I recently studied Ruby.I hit the problem while I am writing a subclass of the file.

class MyFile < File end file_path = "text_file" file = MyFile.open(file_path) do | file | file.each_line do | line | puts line end file.close end 

result:

 line 1 line 2 line 3 

If I want to output by calling the method:

 class MyFile < File def foo self.each_line do | line | puts line end end end file_path = "text_file" my_file = MyFile.open(file_path) do | file | file.foo file.close end 

Result:

 /Users/veightz/Developer/RubyCode/io_error.rb:4:in `write': not opened for writing (IOError) from /Users/veightz/Developer/RubyCode/io_error.rb:4:in `puts' from /Users/veightz/Developer/RubyCode/io_error.rb:4:in `block in foo' from /Users/veightz/Developer/RubyCode/io_error.rb:3:in `each_line' from /Users/veightz/Developer/RubyCode/io_error.rb:3:in `foo' from /Users/veightz/Developer/RubyCode/io_error.rb:20:in `block in <main>' from /Users/veightz/Developer/RubyCode/io_error.rb:19:in `open' from /Users/veightz/Developer/RubyCode/io_error.rb:19:in `<main>' 

Then I add a new bar method

 class MyFile < File def foo self.each_line do | line | puts line end end def bar self.each_line do | line | p line end end end my_file = MyFile.open(file_path) do | file | file.bar file.close end 

Result:

 "line 1\n" "line 2\n" "line 3\n" 

So, I am so confused about IO in Ruby. Why puts line in foo may not work well.

+5
source share
2 answers

There is a puts method in IO , and IO is the superclass File . This means that it is:

 puts line 

actually self.puts , not Kernel#puts , as that is almost wherever you use puts . Therefore, the error message "did not open for writing."

You need an explicit receiver to get the same effect as Kernel#puts ; Kernel#puts equivalent to $stdout.puts , so you want:

 file.each_line do | line | $stdout.puts line end 

Your version of p line working fine because there is no IO#p or File#p , p - Kernel#p method, as elsewhere ..

Keep in mind that we do not have functions in Ruby, since other languages ​​have global functions. The methods you use as a function are almost always methods in Kernel .

+6
source

You can also use $> "default output stream" to redirect the output of methods such as Kernel # puts ... Which is the only task of $> .

 def foo self.each_line do | line | $>.puts line end end 

I added another method showing how you can also “demand” other gems (for example, a beautifully printed gem) and use class << slef .... Therefore, you said: “I recently studied Ruby”: |

The following works as intended.

 #!/usr/bin/env ruby require 'pp' class MyFile < File class << self def foo each_line do | line | $>.puts line end end def bar each_line do | line | p line end end def bam each_line do | line | pp line end end end file_path = "/Users/path/ofdirectory_to/somefile.txt" my_file = MyFile.open(file_path) do | file | file.bam file.foo file.bar File.close end 

Note: using NameOfClass <<self ... wana more info Question SO

What looks like btter:

not-pretty-printed p output:

  #<PP:0x81fedf0 @genspace=#<Proc:0x81feda0>, @group_queue=#<PrettyPrint::GroupQueue:0x81fed3c @queue=[[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], []]>, @buffer=[], @newline="\n", @group_stack=[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], @buffer_width=0, @indent=0, @maxwidth=79, @output_width=2, @output=#<IO:0x8114ee4>> 

pretty printed pp output:

  #<PP:0x81fedf0 @buffer=[], @buffer_width=0, @genspace=#<Proc:0x81feda0>, @group_queue= #<PrettyPrint::GroupQueue:0x81fed3c @queue= [[#<PrettyPrint::Group:0x81fed78 @break=false, @breakables=[], @depth=0>], []]>, @group_stack= [#<PrettyPrint::Group:0x81fed78 @break=false, @breakables=[], @depth=0>], @indent=0, @maxwidth=79, @newline="\n", @output=#<IO:0x8114ee4>, @output_width=2> 

For more on pp, see Ruby-Doc here.

0
source

All Articles