Refactor ActionView::Template::Types to avoid delegation

The `Type` class was introduced in https://github.com/rails/rails/pull/23085
for the sole purpose of breaking the dependency of Action View on Action Dispatch.

Unless you are somehow running Action View standalone, this is actually
never used.

So instead of delegating, we can use constant swapping, this saves us
a useless layer.

Ultimately we could consider moving `Mime::Types` into Active Support
but it requires some more thoughts.
This commit is contained in:
Jean Boussier 2023-05-08 10:10:27 +09:00
parent 4ea4a98234
commit 06d2c2d15b
6 changed files with 44 additions and 43 deletions

@ -73,6 +73,6 @@ def self.eager_load!
ActiveSupport.on_load(:action_view) do ActiveSupport.on_load(:action_view) do
ActionView::Base.default_formats ||= Mime::SET.symbols ActionView::Base.default_formats ||= Mime::SET.symbols
ActionView::Template::Types.delegate_to Mime ActionView::Template.mime_types_implementation = Mime
ActionView::LookupContext::DetailsKey.clear ActionView::LookupContext::DetailsKey.clear
end end

@ -147,6 +147,6 @@ def eager_load!
ActiveSupport.on_load(:action_view) do ActiveSupport.on_load(:action_view) do
ActionView::Base.default_formats ||= Mime::SET.symbols ActionView::Base.default_formats ||= Mime::SET.symbols
ActionView::Template::Types.delegate_to Mime ActionView::Template.mime_types_implementation = Mime
ActionView::LookupContext::DetailsKey.clear ActionView::LookupContext::DetailsKey.clear
end end

@ -42,6 +42,10 @@ def [](type)
Type.lookup_by_extension(type) Type.lookup_by_extension(type)
end end
def symbols
SET.symbols
end
def fetch(type, &block) def fetch(type, &block)
return type if type.is_a?(Type) return type if type.is_a?(Type)
EXTENSION_LOOKUP.fetch(type.to_s, &block) EXTENSION_LOOKUP.fetch(type.to_s, &block)

@ -109,6 +109,7 @@ class Template
autoload :Handlers autoload :Handlers
autoload :HTML autoload :HTML
autoload :Inline autoload :Inline
autoload :Types
autoload :Sources autoload :Sources
autoload :Text autoload :Text
autoload :Types autoload :Types
@ -119,6 +120,17 @@ class Template
singleton_class.attr_accessor :frozen_string_literal singleton_class.attr_accessor :frozen_string_literal
@frozen_string_literal = false @frozen_string_literal = false
class << self # :nodoc:
def mime_types_implementation=(implementation)
# This method isn't thread-safe, but it's not supposed
# to be called after initialization
if self::Types != implementation
remove_const(:Types)
const_set(:Types, implementation)
end
end
end
attr_reader :identifier, :handler attr_reader :identifier, :handler
attr_reader :variable, :format, :variant, :virtual_path attr_reader :variable, :format, :variant, :virtual_path

@ -4,53 +4,38 @@
module ActionView module ActionView
class Template # :nodoc: class Template # :nodoc:
module Types class SimpleType # :nodoc:
class Type SET = Struct.new(:symbols).new([ :html, :text, :js, :css, :xml, :json ])
SET = Struct.new(:symbols).new([ :html, :text, :js, :css, :xml, :json ])
def self.[](type) def self.[](type)
if type.is_a?(self) if type.is_a?(self)
type type
else else
new(type) new(type)
end
end
attr_reader :symbol
def initialize(symbol)
@symbol = symbol.to_sym
end
def to_s
@symbol.to_s
end
alias to_str to_s
def ref
@symbol
end
alias to_sym ref
def ==(type)
@symbol == type.to_sym unless type.blank?
end end
end end
class << self attr_reader :symbol
attr_reader :symbols
def delegate_to(klass) def initialize(symbol)
@symbols = klass::SET.symbols @symbol = symbol.to_sym
@type_klass = klass
end
def [](type)
@type_klass[type]
end
end end
delegate_to Type def to_s
@symbol.to_s
end
alias to_str to_s
def ref
@symbol
end
alias to_sym ref
def ==(type)
@symbol == type.to_sym unless type.blank?
end
end end
Types = SimpleType # :nodoc:
end end
end end

@ -4,7 +4,7 @@
require "active_support/ordered_options" require "active_support/ordered_options"
require "action_dispatch" require "action_dispatch"
ActionView::Template::Types.delegate_to Mime ActionView::Template.mime_types_implementation = Mime
module AssetTagHelperTestHelpers module AssetTagHelperTestHelpers
def with_preload_links_header(new_preload_links_header = true) def with_preload_links_header(new_preload_links_header = true)