Is there any object-oriented File class in ruby?

I am very new to Ruby and my question is about trying to understand
why Ruby is often described as a “pure object-oriented language”, when
the core library seems to be quite procedural.

For example, the class File seems to have a big bunch of procedural
functions (or static methods, or whatever you want to call them) that
needs the filename to be provided as a parameter.

The File class in java is a much better OO class for managing files:
http://java.sun.com/j2se/1.5.0/docs/api/java/io/File.html
than the following ruby class:
http://ruby-doc.org/core/classes/File.html

For example, the ruby method File.basename is documented as only
supporting forward slashes, regardless of the local file system.
File.basename("/home/gumby/work/ruby.rb") #=> “ruby.rb”
Essentially, this seems to be not much more than a string parsing
function with no OO abstraction that represents a file object.
Compare this with doing the same thing with java:
File f = new File("/home/gumby/work/ruby.rb"); // or new File(“C:\home
\gumby\work\ruby.rb”);
f.getName() #=> “ruby.rb”

Now my question is what have I been missing here ?
I mean, is there any other much better File class somewhere in the
Ruby core that is more pure OO, or otherwise why is a language with a
CORE procedural “class” library described as being a pure oo
language ?

/ Tom

tom_33 wrote:

language ?

/ Tom

You seem to only be looking at the class methods for File, which are
basically utilities. Most of the real functionality is in the IO[1]
class, File’s superclass.

-Justin

[1]http://ruby-doc.org/core/classes/IO.html

tom_33 wrote:

I am very new to Ruby and my question is about trying to understand
why Ruby is often described as a “pure object-oriented language”, when
the core library seems to be quite procedural.

For example, the class File seems to have a big bunch of procedural
functions (or static methods, or whatever you want to call them) that
needs the filename to be provided as a parameter.

The File class in java is a much better OO class for managing files:
http://java.sun.com/j2se/1.5.0/docs/api/java/io/File.html
than the following ruby class:
http://ruby-doc.org/core/classes/File.html

For example, the ruby method File.basename is documented as only
supporting forward slashes, regardless of the local file system.
File.basename("/home/gumby/work/ruby.rb") #=> “ruby.rb”
Essentially, this seems to be not much more than a string parsing
function with no OO abstraction that represents a file object.
Compare this with doing the same thing with java:
File f = new File("/home/gumby/work/ruby.rb"); // or new File(“C:\home
\gumby\work\ruby.rb”);
f.getName() #=> “ruby.rb”

Now my question is what have I been missing here ?
I mean, is there any other much better File class somewhere in the
Ruby core that is more pure OO, or otherwise why is a language with a
CORE procedural “class” library described as being a pure oo
language ?

/ Tom

Look at this code:

class A
def hi
puts ‘hi’
end
end

class B
def B.hello
puts ‘hello’
end
end

a = A.new
a.hi

B.hello

–output:–
hi
hello

Personally, I do not like the formal nature of class B. I prefer the
friendlier, more personable class A. As a result, I do not consider
class B to be object oriented.

Is that a logical conclusion?

Let’s try this:

def hi
puts ‘hi’
end

def hello
puts ‘hi mate’
end

hi
hello

–output:–
hi
hi mate

I consider that output superior, therefore I believe that code is more
object oriented. Is that a logical conclusion?

7stud – wrote:

tom_33 wrote:

I am very new to Ruby and my question is about trying to understand
why Ruby is often described as a “pure object-oriented language”, when
the core library seems to be quite procedural.

For example, the class File seems to have a big bunch of procedural
functions (or static methods, or whatever you want to call them) that
needs the filename to be provided as a parameter.

The File class in java is a much better OO class for managing files:
http://java.sun.com/j2se/1.5.0/docs/api/java/io/File.html
than the following ruby class:
http://ruby-doc.org/core/classes/File.html

For example, the ruby method File.basename is documented as only
supporting forward slashes, regardless of the local file system.
File.basename("/home/gumby/work/ruby.rb") #=> “ruby.rb”
Essentially, this seems to be not much more than a string parsing
function with no OO abstraction that represents a file object.
Compare this with doing the same thing with java:
File f = new File("/home/gumby/work/ruby.rb"); // or new File(“C:\home
\gumby\work\ruby.rb”);
f.getName() #=> “ruby.rb”

Now my question is what have I been missing here ?
I mean, is there any other much better File class somewhere in the
Ruby core that is more pure OO, or otherwise why is a language with a
CORE procedural “class” library described as being a pure oo
language ?

/ Tom

I just wanted to add: there are many bad implementations in ruby. In
addition, there are many bad programmers that badly implement
ruby–check out just about any thread on this forum. A lot of
solutions(most?) will string together 3 or 4 ruby method calls in a one
liner with a couple of regex’s sprinkled in for good measure. As far as
I can tell, not many people know how to write clear efficient ruby code.
Of course their battle cry is: ruby is so inefficient anyway, what does
it matter if I write inefficient and obfuscated code.

On Feb 19, 2008, at 2:45 PM, tom_33 wrote:

For example, the ruby method File.basename is documented as only
supporting forward slashes, regardless of the local file system.
File.basename("/home/gumby/work/ruby.rb") #=> “ruby.rb”
Essentially, this seems to be not much more than a string parsing
function with no OO abstraction that represents a file object.
Compare this with doing the same thing with java:
File f = new File("/home/gumby/work/ruby.rb"); // or new File(“C:\
\home
\gumby\work\ruby.rb”);
f.getName() #=> “ruby.rb”

File is an OO abstraction and the fact that you don’t see explicit
support for alternative path separators does not bear on object
orientedness. Consider this:

class WinFile < File
def self.basename(filename, suffix =’’)
File.basename(filename.gsub(/\/, ‘/’), suffix)
end
end

That allows you to use WinFile everywhere you might have used File,
complete with File’s attributes, collections, iterators, and so on. It
sounds like you are more used to Java’s implementation of this class.

The reason for the “pure” adjective is that everything is derived from
a base class, Object. Fixnum, String, File, everything. So anything
that works on Object works on all of these. Try this:

irb

1.public_methods

long list of methods follows

1.public_methods - Object.public_methods

shorter list of methods belonging to Fixnum. How do we know?

1.class
=> Fixnum

This kind of introspection and single-root object-orientation is much
more difficult in more static languages and allows for much of the
“magic” of Ruby.

On Feb 19, 2008, at 5:45 PM, tom_33 wrote:

Now my question is what have I been missing here ?
I mean, is there any other much better File class somewhere in the
Ruby core that is more pure OO, or otherwise why is a language with a
CORE procedural “class” library described as being a pure oo
language ?

It is described as ‘pure’ because almost all actions are a side-
effect of sending a message to an object. In your example

File.basename('/dir/file')

File is the object, basename is the message, and ‘/dir/file’ is an
argument (an instance of String). The most obvious example of the
pervasiveness of this pattern is methods on integers:

3.next            # 4
3.to_s(2)         # "11", 3 as a string of binary digits
(-3).abs          # 3 the absolute value of -3
(3.1415).floor    # float value rounded down to integer

Many static syntactical constructs also have a dynamic/method based
interface:

subclass A statically

class A < B
def foo
42
end
end

subclass A dynamically

class_b = Class.new(A) {
def foo
42
end
}

A big milestone in learning Ruby is to fully understand what it means
for a class to be an object at runtime. With regard to the methods
you were looking at. If you think of File as an object representing
the file system then:

File.basename(path) # file system parses path
File.open(path) # file system looks up path and returns file
instance

There is also Pathname, a class for manipulating file path strings
and looking up file properties. It provides a unifying interface to
other classes such as File, Dir, FileTests, String, and so on.

path = Pathname.new("/etc")
path.directory? # consults filesystem to see if “/etc”
is a directory
path.atime # consutls filesystem to get atime of “/
etc”

It is also important to realize that Ruby is a practical language in
that there is often more than one way to skin a cat with Ruby as
opposed to a ‘one correct way’. So you can muck around with strings
and regular expressions to parse path names or use File or use
Pathname or roll your own class.

Gary W.

On Feb 19, 2008 2:45 PM, tom_33 [email protected] wrote:

I am very new to Ruby and my question is about trying to understand
why Ruby is often described as a “pure object-oriented language”, when
the core library seems to be quite procedural.

It is a pure object-oriented language because everything is an object,
(even, e.g., things like Fixnum), this contrasts with, e.g., Java,
where certain primitive types are not objects.

For example, the class File seems to have a big bunch of procedural
functions (or static methods, or whatever you want to call them) that
needs the filename to be provided as a parameter.

They are called “Class methods” (because, really, they are just
regular instance methods where the receiver happens to be an instance
of class Class.)

And, yes, the class File has a lot of those, because there are a lot
of times when a program will want to get “one shot” information about
a file. You might also note, however, that many of them have
corresponding instance methods either on class File or class
File::Stat, so if you have an existing File instance, so you can do:

File.atime("/home/jsmith/myfile")
or File.new("/home/jsmith/myfile").atime

File.executable?("/home/jsmith/myfile")
or File.new("/home/jsmith/myfile").stat.executable?

Which way is most appropriate in any given use will depend on whether
there is more that you want to do with the file. There is no reason to
create a new file object and keep it around until it gets garbage
collected if you are just doing a one-shot request and don’t need to
do anything more with the same file. As is often the case in Ruby,
there is more than one way to do it: and all of them are object
oriented.

For example, the ruby method File.basename is documented as only
supporting forward slashes, regardless of the local file system.
File.basename("/home/gumby/work/ruby.rb") #=> “ruby.rb”

The documentation is incorrect.

irb(main):049:0> VERSION
=> “1.8.6”
irb(main):050:0> File.basename(“C:\home\gumby\work\ruby.rb”)
=> “ruby.rb”

Essentially, this seems to be not much more than a string parsing
function with no OO abstraction that represents a file object.

Yes, File.basename is a string parsing function.

Compare this with doing the same thing with java:
File f = new File("/home/gumby/work/ruby.rb"); // or new File(“C:\home
\gumby\work\ruby.rb”);
f.getName() #=> “ruby.rb”

Which also seems to be a string parsing function with no necessary OO
abstraction. Handling a variety of path separators is orthogonal to
whether there is OO abstraction going on.

Now my question is what have I been missing here ?

It seems to me the IO#stat and File#lstat methods, and the File::Stat
class, among other things.

In addition, there are many bad programmers that badly implement
ruby–check out just about any thread on this forum. […]
As far as I can tell, not many people know how to write clear
efficient ruby code.

There are also a few trolls that delight in every chance to bash on ruby
and other ruby-ist’s they can get … right 7stud? But I agree on the
obfuscated part, for the following reason - I think a beautiful language
like ruby, and anyone writing in it, should not try to strive to write
ugly
code. We already have a language that does this part, and as far as I
can
tell it always tried to be a practical language without caring much
about
elegance.

As to the specific question of tom_33 about File class not being
“object oriented”, I assume this in part lies with the separation of
tasks, i.e. if you look at FileUtils and its abilities, and class Dir.
I sometimes confuse whether to use File.exist? or File.exists?
or Dir.exists? or Dir.exist? anyway. (But you can use your
own class and make it “object oriented” super easily. This is one of
ruby’s great points.)

Personally, I do not know why there is this separation (with FileUtils),
but I am quite sure that there was a reason for it.

On Feb 19, 2008, at 7:25 PM, Daniel Brumbaugh K. wrote:

The real
shame in my mind is that File.new doesn’t accept a pathname as a first
parameter, only a string.

That works in 1.9. In fact File.new will accept any argument the
implements #to_path, which should return the string to be passed to
the OS.

irb-1.9> File.new(Pathname.new(’/etc/motd’))
=> #<File:/etc/motd>

Christopher D. wrote:

The documentation is incorrect.

irb(main):049:0> VERSION
=> “1.8.6”
irb(main):050:0> File.basename(“C:\home\gumby\work\ruby.rb”)
=> “ruby.rb”

irb(main):001:0> VERSION
=> “1.8.6”
irb(main):002:0> File.basename(“C:\home\gumby\work\ruby.rb”)
=> “C:\home\gumby\work\ruby.rb”
irb(main):003:0>

On Wed, Feb 20, 2008 at 8:09 AM, 7stud – [email protected]
wrote:

irb(main):001:0> VERSION
=> “1.8.6”
irb(main):002:0> File.basename(“C:\home\gumby\work\ruby.rb”)
=> “C:\home\gumby\work\ruby.rb”
irb(main):003:0>

I am on Windows XP:

irb(main):001:0> File.basename(“C:\home\gumby\work\ruby.rb”)
=> “ruby.rb”
irb(main):002:0> VERSION
=> “1.8.6”

On Feb 19, 2008 4:45 PM, tom_33 [email protected] wrote:

File f = new File("/home/gumby/work/ruby.rb"); // or new File(“C:\home
\gumby\work\ruby.rb”);
f.getName() #=> “ruby.rb”

Now my question is what have I been missing here ?
I mean, is there any other much better File class somewhere in the
Ruby core that is more pure OO, or otherwise why is a language with a
CORE procedural “class” library described as being a pure oo
language ?

/ Tom

I too once thought exactly as you do. I still think it would probably
be best if File didn’t have all those class methods. In reality, I
think what you’re looking for is the Pathname class. In my mind, a
Pathname is a file reference, it has all the appropriate methods of a
file like mtime or directory?. A File, on the other hand, is an IO
stream. An IO stream has no concept of mtime or basename, it is for
reading and writing, and has no business with such methods. The real
shame in my mind is that File.new doesn’t accept a pathname as a first
parameter, only a string.

Daniel Brumbaugh K.

On Feb 20, 2008 10:33 PM, Thomas W. [email protected]
wrote:

I am on Windows XP:

irb(main):001:0> File.basename(“C:\home\gumby\work\ruby.rb”)
=> “ruby.rb”
irb(main):002:0> VERSION
=> “1.8.6”

I do believe (as the evidence has shown) that File.basename is
OS-specific.

Arlen

7stud – wrote:

irb(main):001:0> VERSION
=> “1.8.6”
irb(main):002:0> File.basename(“C:\home\gumby\work\ruby.rb”)
=> “C:\home\gumby\work\ruby.rb”
irb(main):003:0>

So you ran ruby on linux (or OSX) and gave it a fully qualified windows
filename, what were you expecting?

Some magical utility that can take a string and work out what operating
system the filename comes from and then parse that?

Patches welcome.

Hi,

On Feb 20, 2008 10:54 PM, Peter H. [email protected] wrote:

So you ran ruby on linux (or OSX) and gave it a fully qualified windows
filename, what were you expecting?

Some magical utility that can take a string and work out what operating
system the filename comes from and then parse that?

Patches welcome.

Taking a quick look at file.c in Ruby’s source code, it seems we’d just
have
to split the function in two (rather than the define mess we have now),
and
then add a short bit to look for the presence of a start like
/[a-zA-Z]:\/,
then use the DOS-like one, otherwise try Unix-like …

Arlen

7stud – wrote:

irb(main):001:0> VERSION
=> “1.8.6”
irb(main):002:0> File.basename(“C:\home\gumby\work\ruby.rb”) =>
“C:\home\gumby\work\ruby.rb”
irb(main):003:0>

No it is correct: On a Non-Windows system you can have a file with the
name “C:\home\gumby\work\ruby.rb” in the actual directory. :stuck_out_tongue:

Regards
Jan

No, the documentation is incorrect: it states that the only path
separator accepted by File.basename is “/” regardless of OS. But the
method clearly accepts “” (properly escaped) on Windows systems.

Le 20 février à 16:06, Christopher D. a écrit :

No, the documentation is incorrect: it states that the only path
separator accepted by File.basename is “/” regardless of OS. But the
method clearly accepts “” (properly escaped) on Windows systems.

Note that (on Windows XP) :

| C:>mkdir tmp
|
| C:>dir tmp
| Le volume dans le lecteur C s’appelle Disque local
| Le numéro de série du volume est 8C46-917E
|
| Répertoire de C:\tmp
|
| 20/02/2008 16:35 .
| 20/02/2008 16:35 …
| 0 fichier(s) 0 octets
| 2 Rép(s) 162.128.375.808 octets libres
|
| C:>mkdir “tmp/test”
|
| C:>dir tmp
| Le volume dans le lecteur C s’appelle Disque local
| Le numéro de série du volume est 8C46-917E
|
| Répertoire de C:\tmp
|
| 20/02/2008 16:35 .
| 20/02/2008 16:35 …
| 20/02/2008 16:35 test
| 0 fichier(s) 0 octets
| 3 Rép(s) 162.128.375.808 octets libres

And the / character is forbidden in file names.

Fred

On Feb 20, 1:06 pm, Christopher D. [email protected] wrote:

No, the documentation is incorrect: it states that the only path
separator accepted by File.basename is “/” regardless of OS. But the
method clearly accepts “” (properly escaped) on Windows systems.

That is because Ruby on Windows defines File::ALT_SEPARATOR and on
*nix doesn’t:

irb(main):001:0> File::SEPARATOR
=> “/”
irb(main):002:0> File::ALT_SEPARATOR
=> “\”
irb(main):003:0> RUBY_PLATFORM
=> “i386-mswin32”

irb(main):001:0> File::SEPARATOR
=> “/”
irb(main):002:0> File::ALT_SEPARATOR
=> nil
irb(main):003:0> RUBY_PLATFORM
=> “x86_64-linux”

HTH,

On Feb 20, 2008, at 4:29 PM, tom_33 wrote:

Yes, that was indeed the kind of class I was looking for.
Obviously Ruby supports a procedural invocation style of using class
methods on the File class (the same way you would do it with non-oo-
language such as C, i.e. providing the same parameters over and over
again since there is no object that can encapsulate it in a
constructor call).

You are faulting File for not being Pathname but the two classes
serve two different purposes.

File is primarily an interface to the OS system calls, but with some
convenience methods(i.e. basename). Given File you can implement
Pathname but given Pathname you can’t implement File.

If File doesn’t seem OO enough for you that is probably because the
underlying Posix interface to filesystems isn’t really OO either.
That mismatch can be hidden via something like Pathname but at some
point a call has to be passed to the OS and its procedural interface,
which is pretty much what File presents.

I think this is another example where Ruby tends to be pragmatic
rather than pedantic about interfaces. For the simple case of
copying the contents of a file to stdout you could write:

fd = File.new(Pathname.new(’/etc/motd’))
while part = fd.read(100)
STDOUT.puts(part)
end
fd.close

or

STDOUT.puts(Pathname.new(’/etc/motd’).read)

or just

puts File.read(’/etc/motd’)

I know which one I prefer.

Gary W.