From: Ezra Zygmuntowicz Date: 2006-10-19T11:48:47+09:00 Subject: Re: whats this lambda code doing? On Oct 18, 2006, at 7:38 PM, Ezra Zygmuntowicz wrote: > Yes thats essentially it. Maybe this helps clear it up a bit. Lets > forget about the with_scope AR stuff for a minute and just mock > this out: > > class Scoper > def self.with_block(hsh={}, &block) > p hsh.merge( {:klass => name}) > block.call > end > end > > class Foo < Scoper > end > > class Bar < Scoper > end > > class Baz < Scoper > end > > def set_scopers(klasses=[Foo, Bar, Baz], &block) > hash = {:test => 'test'} > klasses.inject(block) do |blk, klass| > lambda { klass.with_block hash, &blk } > end.call > end > > puts set_scopers { puts 'done'} > > # outputs > {:test=>"test", :klass=>"Baz"} > {:test=>"test", :klass=>"Bar"} > {:test=>"test", :klass=>"Foo"} > done > > > > Now if you comment out the block.call line in the Scoper.with_block > method: > > class Scoper > def self.with_block(hsh={}, &block) > p hsh.merge( {:klass => name}) > #block.call > end > end > > > > puts set_scopers { puts 'done' } > #ouput > {:test=>"test", :klass=>"Baz"} > nil > > > and run the same code again it only calls the last lambda that gets > made. It is a twisty little mess of block and wrappers that is hard > to follow. But essentially inject is chaning those lambda's > together and the final .call calls the chain which calls the final > &blk in the end. > nil What it is doing with the inject is essentially building up a block with multiple procs inside it and then calling that. So the block that gets called looks something like this by the time it gets call'ed: lambda { lambda { Foo.with_block hash, &blk } lambda { Bar.with_block hash, &blk } lambda { Baz.with_block hash, &blk } }.call Make sense? -- Ezra Zygmuntowicz -- Lead Rails Evangelist -- ez@engineyard.com -- Engine Yard, Serious Rails Hosting -- (866) 518-YARD (9273)