Dave Thomas recently suggested a very promising mechanism for handling
platform dependencies in Ruby's libraries (see [ruby-talk: 36496]). Some of
his suggestions will require big chunks of C (eg the OS-specific
functionality: Win32 events, ACLs etc), but other bits can be done in Ruby
(or at least prototyped like that). See below for the beginnings of such
prototype. I don't have time to take this any further, but I'd be more than
happy if someone else wanted to pick it up. As far as I can see, the work
that can be done without C coding is:
- extend to other classes (Dir, File::Stat, Process, Kernel etc)
- handle special cases like File#open (some optional args are Unix specific)
- sort out the infrastructure: file organisation; write Dave's proposed
Kernel#sysdep method etc
- come up with suggestions for a better way of doing this!
Proviso: I'm not very Unix-aware, so I may have been over-zealous in
assigning 'Unix-only' status to some the methods below. Conversely, I may
have missed some too..
-- George
#################
# Infrastructure
#################
class Object
# Returns the singleton class for self
# FIXME Anyone know how to write this without using globals or similar?
def singleton
class << self
$SINGLETON_CLASS = self
end
return $SINGLETON_CLASS
end
end
class Module
# Removes the methods named in NAMES from the class / module SRC and
recreates them on self
def steal_methods(src, names)
names.each do |name|
m = src.instance_method(name)
src.class_eval {remove_method(name)}
self.class_eval {define_method(name, m)}
end
end
# Removes the singleton method(s) called NAMES from the object SRC
# and recreates them on self
def steal_singleton_methods(src, names)
steal_methods(src.singleton, names)
end
end
#################
# Test on arrays
#################
class Array
module ArrayTest
end
module ArrayTestSingleton
end
end
Array::ArrayTest.steal_methods Array, [ :length ]
Array::ArrayTestSingleton.steal_singleton_methods Array, [ :[] ]
# you'll get an error if you remove either of the include/extend lines below
..
class Array
include ArrayTest
extend ArrayTestSingleton
end
# .. but if you leave them in, the following lines work as expected
a = Array[1,2,3]
print "Test using arrays: length is #{a.length}, contents is #{a.inspect}\n"
##############################################
# This is what the real thing might look like
##############################################
class File
module Posix
end
module PosixSingleton
end
end
File::Posix.steal_methods(
File,
[ # ? :atime, # Is access time recorded on all other OSes?
:chmod, # Permissions - clearly Unix only
:chown, # Ownership - clearly Unix only
# ? :ctime, # Is creation time recorded on all other OSes?
:flock, # Unix specific?
:lstat, # Symbolic links - clearly Unix only
# ? truncate, # Programming Ruby says platform-specific, but surely
doesn't have to be?
] )
File::PosixSingleton.steal_singleton_methods(
File,
[ # ? :atime, # as above
:chmod, # as above
:chown, # as above
# ? :ctime, # as above
:link, # Hard links - clearly Unix only
:lstat, # Symbolic links - clearly Unix only
:readlink, # Symbolic links - clearly Unix only
# ? :stat, # Probably OK, but File::Stat object is Unix-specific
:symlink, # Symbolic links - clearly Unix only
# ? truncate, # as above
:umask, # Permissions - clearly Unix only
# ? utime, # Is access time recorded on all other OSes?
] )