diff options
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r-- | actionpack/lib/action_dispatch/http/mime_type.rb | 6 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/upload.rb | 14 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/url.rb | 4 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/railtie.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/mapper.rb | 11 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/route_set.rb | 66 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/url_for.rb | 8 |
7 files changed, 85 insertions, 26 deletions
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 2152351703..e039eb1288 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -82,7 +82,7 @@ module Mime class << self TRAILING_STAR_REGEXP = /(text|application)\/\*/ - Q_SEPARATOR_REGEXP = /;\s*q=/ + PARAMETER_SEPARATOR_REGEXP = /;\s*\w+="?\w+"?/ def lookup(string) LOOKUP[string] @@ -109,7 +109,7 @@ module Mime def parse(accept_header) if accept_header !~ /,/ - accept_header = accept_header.split(Q_SEPARATOR_REGEXP).first + accept_header = accept_header.split(PARAMETER_SEPARATOR_REGEXP).first if accept_header =~ TRAILING_STAR_REGEXP parse_data_with_trailing_star($1) else @@ -119,7 +119,7 @@ module Mime # keep track of creation order to keep the subsequent sort stable list, index = [], 0 accept_header.split(/,/).each do |header| - params, q = header.split(Q_SEPARATOR_REGEXP) + params, q = header.split(PARAMETER_SEPARATOR_REGEXP) if params.present? params.strip! diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb index 5ab99d1061..c4a915d1ad 100644 --- a/actionpack/lib/action_dispatch/http/upload.rb +++ b/actionpack/lib/action_dispatch/http/upload.rb @@ -4,11 +4,12 @@ module ActionDispatch attr_accessor :original_filename, :content_type, :tempfile, :headers def initialize(hash) + @tempfile = hash[:tempfile] + raise(ArgumentError, ':tempfile is required') unless @tempfile + @original_filename = encode_filename(hash[:filename]) @content_type = hash[:type] @headers = hash[:head] - @tempfile = hash[:tempfile] - raise(ArgumentError, ':tempfile is required') unless @tempfile end def read(*args) @@ -19,15 +20,12 @@ module ActionDispatch [:open, :path, :rewind, :size].each do |method| class_eval "def #{method}; @tempfile.#{method}; end" end - + private + def encode_filename(filename) # Encode the filename in the utf8 encoding, unless it is nil - if filename - filename.force_encoding("UTF-8").encode! - else - filename - end + filename.force_encoding("UTF-8").encode! if filename end end diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 80ffbe575b..f9dae5dad7 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -40,7 +40,9 @@ module ActionDispatch rewritten_url << ":#{options.delete(:port)}" if options[:port] end - path = options.delete(:path) || '' + path = "" + path << options.delete(:script_name).to_s.chomp("/") + path << options.delete(:path).to_s params = options[:params] || {} params.reject! {|k,v| v.to_param.nil? } diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb index 35f901c575..62f906219c 100644 --- a/actionpack/lib/action_dispatch/railtie.rb +++ b/actionpack/lib/action_dispatch/railtie.rb @@ -16,7 +16,7 @@ module ActionDispatch config.action_dispatch.rack_cache = { :metastore => "rails:/", :entitystore => "rails:/", - :verbose => true + :verbose => false } initializer "action_dispatch.configure" do |app| diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 02a27110e4..cd215034dc 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -254,10 +254,15 @@ module ActionDispatch # # For options, see +match+, as +root+ uses it internally. # + # You can also pass a string which will expand + # + # root 'pages#main' + # # You should put the root route at the top of <tt>config/routes.rb</tt>, # because this means it will be matched first. As this is the most popular route # of most Rails applications, this is beneficial. def root(options = {}) + options = { :to => options } if options.is_a?(String) match '/', { :as => :root }.merge(options) end @@ -446,7 +451,11 @@ module ActionDispatch _route = @set.named_routes.routes[name.to_sym] _routes = @set app.routes.define_mounted_helper(name) - app.routes.class_eval do + app.routes.singleton_class.class_eval do + define_method :mounted? do + true + end + define_method :_generate_prefix do |options| prefix_options = options.slice(*_route.segment_keys) # we must actually delete prefix segment keys to avoid passing them to next url_for diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 0ec4e41470..30e9e5634b 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -191,14 +191,50 @@ module ActionDispatch selector = url_helper_name(name, kind) hash_access_method = hash_access_name(name, kind) - @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1 - remove_possible_method :#{selector} - def #{selector}(*args) - url_for(#{hash_access_method}(*args)) - end - END_EVAL + if optimize_helper?(route) + @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1 + remove_possible_method :#{selector} + def #{selector}(*args) + if args.size == #{route.required_parts.size} && !args.last.is_a?(Hash) && optimize_routes_generation? + options = #{options.inspect}.merge!(url_options) + options[:path] = "#{optimized_helper(route)}" + ActionDispatch::Http::URL.url_for(options) + else + url_for(#{hash_access_method}(*args)) + end + end + END_EVAL + else + @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1 + remove_possible_method :#{selector} + def #{selector}(*args) + url_for(#{hash_access_method}(*args)) + end + END_EVAL + end + helpers << selector end + + # Clause check about when we need to generate an optimized helper. + def optimize_helper?(route) #:nodoc: + route.ast.grep(Journey::Nodes::Star).empty? && route.requirements.except(:controller, :action).empty? + end + + # Generates the interpolation to be used in the optimized helper. + def optimized_helper(route) + string_route = route.ast.to_s + + while string_route.gsub!(/\([^\)]*\)/, "") + true + end + + route.required_parts.each_with_index do |part, i| + string_route.gsub!(part.inspect, "\#{Journey::Router::Utils.escape_fragment(args[#{i}].to_param)}") + end + + string_route + end end attr_accessor :formatter, :set, :named_routes, :default_scope, :router @@ -323,7 +359,7 @@ module ActionDispatch # Rails.application.routes.url_helpers.url_for(args) @_routes = routes class << self - delegate :url_for, :to => '@_routes' + delegate :url_for, :optimize_routes_generation?, :to => '@_routes' end # Make named_routes available in the module singleton @@ -557,6 +593,14 @@ module ActionDispatch RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length, :trailing_slash, :anchor, :params, :only_path, :script_name] + def mounted? + false + end + + def optimize_routes_generation? + !mounted? && default_url_options.empty? + end + def _generate_prefix(options = {}) nil end @@ -568,19 +612,17 @@ module ActionDispatch user, password = extract_authentication(options) path_segments = options.delete(:_path_segments) - script_name = options.delete(:script_name) - - path = (script_name.blank? ? _generate_prefix(options) : script_name.chomp('/')).to_s + script_name = options.delete(:script_name).presence || _generate_prefix(options) path_options = options.except(*RESERVED_OPTIONS) path_options = yield(path_options) if block_given? - path_addition, params = generate(path_options, path_segments || {}) - path << path_addition + path, params = generate(path_options, path_segments || {}) params.merge!(options[:params] || {}) ActionDispatch::Http::URL.url_for(options.merge!({ :path => path, + :script_name => script_name, :params => params, :user => user, :password => password diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index ee6616c5d3..94db36ce1f 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -102,6 +102,9 @@ module ActionDispatch super end + # Hook overriden in controller to add request information + # with `default_url_options`. Application logic should not + # go into url_options. def url_options default_url_options end @@ -152,6 +155,11 @@ module ActionDispatch protected + def optimize_routes_generation? + return @_optimized_routes if defined?(@_optimized_routes) + @_optimized_routes = _routes.optimize_routes_generation? && default_url_options.empty? + end + def _with_routes(routes) old_routes, @_routes = @_routes, routes yield |