Today I Learned

hashrocket A Hashrocket project

Ruby Object Reference in blocks

Usually when I want to set the value of a variable by yielding to a block, I will explicity set it

  x = 'something'
  x = yield(x)
  #....

Turns out ruby will treat different types of objects different when yielded to a block (remember everything is an object). If you are yielding an Integer, or String for (a contrived) example:


def do_stuff_by_val
  do_block_stuff_by_val do |name|
    name += 'rocket'
  end
end

def do_block_stuff_by_val
  company_name = 'hash'
  yield(company_name)
  puts company_name #prints 'hash', not 'hashrocket'
end

If we wanted the company name to change to “hashrocket", we would need to explicitly set the variable to the result of yielding:

company_name = yield(company_name)

Other types of objects do not behave this way (hash or array). If we yield a hash and set a key, the hash in the calling method will be updated:


def do_stuff_by_object_reference
  do_block_stuff_by_object_reference do |company|
    company[:name] = 'hashrocket'
  end
end

def do_block_stuff_by_object_reference
  company = {}
  yield(company)
  puts company # { name: 'hashrocket'}
end
See More #ruby TILs
Looking for help? Each developer at Hashrocket has years of experience working with Ruby applications of all types and sizes. We're an active presence at Ruby conferences, have written some of the most popular gems, and have worked on many of the web's Ruby on Rails success stories. Contact us today to talk about your Ruby project.