[LRUG] Enumerator shenanigans
    Andrew Stewart 
    boss at airbladesoftware.com
       
    Thu Nov 14 06:48:59 PST 2013
    
    
  
> You're right, that approach is a little suboptimal. Ruby provides the `enum_for`[1] method for just this use case. See this gist[2] for your complete code, but the trick is to use this  line at the beginning of the method.
> 
>    return enum_for(:find_each) unless block_given?
> 
> You, also then, don't need to explicitly create the Enumerator. Effectively `enum_for` will use the method in-place of the block when initialising the Enumerator.
Aha.  I had read the docs for `enum_for` but didn't understand them.  It makes sense now.  BTW, it turns out I need to pass `params` as the second argument to `enum_for`.
> With regards to lazy enumerators, neither of those examples are using lazy enumeration. IIRC both of those examples will work in Ruby 1.9 and 2.0.
Okey dokey.
> Also, I don't think this example will work as I suspect `reduce`, in this case, doesn't return an `Enumerable`. So `take` will raise an error.
> 
>   Item.find_each.map(&:price).reduce(:+).take(75)
Oops, typo.
> In Ruby 2.0 you need to use the `lazy`[3] method to get a lazy enumerator. So for example:
> 
>    Item.find_each.lazy.take(75).map(&:price).reduce(:+)
> 
> although in this specific case it doesn't change the result – and in all likelihood will make things slower.
OK, I'll leave it up to the caller.
> I did a talk on Enumerators at last months LRUG, the video[4] and slides[5] are online. There's also an example of where I used a similar pattern[6].
Thanks for the links.  I had to read your paginated collection several times to understand it ;)
> Hope thats useful.
Very – thanks for the detailed reply.
Cheers,
Andy
    
    
More information about the Chat
mailing list