[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