From 049b6e670f0a9d7dc03ee4ddf9334ddbeb6c7900 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Wed, 23 Dec 2015 16:01:32 +0800 Subject: Porting ActionController::Caching to ActionMailer::Caching --- actionmailer/lib/action_mailer.rb | 1 + actionmailer/lib/action_mailer/base.rb | 1 + actionmailer/lib/action_mailer/caching.rb | 73 +++++++ .../lib/action_mailer/caching/fragments.rb | 148 +++++++++++++ actionmailer/lib/action_mailer/railtie.rb | 1 + actionmailer/test/caching_test.rb | 232 +++++++++++++++++++++ .../test/fixtures/caching_mailer/_partial.html.erb | 3 + .../caching_mailer/fragment_cache.html.erb | 3 + .../fragment_cache_in_partials.html.erb | 1 + .../skip_fragment_cache_digesting.html.erb | 3 + actionmailer/test/mailers/caching_mailer.rb | 15 ++ 11 files changed, 481 insertions(+) create mode 100644 actionmailer/lib/action_mailer/caching.rb create mode 100644 actionmailer/lib/action_mailer/caching/fragments.rb create mode 100644 actionmailer/test/caching_test.rb create mode 100644 actionmailer/test/fixtures/caching_mailer/_partial.html.erb create mode 100644 actionmailer/test/fixtures/caching_mailer/fragment_cache.html.erb create mode 100644 actionmailer/test/fixtures/caching_mailer/fragment_cache_in_partials.html.erb create mode 100644 actionmailer/test/fixtures/caching_mailer/skip_fragment_cache_digesting.html.erb create mode 100644 actionmailer/test/mailers/caching_mailer.rb (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb index 55c017e338..26fbb48600 100644 --- a/actionmailer/lib/action_mailer.rb +++ b/actionmailer/lib/action_mailer.rb @@ -44,6 +44,7 @@ module ActionMailer autoload :MailHelper autoload :Preview autoload :Previews, 'action_mailer/preview' + autoload :Caching autoload :TestCase autoload :TestHelper autoload :MessageDelivery diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 4259eb0bee..9b14a96d48 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -420,6 +420,7 @@ module ActionMailer class Base < AbstractController::Base include DeliveryMethods include Previews + include Caching abstract! diff --git a/actionmailer/lib/action_mailer/caching.rb b/actionmailer/lib/action_mailer/caching.rb new file mode 100644 index 0000000000..27da8148d1 --- /dev/null +++ b/actionmailer/lib/action_mailer/caching.rb @@ -0,0 +1,73 @@ +require 'active_support/descendants_tracker' + +module ActionMailer + module Caching + extend ActiveSupport::Concern + extend ActiveSupport::Autoload + + eager_autoload do + autoload :Fragments + end + + module ConfigMethods + def cache_store + config.cache_store + end + + def cache_store=(store) + config.cache_store = ActiveSupport::Cache.lookup_store(store) + end + + private + def cache_configured? + perform_caching && cache_store + end + end + + include AbstractController::Helpers + include ConfigMethods + include Fragments + + included do + extend ConfigMethods + + config_accessor :default_static_extension + self.default_static_extension ||= '.html' + + config_accessor :perform_caching + self.perform_caching = true if perform_caching.nil? + + class_attribute :_view_cache_dependencies + self._view_cache_dependencies = [] + helper_method :view_cache_dependencies if respond_to?(:helper_method) + end + + module ClassMethods + def view_cache_dependency(&dependency) + self._view_cache_dependencies += [dependency] + end + end + + def view_cache_dependencies + self.class._view_cache_dependencies.map { |dep| instance_exec(&dep) }.compact + end + + protected + # Convenience accessor. + def cache(key, options = {}, &block) + if cache_configured? + cache_store.fetch(ActiveSupport::Cache.expand_cache_key(key, :controller), options, &block) + else + yield + end + end + + def perform_caching + Base.perform_caching + end + + def controller_name + "ActionMailer" + end + end +end diff --git a/actionmailer/lib/action_mailer/caching/fragments.rb b/actionmailer/lib/action_mailer/caching/fragments.rb new file mode 100644 index 0000000000..6c70137626 --- /dev/null +++ b/actionmailer/lib/action_mailer/caching/fragments.rb @@ -0,0 +1,148 @@ +module ActionMailer + module Caching + # Fragment caching is used for caching various blocks within + # views without caching the entire action as a whole. This is + # useful when certain elements of an action change frequently or + # depend on complicated state while other parts rarely change or + # can be shared amongst multiple parties. The caching is done using + # the +cache+ helper available in the Action View. See + # ActionView::Helpers::CacheHelper for more information. + # + # While it's strongly recommended that you use key-based cache + # expiration (see links in CacheHelper for more information), + # it is also possible to manually expire caches. For example: + # + # expire_fragment('name_of_cache') + module Fragments + extend ActiveSupport::Concern + + included do + if respond_to?(:class_attribute) + class_attribute :fragment_cache_keys + else + mattr_writer :fragment_cache_keys + end + + self.fragment_cache_keys = [] + + helper_method :fragment_cache_key if respond_to?(:helper_method) + end + + module ClassMethods + # Allows you to specify controller-wide key prefixes for + # cache fragments. Pass either a constant +value+, or a block + # which computes a value each time a cache key is generated. + # + # For example, you may want to prefix all fragment cache keys + # with a global version identifier, so you can easily + # invalidate all caches. + # + # class ApplicationController + # fragment_cache_key "v1" + # end + # + # When it's time to invalidate all fragments, simply change + # the string constant. Or, progressively roll out the cache + # invalidation using a computed value: + # + # class ApplicationController + # fragment_cache_key do + # @account.id.odd? ? "v1" : "v2" + # end + # end + def fragment_cache_key(value = nil, &key) + self.fragment_cache_keys += [key || ->{ value }] + end + end + + # Given a key (as described in +expire_fragment+), returns + # a key suitable for use in reading, writing, or expiring a + # cached fragment. All keys begin with views/, + # followed by any controller-wide key prefix values, ending + # with the specified +key+ value. The key is expanded using + # ActiveSupport::Cache.expand_cache_key. + def fragment_cache_key(key) + head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) } + tail = key.is_a?(Hash) ? url_for(key).split("://").last : key + ActiveSupport::Cache.expand_cache_key([*head, *tail], :views) + end + + # Writes +content+ to the location signified by + # +key+ (see +expire_fragment+ for acceptable formats). + def write_fragment(key, content, options = nil) + return content unless cache_configured? + + key = fragment_cache_key(key) + instrument_fragment_cache :write_fragment, key do + content = content.to_str + cache_store.write(key, content, options) + end + content + end + + # Reads a cached fragment from the location signified by +key+ + # (see +expire_fragment+ for acceptable formats). + def read_fragment(key, options = nil) + return unless cache_configured? + + key = fragment_cache_key(key) + instrument_fragment_cache :read_fragment, key do + result = cache_store.read(key, options) + result.respond_to?(:html_safe) ? result.html_safe : result + end + end + + # Check if a cached fragment from the location signified by + # +key+ exists (see +expire_fragment+ for acceptable formats). + def fragment_exist?(key, options = nil) + return unless cache_configured? + key = fragment_cache_key(key) + + instrument_fragment_cache :exist_fragment?, key do + cache_store.exist?(key, options) + end + end + + # Removes fragments from the cache. + # + # +key+ can take one of three forms: + # + # * String - This would normally take the form of a path, like + # pages/45/notes. + # * Hash - Treated as an implicit call to +url_for+, like + # { controller: 'pages', action: 'notes', id: 45} + # * Regexp - Will remove any fragment that matches, so + # %r{pages/\d*/notes} might remove all notes. Make sure you + # don't use anchors in the regex (^ or $) because + # the actual filename matched looks like + # ./cache/filename/path.cache. Note: Regexp expiration is + # only supported on caches that can iterate over all keys (unlike + # memcached). + # + # +options+ is passed through to the cache store's +delete+ + # method (or delete_matched, for Regexp keys). + def expire_fragment(key, options = nil) + return unless cache_configured? + key = fragment_cache_key(key) unless key.is_a?(Regexp) + + instrument_fragment_cache :expire_fragment, key do + if key.is_a?(Regexp) + cache_store.delete_matched(key, options) + else + cache_store.delete(key, options) + end + end + end + + def instrument_fragment_cache(name, key) # :nodoc: + payload = { + controller: controller_name, + action: action_name, + key: key + } + + ActiveSupport::Notifications.instrument("#{name}.action_controller", payload) { yield } + end + end + end +end diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index ae89492b0f..fce0d0f9f1 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -25,6 +25,7 @@ module ActionMailer options.javascripts_dir ||= paths["public/javascripts"].first options.stylesheets_dir ||= paths["public/stylesheets"].first options.show_previews = Rails.env.development? if options.show_previews.nil? + options.perform_caching ||= true if options.show_previews options.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/mailers/previews" : nil diff --git a/actionmailer/test/caching_test.rb b/actionmailer/test/caching_test.rb new file mode 100644 index 0000000000..a92f43a6c5 --- /dev/null +++ b/actionmailer/test/caching_test.rb @@ -0,0 +1,232 @@ +require 'fileutils' +require 'abstract_unit' +require 'mailers/base_mailer' +require 'mailers/caching_mailer' +require 'byebug' + +CACHE_DIR = 'test_cache' +# Don't change '/../temp/' cavalierly or you might hose something you don't want hosed +FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR) + +class FragmentCachingMailer < ActionMailer::Base + abstract! + + include ActionMailer::Caching + + def some_action; end +end + +class BaseCachingTest < ActiveSupport::TestCase + def setup + super + @store = ActiveSupport::Cache::MemoryStore.new + @mailer = FragmentCachingMailer.new + @mailer.perform_caching = true + @mailer.cache_store = @store + end + + def test_fragment_cache_key + assert_equal 'views/what a key', @mailer.fragment_cache_key('what a key') + end +end + +class FragmentCachingTest < BaseCachingTest + def test_read_fragment_with_caching_enabled + @store.write('views/name', 'value') + assert_equal 'value', @mailer.read_fragment('name') + end + + def test_read_fragment_with_caching_disabled + @mailer.perform_caching = false + @store.write('views/name', 'value') + assert_nil @mailer.read_fragment('name') + end + + def test_fragment_exist_with_caching_enabled + @store.write('views/name', 'value') + assert @mailer.fragment_exist?('name') + assert !@mailer.fragment_exist?('other_name') + end + + def test_fragment_exist_with_caching_disabled + @mailer.perform_caching = false + @store.write('views/name', 'value') + assert !@mailer.fragment_exist?('name') + assert !@mailer.fragment_exist?('other_name') + end + + def test_write_fragment_with_caching_enabled + assert_nil @store.read('views/name') + assert_equal 'value', @mailer.write_fragment('name', 'value') + assert_equal 'value', @store.read('views/name') + end + + def test_write_fragment_with_caching_disabled + assert_nil @store.read('views/name') + @mailer.perform_caching = false + assert_equal 'value', @mailer.write_fragment('name', 'value') + assert_nil @store.read('views/name') + end + + def test_expire_fragment_with_simple_key + @store.write('views/name', 'value') + @mailer.expire_fragment 'name' + assert_nil @store.read('views/name') + end + + def test_expire_fragment_with_regexp + @store.write('views/name', 'value') + @store.write('views/another_name', 'another_value') + @store.write('views/primalgrasp', 'will not expire ;-)') + + @mailer.expire_fragment(/name/) + + assert_nil @store.read('views/name') + assert_nil @store.read('views/another_name') + assert_equal 'will not expire ;-)', @store.read('views/primalgrasp') + end + + def test_fragment_for + @store.write('views/expensive', 'fragment content') + fragment_computed = false + + view_context = @mailer.view_context + + buffer = 'generated till now -> '.html_safe + buffer << view_context.send(:fragment_for, 'expensive') { fragment_computed = true } + + assert !fragment_computed + assert_equal 'generated till now -> fragment content', buffer + end + + def test_html_safety + assert_nil @store.read('views/name') + content = 'value'.html_safe + assert_equal content, @mailer.write_fragment('name', content) + + cached = @store.read('views/name') + assert_equal content, cached + assert_equal String, cached.class + + html_safe = @mailer.read_fragment('name') + assert_equal content, html_safe + assert html_safe.html_safe? + end +end + +class FunctionalFragmentCachingTest < BaseCachingTest + def setup + super + @store = ActiveSupport::Cache::MemoryStore.new + @mailer = CachingMailer.new + @mailer.perform_caching = true + @mailer.cache_store = @store + end + + def test_fragment_caching + email = @mailer.fragment_cache + expected_body = "\"Welcome\"" + + assert_match expected_body, email.body.encoded + assert_match "\"Welcome\"", + @store.read("views/caching/#{template_digest("caching_mailer/fragment_cache")}") + end + + def test_fragment_caching_in_partials + email = @mailer.fragment_cache_in_partials + assert_match(/Old fragment caching in a partial/, email.body.encoded) + + assert_match("Old fragment caching in a partial", + @store.read("views/caching/#{template_digest("caching_mailer/_partial")}")) + end + + def test_skip_fragment_cache_digesting + email = @mailer.skip_fragment_cache_digesting + expected_body = "No Digest" + + assert_match expected_body, email.body.encoded + assert_match expected_body, @store.read("views/no_digest") + end + + private + + def template_digest(name) + ActionView::Digestor.digest(name: name, finder: @mailer.lookup_context) + end +end + +class CacheHelperOutputBufferTest < BaseCachingTest + + class MockController + def read_fragment(name, options) + return false + end + + def write_fragment(name, fragment, options) + fragment + end + end + + def setup + super + end + + def test_output_buffer + output_buffer = ActionView::OutputBuffer.new + controller = MockController.new + cache_helper = Class.new do + def self.controller; end; + def self.output_buffer; end; + def self.output_buffer=; end; + end + cache_helper.extend(ActionView::Helpers::CacheHelper) + + cache_helper.stub :controller, controller do + cache_helper.stub :output_buffer, output_buffer do + assert_called_with cache_helper, :output_buffer=, [output_buffer.class.new(output_buffer)] do + assert_nothing_raised do + cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil } + end + end + end + end + end + + def test_safe_buffer + output_buffer = ActiveSupport::SafeBuffer.new + controller = MockController.new + cache_helper = Class.new do + def self.controller; end; + def self.output_buffer; end; + def self.output_buffer=; end; + end + cache_helper.extend(ActionView::Helpers::CacheHelper) + + cache_helper.stub :controller, controller do + cache_helper.stub :output_buffer, output_buffer do + assert_called_with cache_helper, :output_buffer=, [output_buffer.class.new(output_buffer)] do + assert_nothing_raised do + cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil } + end + end + end + end + end +end + +class ViewCacheDependencyTest < BaseCachingTest + class NoDependenciesMailer < ActionMailer::Base + end + class HasDependenciesMailer < ActionMailer::Base + view_cache_dependency { "trombone" } + view_cache_dependency { "flute" } + end + + def test_view_cache_dependencies_are_empty_by_default + assert NoDependenciesMailer.new.view_cache_dependencies.empty? + end + + def test_view_cache_dependencies_are_listed_in_declaration_order + assert_equal %w(trombone flute), HasDependenciesMailer.new.view_cache_dependencies + end +end diff --git a/actionmailer/test/fixtures/caching_mailer/_partial.html.erb b/actionmailer/test/fixtures/caching_mailer/_partial.html.erb new file mode 100644 index 0000000000..8e965f52b4 --- /dev/null +++ b/actionmailer/test/fixtures/caching_mailer/_partial.html.erb @@ -0,0 +1,3 @@ +<% cache :caching do %> + Old fragment caching in a partial +<% end %> diff --git a/actionmailer/test/fixtures/caching_mailer/fragment_cache.html.erb b/actionmailer/test/fixtures/caching_mailer/fragment_cache.html.erb new file mode 100644 index 0000000000..90189627da --- /dev/null +++ b/actionmailer/test/fixtures/caching_mailer/fragment_cache.html.erb @@ -0,0 +1,3 @@ +<% cache :caching do %> +"Welcome" +<% end %> diff --git a/actionmailer/test/fixtures/caching_mailer/fragment_cache_in_partials.html.erb b/actionmailer/test/fixtures/caching_mailer/fragment_cache_in_partials.html.erb new file mode 100644 index 0000000000..2957d083e8 --- /dev/null +++ b/actionmailer/test/fixtures/caching_mailer/fragment_cache_in_partials.html.erb @@ -0,0 +1 @@ +<%= render "partial" %> diff --git a/actionmailer/test/fixtures/caching_mailer/skip_fragment_cache_digesting.html.erb b/actionmailer/test/fixtures/caching_mailer/skip_fragment_cache_digesting.html.erb new file mode 100644 index 0000000000..0d52429a81 --- /dev/null +++ b/actionmailer/test/fixtures/caching_mailer/skip_fragment_cache_digesting.html.erb @@ -0,0 +1,3 @@ +<%= cache :no_digest, skip_digest: true do %> + No Digest +<% end %> diff --git a/actionmailer/test/mailers/caching_mailer.rb b/actionmailer/test/mailers/caching_mailer.rb new file mode 100644 index 0000000000..345d267a36 --- /dev/null +++ b/actionmailer/test/mailers/caching_mailer.rb @@ -0,0 +1,15 @@ +class CachingMailer < ActionMailer::Base + self.mailer_name = "caching_mailer" + + def fragment_cache + mail(subject: "welcome", template_name: "fragment_cache") + end + + def fragment_cache_in_partials + mail(subject: "welcome", template_name: "fragment_cache_in_partials") + end + + def skip_fragment_cache_digesting + mail(subject: "welcome", template_name: "skip_fragment_cache_digesting") + end +end -- cgit v1.2.3 From a24d067343e7b14f066490c011828d57599fa94f Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Wed, 30 Dec 2015 20:48:27 +0800 Subject: Move caching/fragments in ActionMailer and ActionController to action_dispatch/caching/fragments --- actionmailer/lib/action_mailer/caching.rb | 7 +- .../lib/action_mailer/caching/fragments.rb | 148 --------------------- 2 files changed, 2 insertions(+), 153 deletions(-) delete mode 100644 actionmailer/lib/action_mailer/caching/fragments.rb (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer/caching.rb b/actionmailer/lib/action_mailer/caching.rb index 27da8148d1..c5b4890178 100644 --- a/actionmailer/lib/action_mailer/caching.rb +++ b/actionmailer/lib/action_mailer/caching.rb @@ -1,14 +1,11 @@ require 'active_support/descendants_tracker' +require 'action_dispatch/caching/fragments' module ActionMailer module Caching extend ActiveSupport::Concern extend ActiveSupport::Autoload - eager_autoload do - autoload :Fragments - end - module ConfigMethods def cache_store config.cache_store @@ -26,7 +23,7 @@ module ActionMailer include AbstractController::Helpers include ConfigMethods - include Fragments + include ActionDispatch::Caching::Fragments included do extend ConfigMethods diff --git a/actionmailer/lib/action_mailer/caching/fragments.rb b/actionmailer/lib/action_mailer/caching/fragments.rb deleted file mode 100644 index 6c70137626..0000000000 --- a/actionmailer/lib/action_mailer/caching/fragments.rb +++ /dev/null @@ -1,148 +0,0 @@ -module ActionMailer - module Caching - # Fragment caching is used for caching various blocks within - # views without caching the entire action as a whole. This is - # useful when certain elements of an action change frequently or - # depend on complicated state while other parts rarely change or - # can be shared amongst multiple parties. The caching is done using - # the +cache+ helper available in the Action View. See - # ActionView::Helpers::CacheHelper for more information. - # - # While it's strongly recommended that you use key-based cache - # expiration (see links in CacheHelper for more information), - # it is also possible to manually expire caches. For example: - # - # expire_fragment('name_of_cache') - module Fragments - extend ActiveSupport::Concern - - included do - if respond_to?(:class_attribute) - class_attribute :fragment_cache_keys - else - mattr_writer :fragment_cache_keys - end - - self.fragment_cache_keys = [] - - helper_method :fragment_cache_key if respond_to?(:helper_method) - end - - module ClassMethods - # Allows you to specify controller-wide key prefixes for - # cache fragments. Pass either a constant +value+, or a block - # which computes a value each time a cache key is generated. - # - # For example, you may want to prefix all fragment cache keys - # with a global version identifier, so you can easily - # invalidate all caches. - # - # class ApplicationController - # fragment_cache_key "v1" - # end - # - # When it's time to invalidate all fragments, simply change - # the string constant. Or, progressively roll out the cache - # invalidation using a computed value: - # - # class ApplicationController - # fragment_cache_key do - # @account.id.odd? ? "v1" : "v2" - # end - # end - def fragment_cache_key(value = nil, &key) - self.fragment_cache_keys += [key || ->{ value }] - end - end - - # Given a key (as described in +expire_fragment+), returns - # a key suitable for use in reading, writing, or expiring a - # cached fragment. All keys begin with views/, - # followed by any controller-wide key prefix values, ending - # with the specified +key+ value. The key is expanded using - # ActiveSupport::Cache.expand_cache_key. - def fragment_cache_key(key) - head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) } - tail = key.is_a?(Hash) ? url_for(key).split("://").last : key - ActiveSupport::Cache.expand_cache_key([*head, *tail], :views) - end - - # Writes +content+ to the location signified by - # +key+ (see +expire_fragment+ for acceptable formats). - def write_fragment(key, content, options = nil) - return content unless cache_configured? - - key = fragment_cache_key(key) - instrument_fragment_cache :write_fragment, key do - content = content.to_str - cache_store.write(key, content, options) - end - content - end - - # Reads a cached fragment from the location signified by +key+ - # (see +expire_fragment+ for acceptable formats). - def read_fragment(key, options = nil) - return unless cache_configured? - - key = fragment_cache_key(key) - instrument_fragment_cache :read_fragment, key do - result = cache_store.read(key, options) - result.respond_to?(:html_safe) ? result.html_safe : result - end - end - - # Check if a cached fragment from the location signified by - # +key+ exists (see +expire_fragment+ for acceptable formats). - def fragment_exist?(key, options = nil) - return unless cache_configured? - key = fragment_cache_key(key) - - instrument_fragment_cache :exist_fragment?, key do - cache_store.exist?(key, options) - end - end - - # Removes fragments from the cache. - # - # +key+ can take one of three forms: - # - # * String - This would normally take the form of a path, like - # pages/45/notes. - # * Hash - Treated as an implicit call to +url_for+, like - # { controller: 'pages', action: 'notes', id: 45} - # * Regexp - Will remove any fragment that matches, so - # %r{pages/\d*/notes} might remove all notes. Make sure you - # don't use anchors in the regex (^ or $) because - # the actual filename matched looks like - # ./cache/filename/path.cache. Note: Regexp expiration is - # only supported on caches that can iterate over all keys (unlike - # memcached). - # - # +options+ is passed through to the cache store's +delete+ - # method (or delete_matched, for Regexp keys). - def expire_fragment(key, options = nil) - return unless cache_configured? - key = fragment_cache_key(key) unless key.is_a?(Regexp) - - instrument_fragment_cache :expire_fragment, key do - if key.is_a?(Regexp) - cache_store.delete_matched(key, options) - else - cache_store.delete(key, options) - end - end - end - - def instrument_fragment_cache(name, key) # :nodoc: - payload = { - controller: controller_name, - action: action_name, - key: key - } - - ActiveSupport::Notifications.instrument("#{name}.action_controller", payload) { yield } - end - end - end -end -- cgit v1.2.3 From 3e824d3f5b32bae70832fe0c1c329ce062f79ff9 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Wed, 30 Dec 2015 21:07:40 +0800 Subject: Move most caching methods to ActionDispatch::Caching, and let ActionMailer and ActionController to include it --- actionmailer/lib/action_mailer/caching.rb | 57 ++----------------------------- actionmailer/test/caching_test.rb | 1 - 2 files changed, 3 insertions(+), 55 deletions(-) (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer/caching.rb b/actionmailer/lib/action_mailer/caching.rb index c5b4890178..319909d1a7 100644 --- a/actionmailer/lib/action_mailer/caching.rb +++ b/actionmailer/lib/action_mailer/caching.rb @@ -1,62 +1,11 @@ -require 'active_support/descendants_tracker' -require 'action_dispatch/caching/fragments' +require 'action_dispatch/caching' module ActionMailer module Caching - extend ActiveSupport::Concern extend ActiveSupport::Autoload - - module ConfigMethods - def cache_store - config.cache_store - end - - def cache_store=(store) - config.cache_store = ActiveSupport::Cache.lookup_store(store) - end - - private - def cache_configured? - perform_caching && cache_store - end - end - - include AbstractController::Helpers - include ConfigMethods - include ActionDispatch::Caching::Fragments - + extend ActiveSupport::Concern included do - extend ConfigMethods - - config_accessor :default_static_extension - self.default_static_extension ||= '.html' - - config_accessor :perform_caching - self.perform_caching = true if perform_caching.nil? - - class_attribute :_view_cache_dependencies - self._view_cache_dependencies = [] - helper_method :view_cache_dependencies if respond_to?(:helper_method) - end - - module ClassMethods - def view_cache_dependency(&dependency) - self._view_cache_dependencies += [dependency] - end - end - - def view_cache_dependencies - self.class._view_cache_dependencies.map { |dep| instance_exec(&dep) }.compact - end - - protected - # Convenience accessor. - def cache(key, options = {}, &block) - if cache_configured? - cache_store.fetch(ActiveSupport::Cache.expand_cache_key(key, :controller), options, &block) - else - yield - end + include ActionDispatch::Caching end def perform_caching diff --git a/actionmailer/test/caching_test.rb b/actionmailer/test/caching_test.rb index a92f43a6c5..e48d2042ac 100644 --- a/actionmailer/test/caching_test.rb +++ b/actionmailer/test/caching_test.rb @@ -2,7 +2,6 @@ require 'fileutils' require 'abstract_unit' require 'mailers/base_mailer' require 'mailers/caching_mailer' -require 'byebug' CACHE_DIR = 'test_cache' # Don't change '/../temp/' cavalierly or you might hose something you don't want hosed -- cgit v1.2.3 From 1de6f7938dbc58a618a89397aad5f217a6221d17 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Thu, 31 Dec 2015 09:41:48 +0800 Subject: Make caching configuration more flexible --- actionmailer/lib/action_mailer/caching.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer/caching.rb b/actionmailer/lib/action_mailer/caching.rb index 319909d1a7..8e659981a1 100644 --- a/actionmailer/lib/action_mailer/caching.rb +++ b/actionmailer/lib/action_mailer/caching.rb @@ -8,12 +8,15 @@ module ActionMailer include ActionDispatch::Caching end - def perform_caching - Base.perform_caching + def instrument_payload(key) + { + mailer: mailer_name, + key: key + } end - def controller_name - "ActionMailer" + def instrument_name + "action_mailer" end end end -- cgit v1.2.3 From 98fe07a946543a6f4d2d7dc9758f0145e1ab932e Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Wed, 6 Jan 2016 15:29:22 +0800 Subject: Move ActionMailer::Caching's content into ActionMailer::Base instead of including it Remove useless helper in ActionDispatch::Caching and fix indentation --- actionmailer/lib/action_mailer/base.rb | 16 +++++++++++++++- actionmailer/lib/action_mailer/caching.rb | 22 ---------------------- actionmailer/test/caching_test.rb | 2 -- 3 files changed, 15 insertions(+), 25 deletions(-) delete mode 100644 actionmailer/lib/action_mailer/caching.rb (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 9b14a96d48..25be5c3a7f 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -6,6 +6,8 @@ require 'active_support/core_ext/module/anonymous' require 'action_mailer/log_subscriber' +require 'action_dispatch/caching' + module ActionMailer # Action Mailer allows you to send email from your application using a mailer model and views. # @@ -420,7 +422,6 @@ module ActionMailer class Base < AbstractController::Base include DeliveryMethods include Previews - include Caching abstract! @@ -431,6 +432,7 @@ module ActionMailer include AbstractController::Translation include AbstractController::AssetPaths include AbstractController::Callbacks + include ActionDispatch::Caching include ActionView::Layouts @@ -828,6 +830,18 @@ module ActionMailer message end + # This and #instrument_name is for caching instrument + def instrument_payload(key) + { + mailer: mailer_name, + key: key + } + end + + def instrument_name + "action_mailer" + end + protected # Used by #mail to set the content type of the message. diff --git a/actionmailer/lib/action_mailer/caching.rb b/actionmailer/lib/action_mailer/caching.rb deleted file mode 100644 index 8e659981a1..0000000000 --- a/actionmailer/lib/action_mailer/caching.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'action_dispatch/caching' - -module ActionMailer - module Caching - extend ActiveSupport::Autoload - extend ActiveSupport::Concern - included do - include ActionDispatch::Caching - end - - def instrument_payload(key) - { - mailer: mailer_name, - key: key - } - end - - def instrument_name - "action_mailer" - end - end -end diff --git a/actionmailer/test/caching_test.rb b/actionmailer/test/caching_test.rb index e48d2042ac..b4344eb167 100644 --- a/actionmailer/test/caching_test.rb +++ b/actionmailer/test/caching_test.rb @@ -10,8 +10,6 @@ FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR) class FragmentCachingMailer < ActionMailer::Base abstract! - include ActionMailer::Caching - def some_action; end end -- cgit v1.2.3 From 3d7b0d480467b17715941503b1fe598e57c13ac1 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Thu, 7 Jan 2016 13:27:07 +0800 Subject: Change ActionMailer's default caching configuration and update generator's environment templates --- actionmailer/lib/action_mailer/railtie.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index fce0d0f9f1..215d0199af 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -25,7 +25,7 @@ module ActionMailer options.javascripts_dir ||= paths["public/javascripts"].first options.stylesheets_dir ||= paths["public/stylesheets"].first options.show_previews = Rails.env.development? if options.show_previews.nil? - options.perform_caching ||= true + options.cache_store ||= Rails.cache if options.show_previews options.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/mailers/previews" : nil -- cgit v1.2.3 From 40fa818580a9277d8d1a02241f1422dbf83a8aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 23 Feb 2016 19:55:49 -0300 Subject: Move Caching module to Abstract Controller Abstract Controller is the common component between Action Mailer and Action Controller so if we need to share the caching component it need to be there. --- actionmailer/lib/action_mailer.rb | 1 - actionmailer/lib/action_mailer/base.rb | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb index 26fbb48600..55c017e338 100644 --- a/actionmailer/lib/action_mailer.rb +++ b/actionmailer/lib/action_mailer.rb @@ -44,7 +44,6 @@ module ActionMailer autoload :MailHelper autoload :Preview autoload :Previews, 'action_mailer/preview' - autoload :Caching autoload :TestCase autoload :TestHelper autoload :MessageDelivery diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 25be5c3a7f..129aa1edfe 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -6,8 +6,6 @@ require 'active_support/core_ext/module/anonymous' require 'action_mailer/log_subscriber' -require 'action_dispatch/caching' - module ActionMailer # Action Mailer allows you to send email from your application using a mailer model and views. # @@ -432,7 +430,7 @@ module ActionMailer include AbstractController::Translation include AbstractController::AssetPaths include AbstractController::Callbacks - include ActionDispatch::Caching + include AbstractController::Caching include ActionView::Layouts -- cgit v1.2.3 From 338750393d0f19b193f0ead26adff2b9f586ec18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 24 Feb 2016 00:08:01 -0300 Subject: Move private methods to the private visibility --- actionmailer/lib/action_mailer/base.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 129aa1edfe..559cd06d91 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -828,18 +828,6 @@ module ActionMailer message end - # This and #instrument_name is for caching instrument - def instrument_payload(key) - { - mailer: mailer_name, - key: key - } - end - - def instrument_name - "action_mailer" - end - protected # Used by #mail to set the content type of the message. @@ -960,6 +948,18 @@ module ActionMailer container.add_part(part) end + # This and #instrument_name is for caching instrument + def instrument_payload(key) + { + mailer: mailer_name, + key: key + } + end + + def instrument_name + "action_mailer" + end + ActiveSupport.run_load_hooks(:action_mailer, self) end end -- cgit v1.2.3