Programming ≈ Fun

Written by Krešimir Bojčić

Ruby Implicit Blocks Are Evil

Don’t get me wrong, I love Ruby blocks, even the implicit ones because blocks are one of the best things in Ruby. The reason I am writing this post is that it took way too long for me to really get them. I’ve identified two major hurdles:

  • I didn’t know why on earth would I use them
  • That ‘clever’ use of implicit block and yield really messed up my brain

First things first. Why to use them?

You can:

  • Iterate, even to eternal
  • Remove boilerplate code with Execute Around (Kent Beck-Smalltalk Best Practices)
  • Save for later use aka solving-callback-problem

You really owe it to your self to read Eloquent Ruby from Russ Olsen, as he does such a great job of explaining Ruby finer points.

I’ll try to clarify mu second point on example of execute around block where I’ll write implicit vs. explicit version

#Boilerplate code that we hate so much and want to get rid of
def fetch_some_data(id)
  begin
    @logger.info("Starting request")
    @data = Data.find(id) # do the actual thing
    @logger.info("Completed request")
  rescue
    @logger.error("Request failed, it's all your fault!")
  end
end

Implicit version:

def fetch_some_data(id)
  with_logging { @data = Data.find(id) }
end

def with_logging
  begin
    @logger.info("Starting request")
    yield # do the actual thing
    @logger.info("Completed request")
  rescue
    @logger.error("Request failed, it's all your fault!")
  end
end

Explicit version

def fetch_some_data(id)
  with_logging { @data = Data.find(id) }
end

def with_logging( &the_block )
  begin
    @logger.info("Starting request")
    the_block.call # do the actual thing
    @logger.info("Completed request")
  rescue
    @logger.error("Request failed, it's all your fault!")
  end
end

The explicit version clicks with my mind instantly. I am accepting block as a parameter (I’ll admit syntax is a bit C-ish,but…), and then when the time is right I am executing block.

Nothing magical about it, just another parameter that happens to be a block of code.

Example is a bit too simple, because things get really confusing when we include parameters that we send into block. I am not going to start about that, or even worse about closures as it is 2AM, and I still need to deploy this on my home stored Arch/nginx server…me from the past is telling you it was a success as you are reading this :)

Comments