Simple Ruby pleasures

I think I first discovered the joy of take and drop in my journeys through Haskell. But it appears that, since 2008 at least, we have had the pleasure of using them in Ruby too.

Need the first or last N elements from an Enumerable. Easy!

[sourcecode language=“ruby” light=“true”] ary = (1..100).to_a ary.take(5) # => [1, 2, 3, 4, 5] ary.drop(95) # => [96, 97, 98, 99, 100]

range = (1..100) range.take(5) # => [1, 2, 3, 4, 5] range.drop(95) # => [96, 97, 98, 99, 100]

hsh = {:foo => 1, :bar => 2, :baz => 3} hsh.take(1) # => [[:bar, 2]] hsh.drop(2) # => [[:foo, 1]] [/sourcecode]

The real magic is when you use take along with other Enumerable goodies like select and map. Here’s one of my personal favorites amongst the code I wrote in 2010:

[sourcecode language=“ruby” light=“true” highlight=“12,13,14”] class QueryTracer < ActiveSupport::LogSubscriber

ACCEPT = %r{^(app|config|lib)}.freeze FRAMES = 5 THRESHOLD = 300 # In ms

def sql(event) return unless event.duration > THRESHOLD callers = Rails. backtrace_cleaner. clean(caller). select { |f| f =~ ACCEPT }. take(FRAMES). map { |f| f.split(":").take(2).join(":") }. join(" | ")

# Shamelessly stolen from ActiveRecord::LogSubscriber
warning = color(&quot;SLOW QUERY&quot;, RED, true)
name = '%s (%.1fms)' % [event.payload[:name], event.duration]
sql  = event.payload[:sql].squeeze(' ')

warn &quot;  #{warning}&quot;
warn &quot;    #{name} #{sql}&quot;
warn &quot;    Trace: #{callers}&quot;

end

end

QueryTracer.attach_to :active_record [/sourcecode]

This little ditty is awesome because:

  • It's super-practical. Drop this in your Rails 3 app, tail your production log, see the slow queries, go to the method in your app calling it, and fix it. Easy.
  • It only activates itself when it's needed. Queries that execute quickly return immediately.
  • No framework spelunking required. Rails 3's notification system handles all of it. Rails' backtace cleaner gizmo even makes the backtraces much nicer to read.
  • It chains methods to make something that reads like a nice, concise functional program.
For more Enumerable joy, read up on each_cons.
Adam Keys @therealadam