class Poro::ContextFactories::NamespaceFactory
The NamespaceFactory
uses the module namespace of the class to determine which factory should be used to create a class instance.
On initialization, the default factory should be set. Until other factories are registerd, all classes will recieve contexts created by this factory.
Other factories can be registered against various namespaces. Namespaces are given as a string and are evaluated from the bottom up. For example, if a factory is registered against the class Foo::Bar, then Foo::Bar and Foo::Bar::Baz would each recieve contexts created via that factory, while contexts registered against Foo::Zap would use the default context.
Public Class Methods
Initialize this namespace factory instance with the given default factory. Use register_factory
to add more kinds of factories to this app.
If given a block, it is yielded self for further configuration. This departs slightly from the standard of yielding a Class or Class and Context
for configuration, but as this is more useful for practicle applications. (It also doesn’t configure a context itself, so giving separate blocks to the sub-factories given to it is more appropriate.
# File lib/poro/context_factories/namespace_factory.rb, line 27 def initialize(default_factory=nil) @root_node = CacheNode.new @root_node.factory = default_factory yield(self) if block_given? super() do |klass| factory = self.fetch_factory(klass) factory.nil? ? nil : factory.fetch(klass) end end
Public Instance Methods
Fetches the factory for a given namespace.
This grabs the factory for the most specific matching namespace.
# File lib/poro/context_factories/namespace_factory.rb, line 67 def fetch_factory(namespace='') namespace_stack = namespace.to_s.split('::') lookup_block = lambda do |namespace_stack, last_seen_factory, node| last_seen_factory = node.factory || last_seen_factory if( namespace_stack.length == 0 ) last_seen_factory elsif( !(node.children.include?(namespace_stack[0])) ) last_seen_factory else name, *rest = namespace_stack lookup_block.call(rest, last_seen_factory, node.children[name]) end end return lookup_block.call(namespace_stack, nil, @root_node) end
Registers a factory for a given namespace, given by a string. If a factory is already registered for this namespace, it overrides it.
This registers the given factory not only for this namespace, but for any sub-namespaces that haven’t been specifically overriden. Sub-namespace overrides can be registered either before or after the namespace it overrides.
# File lib/poro/context_factories/namespace_factory.rb, line 45 def register_factory(factory, namespace='') namespace_stack = namespace.to_s.split('::') parse_block = lambda do |factory, namespace_stack, node| if( namespace_stack.length == 0 ) node.factory = factory else name, *rest = namespace_stack child_node = node.children[name] || CacheNode.new node.children[name] = child_node parse_block.call(factory, rest, child_node) end end parse_block.call(factory, namespace_stack, @root_node) return factory end