Skip to content

Instantly share code, notes, and snippets.

@danwrong
Created April 16, 2012 15:17
Show Gist options
  • Save danwrong/2399405 to your computer and use it in GitHub Desktop.
Save danwrong/2399405 to your computer and use it in GitHub Desktop.
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
@danwrong
Copy link
Author

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.

@danwrong
Copy link
Author

Update: fixed #1.

@tomafro
Copy link

tomafro commented Apr 16, 2012

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.

@tomafro
Copy link

tomafro commented Apr 16, 2012

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment