7 messages in com.googlegroups.sketchuprubyNone Re: Can you Print from inside Ruby?
FromSent OnAttachments
August25 Jun 2008 16:49 
Jim25 Jun 2008 17:33 
August25 Jun 2008 22:12 
August25 Jun 2008 22:16 
Jim26 Jun 2008 03:27 
August26 Jun 2008 07:52 
Greg Ewing26 Jun 2008 17:53 
Subject:None Re: Can you Print from inside Ruby?
From:Jim (jim.@gmail.com)
Date:06/26/2008 03:27:25 AM
List:com.googlegroups.sketchupruby

On Jun 26, 1:13 am, August <asm@yahoo.com> wrote:

Thanks Jim,

That's a big help.  So is the link towww.ruby-doc.org.

Opening a file handle in read mode or write mode I get.

I presume "filename" should be a complete path, and your link to ...classes/IO.html is helpful.  It makes it clear that a Windows path cannot simply be pasted in but the backslashes must either be doubled to escape them or changed to forward slashes which Ruby will properly interpret in the context of Windows.  That page is not explicit about drive letters with forward slashes, but I think it implies that they are OK together.

Yes, the "filename" string can be a complete path, and it can also be a relative path.

absolute path: path = "c:\\my\\working\\folder\\test_file.txt"

relative path: path = "../../some/folder/test_file.txt" (the "../" means go up one level)

I typically use File.join to concatenate paths as it seems to work on all platforms:

path = File.join( "c:", "my", "working", "folder", "test_file.txt" ) ==> "c:/my/working/folder/test_file.txt"

I don't think there is any problem using / as the path separator on either platform, so this example uses just "/" to get the root folder (which is c: on most systems.)

path = File.join("/my", "working", "folder", "test_file.txt"), or just path = "/my/working/folder/test_file.txt" hould be fine on all platforms.

The exception to using "/" is the UI.openpanel (and maybe UI.savepanel). They expect the path string to use \, which needs to be escaped: "c:\\my\\working\ \folder\\" at least on Windows.

However, the second example, I'm not totally sure I'm reading it properly.  I'm tempted to interpret it in a UNIX-pipe-like way, with the open curly brace acting the part of a UNIX pipe.  This feels like a kind of stretch, and I haven't been able to find anything inwww.ruby-doc.org to confirm this idea, but it does make the whole thing make sense in my mind.  I hope I'm not too far off.

In this interpretation, the output of the File.open, a file handle, is passed to the curly braces and inside that the fh variable gets assigned whatever is passed to the braces, in this case the file hande.  With a file handle in place as fh, you can now use the handle method, print, so the actual command, fh.print "Hello" is the same in both examples.  With the closing curly brace, fh goes away because it never existed outside the braces, which closes the file.

File.open may take an optional code block as an argument. If it does, the code block will be passed the IO object as an argument, and will be closed on exiting the block.

So for my case of how to print Object.to_s, I could do:

s = Object.to_s File.open("c:/temp/rubyout.txt", "a") { |fh|   fh.print s }

In this example, you don't really need the variable s if you just use Object inline:

File.open("c:/temp/rubyout.txt", "a") { |fh| fh.print Object.to_s } (The line-breaks and indentation don't mean anything to Ruby, it's for you and me.) Note also, opening and closing files can take up a lot ofresources. If you plan on printing a lot of output, it may be better to open the file once, perform all the output, and close it when you're done. In the above example, there is alot of overhead in opening and closing the file object for each thing you print.

which would create a new file if it did not exist and append to it if it did.

Or raise an exception if it could not.

If it does work like I'm starting to think it does, could I nest them?  Could I do something like:

Object.to_s { |s| File.open("c:/temp/rubyout.txt", "a") { |fh|   fh.print s } } or with possibly clearer indenting:

Object.to_s \ { |s|     File.open("c:/temp/rubyout.txt", "a") \     { |fh|         fh.print s     }

}

Here I'm assuming that the inner braces (does this have a name? Am I talking about it the right way?) will know about the s variable created in the outer braces.

It's a code block, and the block is being passed to the "open" method as an argument. The variable inside the |bars| is an argument passed to the code block. It's harder to explain than to understand.

1.upto(5) { |x| print x }

The code block is being passed to the method call upto. What you need to know is that the method upto is written to accept a code block. the method to_s is not.

Please let me know if I'm on the right track, particularly about the open-curly-brace-as-UNIX-pipe assumption.

No, to_s is a method call. It does not accept any arguments, much less a code block as an argument. It returns a String representation of the object.

class N; end n = N.new n.to_s ==> #<N:0x3c86e88>

If you want to change it so all instances of class N use the modified to_s, you need to re-define it.

class N def to_s print "Hi, I'm an N: " end end

print n

I hope this helps some. Some of it may be fragmented as I was jumping around a lot.