Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

tentatively complete

base and raw seem to be working as planned
lots of tests added and passing all of them
  • Loading branch information...
commit 7260e8d3cdd73c98617870c42906ec5b016ba7fc 1 parent 158da48
thorny_sun authored
View
5 lib/prawnto/action_controller.rb
@@ -30,12 +30,11 @@ def prawnto(options)
private
def reset_prawnto_options
- @prawnto_options = nil
+ @prawnto_options = {:inline=> true}
end
def compute_prawnto_options
-
- @prawnto_options ||= {}
+ @prawnto_options ||= reset_prawnto_options
@prawnto_options[:prawn] ||= {}
@prawnto_options[:prawn].merge!(self.class.read_inheritable_attribute(:prawn) || {}) {|k,o,n| o}
@prawnto_options.merge!(self.class.read_inheritable_attribute(:prawnto) || {}) {|k,o,n| o}
View
BIN  lib/prawnto/template_handler/.base.rb.swp
Binary file not shown
View
BIN  lib/prawnto/template_handler/.raw.rb.swp
Binary file not shown
View
115 lib/prawnto/template_handler/base.rb
@@ -1,81 +1,72 @@
module Prawnto
module TemplateHandler
class Base < ActionView::TemplateHandler
- include ActionView::TemplateHandlers::Compilable
- def self.line_offset
- # looks for spot where binding is called-- since that is where the template is ultimately evaluated -- and that is what will give us accurate line # reporting
- @@line_offset ||= template_wrapper_source.split(/^.*=\s*binding/)[0].count("\n")
+ attr_reader :prawnto_options
+
+ # TODO: kept around from railspdf-- maybe not needed anymore? should check.
+ def ie_request?
+ @view.request.env['HTTP_USER_AGENT'] =~ /msie/i
end
- def compile(template)
- self.class.template_wrapper_source.sub(/^\s*yield/, template.source)
+ # TODO: kept around from railspdf-- maybe not needed anymore? should check.
+ def set_pragma
+ @view.headers['Pragma'] ||= ie_request? ? 'no-cache' : ''
end
- private
+ # TODO: kept around from railspdf-- maybe not needed anymore? should check.
+ def set_cache_control
+ @view.headers['Cache-Control'] ||= ie_request? ? 'no-cache, must-revalidate' : ''
+ end
- # this is a dummy method to let me see code with editor's syntax goodness.
- # it is erased immediately afterwards
- # this method is never called, but instead the code is stripped out and pasted
- # as code to be run by the caller of compile method
- def template_wrapper_source_container
- @prawnto_options = controller.send :compute_prawnto_options
- # underscores are an attempt to avoid name clashes with user's local view variables
-
- #TODO: check if this really makes sense-- kept around from railspdf, but maybe not needed?
- _pragma = 'no-cache'
- _cache_control = 'no-cache, must-revalidate'
- _pragma = _cache_control = '' if request.env['HTTP_USER_AGENT'] =~ /msie/i #keep ie happy (from railspdf-- no personal knowledge of these issues)
- response.headers['Pragma'] ||= _pragma
- response.headers['Cache-Control'] ||= _cache_control
-
- response.content_type = Mime::PDF
+ def set_content_type
+ @view.response.content_type = Mime::PDF
+ end
- _inline = @prawnto_options[:inline] ? 'inline' : 'attachment'
- _filename = @prawnto_options[:filename] ? "filename=#{@prawnto_options[:filename]}" : nil
- _disposition = [_inline,_filename].compact.join(';')
+ def set_disposition
+ inline = @prawnto_options[:inline] ? 'inline' : 'attachment'
+ filename = @prawnto_options[:filename] ? "filename=#{@prawnto_options[:filename]}" : nil
+ @view.headers["Content-Disposition"] = [inline,filename].compact.join(';')
+ end
- response.headers["Content-Disposition"] = _disposition if _disposition.length > 0
+ def build_headers
+ set_pragma
+ set_cache_control
+ set_content_type
+ set_disposition
+ end
- _binding = nil
- pdf = Prawn::Document.new(@prawnto_options[:prawn])
- if _dsl = @prawnto_options[:dsl]
- _variable_transfer = if _dsl.kind_of?(Array)
- _dsl.map {|v| v = v[1..-1] if v[0,1]=="@"; "#{v}=@#{v};"}.join('')
- elsif _dsl.kind_of?(Hash)
- _dsl.map {|k,v| "#{k}=#{v};"}.join('')
- else
- ""
+ def build_source_to_establish_locals(template)
+ prawnto_locals = {}
+ if dsl = @prawnto_options[:dsl]
+ if dsl.kind_of?(Array)
+ dsl.each {|v| v = v.to_s.gsub(/^@/,''); prawnto_locals[v]="@#{v}"}
+ elsif dsl.kind_of?(Hash)
+ prawnto_locals.merge!(dsl)
end
- #eval _variable_transfer
- eval "x=1"
- puts x
- puts _variable_transfer
- puts "x"
- puts x
- puts "------------"
- pdf.instance_eval do
- _binding = binding; end; else; _binding = binding; #stuck together to keep binding captures on same line so line_offset is valid in both cases
end
+ prawnto_locals.merge!(template.locals)
+ prawnto_locals.map {|k,v| "#{k} = #{v};"}.join("")
+ end
- _view = <<EOS
- yield
-EOS
- eval(_view,_binding)
- pdf.render
+ def pull_prawnto_options
+ @prawnto_options = @view.controller.send :compute_prawnto_options
end
- remove_method :template_wrapper_source_container
-
-
- # snips out source code from dummy method below (used by compile method)
- def self.template_wrapper_source
- @@template_wrapper_source ||=
- begin
- method = 'template_wrapper_source_container'
- regex_s = '(\s*)def\s' + method + '\s*\n(.*?\n)\1end'
- source_regex = Regexp.new regex_s, Regexp::MULTILINE
- source_regex.match(File.read(__FILE__))[2]
- end
+
+ def render(template)
+ pull_prawnto_options
+ build_headers
+
+ source = build_source_to_establish_locals(template)
+ if @prawnto_options[:dsl]
+ source += "pdf.instance_eval do\n#{template.source}\nend"
+ else
+ source += "\n#{template.source}"
+ end
+
+ pdf = Prawn::Document.new(@prawnto_options[:prawn])
+ @view.instance_eval source, template.filename, 1
+ pdf.render
end
end
View
97 lib/prawnto/template_handler/raw.rb
@@ -1,83 +1,54 @@
module Prawnto
module TemplateHandler
- class Raw < ActionView::TemplateHandler
- include ActionView::TemplateHandlers::Compilable
+ class Raw < Base
- GENERATE_REGULAR_EXPRESSION = /^\s*Prawn\:\:Document\.generate(\(?)\s*([^,]*?)\s*?(\,(.*))?(\s*\)?\s+do(.*?))$/m
- RENDER_FILE_REGULAR_EXPRESSION = /(\w+)\.render_file\(?\s*(.*?)\s*\)?\s*$/
+ attr_reader :run_environment
- def self.line_offset
- @@line_offset ||= template_wrapper_source.split(/^\s*yield/)[0].count("\n")
+ GENERATE_REGULAR_EXPRESSION = /^\s*Prawn\:\:Document\.generate(\(?)(.*?)(\,(.*))?(\s*\)?\s+do(.*?))$/m
+ RENDER_FILE_REGULAR_EXPRESSION = /(\w+)\.render_file\(?(.*?)\)?\s*$/
+
+
+ def render(template)
+ setup_run_environment
+ pull_prawnto_options
+ source,filename = massage_template_source(template)
+ @prawnto_options[:filename] = filename if filename
+ build_headers
+ @run_environment.instance_eval(source, template.filename, 0) #run in anonymous class
end
- def compile(template)
- variable, source = source_cleanup template.source
- self.class.template_wrapper_source.sub(/^\s*yield/, source) + "\n#{variable}.render\n"
+
+ protected
+
+ def setup_run_environment
+ @run_environment = Object.new
end
- def source_cleanup(source)
- variable = '_pdf'
- filename_source = nil
+ def massage_template_source(template)
+ source = template.source
+ variable_name = '_pdf'
+ filename = nil
+
source.gsub! /^(\s*?)(\$LOAD_PATH)/, '\1#\2'
source.gsub! /^(\s*?)(require\(?\s*['"]rubygems['"]\s*\)?\s*)$/, '\1#\2'
source.gsub! /^(\s*?)(require\(?\s*['"]prawn['"]\s*\)?\s*)$/, '\1#\2'
+
if (source =~ GENERATE_REGULAR_EXPRESSION)
- filename_source = $2
- source.sub! GENERATE_REGULAR_EXPRESSION, "#{variable} = Prawn::Document.new\\1\\4\\5"
+ filename = $2
+ source.sub! GENERATE_REGULAR_EXPRESSION, "#{variable_name} = Prawn::Document.new\\1\\4\\5"
elsif (source =~ RENDER_FILE_REGULAR_EXPRESSION)
- variable = $1
- filename_source = $2
+ variable_name = $1
+ filename = $2
source.sub! RENDER_FILE_REGULAR_EXPRESSION, '#\0'
end
- source.gsub! /^(\s*)(class\s|def\s).*?\1end/m do |match|
- ::ApplicationHelper.module_eval(match)
+ source.gsub! /^(\s*)(class\s|def\s).*?\n\1end/m do |match|
+ eval "class <<@run_environment; #{match}; end;"
"\n" * match.count("\n")
end
- source += "\n@prawnto_options.merge!(:filename=>#{filename_source})\n"
- [variable, source]
- end
-
- private
-
- # this is a dummy method to let me see code with editor's syntax goodness.
- # it is erased immediately afterwards
- # this method is never called, but instead the code is stripped out and pasted
- # as code to be run by the caller of compile method
- def template_wrapper_source_container
- @prawnto_options = controller.send :compute_prawnto_options
- # underscores are an attempt to avoid name clashes with user's local view variables
-
- yield
-
- #TODO: check if this really makes sense-- kept around from railspdf, but maybe not needed?
- _pragma = 'no-cache'
- _cache_control = 'no-cache, must-revalidate'
- _pragma = _cache_control = '' if request.env['HTTP_USER_AGENT'] =~ /msie/i #keep ie happy (from railspdf-- no personal knowledge of these issues)
- response.headers['Pragma'] ||= _pragma
- response.headers['Cache-Control'] ||= _cache_control
-
- response.content_type = Mime::PDF
-
- _inline = @prawnto_options[:inline] ? 'inline' : 'attachment'
- _filename = @prawnto_options[:filename] ? "filename=#{@prawnto_options[:filename]}" : nil
- _disposition = [_inline,_filename].compact.join(';')
-
- response.headers["Content-Disposition"] = _disposition if _disposition.length > 0
-
- #pdf.render
- end
- remove_method :template_wrapper_source_container
-
-
- # snips out source code from dummy method below (used by compile method)
- def self.template_wrapper_source
- @@template_wrapper_source ||=
- begin
- method = 'template_wrapper_source_container'
- regex_s = '(\s*)def\s' + method + '\s*\n(.*?\n)\1end'
- source_regex = Regexp.new regex_s, Regexp::MULTILINE
- source_regex.match(File.read(__FILE__))[2]
- end
+ source += "\n[#{variable_name}.render,#{filename}]\n"
+ puts ">>>>"
+ puts source
+ source
end
end
View
48 test/base_template_handler_test.rb
@@ -11,25 +11,47 @@ class BaseTemplateHandlerTest < Test::Unit::TestCase
def setup
@view = ActionView.new
@handler = Prawnto::TemplateHandler::Base.new(@view)
+ @controller = @view.controller
end
-
def test_prawnto_options_dsl_hash
- x_value = 3231
- y_value = 5322
- x_grab = 0
- @view.instance_eval do
- @x = x_value
- @y = y_value
- end
- @view.controller.prawnto_options.merge! :dsl=>{'x'=>:@x, :y=>'@y'}
- source = @handler.compile(Template.new(""))
- @view.instance_eval source+"\nx_grab = x\n", "base.rb", 22
- assert_equal x_value, x_grab
- assert_equal y_value, y
+ @y = 3231; @x = 5322
+ @controller.prawnto :dsl=> {'x'=>:@x, :y=>'@y'}
+ @handler.pull_prawnto_options
+ source = @handler.build_source_to_establish_locals(Template.new(""))
+
+ assert_equal @x, eval(source + "\nx")
+ assert_equal @y, eval(source + "\ny")
end
def test_prawnto_options_dsl_array
+ @y = 3231; @x = 5322
+ @controller.prawnto :dsl=> ['x', :@y]
+ @handler.pull_prawnto_options
+ source = @handler.build_source_to_establish_locals(Template.new(""))
+
+ assert_equal @x, eval(source + "\nx")
+ assert_equal @y, eval(source + "\ny")
+ end
+
+ def test_headers_disposition_inline_and_filename
+ @controller.prawnto :filename=>'xxx.pdf', :inline=>true
+ @handler.pull_prawnto_options
+ @handler.set_disposition
+ assert_equal 'inline;filename=xxx.pdf', @view.headers['Content-Disposition']
+ end
+
+ def test_headers_disposition_attachment_and_filename
+ @controller.prawnto :filename=>'xxx.pdf', :inline=>false
+ @handler.pull_prawnto_options
+ @handler.set_disposition
+ assert_equal 'attachment;filename=xxx.pdf', @view.headers['Content-Disposition']
+ end
+
+ def test_headers_disposition_default
+ @handler.pull_prawnto_options
+ @handler.set_disposition
+ assert_equal 'inline', @view.headers['Content-Disposition']
end
end
View
145 test/raw_template_handler_test.rb
@@ -7,8 +7,90 @@
require 'test/unit'
require File.dirname(__FILE__) + '/../lib/prawnto'
+require File.dirname(__FILE__) + '/template_handler_test_mocks'
+
class RawTemplateHandlerTest < Test::Unit::TestCase
+ include TemplateHandlerTestMocks
+ class ::ApplicationHelper
+ end
+
+ def setup
+ @view = ActionView.new
+ @handler = Prawnto::TemplateHandler::Raw.new(@view)
+ end
+
+
+ def test_massage_template_source_header_comments
+ expected_commented_lines = [0,2,3]
+ source = <<EOS
+ require 'prawn'
+ require 'hello'
+ require "rubygems"
+ $LOAD_PATH.unshift blah blah
+ LOAD_PATH.unshift blah blah
+EOS
+ output_lines = @handler.send(:massage_template_source, Template.new(source)).split("\n")
+ output_lines.each_with_index do |line, i|
+ method = expected_commented_lines.include?(i) ? :assert_match : :assert_no_match
+ self.send method, /^\s*\#/, line
+ end
+ end
+
+ def test_massage_template_source_generate
+ @handler.pull_prawnto_options
+ changed_lines = [0,2,3]
+ source = <<EOS
+ Prawn::Document.generate('hello.pdf') do |pdf|
+ end
+EOS
+ output_lines = @handler.send(:massage_template_source, Template.new(source)).split("\n")
+ assert_match(/^\s*(\S+)\s*\=\s*Prawn\:\:Document\.new\(?\s*\)?\s*do\s*\|pdf\|/, output_lines.first)
+ variable = $1
+ assert_match(/^\s*\[(\S+)\.render\s*\,\s*\'hello\.pdf\'\s*\]\s*$/, output_lines.last)
+ assert_equal variable, $1
+ end
+
+ def test_massage_template_source_new
+ @handler.pull_prawnto_options
+ unchanged_lines = [0,1,2]
+ source = <<EOS
+ x = Prawn::Document.new do |pdf|
+ text.blah blah blah
+ end
+ x.render_file('hello.pdf')
+EOS
+ source_lines = source.split("\n")
+ output_lines = @handler.send(:massage_template_source, Template.new(source)).split("\n")
+ output_lines.each_with_index do |line, i|
+ method = unchanged_lines.include?(i) ? :assert_equal : :assert_not_equal
+ self.send method, source_lines[i], line
+ end
+ assert_match(/^\s*\#\s*x\.render\_file\(\'hello.pdf\'\)/, output_lines[3])
+ assert_match(/^\s*\[\s*x\.render\s*\,\s*\'hello\.pdf\'\s*\]\s*$/, output_lines.last)
+ end
+
+ def test_massage_template_source_classes_methods
+ source = <<EOS
+ class Foo
+ def initialize
+ @foo = true
+ end
+ end
+
+ def bar(*args)
+ if args[0]==true
+ z = false
+ end
+ end
+EOS
+ @handler.send :setup_run_environment
+ output_lines = @handler.send(:massage_template_source, Template.new(source)).split("\n")
+ output_lines.pop
+ output_lines.each {|l| assert_match(/^\s*$/, l)}
+ assert @handler.run_environment.methods(false).include?('bar')
+ assert class <<@handler.run_environment; self; end.constants.include?('Foo')
+ end
CURRENT_PATH = Pathname('.').realpath
PRAWN_PATH = Pathname(Prawn::BASEDIR).realpath
@@ -49,11 +131,6 @@ def self.ensure_reference_pdfs_are_recent
#ensure_reference_pdfs_are_recent
- def setup
- @view = ActionView.new
- @handler = Prawnto::TemplateHandler::Raw.new(@view)
- end
-
def assert_renders_correctly(name, path)
input_source = path.read
output_source = @handler.compile(Template.new(input_source))
@@ -81,64 +158,6 @@ def assert_renders_correctly(name, path)
-
- # stubbing/mocking/whatever it's called
- class ActionView
-
- class ActionController
- class Response
- def headers
- {}
- end
-
- def content_type=(value)
- end
- end
-
- class Request
- def env
- {}
- end
- end
-
- def compute_prawnto_options
- {}
- end
-
- def response
- @response ||= Response.new
- end
-
- def request
- @request ||= Request.new
- end
- end
- attr_reader :prawnto_options
-
- def initialize
- @prawnto_options= {}
- end
-
- def controller
- @controller ||= ActionController.new
- end
-
- def response
- controller.response
-
- end
- def request
- controller.request
- end
- end
-
- class Template
- attr_reader :source
- def initialize(source)
- @source = source
- end
- end
-
end
View
36 test/template_handler_test_mocks.rb
@@ -1,17 +1,25 @@
+require File.dirname(__FILE__) + '/../lib/prawnto'
+
module TemplateHandlerTestMocks
class Template
- attr_reader :source
+ attr_reader :source, :locals, :filename
- def initialize(source)
+ def initialize(source, locals={})
@source = source
+ @locals = locals
+ @filename = "blah.pdf"
end
end
class Response
+ def initialize
+ @headers = {}
+ end
+
def headers
- {}
+ @headers
end
def content_type=(value)
@@ -25,16 +33,16 @@ def env
end
class ActionController
- attr_reader :prawnto_options
+ def self.before_filter(method)
+ @@init_method = method
+ end
def initialize
- @prawnto_options = {:prawn=>{}}
- end
-
- def compute_prawnto_options
- @prawnto_options
+ eval @@init_method.to_s
end
+ include Prawnto::ActionController
+
def response
@response ||= Response.new
end
@@ -42,6 +50,10 @@ def response
def request
@request ||= Request.new
end
+
+ def headers
+ response.headers
+ end
end
class ActionView
@@ -57,8 +69,12 @@ def request
controller.request
end
+ def headers
+ controller.headers
+ end
+
def prawnto_options
- controller.prawnto_options
+ controller.get_instance_variable(:@prawnto_options)
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.