Ruby Tricks I've learned

I’m not sure if this will be an constantly updated post or if I’ll just make new blog posts as I discover new tricks but here are some interesting ruby tricks I’ve recently learned anyway

#partition

So this is one I actually learned from elixir but I’m happy to say it’s available in ruby and javascript (via lo-dash)

Say you have two groups of things and you need to separate them. For example you have a collection of objects that you want to save, and you want to report how many succeeded and how many failed you could do something like this:

saved, failed = array_of_objects.map(&:save).partition(&:saved?)
puts "#{saved.size} saved successfully, #{failed.size} failed to save

This is actually two tricks in one, so partition will take your array and as the name suggests will partition it into two arrays based on the result of the predicate function, with the first array being items that the function returned true, and the rest being the ones the function returned false. since the return will be [[objs], [objs]] we can use ruby’s parallel assignment to assign the first value of the array to the first variable and the second to the second.

#& (array intersect)

Array intersection finds the similar elements in two arrays, and usually is used to determine if “any of these elements exist in this set”. For whatever reason I’ve always found a difficult way to implement this but it turns out there is an operator for this in ruby the & operator. So [1,2,3] & [3,4,5] would return 3 since that element is common in both arrays.

You can use this to implement an any_x_in_y function like so

x = [1,2,3,4,5]

def any_x_in?(y)
  (x & y).any?
end
any_x_in?([3,4])
=> true

#tap

So you may have wondered about my previous example of saving via map then calling saved? on the result. There is a strong possibility that your framework returns the result of the save instead of the object that was saved (I know ActiveRecord does). So what do you do when you want to modify an object and return it instead of returning the result of the method call? You use the tap method.

Tap takes an object, passes it to a block where the object can be modified then afterwards returns the object, like so:

model = some_model.save
puts model
=> true

vs

model = some_model.tap do |some_model|
  some_model.save
end

puts model 
=> some_model

or

model = some_model.tap(&:save)

So while not as nice, to map my previous example work you’d likely have to expand the map and drop a tap in

saved, failed = array_of_models.map do | model | 
  model.tap(&:save)
end.partition(&:saved?)

#lazy

It’s not uncommon that you’ll have an enumerable set that’s expensive to compute, for example, if you need to hit an API that doesn’t have a bulk result endpoint.

Fortunately, ruby has your back here in the form of Enumerable#lazy. For example, I’ll use the example directly from the ruby docs

(1..Float::INFINITY).lazy.filter_map{|i| i*i if i.even?}.first(5)
# => [4, 16, 36, 64, 100]

If you don’t include the .first(5) portion it will return an Enumberable you can iterate with #next

e = (1..Float::INFINITY).lazy.select{|i| i*i if i.even?}
=> #<Enumerator::Lazy: #<Enumerator::Lazy: 1..Infinity>:select>

e.next
=> 2

e.next
=> 4

e.next
=> 6

etc