I'm working on a class that generates a PDF using Prawn gem. I have some similar methods. All of them start with the same line. Here is the code:
module PDFGenerator
class MatchTeamInfo
include Prawn::View
def initialize(match)
@match = match
@output = Prawn::Document.new page_layout: :landscape
defaults
header
footer
end
def render
@output.render
end
def defaults
@output.instance_exec do
font_size 16
text 'hola'
end
end
def header
@output.instance_exec do
bounding_box [bounds.left, bounds.top], :width => bounds.width do
text "Fulbo", align: :center, size: 32
stroke_horizontal_rule
move_down(5)
end
end
end
def footer
@output.instance_exec do
bounding_box [bounds.left, bounds.bottom + 25], :width => bounds.width do
stroke_horizontal_rule
move_down(5)
text "Tu sitio favorito!", align: :center
end
end
end
end
end
Is there a way to avoid @output.instance_exec in every method and use something like blocks? I tried it, but I can't get it work. Can I do something like this?
def apply
@output.instance_exec do
yield
end
end
How am I supposed to define the code blocks?

First of all, you need to make all helper methods to return
lambdainstance:Now you might pass lambdas returned by your helpers to
instance_exec. To acknowledge it about “this is code block rather than regular param,” lambda is to be prefixed with ampersand:If you want to pass a codeblock to
apply, you should re-pass it toinstance_exec. Unfortunately I know no way to re-pass it usingyieldkeyword, but here is a trick:Proc.newcalled without parameters inside a method that was called with a codeblock given, is instantiated with this codeblock, so here you go: