[rspec-users] WDYT, simple, anonymous story listeners?

Zach Dennis zach.dennis at gmail.com
Wed Aug 13 00:54:51 EDT 2008


On Wed, Aug 13, 2008 at 12:24 AM, Tero Tilus <tero at tilus.net> wrote:
> 2008-08-12 20:25, Zach Dennis:
>> Sometimes I don't have a full need to make a class to do something,
>
> How's that _essentially_ different from making a class or extending an
> existing class?  I am not knowledgeable enough to "just see" it, and
> becaus I can't understand the motivation, I'm bound to hate it.  ;)

The biggest difference is that you can pass the whole thing as an
argument into the method you're calling (reduce noise, increase
clarity). If you used something like OpenStruct you couldn't do it,
because in Ruby you can't force invocation of a Proc object (you have
to call "call" on it).

For example, this wouldn't work using an OpenStruct:

  Spec::Story::Runner.register_listener OpenStruct.new(
   :run_started => lambda { |*args|
     Generate.user(:login => "normal user")
   },
   :run_ended => lambda { |*args|
       User.destroy_all
   },
   :method_missing => lambda { |*a| }
  )

In order for this to work we'd have to create a class for our listener, like so:

  class MyStoryListener
    def run_started(*args)
      Generate.user(:login => "normal user")
    end

    def run_ended(*args)
      User.destroy_all
    end

    def method_missing(*args)
    end
  end

   # and register it separately
   Spec::Story::Runner.register_listener MyStoryListener.new

There is nothing wrong with this, but there are times when it feels
dirty and unnecessary to create yet another class with some methods,
just so the thing can be instantiated one time and passed in as an
argument. That's why I decided to throw together a little
FunctionalStruct, so if Proc objects got passed in they would be
invokable.

Here's a more specific example of the different between OpenStruct and
FunctionalStruct:

  # openstruct example
  o = OpenStruct.new :foo => lambda { "foo" }
  o.foo # => <Proc:#asfsblahblahblah>
  o.foo.call # => "foo"

  # functionalstruct example
  f = FunctionalStruct.new :foo => lambda { "foo" }
  f.foo # => "foo"

>> This is influenced from the joys of JavaScript.
>
> It even looks like JavaScript.  :D

One thing I miss from JavaScript is that functions are truly first
class citizens. The beauty of Ruby is that I can mimic that by writing
something like FunctionalStruct.


-- 
Zach Dennis
http://www.continuousthinking.com
http://www.mutuallyhuman.com


More information about the rspec-users mailing list