From a6dad77b041231b6ad70bce37e4a131ab744c83c Mon Sep 17 00:00:00 2001 From: Sascha Konietzke Date: Thu, 26 Jan 2012 10:44:26 +0100 Subject: [PATCH] Cache I18n lookups in Formtastic::Localizer --- lib/formtastic/form_builder.rb | 1 + lib/formtastic/localizer.rb | 52 +++++++++++++++++++++++--- lib/generators/templates/formtastic.rb | 4 ++ spec/actions/generic_action_spec.rb | 1 + spec/spec_helper.rb | 6 ++- 5 files changed, 57 insertions(+), 7 deletions(-) diff --git a/lib/formtastic/form_builder.rb b/lib/formtastic/form_builder.rb index 076d8581e..dfb7aa327 100644 --- a/lib/formtastic/form_builder.rb +++ b/lib/formtastic/form_builder.rb @@ -23,6 +23,7 @@ def self.configure(name, value = nil) configure :file_metadata_suffixes, ['content_type', 'file_name', 'file_size'] configure :priority_countries, ["Australia", "Canada", "United Kingdom", "United States"] configure :i18n_lookups_by_default, true + configure :i18n_cache_lookups, true configure :i18n_localizer, Formtastic::Localizer configure :escape_html_entities_in_hints_and_labels, true configure :default_commit_button_accesskey diff --git a/lib/formtastic/localizer.rb b/lib/formtastic/localizer.rb index b5c39a33c..a50e878e0 100644 --- a/lib/formtastic/localizer.rb +++ b/lib/formtastic/localizer.rb @@ -24,27 +24,59 @@ module Formtastic # 'formtastic.labels.post.title' # 'formtastic.labels.title' class Localizer - + class Cache + def get(key) + cache[key] + end + + def has_key?(key) + cache.has_key?(key) + end + + def set(key, result) + cache[key] = result + end + + def cache + @cache ||= {} + end + + def clear! + cache.clear + end + end + attr_accessor :builder - + + def self.cache + @cache ||= Cache.new + end + def initialize(current_builder) self.builder = current_builder end def localize(key, value, type, options = {}) #:nodoc: key = value if value.is_a?(::Symbol) - + if value.is_a?(::String) escape_html_entities(value) else use_i18n = value.nil? ? i18n_lookups_by_default : (value != false) - + use_cache = i18n_cache_lookups + cache = self.class.cache + if use_i18n model_name, nested_model_name = normalize_model_name(builder.model_name.underscore) action_name = builder.template.params[:action].to_s rescue '' attribute_name = key.to_s - + + # look in the cache first + if use_cache + cache_key = [::I18n.locale, action_name, model_name, nested_model_name, attribute_name, key, value, type, options] + return cache.get(cache_key) if cache.has_key?(cache_key) + end defaults = Formtastic::I18n::SCOPES.reject do |i18n_scope| nested_model_name.nil? && i18n_scope.match(/nested_model/) @@ -71,7 +103,11 @@ def localize(key, value, type, options = {}) #:nodoc: options[:default] = defaults i18n_value = ::I18n.t(default_key, options) end - (i18n_value.is_a?(::String) && i18n_value.present?) ? escape_html_entities(i18n_value) : nil + + # save the result to the cache + result = (i18n_value.is_a?(::String) && i18n_value.present?) ? escape_html_entities(i18n_value) : nil + cache.set(cache_key, result) if use_cache + result end end end @@ -105,6 +141,10 @@ def escape_html_entities(string) #:nodoc: def i18n_lookups_by_default builder.i18n_lookups_by_default end + + def i18n_cache_lookups + builder.i18n_cache_lookups + end end end diff --git a/lib/generators/templates/formtastic.rb b/lib/generators/templates/formtastic.rb index ce3f0378c..1ae9032fb 100644 --- a/lib/generators/templates/formtastic.rb +++ b/lib/generators/templates/formtastic.rb @@ -68,6 +68,10 @@ # i.e. :label => true, or :hint => true (or opposite depending on initialized value) # Formtastic::FormBuilder.i18n_lookups_by_default = false +# Specifies if I18n lookups of the default I18n Localizer should be cached to improve performance. +# Defaults to false. +# Formtastic::FormBuilder.i18n_cache_lookups = true + # Specifies the class to use for localization lookups. You can create your own # class and use it instead by subclassing Formtastic::Localizer (which is the default). # Formtastic::FormBuilder.i18n_localizer = MyOwnLocalizer diff --git a/spec/actions/generic_action_spec.rb b/spec/actions/generic_action_spec.rb index 64b8f01a4..3fb451ffb 100644 --- a/spec/actions/generic_action_spec.rb +++ b/spec/actions/generic_action_spec.rb @@ -213,6 +213,7 @@ def to_html } } } + concat(semantic_form_for(:post, :url => 'http://example.com') do |builder| concat(builder.action(:submit, :as => :generic)) concat(builder.action(:reset, :as => :generic)) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 61adf866f..f0d8951c2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -419,10 +419,14 @@ def with_config(config_method_name, value, &block) ::ActiveSupport::Deprecation.silenced = false RSpec.configure do |config| + config.before(:each) do + Formtastic::Localizer.cache.clear! + end + config.before(:all) do DeferredGarbageCollection.start unless ENV["DEFER_GC"] == "false" end config.after(:all) do - DeferredGarbageCollection.reconsider unless ENV["DEFER_GC"] == "false" + DeferredGarbageCollection.reconsider unless ENV["DEFER_GC"] == "false" end end