public
Created

  • Download Gist
gistfile1.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
module Mustache
class << self
import com.github.mustachejava.DefaultMustacheFactory
import com.github.mustachejava.jruby.JRubyObjectHandler
 
def template_dir
Rails.root.join('app', 'templates')
end
 
def factory
@factory ||= begin
factory = DefaultMustacheFactory.new java.io.File.new(template_dir.to_s)
factory.setObjectHandler(JRubyObjectHandler.new)
factory
end
end
 
def compile(template)
CompiledTemplate.new(factory.compile(template))
end
end
 
class View < Hash
def self.inherited(subclass)
class << subclass
attr_accessor :template_path
end
 
subclass.template_path = subclass.name.underscore.gsub(/_view$/, '') + '.html'
end
 
def initialize(context={})
self.update(context)
end
 
def render_string
Mustache.compile(self.class.template_path).render_string(self)
end
 
def render
Mustache.compile(self.class.template_path).render(self)
end
end
 
class CompiledTemplate
def initialize(template)
@template = template
end
 
def render_string(context)
out = string_writer
@template.execute(out, context).flush
out.to_s
end
 
def render(context)
stream, out = streaming_writer
@template.execute(out, context)
stream
end
 
protected
 
def string_writer
java.io.StringWriter.new
end
 
def streaming_writer
reader = java.io.PipedReader.new
writer = java.io.PipedWriter.new(reader)
 
[Stream.new(reader), writer]
end
 
end
 
class Stream
def initialize(reader)
@reader = reader
end
 
def each
buf = Java::char[1024].new
read = 0
while @reader.read(buf) >= 0
yield java.lang.String.new(buf)
buf = Java::char[1024].new
end
end
end
end

Two issues:

1) The char array needs converting to a string.
2) It seems that the first call to @reader.read returns 10 (length of the template) which means it re-enters the while loop but then it hangs rather than returning -1 as its reached the end.

Update: fixed #1.

a) How are you including/adding this functionality to rails (and if you're not, how are you testing what works and doesn't?)
b) I believe the call on line #58 to @template.execute(...) will do the full render, so though all the bytes might pass through the pipe and stream, it won't really be streaming as the first byte won't be ready until all bytes are ready. In which case you may as well render straight to a string.

As for your specific problems, for 1) I think you can do something like yield buf.to_a.pack('c*'). For 2) I think you might have more joy with while @reader.ready. You should probably also call @reader.read with an offset and limit as I think otherwise it'll may fuckup with a longer template (or use a shorter character array). Something like @reader.read(buf, 0, buf.length). Java can be stupid about these things.

Your solution to 1) is much neater, keeping character handling within the java ecosystem.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.