Ara.T.Howard wrote: ... > class JobRunner > class AbstractJobRunner ... > end > class FTPJobRunner < AbstractJobRunner ... > end > class HTTPJobRunner < AbstractJobRunner ... > end > class SCPJobRunner < AbstractJobRunner ... > end > class << self > def new job > klass = > case job.input > when %r|^ftp://| > FTPJobRunner > when %r|^scp://| > SCPJobRunner > when %r|^http://| > HTTPJobRunner > end > klass::new job > end > end > end In this kind of situation, I like to try to refactor so that the switching is done in the subclasses rather than a big case (as I'm sure you would have done if this had been a real example with a large number of cases). That can be done, for example, by: require 'subclass-keeper' # see below class JobRunner class AbstractJobRunner extend SubclassKeeper def initialize(*args); end end class FTPJobRunner < AbstractJobRunner PAT = %r|^ftp://| end class HTTPJobRunner < AbstractJobRunner PAT = %r|^http://| end class SCPJobRunner < AbstractJobRunner PAT = %r|^scp://| end class << self def new job klass = AbstractJobRunner.proper_subclasses.find do |c| c::PAT === job.input end klass::new job end end end job = Object.new def job.input; "scp://foo.bar"; end jr = JobRunner.new job p jr.class # ==> JobRunner::SCPJobRunner ----- subclass-keeper.rb ---- # Extend a class by SubclassKeeper to record all subclasses (including itself) # and make the list available with the #subclasses method. module SubclassKeeper def inherited(sub) super add_subclass(sub) end def add_subclass(sub) superclass.add_subclass(sub) if superclass.respond_to? :add_subclass (@proper_subclasses ||= []) << sub end protected :add_subclass def proper_subclasses (@proper_subclasses ||= []).dup end def subclasses proper_subclasses.unshift(self) end end if __FILE__ == $0 class Base extend SubclassKeeper end class Sub1 < Base; end class Sub2 < Sub1; end p Base.subclasses p Sub1.subclasses p Sub2.subclasses end