If you need to get something out of the database, consider using
pluck to avoid
creating instances you don't need.
I am working with an old code base at the moment and do a lot of refactoring. That provides me with something to think about every day.
In this particular code base I see a lot of transformation of database objects in Ruby, but is that effective? Let's check and see if we can improve anything.
Before venturing off let's create a test bench to measure performance:
map on this particular piece of code:
We see almost no difference, so what's the point? But performance depends on other factors.
Let's try it with something more substantial:
Now, we're talking, but in fact we're not. This code is used once in the controller, and it might be that there is no actual performance benefit especially when using small amount of data:
You have to be especially careful inside of the loops. This is not a rule of the thumb
but when dealing with database I would conside using
select is a different beast. Affected by Rails Magic it can act differently
things depending on its position in
ActiveRecord chain. Plus there are different
What is important to rememeber is that
select might return instanciated real-only objects
with paritally filled attributes. It can also return a sub-query, but that's another topic.
Armed with this knowlegde, let's find a better specimen for refactoring.
A better example
Here is a good candidate for improvement I stumbled upon in a few places. It returns an array of first letters in names in collection to build and alphabetic lister later.
What immediately grabs attention is how database output that ends at
.all being treated in Ruby.
Let's look at
The query does not look particulary mean or anything, again, especially if your
database is not that big. Unfortunately for us
select instantiates a bunch of
half-filled (or half-empty) objects:
This is unacceptable, lets rewrite this using
pluck instead of
DISTINCT instead of
uniq and throw away the rest:
Another thing to keep in mind when using
pluck - it returns the array and
ActiveRecord query method chain. And if you need to use the values
in a subsequent query you might be actually needing
select as it would
construct a subquery to use. But in our case we don't need anything else so that's fine.
Finally, something good comes out of this refactoring. Moving the code to concern:
Hey, what about sorting?
Okay, you got me. Yes that is a good question. But let's think about it first. As I output the results in alphabetical order and numbers separated from letters that means I have a knowledge of that.
And this knowledge is kept in the view layer. I am simply intersecting arrays like this:
This construct gives me intersections ordered by alphabet and in numerical order if there are any.
One thing less to worry about. That frees up some brain capacity what is in my book ultimately is the point of refactoring.