The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Now that’s cool…

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Jamis Buck

Posts: 184
Nickname: minam
Registered: Oct, 2004

Jamis Buck is a C/Java software developer for BYU, and hacks in Ruby for fun.
Now that’s cool… Posted: Nov 13, 2004 10:50 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Jamis Buck.
Original Post: Now that’s cool…
Feed Title: the buckblogs here
Feed URL: http://weblog.jamisbuck.org/blog.cgi/programming/index.rss
Feed Description: Jamis Buck's corner of the blogging universe. Mostly about ruby, but includes ramblings on a variety of topics.
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Jamis Buck
Latest Posts From the buckblogs here

Advertisement

Christian Neukirchen asked me a question this morning on IRC. He wanted to know if there was a way to pass parameters to a service’s constructor (in Needle) at the moment the service was requested. This is particularly useful for prototype services, where each request of the service returns a new instance—often, you will want to pass some context-specific data to the constructor of that service.

The short answer is “no”, you can’t really do specifically that in Needle. When I’ve needed something like that, I’ve usually split the constructor in two—creating an “injectible” constructor, and a separate #init method that must be invoked manually after obtaining the service handle in order to pass in the context-specific stuff:

  class Foo
    def initialize( bar )
      @bar = bar
    end

    def init( baz )
      @baz = baz
      do_initialization
      ...
      self
    end
  end

  registry.define.foo( :model => :prototype ) { |c,| Foo.new( c[:bar] ) }

  foo1 = registry.foo.init( "hello" )
  foo2 = registry.foo.init( "world" )

It works, but it is clunky.

This morning, I found a better way, thanks to the power of Ruby’s closures. Ladies and gentlemen, consider the following:

  class Foo
    def initialize( bar, baz )
      @bar = bar
      @baz = baz
      do_initialization
      ...
    end
  end

  registry.define.foo( :model => :prototype ) do |c,|
    lambda { |baz| Foo.new( c[:bar], baz ) }
  end

  foo1 = registry.foo.call( "hello" )
  foo2 = registry.foo.call( "world" )

I love closures! True, the invocation to #call is still a bit clunky, but there’s not really a way to get around it. Besides, if you think about it, what you’ve done is turned the foo service (above) into a factory, which accepts parameters and returns object instances tailored according to those parameters.

I’ve already reworked portions of the Net::SSH rewrite to take advantage of this approach—it’s really slick.

(Oh, and speaking of Net::SSH…connections and channels work! You can now execute processes remotely and respond to events. Remaining to finish: the port forwarding manager, the process manager, and the SFTP subsystem. Whew!)

Read: Now that’s cool…

Topic: Another day in the world-conversion business Previous Topic   Next Topic Topic: Ruby FAQ and RCRchive are put on Rails

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use