Module: Doodle::Factory

Defined in:
lib/doodle.rb

Overview

A factory function is a function that has the same name as a class which acts just like class.new. For example:

Cat(:name => 'Ren')

is the same as:

Cat.new(:name => 'Ren')

As the notion of a factory function is somewhat contentious [xref ruby-talk], you need to explicitly ask for them by including Factory in your base class:

class Base < Doodle::Root
  include Factory
end
class Dog < Base
end
stimpy = Dog(:name => 'Stimpy')

etc.

Constant Summary collapse

RX_IDENTIFIER =
/^[A-Za-z_][A-Za-z_0-9]+\??$/

Class Method Summary collapse

Class Method Details

.factory(konst) ⇒ Object

create a factory function in appropriate module for the specified class



870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
# File 'lib/doodle.rb', line 870

def factory(konst)
  name = konst.to_s
  names = name.split(/::/)
  name = names.pop
  if names.empty?
    # top level class - should be available to all
    klass = Object
    method_defined = begin
                       method(name)
                       true
                     rescue Object
                       false
                     end
    
    if name =~ Factory::RX_IDENTIFIER && !method_defined && !klass.respond_to?(name) && !eval("respond_to?(:#{name})", TOPLEVEL_BINDING) 
      eval("def #{ name }(*args, &block); ::#{name}.new(*args, &block); end", ::TOPLEVEL_BINDING, __FILE__, __LINE__)
    end
  else
    klass = names.inject(self) {|c, n| c.const_get(n)}
    # todo[check how many times this is being called]
    if name =~ Factory::RX_IDENTIFIER && !klass.respond_to?(name)
      klass.module_eval("def self.#{name}(*args, &block); #{name}.new(*args, &block); end", __FILE__, __LINE__)
    end
  end
end

.included(other) ⇒ Object

inherit the factory function capability



897
898
899
900
901
# File 'lib/doodle.rb', line 897

def included(other)
  super
  # make +factory+ method available
  factory other
end