Is there any object-oriented File class in ruby ?

T

tom_33

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
 
J

Justin Collins

tom_33 said:
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.

<snip>

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


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
 
7

7stud --

tom_33 said:
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?
 
S

s.ross

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=> 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.
 
7

7stud --

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.
 
G

Gary Wright

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 Wright
 
C

Christopher Dicely

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.
 
M

Marc Heiler

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.
 
D

Daniel Brumbaugh Keeney

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.

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 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 Keeney
 
G

Gary Wright

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>
 
7

7stud --

Christopher said:
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>
 
T

Thomas Wieczorek

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"
 
A

Arlen Cuss

[Note: parts of this message were removed to make it a legal post.]

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
 
P

Peter Hickman

7stud said:
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.
 
A

Arlen Cuss

[Note: parts of this message were removed to make it a legal post.]

Hi,

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
 
J

Jan Friedrich

7stud said:
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. :p

Regards
Jan
 
C

Christopher Dicely

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.
 
F

F. Senault

Le 20 février à 16:06, Christopher Dicely 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 <REP> .
| 20/02/2008 16:35 <REP> ..
| 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 <REP> .
| 20/02/2008 16:35 <REP> ..
| 20/02/2008 16:35 <REP> 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
 
L

Luis Lavena

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,
 
T

tom_33

Yes, File.basename *is* a string parsing function.


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.

Yes, you are right and internally the implemention of the java method
will need to parse the string somehow.
However, an important difference with ruby File class and the java
File class is that the java class provides a cohesive unit of instance
methods that encapsulates a file path, without having to provide a
string as parameter to every method.
Since the ruby class method "File.basename(filename)" is nothing but a
string parsing method it does IMHO not provide much useful value over
instead having a class method such as
"String.getStringPartAfterLastSlash(anyStringIncludingSomeSlash)"
or
"String.getStringPartAfterLastOccuranceOfSpecifiedCharacter(anyString,
someCharacter)".

Anyway, I have found what I was looking for in another reponse in this
thread:


On Feb 19, 2008, at 5:45 PM, tom_33 wrote:
There is also Pathname, a class for manipulating file path strings
and looking up file properties.

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).

For example, if you would want to implement a methods that renames
files that are old and big (for some reason) then you would do this
kind of stuff with the File class:

if File.size(file_name) > someSizeLimit and File.mtime(file_name) <
someTimeLimit then
... do some string manipulation to extract the filename part from the
full path
... and also extract the directory part ...
new_name = "big_old_file_" + fileNamePart
new_nameWithFullPath = directoryPart + "/" + new_name
File.rename(file_name, new_nameWithFullPath)
end

But with the much better Pathname class you can get an object with
instance methods:

path = Pathname.new(file_name)
if path.size() > someSizeLimit and path.mtime() < someTimeLimit then
directory = path.parent
fileNamePart = path.basename
new_name = "big_old_file_" + fileNamePart
# below file separator concatenation seems to be automatically
included if needed:
newPath = directory + new_name
path.rename(newPath)
end

There are two things that are better with the above code that uses
Pathname instead of File:
(1) You do not have to keep sending the same path string to the
methods but in can be encapsulated and memorized by the Pathname
instance.
(2) You do not need to extract (and concatenate with separators) the
directory part and the filename part through low level string parsing.

Lastly, I just want to complain a little bit about the documentation
of the File class, and hope that someone with write access to the
following page:
http://www.ruby-doc.org/core/classes/File.html
will update it with a reference to the Pathname class, from the the
description section in the beginning.
Without such a reference, it is likely that other people will use the
File class methods, without finding the Pathname class and its nice
instance methods.
Actually, I do not only think it should be mentioned, but it should be
encouraged to use them instead of the File class methods.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top