Richard Hart

Head of Something @ Somewhere
Kent, UK

My Music
My Photos

LinkedIn
Mastodon

Using blocks in Ruby for lazy evaluation

I’ve been working on a templating engine recently and had the need to substitute some variables on the page with the result of an slightly expensive remote API call. The first iteration was just a simple replace on the page:


render_placeholder result, 
    "some_page_var", 
    ApiWrapper.some_expensive_call

def render_placeholder result, name, value
  result.gsub! name, value
end

This “worked” but the problem is the call would be made even if the variable that needed replacing wasn’t on the page. The easy fix is to check it exists before making the substitution:


render_placeholder(result, 
  "some_page_var", 
   ApiWrapper.some_expensive_call) if has_placeholder?(result, "some_page_var")

def has_placeholder? result, name
  !!result[name]
end

def render_placeholder result, name, value
  result.gsub! name, value
end

While this works, once you have a load of results you want to replace there ends up being a lot of duplication, and it’s easy to check the wrong variable compared to what you want to replace. One way to solve it is by passing the api call as a block to the substitution method. This way we can tidy up the code:


render_placeholder(result, "some_page_var") { ApiWrapper.some_expensive_call }

def has_placeholder? result, name
  !!result[name]
end

def render_placeholder result, name
  return "" unless has_placeholder?(result, name)
  result.gsub! name", yield
end