Blocks are probably one of the best parts of Ruby. They bring much of its flexibility and power.

They have their own scope and can be used to create closures.

This lead me to introduce a bug in an app recently. Here is somewhat how the code looked like:

def update

availability.update(availability_params)

metrics_tracker = MetricsTracker.build_for(activity)

metrics_tracker.save if metrics_tracker.trigger_notification?

# send email to admin

end

# rendering code

end # code omitted... def metrics_tracker

@metrics_tracker ||= MetricsTracker.new(current_user)

end

We had a first bug because there was no database transaction. So I did add one:

def update

ApplicationRecord.transaction do # <= added transaction here

availability.update!(availability_params)

metrics_tracker = MetricsTracker.build_for(activity)

metrics_tracker.save!

end if metrics_tracker.trigger_notification?

# send email to admin

end

# rendering code

end

But then no more emails were sent to admins… Why?

Let’s look back at our transaction:

ApplicationRecord.transaction do

availability.update!(availability_params)

metrics_tracker = MetricsTracker.build_for(activity)

metrics_tracker.save!

end