2015-09-24 6 views
1

Я работаю над классом, который создает PDF-файл с использованием драгоценного камня «Креветка». У меня есть аналогичные методы. Все они начинаются с той же строки. Вот код:Как сделать код рефакторинга, который использует `instance_exec` несколько раз?

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 

Есть ли способ избежать @output.instance_exec в каждом методе и использовать что-то вроде блоков? Я попробовал, но я не могу заставить его работать. Могу ли я сделать что-то вроде этого?

def apply 
    @output.instance_exec do 
    yield 
    end 
end 

Как я могу определить блоки кода?

ответ

1

Прежде всего, вам нужно сделать все вспомогательные методы для возвращения lambda экземпляра:

def defaults 
    lambda do 
    font_size 16 
    text 'hola' 
    end 
end 

Теперь вы можете передать лямбды возвращаемых вашим помощникам в instance_exec. Для того, чтобы признать это о «это блок кода, а не регулярные пары,» лямбда должны быть с префиксом амперсандом:

def apply 
    #      ⇓ NB! codeblock is passed! 
    @output.instance_exec &defaults 
end 

Если вы хотите передать кодоблок в apply, вы должны повторно передать его instance_exec. К сожалению, я не знаю, как повторно передать его, используя yield ключевое слово, но вот трюк: Proc.new вызывается без параметров внутри метода, который вызывается с кодоблок данной, создаются с этой кодоблоком, так что здесь вы идете:

def apply 
    raise 'Codeblock expected' unless block_given? 
    @output.instance_exec &Proc.new 
end 
+0

Спасибо так много! Это я искал, но я не знал, как это сделать. –

1

Вы можете определить способ document, который возвращает экземпляр Prawn::Document.

Prawn::View затем делегирует вызовы метода этому документу. Вот пример: использование

module PDFGenerator 
    class MatchTeamInfo 
    include Prawn::View 

    def initialize(match) 
     @match = match 
     defaults 
     header 
     footer 
    end 

    def document 
     @document ||= Prawn::Document.new page_layout: :landscape 
    end 

    def defaults 
     font_size 16 
     text 'hola' 
    end 

    def header 
     bounding_box [bounds.left, bounds.top], :width => bounds.width do 
     text "Fulbo", align: :center, size: 32 
     stroke_horizontal_rule 
     move_down(5) 
     end 
    end 

    def footer 
     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 

Пример:

pdf = PDFGenerator::MatchTeamInfo.new(nil) 
pdf.save_as('team_info.pdf') 

Выход: (преобразуется в PNG)

team_info.pdf

+0

Спасибо большое! Я отметил, что принял ответ от @mudasobwa, потому что он ответил точно на мой вопрос. Тем не менее, ваше предложение очень приятно, и результаты кода более понятны. Я предполагаю, что это «правильный» способ сделать это с креветкой. Итак, я сделаю это таким образом. Снова, спасибо и приветствую! –

+0

@ Lucho-Rocha приветствуется. Не забывайте поднимать полезные ответы, как только у вас достаточно репутации ;-) – Stefan

+0

@Stefan У меня достаточно репутации, чтобы поддержать полезные ответы, так что вот мы идем :) – mudasobwa