[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