From: Jamis Buck Date: 2004-10-15T13:25:05+09:00 Subject: [ANN] Needle 0.5.0 Needle is a new dependency injection (a.k.a. "inversion of control") container for Ruby. Project Page/Downloads:: http://rubyforge.org/projects/needle User Manual (work in progress):: http://needle.rubyforge.org API Documentation:: http://needle.rubyforge.org/api Needle Wiki:: http://needle.rubyforge.org/wiki/wiki.pl This release (0.5) is the first public release. Needle is currently considered experimental software. You are encouraged to download it and try it out, but be warned that subsequent releases of Needle may change the API in non-backwards-compatible ways. This trend will continue until the release of Needle 1.0, at which point Needle will be considered "stable". Please report any bugs. The bug tracker on the project page is a good place to do so, or you can just email me (jgb3@email.byu.edu). Additionally, you might consider taking advantage of the following resources: Bug Reports:: http://rubyforge.org/tracker/?atid=1642&group_id=410&func=browse Forums:: http://rubyforge.org/forum/?group_id=410 Mailing List:: http://rubyforge.org/mailman/listinfo/needle-discuss Feature Requests:: http://rubyforge.org/tracker/?atid=1645&group_id=410&func=browse == FEATURES * Type 2 (setter) injection. This means you can satisfy service dependencies by setting properties on the services. * Type 3 (constructor) injection. This means you can satisfy service dependencies by passing them as parameters to the constructors of the services. * Service Interceptors. This allows you to specify non-intrusive "interceptor" objects that sit between the client and the service, intercepting all method calls to the service. You can implement some simple AOP-like functionality this way. * Integrated, highly-configurable logging subsystem, available as a service. * Service configuration in Ruby (no external configuration files). * Lifecycle management. Configure services to be singletons or prototypes, and to use either immediate or deferred instantiation. * Light-weight, and fast (as compared to Copland) == EXAMPLES Jim (Weirich)'s originally proposed syntax is still completely valid: require 'needle' registry = Needle::Registry.new registry.register( :foo ) { |c| Struct.new( :value ).new( 5 ) } registry.register( :bar ) { |c| Struct.new( :value ).new( c.foo ) } bar = registry.bar p bar.value #-> 5 Additionally, Eivind Eklund suggested a "domain language" approach that is also available: require 'needle' registry = Needle::Registry.new registry.register! do foo { Struct.new( :value ).new( 5 ) } bar { Struct.new( :value ).new( foo ) } end bar = registry.bar p bar.value #-> 5 You can also create hierarchical namespaces inside of a registry: registry.namespace :level1 do |l1| l1.namespace :level2 do |l2| l2.register( :foo ) { "hello" } end end p registry.level1.level2.foo #-> "hello" For more, see the User Manual, and the "examples" subdirectory of the Needle distribution. == HISTORY At RubyConf 2004, Jim Weirich approached me (Jamis Buck) after my presentation on Copland and mused aloud, "I wonder what would happen if you started with Ruby's features and evolved a DI container?" I agreed that it would be an interesting exercise. Jim (being who he is) sent me a rough draft of an article a few days later. This article was one he was going to post on his blog, entitled "Dependency Injection in Ruby" (http://onestepback.org/index.cgi/Tech/Ruby/DependencyInjectionInRuby.rdoc). In it he laid out a bare-bones implementation of DI using some of Ruby's most compelling features, like blocks. Jim granted me permission to work on his implementation, and Needle was born. Eivind Eklund and Mauricio Fern�ndez were both kind enough to review my additions and offer suggestions. -- Jamis Buck jgb3@email.byu.edu http://www.jamisbuck.org/jamis