From 00d6271d2b11a14065925529af0c1200406f8beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 9 Mar 2010 13:12:11 +0100 Subject: Clean up the API required from ActionView::Template. --- actionpack/lib/abstract_controller/rendering.rb | 2 +- actionpack/lib/action_view/template.rb | 32 ++++++++++++------------- actionpack/lib/action_view/template/resolver.rb | 31 ++++++++++-------------- actionpack/lib/action_view/template/text.rb | 6 +---- 4 files changed, 30 insertions(+), 41 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 5048754e33..5c34b83563 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -108,7 +108,7 @@ module AbstractController end def _with_template_hook(template) - self.formats = template.details[:formats] + self.formats = template.formats end end end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index cd6b1930a1..b4fdb49d3b 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -16,23 +16,22 @@ module ActionView end extend Template::Handlers - attr_reader :source, :identifier, :handler, :mime_type, :formats, :details + + attr_reader :source, :identifier, :handler, :virtual_path, :formats def initialize(source, identifier, handler, details) @source = source @identifier = identifier @handler = handler - @details = details + + @partial = details[:partial] + @virtual_path = details[:virtual_path] @method_names = {} - format = details.delete(:format) || begin - # TODO: Clean this up - handler.respond_to?(:default_format) ? handler.default_format.to_sym.to_s : "html" - end - @mime_type = Mime::Type.lookup_by_extension(format.to_s) - @formats = [format.to_sym] - @formats << :html if format == :js - @details[:formats] = Array.wrap(format.to_sym) + format = details[:format] + format ||= handler.default_format.to_sym if handler.respond_to?(:default_format) + format ||= :html + @formats = [format.to_sym] end def render(view, locals, &block) @@ -47,19 +46,20 @@ module ActionView end end - # TODO: Figure out how to abstract this + def mime_type + @mime_type ||= Mime::Type.lookup_by_extension(@formats.first.to_s) if @formats.first + end + def variable_name - @variable_name ||= identifier[%r'_?(\w+)(\.\w+)*$', 1].to_sym + @variable_name ||= @virtual_path[%r'_?(\w+)(\.\w+)*$', 1].to_sym end - # TODO: Figure out how to abstract this def counter_name @counter_name ||= "#{variable_name}_counter".to_sym end - # TODO: kill hax def partial? - @details[:partial] + @partial end def inspect @@ -87,7 +87,7 @@ module ActionView source = <<-end_src def #{method_name}(local_assigns) - _old_virtual_path, @_virtual_path = @_virtual_path, #{@details[:virtual_path].inspect};_old_output_buffer = output_buffer;#{locals_code};#{code} + _old_virtual_path, @_virtual_path = @_virtual_path, #{@virtual_path.inspect};_old_output_buffer = output_buffer;#{locals_code};#{code} ensure @_virtual_path, self.output_buffer = _old_virtual_path, _old_output_buffer end diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 6e6c4c21ee..c43b357e9e 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -74,7 +74,7 @@ module ActionView def find_templates(name, prefix, partial, details) path = build_path(name, prefix, partial, details) - query(path, EXTENSION_ORDER.map { |ext| details[ext] }) + query(partial, path, EXTENSION_ORDER.map { |ext| details[ext] }) end def build_path(name, prefix, partial, details) @@ -84,34 +84,27 @@ module ActionView path end - def query(path, exts) + def query(partial, path, exts) query = File.join(@path, path) + exts.each do |ext| query << '{' << ext.map {|e| e && ".#{e}" }.join(',') << '}' end Dir[query].reject { |p| File.directory?(p) }.map do |p| - Template.new(File.read(p), File.expand_path(p), *path_to_details(p)) + handler, format = extract_handler_and_format(p) + Template.new(File.read(p), File.expand_path(p), handler, + :partial => partial, :virtual_path => path, :format => format) end end - # # TODO: fix me - # # :api: plugin - def path_to_details(path) - # [:erb, :format => :html, :locale => :en, :partial => true/false] - if m = path.match(%r'((^|.*/)(_)?[\w-]+)((?:\.[\w-]+)*)\.(\w+)$') - partial = m[3] == '_' - details = (m[4]||"").split('.').reject { |e| e.empty? } - handler = Template.handler_class_for_extension(m[5]) - - format = Mime[details.last] && details.pop.to_sym - locale = details.last && details.pop.to_sym + def extract_handler_and_format(path) + pieces = File.basename(path).split(".") + pieces.shift - virtual_path = (m[1].gsub("#{@path}/", "") << details.join(".")) - - return handler, :format => format, :locale => locale, :partial => partial, - :virtual_path => virtual_path - end + handler = Template.handler_class_for_extension(pieces.pop) + format = pieces.last && Mime[pieces.last] && pieces.pop.to_sym + [handler, format] end end diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb index 5978a8a3ac..df394b0fb0 100644 --- a/actionpack/lib/action_view/template/text.rb +++ b/actionpack/lib/action_view/template/text.rb @@ -7,10 +7,6 @@ module ActionView #:nodoc: @content_type ||= Mime::TEXT end - def details - {:formats => [@content_type.to_sym]} - end - def identifier 'text template' end @@ -28,7 +24,7 @@ module ActionView #:nodoc: end def formats - [mime_type] + [@content_type.to_sym] end def partial? -- cgit v1.2.3 From ec0973c2abeb80eb3c93c5df070592da56ef5b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 10 Mar 2010 16:44:24 +0100 Subject: Remove uneeded methods. --- .../action_controller/metal/http_authentication.rb | 22 ++++------------------ .../lib/action_dispatch/http/mime_negotiation.rb | 15 --------------- 2 files changed, 4 insertions(+), 33 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index f1355a83a3..6ec788f302 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -124,7 +124,7 @@ module ActionController end def authenticate(request, &login_procedure) - unless authorization(request).blank? + unless request.authorization.blank? login_procedure.call(*user_name_and_password(request)) end end @@ -133,15 +133,8 @@ module ActionController decode_credentials(request).split(/:/, 2) end - def authorization(request) - request.env['HTTP_AUTHORIZATION'] || - request.env['X-HTTP_AUTHORIZATION'] || - request.env['X_HTTP_AUTHORIZATION'] || - request.env['REDIRECT_X_HTTP_AUTHORIZATION'] - end - def decode_credentials(request) - ActiveSupport::Base64.decode64(authorization(request).split(' ', 2).last || '') + ActiveSupport::Base64.decode64(request.authorization.split(' ', 2).last || '') end def encode_credentials(user_name, password) @@ -176,14 +169,7 @@ module ActionController # Returns false on a valid response, true otherwise def authenticate(secret_key, request, realm, &password_procedure) - authorization(request) && validate_digest_response(secret_key, request, realm, &password_procedure) - end - - def authorization(request) - request.env['HTTP_AUTHORIZATION'] || - request.env['X-HTTP_AUTHORIZATION'] || - request.env['X_HTTP_AUTHORIZATION'] || - request.env['REDIRECT_X_HTTP_AUTHORIZATION'] + request.authorization && validate_digest_response(secret_key, request, realm, &password_procedure) end # Returns false unless the request credentials response value matches the expected value. @@ -226,7 +212,7 @@ module ActionController end def decode_credentials_header(request) - decode_credentials(authorization(request)) + decode_credentials(request.authorization) end def decode_credentials(header) diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb index 40617e239a..fec250e928 100644 --- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb +++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb @@ -67,21 +67,6 @@ module ActionDispatch @env["action_dispatch.request.formats"] = [Mime::Type.lookup_by_extension(parameters[:format])] end - # Returns a symbolized version of the :format parameter of the request. - # If no \format is given it returns :jsfor Ajax requests and :html - # otherwise. - def template_format - parameter_format = parameters[:format] - - if parameter_format - parameter_format - elsif xhr? - :js - else - :html - end - end - # Receives an array of mimes and return the first user sent mime that # matches the order array. # -- cgit v1.2.3 From 07cf49aadf3195db6ddefc58932efc88a6704a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 10 Mar 2010 22:11:48 +0100 Subject: Optimize and clean up how details key get expired. --- actionpack/lib/abstract_controller.rb | 1 + actionpack/lib/abstract_controller/rendering.rb | 28 ++++++++++++ actionpack/lib/abstract_controller/view_paths.rb | 3 +- actionpack/lib/action_view.rb | 1 + actionpack/lib/action_view/base.rb | 2 +- actionpack/lib/action_view/lookup_context.rb | 57 ++++++++++++------------ actionpack/lib/action_view/template/resolver.rb | 5 +++ 7 files changed, 67 insertions(+), 30 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index 7028cd0379..2da4dc052c 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -7,6 +7,7 @@ require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/module/attr_internal' require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/module/anonymous' +require 'active_support/i18n' module AbstractController extend ActiveSupport::Autoload diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 5c34b83563..42f4939108 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -9,10 +9,38 @@ module AbstractController end end + # This is a class to fix I18n global state. Whenever you provide I18n.locale during a request, + # it will trigger the lookup_context and consequently expire the cache. + # TODO Add some deprecation warnings to remove I18n.locale from controllers + class I18nProxy < ::I18n::Config #:nodoc: + attr_reader :i18n_config, :lookup_context + + def initialize(i18n_config, lookup_context) + @i18n_config, @lookup_context = i18n_config, lookup_context + end + + def locale + @i18n_config.locale + end + + def locale=(value) + @i18n_config.locale = value + @lookup_context.update_details(:locale => @i18n_config.locale) + end + end + module Rendering extend ActiveSupport::Concern include AbstractController::ViewPaths + # Overwrite process to setup I18n proxy. + def process(*) #:nodoc: + old_config, I18n.config = I18n.config, I18nProxy.new(I18n.config, lookup_context) + super + ensure + I18n.config = old_config + end + # An instance of a view class. The default view class is ActionView::Base # # The view class must have the following methods: diff --git a/actionpack/lib/abstract_controller/view_paths.rb b/actionpack/lib/abstract_controller/view_paths.rb index 6513c0778e..c2a9f6336d 100644 --- a/actionpack/lib/abstract_controller/view_paths.rb +++ b/actionpack/lib/abstract_controller/view_paths.rb @@ -7,7 +7,8 @@ module AbstractController self._view_paths = ActionView::PathSet.new end - delegate :template_exists?, :view_paths, :formats, :formats=, :to => :lookup_context + delegate :template_exists?, :view_paths, :formats, :formats=, + :locale, :locale=, :to => :lookup_context # LookupContext is the object responsible to hold all information required to lookup # templates, i.e. view paths and details. Check ActionView::LookupContext for more diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 7e9ac8720c..afe6386105 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -58,6 +58,7 @@ module ActionView autoload :TestCase, 'action_view/test_case' end +require 'active_support/i18n' require 'active_support/core_ext/string/output_safety' I18n.load_path << "#{File.dirname(__FILE__)}/action_view/locale/en.yml" diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 564ea6684c..ffe3060404 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -194,7 +194,7 @@ module ActionView #:nodoc: attr_accessor :base_path, :assigns, :template_extension, :lookup_context attr_internal :captures, :request, :layout, :controller, :template, :config - delegate :find, :exists?, :formats, :formats=, + delegate :find, :exists?, :formats, :formats=, :locale, :locale=, :view_paths, :view_paths=, :with_fallbacks, :update_details, :to => :lookup_context delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers, diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index 4a4dc0d06c..91885c7370 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/object/try' +require 'active_support/core_ext/object/blank' module ActionView # LookupContext is the object responsible to hold all information required to lookup @@ -14,16 +15,14 @@ module ActionView def self.register_detail(name, options = {}) registered_details[name] = lambda do |value| - value = (value.blank? || options[:accessible] == false) ? - Array(yield) : Array(value) + value = Array(value.presence || yield) value |= [nil] unless options[:allow_nil] == false value end end register_detail(:formats) { Mime::SET.symbols } - register_detail(:locale, :accessible => false) { [I18n.locale] } - register_detail(:handlers, :accessible => false) { Template::Handlers.extensions } + register_detail(:locale) { [I18n.locale] } class DetailsKey #:nodoc: attr_reader :details @@ -38,16 +37,12 @@ module ActionView def initialize(details) @details, @hash = details, details.hash end - - def outdated?(details) - @details != details - end end def initialize(view_paths, details = {}) + @details_key = nil self.view_paths = view_paths self.details = details - @details_key = nil end module ViewPaths @@ -60,18 +55,15 @@ module ActionView end def find(name, prefix = nil, partial = false) - key = details_key - @view_paths.find(name, prefix, partial || false, key.details, key) + @view_paths.find(name, prefix, partial || false, details, details_key) end def find_all(name, prefix = nil, partial = false) - key = details_key - @view_paths.find_all(name, prefix, partial || false, key.details, key) + @view_paths.find_all(name, prefix, partial || false, details, details_key) end def exists?(name, prefix = nil, partial = false) - key = details_key - @view_paths.exists?(name, prefix, partial || false, key.details, key) + @view_paths.exists?(name, prefix, partial || false, details, details_key) end # Add fallbacks to the view paths. Useful in cases you are rendering a file. @@ -89,25 +81,20 @@ module ActionView end module Details - def details - @details = normalize_details(@details) - end + attr_reader :details - def details=(new_details) - @details = new_details - details + def details=(details) + @details = normalize_details(details) + @details_key = nil if @details_key && @details_key.details != @details end - # TODO This is too expensive. Revisit this. def details_key - latest_details = self.details - @details_key = nil if @details_key.try(:outdated?, latest_details) - @details_key ||= DetailsKey.get(latest_details) + @details_key ||= DetailsKey.get(@details) end # Shortcut to read formats from details. def formats - self.details[:formats] + @details[:formats].compact end # Shortcut to set formats in details. @@ -115,11 +102,25 @@ module ActionView self.details = @details.merge(:formats => value) end + # Shortcut to read locale. + def locale + I18n.locale + end + + # Shortcut to set locale in details and I18n. + def locale=(value) + I18n.locale = value + + unless I18n.config.respond_to?(:lookup_context) + self.details = @details.merge(:locale => value) + end + end + # Update the details keys by merging the given hash into the current # details hash. If a block is given, the details are modified just during # the execution of the block and reverted to the previous value after. def update_details(new_details) - old_details = self.details + old_details = @details self.details = old_details.merge(new_details) if block_given? @@ -140,7 +141,7 @@ module ActionView self.class.registered_details.each do |k, v| details[k] = v.call(details[k]) end - details + details.freeze end end diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index c43b357e9e..a43597e728 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -21,6 +21,7 @@ module ActionView # Normalizes the arguments and passes it on to find_template. def find_all(name, prefix=nil, partial=false, details={}, key=nil) name, prefix = normalize_name(name, prefix) + details = details.merge(:handlers => default_handlers) cached(key, prefix, name, partial) do find_templates(name, prefix, partial, details) @@ -33,6 +34,10 @@ module ActionView @caching ||= !defined?(Rails.application) || Rails.application.config.cache_classes end + def default_handlers + Template::Handlers.extensions + [nil] + end + # This is what child classes implement. No defaults are needed # because Resolver guarantees that the arguments are present and # normalized. -- cgit v1.2.3