Skip to content

Commit

Permalink
tentatively complete
Browse files Browse the repository at this point in the history
base and raw seem to be working as planned
lots of tests added and passing all of them
  • Loading branch information
thorny_sun committed Aug 26, 2008
1 parent 158da48 commit 7260e8d
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 214 deletions.
5 changes: 2 additions & 3 deletions lib/prawnto/action_controller.rb
Expand Up @@ -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}
Expand Down
Binary file removed lib/prawnto/template_handler/.base.rb.swp
Binary file not shown.
Binary file removed lib/prawnto/template_handler/.raw.rb.swp
Binary file not shown.
115 changes: 53 additions & 62 deletions 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
Expand Down
97 changes: 34 additions & 63 deletions 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
Expand Down
48 changes: 35 additions & 13 deletions test/base_template_handler_test.rb
Expand Up @@ -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
Expand Down

0 comments on commit 7260e8d

Please sign in to comment.