def webs @webs ||= Web.find(:all).inject({}) { |webs, web| webs.merge(web.address => web) } end -- Posted via http://www.ruby-forum.com/.
Eric Anderson
2006-Jul-25 13:57 UTC
[Rails] Re: Can anyone explain this code? It uses Inject
Chris wrote:> def webs > @webs ||= Web.find(:all).inject({}) { |webs, web| > webs.merge(web.address => web) } > end >Turns an array into a hash with the web address as a key. Eric
On 7/25/06, Chris <cadams1342@hotmail.com> wrote:> > def webs > @webs ||= Web.find(:all).inject({}) { |webs, web| > webs.merge(web.address => web) } > end > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >@webs ||= # if @webs has a vaule do nothing, if it''s nil then put whatever is on the right into @webs Web.find(:all).inject({}){ |webs, web| webs.merge(web.address => web)} Inject can be a bit tricky. basically It might be easier to abstract it. Inject replaces the cumulative with whatever the block evaluates to each iteration starting with the inject parameter. [1,2,3].inject({}) { |cumulative, element| cumulative.merge( element.to_s => element ) } Walking through this one Element 1 cumulative = {} (the param in inject element = 1 (The first element to be iterated over) evaluate block and replace the cumulative cumulative = cumulative.merge( element.to_s => element) #=> gives { ''1'' => 1 } end iteration Element 2 cumulative = { ''1'' => 1 } - The result of the last iteration element = 2 evaluate block and replace the cumulative cumulative = cumulative.merge( element.to_s => element) #=> gives { ''1'' => 1, ''2'' => 2 } end iteration Element 3 cumulative = { ''1'' => 1, ''2'' => 2 } - The result of the last iteration element = 3 evaluate block and replace the cumulative cumulative = cumulative.merge( element.to_s => element) #=> gives { ''1'' => 1, ''2'' =>2, ''3'' => 3 } end iteration and so on. so in the example you would be building a hash of all the web objects of the form web.address => web Hope that helps -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060725/be0793c9/attachment.html
Thanks... that helped -- Posted via http://www.ruby-forum.com/.
Russell Tracey
2006-Jul-26 00:30 UTC
[Rails] Re: Can anyone explain this code? It uses Inject
One other thing to note about the code is that it creates quite a few hashes, 1 initial hash and one for each element in the array. Using the more abstract example and irb: irb(main):001:0> [1,2,3].inject({}) { |cumulative, element| puts cumulative.object_id; cumulative.merge( element.to_s => element ) } 23135864 23135732 23135648 => {"1"=>1, "2"=>2, "3"=>3} Here you can see the object_id is different each time, indicating that cumulative is different on each interation and therefore a new object. This can be avoided by using the merge! method that will modify the cumulative object instead of returning a new Hash on each iteration. irb(main):002:0> [1,2,3].inject({}) { |cumulative, element| puts cumulative.object_id; cumulative.merge!( element.to_s => element ) } 23116412 23116412 23116412 => {"1"=>1, "2"=>2, "3"=>3} russ. -- Posted via http://www.ruby-forum.com/.
On 7/25/06, Chris <cadams1342@hotmail.com> wrote:> def webs > @webs ||= Web.find(:all).inject({}) { |webs, web| > webs.merge(web.address => web) } > endFYI in edge rails: def webs @webs ||= Web.find(:all).index_by &:address end -- Rick Olson http://techno-weenie.net
Rick Olson wrote:> On 7/25/06, Chris <cadams1342@hotmail.com> wrote: >> def webs >> @webs ||= Web.find(:all).inject({}) { |webs, web| >> webs.merge(web.address => web) } >> end > > FYI in edge rails: > > def webs > @webs ||= Web.find(:all).index_by &:address > endDoes the ampersand mean anything, or is it a typo? Joe -- Posted via http://www.ruby-forum.com/.
On 7/27/06, Joe <joe@yahoo.com> wrote:> > Rick Olson wrote: > > On 7/25/06, Chris <cadams1342@hotmail.com> wrote: > >> def webs > >> @webs ||= Web.find(:all).inject({}) { |webs, web| > >> webs.merge(web.address => web) } > >> end > > > > FYI in edge rails: > > > > def webs > > @webs ||= Web.find(:all).index_by &:address > > end > > Does the ampersand mean anything, or is it a typo? > > Joe >--> Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >The ampersand is a Symbol#to_proc. It''s a nice shorcut and basically says use the address method on the object passed into the block. The equivelant is @webs || Web.find(:all).index_by { |web| web.address } -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060727/ede59bee/attachment.html
Peter De Berdt
2006-Jul-27 12:39 UTC
[Rails] Re: Can anyone explain this code? It uses Inject
On 27 Jul 2006, at 07:03, Joe wrote:> Rick Olson wrote: >> On 7/25/06, Chris <cadams1342@hotmail.com> wrote: >>> def webs >>> @webs ||= Web.find(:all).inject({}) { |webs, web| >>> webs.merge(web.address => web) } >>> end >> >> FYI in edge rails: >> >> def webs >> @webs ||= Web.find(:all).index_by &:address >> end > > Does the ampersand mean anything, or is it a typo?It converts the argument to a Proc. You can find everything you need to know at http://eli.thegreenplace.net/2006/04/18/understanding-ruby- blocks-procs-and-methods/ (search for "The ampersand (&)" in the article). Best regards Peter De Berdt