# encoding: UTF-8 # # prawn/view.rb : Implements a mixin for Prawn's DSL # # This is free software. Please see the LICENSE and COPYING files for details. module Prawn # This mixin allows you to create modular Prawn code without the # need to create subclasses of Prawn::Document. # # class Greeter # include Prawn::View # # def initialize(name) # @name = name # end # # def say_hello # text "Hello, #{@name}!" # end # # def say_goodbye # font("Courier") do # text "Goodbye, #{@name}!" # end # end # end # # greeter = Greeter.new("Gregory") # # greeter.say_hello # greeter.say_goodbye # # greeter.save_as("greetings.pdf") # # The short story about why you should use this mixin rather than # creating subclasses of +Prawn::Document+ is that it helps # prevent accidental conflicts between your code and Prawn's # code. # # Here's the slightly longer story... # # By using composition rather than inheritance under the hood, this # mixin allows you to keep your state separate from +Prawn::Document+'s # state, and also will prevent unexpected method name collisions due # to late binding effects. # # This mixin is mostly meant for extending Prawn's functionality # with your own additions, but you can also use it to replace or # wrap existing Prawn methods. Calling +super+ will still work # as expected, and alternatively you can explictly call # +document.some_method+ to delegate to Prawn where needed. module View # @group Experimental API # Lazily instantiates a +Prawn::Document+ object. # # You can also redefine this method in your own classes to use # a custom document class. def document @document ||= Prawn::Document.new end # Delegates all unhandled calls to object returned by +document+ method. # (which is an instance of Prawn::Document by default) def method_missing(m, *a, &b) return super unless document.respond_to?(m) document.send(m, *a, &b) end # Syntactic sugar that uses +instance_eval+ under the hood to provide # a block-based DSL. # # greeter.update do # say_hello # say_goodbye # end # def update(&b) instance_eval(&b) end # Syntatic sugar that calls +document.render_file+ under the hood. # # greeter.save_as("greetings.pdf") def save_as(filename) document.render_file(filename) end end end