Assigning variables in a block
I am afraid your code cannot be simplified further due to the imperative nature of Benchmark.realtime (it would have been better if it also returned the result of the block). Anyway, I think the best solution is to abstract it and write a wrapper method. For example:

def benchmark(msg)
  logger.debug(msg)
  result = nil
  ts = Benchmark.realtime(&amp;block) { result = yield }
  logger.debug("Completed in #{ts} seconds")
  result
end

def query(sql)
  benchmark("DB: Executing query #{sql}") do
    @db.exec(sql)
  end
end


Now, if your question was on a more generic plane, let's say, that you have lots of methods that work like realtime which force you write a lot of boilerplate, I'd propose this generic Object#capture wrapper:

class Object
  def capture(method, *args)
    result2 = nil
    result1 = send(method, *args) { |*bargs| result2 = yield(*bargs) }
    [result1, result2]
  end
end

realtime_output, block_output = Benchmark.capture(:realtime) do
  "my output"
end #=&gt; [7.263e-06, "my output"]