Evgeniy Dolzhenko
10/21/2008 10:08:00 AM
This example is slightly contrived, but I hope it does illustrate the question.
Say you're generating table from an array and want to output header row
only if there will be actual rows in the table.
Basically I would like something like this:
rows = ["row1", "row2"]
rows.each do |row|
do_once do
write(header) # this block gets executed only once for whole loop
end
write(row)
end
I know, it's very questionable from the "best practices" point of view
as it breaks execution sequence, but it would be interesting to see
possible solutions.
Here is dumb one which relies on Proc#binding for keeping flags about
executed blocks and Kernel#caller for identifying them:
def do_once(&block)
executed_flag_name = "__#{caller[0].gsub(/\W/, "_")}_executed"
if (eval(executed_flag_name, block) rescue nil) # works only with
non-scoped "for" loops
return
else
eval("#{executed_flag_name} = true", block)
yield
end
end