Sometimes I don''t have a full need to make a class to do something, yet I want something readable and concise. This is influenced from the joys of JavaScript. Today I made this happen. Love it, like it, hate it, WDYT? Spec::Story::Runner.register_listener FunctionalStruct.new( :run_started => lambda { |*args| Generate.user(:login => "normal user") }, :run_ended => lambda { |*args| User.destroy_all }, :method_missing => lambda { |*a| } ) -- Zach Dennis http://www.continuousthinking.com http://www.mutuallyhuman.com
David Chelimsky
2008-Aug-13 01:25 UTC
[rspec-users] WDYT, simple, anonymous story listeners?
On Tue, Aug 12, 2008 at 7:25 PM, Zach Dennis <zach.dennis at gmail.com> wrote:> Sometimes I don''t have a full need to make a class to do something, > yet I want something readable and concise. This is influenced from the > joys of JavaScript. > > Today I made this happen. Love it, like it, hate it, WDYT? > > Spec::Story::Runner.register_listener FunctionalStruct.new( > :run_started => lambda { |*args| > Generate.user(:login => "normal user") > }, > :run_ended => lambda { |*args| > User.destroy_all > }, > :method_missing => lambda { |*a| } > )Love is a bit strong. Like++
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. ;)> This is influenced from the joys of JavaScript.It even looks like JavaScript. :D -- Tero Tilus ## 050 3635 235 ## http://www.tilus.net/koti/tero/
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. :DOne 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
On Tue, Aug 12, 2008 at 9:54 PM, Zach Dennis <zach.dennis at gmail.com> wrote:> There is nothing wrong with this, but there are times when it feels > dirty and unnecessary to create yet another class with some methodsThe proposed solution looks very nice, but I''ve never been convinced by the "yet another class" argument. It''s not like you''re only allowed a certain number. That hasn''t always been the case, however. When I worked at Sierra On-Line in the early ''90s, I broke the compiler of our proprietary OOP language because I exceeded its maximum class count. Those were the days...:) ///ark -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20080812/c9cbc5a3/attachment-0001.html>
It looks like a nice shortcut for those times when you are registering simple one-off listeners. While it does provide a nice shortcut I can see reasons why that shortcut might be bad(in some cases). Separating registering and implementation can be a good thing. *Split the logic. *Organise files/classes nicely *Enable inheritance from the listeners If it was anything that I had to maintain or touch regularly I would be happier with a class. Can/Could you support mixins inside FunctionalStruct? That would help overcome some of those points. I can think of a couple of places that I would be happy using FunctionalStruct. Is the source for ''FunctionalStruct'' written/available? -- Joseph Wilk http://www.joesniff.co.uk Mark Wilden wrote:> On Tue, Aug 12, 2008 at 9:54 PM, Zach Dennis <zach.dennis at gmail.com> > wrote: > > >> There is nothing wrong with this, but there are times when it feels >> dirty and unnecessary to create yet another class with some methods > > > The proposed solution looks very nice, but I''ve never been convinced by > the > "yet another class" argument. It''s not like you''re only allowed a > certain > number. > > That hasn''t always been the case, however. When I worked at Sierra > On-Line > in the early ''90s, I broke the compiler of our proprietary OOP language > because I exceeded its maximum class count. Those were the days...:) > > ///ark-- Posted via http://www.ruby-forum.com/.
aslak hellesoy
2008-Aug-13 12:29 UTC
[rspec-users] WDYT, simple, anonymous story listeners?
On Wed, Aug 13, 2008 at 2:25 AM, Zach Dennis <zach.dennis at gmail.com> wrote:> Sometimes I don''t have a full need to make a class to do something, > yet I want something readable and concise. This is influenced from the > joys of JavaScript. > > Today I made this happen. Love it, like it, hate it, WDYT? >As mentioned earlier on the RSpec development list, we''re considering replacing the Story runner with a new implementation: http://github.com/aslakhellesoy/cucumber http://gojko.net/2008/08/06/cucumber-next-generation-ruby-bdd-tool/ http://www.nabble.com/-ANN--Cucumber-td18876816.html I''d rather see a similar construct for Cucumber, which already is (IMHO) much better than the Story Runner. Before(:all) do end After(:all) do end (per-scenarion Before/After is already implemented). Aslak> Spec::Story::Runner.register_listener FunctionalStruct.new( > :run_started => lambda { |*args| > Generate.user(:login => "normal user") > }, > :run_ended => lambda { |*args| > User.destroy_all > }, > :method_missing => lambda { |*a| } > ) > > > -- > Zach Dennis > http://www.continuousthinking.com > http://www.mutuallyhuman.com > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On Wed, Aug 13, 2008 at 5:26 AM, Joseph Wilk <lists at ruby-forum.com> wrote:> It looks like a nice shortcut for those times when you are registering > simple one-off listeners. > > While it does provide a nice shortcut I can see reasons why that > shortcut might be bad(in some cases). > > Separating registering and implementation can be a good thing. > *Split the logic. > *Organise files/classes nicely > *Enable inheritance from the listeners > > If it was anything that I had to maintain or touch regularly I would be > happier with a class. > > Can/Could you support mixins inside FunctionalStruct? That would help > overcome some of those points.Yeah you definitely could, perhaps something like: FunctionalStruct.new( SomeModule, :foo => ..., :bar => ..., )> I can think of a couple of places that I would be happy using > FunctionalStruct. Is the source for ''FunctionalStruct'' > written/available?http://github.com/zdennis/functional_struct/tree/master -- Zach Dennis http://www.continuousthinking.com http://www.mutuallyhuman.com
On Wed, Aug 13, 2008 at 8:29 AM, aslak hellesoy <aslak.hellesoy at gmail.com> wrote:> On Wed, Aug 13, 2008 at 2:25 AM, Zach Dennis <zach.dennis at gmail.com> wrote: >> Sometimes I don''t have a full need to make a class to do something, >> yet I want something readable and concise. This is influenced from the >> joys of JavaScript. >> >> Today I made this happen. Love it, like it, hate it, WDYT? >> > > As mentioned earlier on the RSpec development list, we''re considering > replacing the Story runner with a new implementation: > > http://github.com/aslakhellesoy/cucumber > http://gojko.net/2008/08/06/cucumber-next-generation-ruby-bdd-tool/ > http://www.nabble.com/-ANN--Cucumber-td18876816.html > > > I''d rather see a similar construct for Cucumber, which already is > (IMHO) much better than the Story Runner. > > > Before(:all) do > end > > After(:all) do > end > > (per-scenarion Before/After is already implemented). >When you say "rather see a similar construct" -- are you referring to having the Before(:all) and After(:all) capability that you posted, or something similar to what I posted with using a FuncionalStruct as an argument to register a listener on the existing StoryRunner (a clear/concise way to hook-in with those one off listeners) ? -- Zach Dennis http://www.continuousthinking.com http://www.mutuallyhuman.com
aslak hellesoy
2008-Aug-13 15:00 UTC
[rspec-users] WDYT, simple, anonymous story listeners?
On Wed, Aug 13, 2008 at 4:50 PM, Zach Dennis <zach.dennis at gmail.com> wrote:> On Wed, Aug 13, 2008 at 8:29 AM, aslak hellesoy > <aslak.hellesoy at gmail.com> wrote: >> On Wed, Aug 13, 2008 at 2:25 AM, Zach Dennis <zach.dennis at gmail.com> wrote: >>> Sometimes I don''t have a full need to make a class to do something, >>> yet I want something readable and concise. This is influenced from the >>> joys of JavaScript. >>> >>> Today I made this happen. Love it, like it, hate it, WDYT? >>> >> >> As mentioned earlier on the RSpec development list, we''re considering >> replacing the Story runner with a new implementation: >> >> http://github.com/aslakhellesoy/cucumber >> http://gojko.net/2008/08/06/cucumber-next-generation-ruby-bdd-tool/ >> http://www.nabble.com/-ANN--Cucumber-td18876816.html >> >> >> I''d rather see a similar construct for Cucumber, which already is >> (IMHO) much better than the Story Runner. >> >> >> Before(:all) do >> end >> >> After(:all) do >> end >> >> (per-scenarion Before/After is already implemented). >> > > When you say "rather see a similar construct" -- are you referring to > having the Before(:all) and After(:all) capability that you posted, or > something similar to what I posted with using a FuncionalStruct as an > argument to register a listener on the existing StoryRunner (a > clear/concise way to hook-in with those one off listeners) ? >By "similar construct" I meant something that achievs the same goal (running pieces of code at different times during the run). I suggested Before(:all) and After(:all) because: * It''s a familiar concept from RSpec examples * It''s much easier to read/write Compare these: # Your suggestion Spec::Story::Runner.register_listener FunctionalStruct.new( :run_started => lambda { |*args| Generate.user(:login => "normal user") } ) # My suggestion: Before(:all) do # We can pass args to the block if we want to Generate.user(:login => "normal user") end Aslak> -- > Zach Dennis > http://www.continuousthinking.com > http://www.mutuallyhuman.com >
On Wed, Aug 13, 2008 at 11:00 AM, aslak hellesoy <aslak.hellesoy at gmail.com> wrote:> On Wed, Aug 13, 2008 at 4:50 PM, Zach Dennis <zach.dennis at gmail.com> wrote: >> On Wed, Aug 13, 2008 at 8:29 AM, aslak hellesoy >> <aslak.hellesoy at gmail.com> wrote: >>> On Wed, Aug 13, 2008 at 2:25 AM, Zach Dennis <zach.dennis at gmail.com> wrote: >>>> Sometimes I don''t have a full need to make a class to do something, >>>> yet I want something readable and concise. This is influenced from the >>>> joys of JavaScript. >>>> >>>> Today I made this happen. Love it, like it, hate it, WDYT? >>>> >>> >>> As mentioned earlier on the RSpec development list, we''re considering >>> replacing the Story runner with a new implementation: >>> >>> http://github.com/aslakhellesoy/cucumber >>> http://gojko.net/2008/08/06/cucumber-next-generation-ruby-bdd-tool/ >>> http://www.nabble.com/-ANN--Cucumber-td18876816.html >>> >>> >>> I''d rather see a similar construct for Cucumber, which already is >>> (IMHO) much better than the Story Runner. >>> >>> >>> Before(:all) do >>> end >>> >>> After(:all) do >>> end >>> >>> (per-scenarion Before/After is already implemented). >>> >> >> When you say "rather see a similar construct" -- are you referring to >> having the Before(:all) and After(:all) capability that you posted, or >> something similar to what I posted with using a FuncionalStruct as an >> argument to register a listener on the existing StoryRunner (a >> clear/concise way to hook-in with those one off listeners) ? >> > > By "similar construct" I meant something that achievs the same goal > (running pieces of code at different times during the run). > > I suggested Before(:all) and After(:all) because: > > * It''s a familiar concept from RSpec examples > * It''s much easier to read/write > > Compare these: > > # Your suggestion > Spec::Story::Runner.register_listener FunctionalStruct.new( > :run_started => lambda { |*args| > Generate.user(:login => "normal user") > } > ) > > # My suggestion: > Before(:all) do # We can pass args to the block if we want to > Generate.user(:login => "normal user") > end >Before/After is definitely much cleaner, although I''m not a fan of more global namespace pollution, but it may not be a problem in practice (and/or maybe it''s scoped in to another namespace like Feature::Before(:all)) Are you thinking of allowing for multiple Before/After(:all) blocks? -- Zach Dennis http://www.continuousthinking.com http://www.mutuallyhuman.com
aslak hellesoy
2008-Aug-13 15:26 UTC
[rspec-users] WDYT, simple, anonymous story listeners?
On Wed, Aug 13, 2008 at 5:18 PM, Zach Dennis <zach.dennis at gmail.com> wrote:> On Wed, Aug 13, 2008 at 11:00 AM, aslak hellesoy > <aslak.hellesoy at gmail.com> wrote: >> On Wed, Aug 13, 2008 at 4:50 PM, Zach Dennis <zach.dennis at gmail.com> wrote: >>> On Wed, Aug 13, 2008 at 8:29 AM, aslak hellesoy >>> <aslak.hellesoy at gmail.com> wrote: >>>> On Wed, Aug 13, 2008 at 2:25 AM, Zach Dennis <zach.dennis at gmail.com> wrote: >>>>> Sometimes I don''t have a full need to make a class to do something, >>>>> yet I want something readable and concise. This is influenced from the >>>>> joys of JavaScript. >>>>> >>>>> Today I made this happen. Love it, like it, hate it, WDYT? >>>>> >>>> >>>> As mentioned earlier on the RSpec development list, we''re considering >>>> replacing the Story runner with a new implementation: >>>> >>>> http://github.com/aslakhellesoy/cucumber >>>> http://gojko.net/2008/08/06/cucumber-next-generation-ruby-bdd-tool/ >>>> http://www.nabble.com/-ANN--Cucumber-td18876816.html >>>> >>>> >>>> I''d rather see a similar construct for Cucumber, which already is >>>> (IMHO) much better than the Story Runner. >>>> >>>> >>>> Before(:all) do >>>> end >>>> >>>> After(:all) do >>>> end >>>> >>>> (per-scenarion Before/After is already implemented). >>>> >>> >>> When you say "rather see a similar construct" -- are you referring to >>> having the Before(:all) and After(:all) capability that you posted, or >>> something similar to what I posted with using a FuncionalStruct as an >>> argument to register a listener on the existing StoryRunner (a >>> clear/concise way to hook-in with those one off listeners) ? >>> >> >> By "similar construct" I meant something that achievs the same goal >> (running pieces of code at different times during the run). >> >> I suggested Before(:all) and After(:all) because: >> >> * It''s a familiar concept from RSpec examples >> * It''s much easier to read/write >> >> Compare these: >> >> # Your suggestion >> Spec::Story::Runner.register_listener FunctionalStruct.new( >> :run_started => lambda { |*args| >> Generate.user(:login => "normal user") >> } >> ) >> >> # My suggestion: >> Before(:all) do # We can pass args to the block if we want to >> Generate.user(:login => "normal user") >> end >> > > Before/After is definitely much cleaner, although I''m not a fan of > more global namespace pollution, but it may not be a problem in > practice (and/or maybe it''s scoped in to another namespace like > Feature::Before(:all)) >I''ve thought about that a bit, and decided that I want to keep it global (because it means less typing and looks nicer) until it poses a problem to someone.> Are you thinking of allowing for multiple Before/After(:all) blocks? >Definitely. Before/After (without :all) already supports multiple. Aslak> -- > Zach Dennis > http://www.continuousthinking.com > http://www.mutuallyhuman.com >