From 3ffb5685f83875b66a0cf68f3a058a223a47b911 Mon Sep 17 00:00:00 2001 From: Adam Becker Date: Thu, 3 Dec 2015 11:22:04 -0500 Subject: [PATCH 1/4] WIP caching module --- lib/fortitude/widget.rb | 3 ++ lib/fortitude/widget/caching.rb | 38 +++++++++++++++++++ spec/rails/cacheable_method_system_spec.rb | 10 +++++ ...cacheable_method_system_spec_controller.rb | 11 ++++++ .../localization.rb | 12 ++++++ .../config/locales/en.yml | 4 ++ .../config/locales/fr.yml | 4 ++ 7 files changed, 82 insertions(+) create mode 100644 lib/fortitude/widget/caching.rb create mode 100644 spec/rails/cacheable_method_system_spec.rb create mode 100644 spec/rails/templates/cacheable_method_system_spec/app/controllers/cacheable_method_system_spec_controller.rb create mode 100644 spec/rails/templates/cacheable_method_system_spec/app/views/cacheable_method_system_spec/localization.rb create mode 100644 spec/rails/templates/cacheable_method_system_spec/config/locales/en.yml create mode 100644 spec/rails/templates/cacheable_method_system_spec/config/locales/fr.yml diff --git a/lib/fortitude/widget.rb b/lib/fortitude/widget.rb index 2618043..90a133e 100644 --- a/lib/fortitude/widget.rb +++ b/lib/fortitude/widget.rb @@ -46,6 +46,9 @@ class Widget if defined?(::Rails) require 'fortitude/rails/widget_methods' include Fortitude::Rails::WidgetMethods + + require 'fortitude/widget/caching' + include Fortitude::Widget::Caching else require 'fortitude/widget/non_rails_widget_methods' include Fortitude::Widget::NonRailsWidgetMethods diff --git a/lib/fortitude/widget/caching.rb b/lib/fortitude/widget/caching.rb new file mode 100644 index 0000000..553c91f --- /dev/null +++ b/lib/fortitude/widget/caching.rb @@ -0,0 +1,38 @@ +module Fortitude + class Widget + module Caching + extend ActiveSupport::Concern + include ActionView::Helpers::CacheHelper + + module ClassMethods + # PUBLIC API + def cacheable(opts = {}) + if extra_assigns == :use + extra_assigns :ignore + end + + static_keys = opts.fetch(:key, []) + options = opts.fetch(:options, {}) + + define_method(:cache_contents) do |&block| + cache calculate_cache_dependencies(assigns, static_keys), options do + block.call + end + end + + around_content :cache_contents + end + end + + private + + def calculate_cache_dependencies(assigns, static_keys) + ( + assigns.to_a.sort_by(&:first).flatten + + static_keys + + [widget_locale] + ) + end + end + end +end diff --git a/spec/rails/cacheable_method_system_spec.rb b/spec/rails/cacheable_method_system_spec.rb new file mode 100644 index 0000000..c26c36f --- /dev/null +++ b/spec/rails/cacheable_method_system_spec.rb @@ -0,0 +1,10 @@ +describe "Fortitude cacheable method behavior in Rails", :type => :rails do + uses_rails_with_template :cacheable_method_system_spec + + it "caches properly" do + expect_match("localization?locale=en", /hello is: hello 1/) + expect_match("localization?locale=en", /hello is: hello 1/) + expect_match("localization?locale=fr", /hello is: bonjour 2/) + expect_match("localization?locale=fr", /hello is: bonjour 2/) + end +end diff --git a/spec/rails/templates/cacheable_method_system_spec/app/controllers/cacheable_method_system_spec_controller.rb b/spec/rails/templates/cacheable_method_system_spec/app/controllers/cacheable_method_system_spec_controller.rb new file mode 100644 index 0000000..f8f35a6 --- /dev/null +++ b/spec/rails/templates/cacheable_method_system_spec/app/controllers/cacheable_method_system_spec_controller.rb @@ -0,0 +1,11 @@ +class CacheableMethodSystemSpecController < ApplicationController + before_filter :set_locale + + def set_locale + I18n.locale = params[:locale] if params[:locale] + end + + def localization + # nothing here + end +end diff --git a/spec/rails/templates/cacheable_method_system_spec/app/views/cacheable_method_system_spec/localization.rb b/spec/rails/templates/cacheable_method_system_spec/app/views/cacheable_method_system_spec/localization.rb new file mode 100644 index 0000000..63a0e84 --- /dev/null +++ b/spec/rails/templates/cacheable_method_system_spec/app/views/cacheable_method_system_spec/localization.rb @@ -0,0 +1,12 @@ +class Views::CacheableMethodSystemSpec::Localization < Fortitude::Widgets::Html5 + cacheable + + def content + text "hello is: #{t('.hello')} #{times_called}" + end + + def times_called + @@times_called ||= 0 + @@times_called += 1 + end +end diff --git a/spec/rails/templates/cacheable_method_system_spec/config/locales/en.yml b/spec/rails/templates/cacheable_method_system_spec/config/locales/en.yml new file mode 100644 index 0000000..e237774 --- /dev/null +++ b/spec/rails/templates/cacheable_method_system_spec/config/locales/en.yml @@ -0,0 +1,4 @@ +en: + cacheable_method_system_spec: + localization: + hello: "hello" diff --git a/spec/rails/templates/cacheable_method_system_spec/config/locales/fr.yml b/spec/rails/templates/cacheable_method_system_spec/config/locales/fr.yml new file mode 100644 index 0000000..b83813a --- /dev/null +++ b/spec/rails/templates/cacheable_method_system_spec/config/locales/fr.yml @@ -0,0 +1,4 @@ +fr: + cacheable_method_system_spec: + localization: + hello: "bonjour" From dfdf4f694cee404766e79ede102599661ea83627 Mon Sep 17 00:00:00 2001 From: Adam Becker Date: Thu, 3 Dec 2015 16:47:37 -0500 Subject: [PATCH 2/4] set @virtual_path instance var --- lib/fortitude/rails/renderer.rb | 7 ++++++- lib/fortitude/rails/template_handler.rb | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/fortitude/rails/renderer.rb b/lib/fortitude/rails/renderer.rb index 0de140b..45d9189 100644 --- a/lib/fortitude/rails/renderer.rb +++ b/lib/fortitude/rails/renderer.rb @@ -11,7 +11,7 @@ module Rails class Renderer class << self # TODO: Refactor this and render :widget => ... support into one method somewhere. - def render(widget_class, template_handler, local_assigns, is_partial, &block) + def render(widget_class, template_handler, local_assigns, is_partial, options = {}, &block) if ::Fortitude::Erector.is_erector_widget_class?(widget_class) return ::Erector::Rails.render(widget_class, template_handler, local_assigns, is_partial, &block) end @@ -25,6 +25,11 @@ def render(widget_class, template_handler, local_assigns, is_partial, &block) end widget = widget_class.new(needed_assigns) + + if options[:pathname] + widget.instance_variable_set(:@virtual_path, options[:pathname]) + end + template_handler.with_output_buffer do rendering_context = template_handler.controller.fortitude_rendering_context_for(template_handler, block) diff --git a/lib/fortitude/rails/template_handler.rb b/lib/fortitude/rails/template_handler.rb index dad61e3..f5dc200 100644 --- a/lib/fortitude/rails/template_handler.rb +++ b/lib/fortitude/rails/template_handler.rb @@ -14,8 +14,10 @@ def call(template, &block) is_partial = !! File.basename(template.identifier) =~ /^_/ + pathname = "#{template.identifier =~ %r(views/(.*)) && $1}" + <<-SRC - Fortitude::Rails::Renderer.render(#{widget_class.name}, self, local_assigns, #{is_partial.inspect}) { |*args| yield *args } + Fortitude::Rails::Renderer.render(#{widget_class.name}, self, local_assigns, #{is_partial.inspect}, pathname: "#{pathname}") { |*args| yield *args } SRC end From 43e973d38a2d8ee4bf9fbc346cb464808bf54385 Mon Sep 17 00:00:00 2001 From: Adam Becker Date: Thu, 3 Dec 2015 16:47:44 -0500 Subject: [PATCH 3/4] coerce to array, why not --- lib/fortitude/widget/caching.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fortitude/widget/caching.rb b/lib/fortitude/widget/caching.rb index 553c91f..a74c1d8 100644 --- a/lib/fortitude/widget/caching.rb +++ b/lib/fortitude/widget/caching.rb @@ -11,7 +11,7 @@ def cacheable(opts = {}) extra_assigns :ignore end - static_keys = opts.fetch(:key, []) + static_keys = Array(opts.fetch(:key, [])) options = opts.fetch(:options, {}) define_method(:cache_contents) do |&block| From bff40dee78cb30102f6027cfe59da04310c5cf60 Mon Sep 17 00:00:00 2001 From: Adam Becker Date: Mon, 25 Jan 2016 18:08:37 -0500 Subject: [PATCH 4/4] update find_templates monkeypatch for rails 4.2.5.1 --- lib/fortitude/rails/railtie.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fortitude/rails/railtie.rb b/lib/fortitude/rails/railtie.rb index cdb7af8..914bc9b 100644 --- a/lib/fortitude/rails/railtie.rb +++ b/lib/fortitude/rails/railtie.rb @@ -294,7 +294,7 @@ def eager_load_fortitude_views! # searching Fortitude templates (the +.rb+ handler), then we try again, turning off the # +partial+ flag, and return that instead. ::ActionView::PathResolver.class_eval do - def find_templates_with_fortitude(name, prefix, partial, details) + def find_templates_with_fortitude(name, prefix, partial, details, outside_app_allowed = false) templates = find_templates_without_fortitude(name, prefix, partial, details) if partial && templates.empty? && details[:handlers] && details[:handlers].include?(:rb) templates = find_templates_without_fortitude(name, prefix, false, details.merge(:handlers => [ :rb ]))