To me, it's all about context, or what the problem domain is.

Ruby makes the right choices about the boundaries between objects in 
its problem domain (IMO and AFAIK), which is telling a computer system 
what to do. When we 'print' a 'string' we are sending a stream of 
characters to a device. Our objects are the source of the stream, the 
string, the stream itself, an IO pipe, and the destination, a file or 
something like a file (at least in Unix).

But when, as a simple example, we write a program to print a create a 
standard form document to be filled in by the user and printed on a 
printer attached to their computer (in some fashion and over whatever 
distance) we are in a different problem domain with different objects.

We have template documents. Each template document object has 
attributes (the standard text and 'fields' into which customized 
information is added) and methods (get information and add to 
appropriate field). Each document object created from the template 
object has its own attributes and its own methods. Do we send it a 
message saying print yourself? Maybe. Might the object turn around and 
send its data to another object and say print what I give you? Again, 
maybe. Might this be handled differently, by sending a message to a 
printer object saying go get the document object (or rather, Printer, 
send Document a message saying give me stuff to 'print') and print 
whatever the document object has to be printed. Again, maybe.

Which should we choose? It depends, but the answer has almost nothing 
to do with object oriented programming in and of itself, and everything 
to do with our problem domain. How do we answer the question? In my 
opinion, the best way to answer the question is to start with a use 
case and then begin unit testing (using all or our knowledge and 
experience as point of departure).

Regards,

Mark