Daniel DeLorme
8/11/2007 1:32:00 AM
Noah Easterly wrote:
> I'm working on a script that has to work across several versions of
> ruby.
> Sometimes, some versions don't have libraries that I require, so I get
> around that by
> having an alternate implementation for those versions.
>
> For easy testing I like to be able to declare all the implementations
> so I can run them in parallel, and compare results, and create aliases
> to the 'best' implementation.
>
> For example, if in 1.8.8, dentist.rb is available, and before that,
> you could only get hygenist.rb, I might do something like this:
>
> | class ToothCare
> | dentist_load_error = nil
> | begin
> | require 'dentist'
> | # gargle!
> | def dentist_gargle
> | #...
> | end
> | # rinse!
> | def dentist_rinse
> | #...
> | end
> | # spit!
> | def dentist_spit
> | #...
> | end
> | rescue LoadError => dentist_load_error
> | end
> | hygenist_load_error = nil
> | begin
> | require 'hygenist'
> | # gargle!
> | def hygenist_gargle
> | #...
> | end
> | # rinse!
> | def hygenist_rinse
> | #...
> | end
> | # spit!
> | def hygenist_spit
> | #...
> | end
> | rescue LoadError => hygenist_load_error
> | end
> | prefix = if dentist_load_error.nil?
> | 'dentist'
> | elsif hygenist_load_error.nil?
> | 'hygenist'
> | else
> | raise LoadError, [
> | "Could not find dentist or hygenist, sorry...",
> | dentist_load_error,
> | hygenist_load_error
> | ].join("\n")
> | instance_methods.each do |method|
> | next unless method =~ /^#{prefix}_(\w+)$/
> | alias_method $1, method
> | end
> | end
>
> Whoever uses ToothCare can just call #gargle,#rinse,or #spit - they
> don't have to worry about which implementation they're using.
> Meanwhile, I can use #dentist_gargle and #hygenist_gargle to test and
> compare.
>
> This works pretty well, except when I run RDoc. It's not smart enough
> to figure out that the alias_method creates instance methods named
> #gargle,#rinse, and #spit, and so they don't get documented.
>
> Is there any easy and DRY way I can tell RDoc to document those
> methods?
hmm, maybe you can split your code into mixins;
begin
require 'dentist'
module DentistToothCare
def dentist_gargle
#...
end
...
instance_methods.each do |method|
alias_method method, "dentist_#{method}"
end
end
rescue LoadError => dentist_load_error
end
class ToothCare
if dentist_load_error.nil?
include DentistToothCare
else
include HygenistToothCare
end
#doc for "gargle"
def gargle; super; end
end
Just a (dumb?) idea
Daniel