diff options
-rw-r--r-- | actionview/lib/action_view/renderer/partial_renderer.rb | 14 | ||||
-rw-r--r-- | actionview/test/template/csp_helper_test.rb | 31 | ||||
-rw-r--r-- | actionview/test/template/render_test.rb | 11 | ||||
-rw-r--r-- | activejob/lib/active_job/core.rb | 7 | ||||
-rw-r--r-- | activejob/lib/active_job/logging.rb | 2 | ||||
-rw-r--r-- | activejob/test/cases/job_serialization_test.rb | 11 | ||||
-rw-r--r-- | activejob/test/cases/logging_test.rb | 2 | ||||
-rw-r--r-- | activerecord/CHANGELOG.md | 6 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation.rb | 4 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/spawn_methods.rb | 2 | ||||
-rw-r--r-- | activerecord/test/cases/scoping/named_scoping_test.rb | 5 | ||||
-rw-r--r-- | activerecord/test/models/reply.rb | 2 | ||||
-rw-r--r-- | activerecord/test/models/topic.rb | 3 | ||||
-rw-r--r-- | activesupport/lib/active_support/cache/file_store.rb | 13 | ||||
-rw-r--r-- | activesupport/test/cache/stores/file_store_test.rb | 2 |
15 files changed, 84 insertions, 31 deletions
diff --git a/actionview/lib/action_view/renderer/partial_renderer.rb b/actionview/lib/action_view/renderer/partial_renderer.rb index 800a62eaa1..f8a6f13ae9 100644 --- a/actionview/lib/action_view/renderer/partial_renderer.rb +++ b/actionview/lib/action_view/renderer/partial_renderer.rb @@ -308,6 +308,9 @@ module ActionView template = find_partial(@path, @template_keys) @variable ||= template.variable else + if options[:cached] + raise NotImplementedError, "render caching requires a template. Please specify a partial when rendering" + end template = nil end @@ -337,9 +340,14 @@ module ActionView spacer = find_template(@options[:spacer_template], @locals.keys).render(view, @locals) end - cache_collection_render(payload, view, template) do - template ? collection_with_template(view, template) : collection_without_template(view) - end.join(spacer).html_safe + collection_body = if template + cache_collection_render(payload, view, template) do + collection_with_template(view, template) + end + else + collection_without_template(view) + end + collection_body.join(spacer).html_safe end end diff --git a/actionview/test/template/csp_helper_test.rb b/actionview/test/template/csp_helper_test.rb new file mode 100644 index 0000000000..8bad25ba7d --- /dev/null +++ b/actionview/test/template/csp_helper_test.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require "abstract_unit" + +class CspHelperWithCspEnabledTest < ActionView::TestCase + tests ActionView::Helpers::CspHelper + + def content_security_policy_nonce + "iyhD0Yc0W+c=" + end + + def content_security_policy? + true + end + + def test_csp_meta_tag + assert_equal "<meta name=\"csp-nonce\" content=\"iyhD0Yc0W+c=\" />", csp_meta_tag + end +end + +class CspHelperWithCspDisabledTest < ActionView::TestCase + tests ActionView::Helpers::CspHelper + + def content_security_policy? + false + end + + def test_csp_meta_tag + assert_nil csp_meta_tag + end +end diff --git a/actionview/test/template/render_test.rb b/actionview/test/template/render_test.rb index 88047fd920..cda8c942d8 100644 --- a/actionview/test/template/render_test.rb +++ b/actionview/test/template/render_test.rb @@ -770,6 +770,17 @@ class CachedCollectionViewRenderTest < ActiveSupport::TestCase @view.render(partial: "test/cached_customer", collection: [customer], cached: true) end + test "collection caching does not work on multi-partials" do + a = Object.new + b = Object.new + def a.to_partial_path; "test/partial_iteration_1"; end + def b.to_partial_path; "test/partial_iteration_2"; end + + assert_raises(NotImplementedError) do + @controller_view.render(partial: [a, b], cached: true) + end + end + private def cache_key(*names, virtual_path) digest = ActionView::Digestor.digest name: virtual_path, finder: @view.lookup_context, dependencies: [] diff --git a/activejob/lib/active_job/core.rb b/activejob/lib/active_job/core.rb index 487cdd6d38..2ce008e3da 100644 --- a/activejob/lib/active_job/core.rb +++ b/activejob/lib/active_job/core.rb @@ -40,6 +40,9 @@ module ActiveJob # Timezone to be used during the job. attr_accessor :timezone + # Track when a job was enqueded + attr_accessor :enqueued_at + # These methods will be included into any Active Job object, adding # helpers for de/serialization and creation of job instances. module ClassMethods @@ -97,7 +100,8 @@ module ActiveJob "executions" => executions, "exception_executions" => exception_executions, "locale" => I18n.locale.to_s, - "timezone" => Time.zone.try(:name) + "timezone" => Time.zone.try(:name), + "enqueued_at" => Time.now.utc.iso8601 } end @@ -137,6 +141,7 @@ module ActiveJob self.exception_executions = job_data["exception_executions"] self.locale = job_data["locale"] || I18n.locale.to_s self.timezone = job_data["timezone"] || Time.zone.try(:name) + self.enqueued_at = job_data["enqueued_at"] end private diff --git a/activejob/lib/active_job/logging.rb b/activejob/lib/active_job/logging.rb index 416be83c24..1134e718a8 100644 --- a/activejob/lib/active_job/logging.rb +++ b/activejob/lib/active_job/logging.rb @@ -70,7 +70,7 @@ module ActiveJob def perform_start(event) info do job = event.payload[:job] - "Performing #{job.class.name} (Job ID: #{job.job_id}) from #{queue_name(event)}" + args_info(job) + "Performing #{job.class.name} (Job ID: #{job.job_id}) from #{queue_name(event)} enqueued at #{job.enqueued_at}" + args_info(job) end end diff --git a/activejob/test/cases/job_serialization_test.rb b/activejob/test/cases/job_serialization_test.rb index 86f3651564..c1cec1f1d6 100644 --- a/activejob/test/cases/job_serialization_test.rb +++ b/activejob/test/cases/job_serialization_test.rb @@ -61,4 +61,15 @@ class JobSerializationTest < ActiveSupport::TestCase assert_equal "Hawaii", job.serialize["timezone"] end end + + test "serialize stores the enqueued_at time" do + h1 = HelloJob.new + type = h1.serialize["enqueued_at"].class + assert_equal String, type + + h2 = HelloJob.deserialize(h1.serialize) + # We should be able to parse a timestamp + type = Time.parse(h2.enqueued_at).class + assert_equal Time, type + end end diff --git a/activejob/test/cases/logging_test.rb b/activejob/test/cases/logging_test.rb index 6154ba301d..acd37456c9 100644 --- a/activejob/test/cases/logging_test.rb +++ b/activejob/test/cases/logging_test.rb @@ -115,6 +115,8 @@ class LoggingTest < ActiveSupport::TestCase perform_enqueued_jobs do LoggingJob.perform_later "Dummy" assert_match(/Performing LoggingJob \(Job ID: .*?\) from .*? with arguments:.*Dummy/, @logger.messages) + + assert_match(/enqueued at /, @logger.messages) assert_match(/Dummy, here is it: Dummy/, @logger.messages) assert_match(/Performed LoggingJob \(Job ID: .*?\) from .*? in .*ms/, @logger.messages) end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index f16a746b91..7b4f3c617c 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -4,12 +4,6 @@ *Ryuta Kamizono* -* Chaining named scope is no longer leaking to class level querying methods. - - Fixes #14003. - - *Ryuta Kamizono* - * Allow applications to automatically switch connections. Adds a middleware and configuration options that can be used in your diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 347d745d19..f98d9bb2c0 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -321,12 +321,12 @@ module ActiveRecord # Please check unscoped if you want to remove all previous scopes (including # the default_scope) during the execution of a block. def scoping - @delegate_to_klass && klass.current_scope(true) ? yield : _scoping(self) { yield } + @delegate_to_klass ? yield : _scoping(self) { yield } end def _exec_scope(*args, &block) # :nodoc: @delegate_to_klass = true - _scoping(nil) { instance_exec(*args, &block) || self } + instance_exec(*args, &block) || self ensure @delegate_to_klass = false end diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index 8cf4fc469f..7874c4c35a 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -8,7 +8,7 @@ module ActiveRecord module SpawnMethods # This is overridden by Associations::CollectionProxy def spawn #:nodoc: - @delegate_to_klass && klass.current_scope(true) ? klass.all : clone + @delegate_to_klass ? klass.all : clone end # Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation. diff --git a/activerecord/test/cases/scoping/named_scoping_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb index 27f9df295f..1a3a95f168 100644 --- a/activerecord/test/cases/scoping/named_scoping_test.rb +++ b/activerecord/test/cases/scoping/named_scoping_test.rb @@ -447,9 +447,8 @@ class NamedScopingTest < ActiveRecord::TestCase assert_equal [posts(:sti_comments)], Post.with_special_comments.with_post(4).to_a.uniq end - def test_chaining_doesnt_leak_conditions_to_another_scopes - expected = Topic.where(approved: false).where(id: Topic.children.select(:parent_id)) - assert_equal expected.to_a, Topic.rejected.has_children.to_a + def test_class_method_in_scope + assert_equal [topics(:second)], topics(:first).approved_replies.ordered end def test_nested_scoping diff --git a/activerecord/test/models/reply.rb b/activerecord/test/models/reply.rb index 0807bcf875..b35623a344 100644 --- a/activerecord/test/models/reply.rb +++ b/activerecord/test/models/reply.rb @@ -7,6 +7,8 @@ class Reply < Topic belongs_to :topic_with_primary_key, class_name: "Topic", primary_key: "title", foreign_key: "parent_title", counter_cache: "replies_count", touch: true has_many :replies, class_name: "SillyReply", dependent: :destroy, foreign_key: "parent_id" has_many :silly_unique_replies, dependent: :destroy, foreign_key: "parent_id" + + scope :ordered, -> { Reply.order(:id) } end class SillyReply < Topic diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index fdb461ed7f..75890c327a 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -10,9 +10,6 @@ class Topic < ActiveRecord::Base scope :approved, -> { where(approved: true) } scope :rejected, -> { where(approved: false) } - scope :children, -> { where.not(parent_id: nil) } - scope :has_children, -> { where(id: Topic.children.select(:parent_id)) } - scope :scope_with_lambda, lambda { all } scope :by_lifo, -> { where(author_name: "lifo") } diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index de1fb1886c..f43894a1ea 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -18,7 +18,6 @@ module ActiveSupport DIR_FORMATTER = "%03X" FILENAME_MAX_SIZE = 228 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write) FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room - EXCLUDED_DIRS = [".", ".."].freeze GITKEEP_FILES = [".gitkeep", ".keep"].freeze def initialize(cache_path, options = nil) @@ -35,7 +34,7 @@ module ActiveSupport # file store directory except for .keep or .gitkeep. Be careful which directory is specified in your # config file when using +FileStore+ because everything in that directory will be deleted. def clear(options = nil) - root_dirs = exclude_from(cache_path, EXCLUDED_DIRS + GITKEEP_FILES) + root_dirs = (Dir.children(cache_path) - GITKEEP_FILES) FileUtils.rm_r(root_dirs.collect { |f| File.join(cache_path, f) }) rescue Errno::ENOENT end @@ -154,7 +153,7 @@ module ActiveSupport # Delete empty directories in the cache. def delete_empty_directories(dir) return if File.realpath(dir) == File.realpath(cache_path) - if exclude_from(dir, EXCLUDED_DIRS).empty? + if Dir.children(dir).empty? Dir.delete(dir) rescue nil delete_empty_directories(File.dirname(dir)) end @@ -167,8 +166,7 @@ module ActiveSupport def search_dir(dir, &callback) return if !File.exist?(dir) - Dir.foreach(dir) do |d| - next if EXCLUDED_DIRS.include?(d) + Dir.each_child(dir) do |d| name = File.join(dir, d) if File.directory?(name) search_dir(name, &callback) @@ -193,11 +191,6 @@ module ActiveSupport end end end - - # Exclude entries from source directory - def exclude_from(source, excludes) - Dir.entries(source).reject { |f| excludes.include?(f) } - end end end end diff --git a/activesupport/test/cache/stores/file_store_test.rb b/activesupport/test/cache/stores/file_store_test.rb index f6855bb308..0364d9ab64 100644 --- a/activesupport/test/cache/stores/file_store_test.rb +++ b/activesupport/test/cache/stores/file_store_test.rb @@ -101,7 +101,7 @@ class FileStoreTest < ActiveSupport::TestCase end assert File.exist?(cache_dir), "Parent of top level cache dir was deleted!" assert File.exist?(sub_cache_dir), "Top level cache dir was deleted!" - assert_empty Dir.entries(sub_cache_dir).reject { |f| ActiveSupport::Cache::FileStore::EXCLUDED_DIRS.include?(f) } + assert_empty Dir.children(sub_cache_dir) end def test_log_exception_when_cache_read_fails |