diff --git a/README.md b/README.md index fe0c322..1a3064a 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Interestingly, this JSON output is also a valid BABL template. In fact, BABL is - [Understanding BABL: fundamental concepts](pages/concepts.md) - [Playing with `BABL::Template`](pages/templates.md) - [List of all operators](pages/operators.md) -- [Limitations / known issues](pages/limitations.md) +- [Limitations](pages/limitations.md) - [Changelog](CHANGELOG.md) # License diff --git a/lib/babl.rb b/lib/babl.rb index 6e70ca0..daa7bda 100644 --- a/lib/babl.rb +++ b/lib/babl.rb @@ -7,12 +7,13 @@ module Babl class Config - attr_accessor :search_path, :preloader, :pretty + attr_accessor :search_path, :preloader, :pretty, :cache_templates def initialize @search_path = nil @preloader = Babl::Rendering::NoopPreloader @pretty = true + @cache_templates = false end end diff --git a/lib/babl/railtie.rb b/lib/babl/railtie.rb index 38b8c84..afdb0a5 100644 --- a/lib/babl/railtie.rb +++ b/lib/babl/railtie.rb @@ -1,19 +1,40 @@ # frozen_string_literal: true module Babl module ActionView - module Template - class Handler - class_attribute :default_format - self.default_format = Mime[:json] + class TemplateHandler + class_attribute :default_format + self.default_format = Mime[:json] - def self.call(template) - # This implementation is not efficient: it will recompile the BABL template - # for each request. I still don't get why Rails template handlers MUST - # return Ruby code ?! Sucks too much. Ideally, we would like to keep the compiled - # template somewhere. However, I've not yet measured how much like is wasted. - # Maybe it is negligible ? - <<~RUBY - Babl.compile { #{template.source} }.json(local_assigns) + class << self + def cached_templates + @cached_templates ||= {} + end + + def call(template) + Babl.config.cache_templates ? cached_call(template) : uncached_call(template) + end + + private + + def cached_call(template) + cached_templates[template.identifier] ||= Babl.compile { + source(template.source, template.identifier) + } + + <<-RUBY + compiled = ::Babl::ActionView::TemplateHandler.cached_templates[#{template.identifier.inspect}] + compiled.json(local_assigns) + RUBY + end + + def uncached_call(template) + <<-RUBY + Babl.compile { + source( + #{template.source.inspect}, + #{template.identifier.inspect} + ) + }.json(local_assigns) RUBY end end @@ -23,7 +44,7 @@ def self.call(template) class Railtie < Rails::Railtie initializer "babl.initialize" do ActiveSupport.on_load(:action_view) do - ::ActionView::Template.register_template_handler(:babl, Babl::ActionView::Template::Handler) + ::ActionView::Template.register_template_handler(:babl, Babl::ActionView::TemplateHandler) end end end diff --git a/pages/limitations.md b/pages/limitations.md index 3f9324d..3757277 100644 --- a/pages/limitations.md +++ b/pages/limitations.md @@ -1,12 +1,4 @@ -# Known issues - -## Rails integration - -This gem implements support of `*.babl` views in [Rails](https://github.com/rails/rails/). - -Ideally, the template should be compiled once for all and re-used for all subsequent requests. In practice, today's implementation will re-compile the template at every request, because Rails templating mechanism doesn't make our life easy. Template compilation time is non negligible, and it could become a real problem with [code generation](https://github.com/getbannerman/babl/pull/21). - -I will probably hack something soon in order to work around this issue. +# Limitations ## No recursion