Can anyone give me a good small sample for Metapgramming with Ruby?
There you go:
require 'fileutils'
module Files
extend self
def in(dir)
dir = File.expand_path(dir)
Class.new do
extend Enumerable
@@dir = dir
class <<self; self; end.class_eval do
alias old_new new
private
ld_new
def new(filename, contents=nil, &blk)
if contents
open("#{dirname}/#{filename}", "w") do |f|
f.write contents
end
elsif blk
open("#{dirname}/#{filename}", "w", &blk)
else
open("#{dirname}/#{filename}", "w") {}
end
old_new(filename)
end
def dirname() @@dir end
def each()
Dir.glob("#{dirname}/*") {|f| yield old_new(f)}
end
def to_s()
"#{dirname}"
end
def inspect
"Directory: #{self}"
end
Dir.glob("#{dir}/*") do |file|
define_method(File.basename file) do
old_new(File.basename file)
end
end
end
def initialize(filename)
@filename = filename
end
def path()
"#{self.class.dirname}/#{@filename}"
end
alias to_s path
def inspect
"File: #{self}"
end
def open(*args, &blk)
Kernel.open(path, *args, &blk)
end
def delete
FileUtils.rm(path)
name = @filename
class <<self.class; self end.class_eval do
undef_method(name)
end
end
end
end
end
Ok, this took way more time to write than I expected and also turned out quite
a bit bigger and isn't really tested very thoroughly. But the idea is a such:
Using Files.in(dirname) you can get a class representing that directory.
This class will have a method for every file in that directory.
Calling such a method will give you an instance of the class, representing the
specific file.
Calling new(filename) on the class will create a file in that directory.
The class is extended with Enumerable and you can use it to iterate over its
instances representing the files that exist the directory.
Of course this is quite a complicated way to work with files, but you wanted
meta-programming, so there you go.
(I did intend this to be simpler than it turned out to be, though)
HTH,
Sebastian