From 72608521871f73d6b07afa5f6f36e0dedcf1d079 Mon Sep 17 00:00:00 2001
From: Josh <shup_d@cube.(none)>
Date: Sun, 4 Jan 2009 14:54:35 +0000
Subject: Fix date_select within fields_for with an index [#1666
 state:resolved] [Josh, Frederick Cheung]

Signed-off-by: Frederick Cheung <frederick.cheung@gmail.com>
---
 actionpack/lib/action_view/helpers/date_helper.rb | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'actionpack/lib')

diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index 4305617ac8..b4c1adbe76 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -860,7 +860,7 @@ module ActionView
         #  => post[written_on(1i)]
         def input_name_from_type(type)
           prefix = @options[:prefix] || ActionView::Helpers::DateTimeSelector::DEFAULT_PREFIX
-          prefix += "[#{@options[:index]}]" if @options[:index]
+          prefix += "[#{@options[:index]}]" if @options.has_key?(:index)
 
           field_name = @options[:field_name] || type
           if @options[:include_position]
@@ -923,7 +923,7 @@ module ActionView
           options[:field_name]           = @method_name
           options[:include_position]     = true
           options[:prefix]             ||= @object_name
-          options[:index]              ||= @auto_index
+          options[:index]                = @auto_index if @auto_index && !options.has_key?(:index)
           options[:datetime_separator] ||= ' &mdash; '
           options[:time_separator]     ||= ' : '
 
@@ -961,15 +961,15 @@ module ActionView
 
     class FormBuilder
       def date_select(method, options = {}, html_options = {})
-        @template.date_select(@object_name, method, options.merge(:object => @object), html_options)
+        @template.date_select(@object_name, method, objectify_options(options), html_options)
       end
 
       def time_select(method, options = {}, html_options = {})
-        @template.time_select(@object_name, method, options.merge(:object => @object), html_options)
+        @template.time_select(@object_name, method, objectify_options(options), html_options)
       end
 
       def datetime_select(method, options = {}, html_options = {})
-        @template.datetime_select(@object_name, method, options.merge(:object => @object), html_options)
+        @template.datetime_select(@object_name, method, objectify_options(options), html_options)
       end
     end
   end
-- 
cgit v1.2.3


From 78af2710695973bbd747738d175fb3b1f488df6c Mon Sep 17 00:00:00 2001
From: Jeremy Kemper <jeremy@bitsweat.net>
Date: Wed, 14 Jan 2009 19:00:07 -0800
Subject: Skip respond_to check so rack.input doesn't have to implement it

---
 actionpack/lib/action_controller/rack_ext.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'actionpack/lib')

diff --git a/actionpack/lib/action_controller/rack_ext.rb b/actionpack/lib/action_controller/rack_ext.rb
index 3b142307e9..3d6f1f9256 100644
--- a/actionpack/lib/action_controller/rack_ext.rb
+++ b/actionpack/lib/action_controller/rack_ext.rb
@@ -6,8 +6,8 @@ module Rack
           result = parse_multipart_without_rewind(env)
 
           begin
-            env['rack.input'].rewind if env['rack.input'].respond_to?(:rewind)
-          rescue Errno::ESPIPE
+            env['rack.input'].rewind
+          rescue NoMethodError, Errno::ESPIPE
             # Handles exceptions raised by input streams that cannot be rewound
             # such as when using plain CGI under Apache
           end
-- 
cgit v1.2.3


From fe013ce93415a88b6c23fd750bd8cbab60d6395d Mon Sep 17 00:00:00 2001
From: Jeremy Kemper <jeremy@bitsweat.net>
Date: Fri, 16 Jan 2009 20:36:50 -0800
Subject: Fix performance regression

---
 actionpack/lib/action_view/template.rb          | 2 +-
 actionpack/lib/action_view/template_handlers.rb | 6 +++++-
 2 files changed, 6 insertions(+), 2 deletions(-)

(limited to 'actionpack/lib')

diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 88ee07d95b..9d1e0d3ac5 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -204,7 +204,7 @@ module ActionView #:nodoc:
 
     private
       def valid_extension?(extension)
-        Template.template_handler_extensions.include?(extension)
+        !Template.registered_template_handler(extension).nil?
       end
 
       def find_full_path(path, load_paths)
diff --git a/actionpack/lib/action_view/template_handlers.rb b/actionpack/lib/action_view/template_handlers.rb
index d06ddd5fb5..205f8628f0 100644
--- a/actionpack/lib/action_view/template_handlers.rb
+++ b/actionpack/lib/action_view/template_handlers.rb
@@ -32,13 +32,17 @@ module ActionView #:nodoc:
       @@template_handlers.keys.map(&:to_s).sort
     end
 
+    def registered_template_handler(extension)
+      extension && @@template_handlers[extension.to_sym]
+    end
+
     def register_default_template_handler(extension, klass)
       register_template_handler(extension, klass)
       @@default_template_handlers = klass
     end
 
     def handler_class_for_extension(extension)
-      (extension && @@template_handlers[extension.to_sym]) || @@default_template_handlers
+      registered_template_handler(extension) || @@default_template_handlers
     end
   end
 end
-- 
cgit v1.2.3


From 515a1a332808eb7c2f9c006fc1903e1e8555b7fa Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 17 Jan 2009 10:16:31 -0600
Subject: Lock middleware has been committed upstream

---
 actionpack/lib/action_controller.rb                |  1 -
 actionpack/lib/action_controller/lock.rb           | 16 ---------------
 actionpack/lib/action_controller/middlewares.rb    |  2 +-
 actionpack/lib/action_controller/rack_ext.rb       | 24 ++--------------------
 actionpack/lib/action_controller/rack_ext/lock.rb  | 21 +++++++++++++++++++
 .../lib/action_controller/rack_ext/multipart.rb    | 22 ++++++++++++++++++++
 6 files changed, 46 insertions(+), 40 deletions(-)
 delete mode 100644 actionpack/lib/action_controller/lock.rb
 create mode 100644 actionpack/lib/action_controller/rack_ext/lock.rb
 create mode 100644 actionpack/lib/action_controller/rack_ext/multipart.rb

(limited to 'actionpack/lib')

diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index f808bdd910..7a71c64695 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -56,7 +56,6 @@ module ActionController
   autoload :Integration, 'action_controller/integration'
   autoload :IntegrationTest, 'action_controller/integration'
   autoload :Layout, 'action_controller/layout'
-  autoload :Lock, 'action_controller/lock'
   autoload :MiddlewareStack, 'action_controller/middleware_stack'
   autoload :MimeResponds, 'action_controller/mime_responds'
   autoload :PolymorphicRoutes, 'action_controller/polymorphic_routes'
diff --git a/actionpack/lib/action_controller/lock.rb b/actionpack/lib/action_controller/lock.rb
deleted file mode 100644
index c50762216e..0000000000
--- a/actionpack/lib/action_controller/lock.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-module ActionController
-  class Lock
-    FLAG = 'rack.multithread'.freeze
-
-    def initialize(app, lock = Mutex.new)
-      @app, @lock = app, lock
-    end
-
-    def call(env)
-      old, env[FLAG] = env[FLAG], false
-      @lock.synchronize { @app.call(env) }
-    ensure
-      env[FLAG] = old
-    end
-  end
-end
diff --git a/actionpack/lib/action_controller/middlewares.rb b/actionpack/lib/action_controller/middlewares.rb
index 0f038b8856..cbcb5cb3e4 100644
--- a/actionpack/lib/action_controller/middlewares.rb
+++ b/actionpack/lib/action_controller/middlewares.rb
@@ -1,4 +1,4 @@
-use "ActionController::Lock", :if => lambda {
+use "Rack::Lock", :if => lambda {
   !ActionController::Base.allow_concurrency
 }
 
diff --git a/actionpack/lib/action_controller/rack_ext.rb b/actionpack/lib/action_controller/rack_ext.rb
index 3d6f1f9256..17cd08f39a 100644
--- a/actionpack/lib/action_controller/rack_ext.rb
+++ b/actionpack/lib/action_controller/rack_ext.rb
@@ -1,22 +1,2 @@
-module Rack
-  module Utils
-    module Multipart
-      class << self
-        def parse_multipart_with_rewind(env)
-          result = parse_multipart_without_rewind(env)
-
-          begin
-            env['rack.input'].rewind
-          rescue NoMethodError, Errno::ESPIPE
-            # Handles exceptions raised by input streams that cannot be rewound
-            # such as when using plain CGI under Apache
-          end
-
-          result
-        end
-
-        alias_method_chain :parse_multipart, :rewind
-      end
-    end
-  end
-end
+require 'action_controller/rack_ext/lock'
+require 'action_controller/rack_ext/multipart'
diff --git a/actionpack/lib/action_controller/rack_ext/lock.rb b/actionpack/lib/action_controller/rack_ext/lock.rb
new file mode 100644
index 0000000000..9bf1889065
--- /dev/null
+++ b/actionpack/lib/action_controller/rack_ext/lock.rb
@@ -0,0 +1,21 @@
+module Rack
+  # Rack::Lock was commited to Rack core
+  # http://github.com/rack/rack/commit/7409b0c
+  # Remove this when Rack 1.0 is released
+  unless defined? Lock
+    class Lock
+      FLAG = 'rack.multithread'.freeze
+
+      def initialize(app, lock = Mutex.new)
+        @app, @lock = app, lock
+      end
+
+      def call(env)
+        old, env[FLAG] = env[FLAG], false
+        @lock.synchronize { @app.call(env) }
+      ensure
+        env[FLAG] = old
+      end
+    end
+  end
+end
diff --git a/actionpack/lib/action_controller/rack_ext/multipart.rb b/actionpack/lib/action_controller/rack_ext/multipart.rb
new file mode 100644
index 0000000000..3d6f1f9256
--- /dev/null
+++ b/actionpack/lib/action_controller/rack_ext/multipart.rb
@@ -0,0 +1,22 @@
+module Rack
+  module Utils
+    module Multipart
+      class << self
+        def parse_multipart_with_rewind(env)
+          result = parse_multipart_without_rewind(env)
+
+          begin
+            env['rack.input'].rewind
+          rescue NoMethodError, Errno::ESPIPE
+            # Handles exceptions raised by input streams that cannot be rewound
+            # such as when using plain CGI under Apache
+          end
+
+          result
+        end
+
+        alias_method_chain :parse_multipart, :rewind
+      end
+    end
+  end
+end
-- 
cgit v1.2.3


From 29e7a0242853a5e102b6846b87723fc26a1ffb08 Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 17 Jan 2009 11:12:18 -0600
Subject: Ensure any method sent to RewindableIO reads the original IO object
 [#1767 state:resolved]

---
 .../lib/action_controller/rack_ext/multipart.rb    |  4 +--
 .../lib/action_controller/rewindable_input.rb      | 30 +++++-----------------
 2 files changed, 9 insertions(+), 25 deletions(-)

(limited to 'actionpack/lib')

diff --git a/actionpack/lib/action_controller/rack_ext/multipart.rb b/actionpack/lib/action_controller/rack_ext/multipart.rb
index 3d6f1f9256..3b142307e9 100644
--- a/actionpack/lib/action_controller/rack_ext/multipart.rb
+++ b/actionpack/lib/action_controller/rack_ext/multipart.rb
@@ -6,8 +6,8 @@ module Rack
           result = parse_multipart_without_rewind(env)
 
           begin
-            env['rack.input'].rewind
-          rescue NoMethodError, Errno::ESPIPE
+            env['rack.input'].rewind if env['rack.input'].respond_to?(:rewind)
+          rescue Errno::ESPIPE
             # Handles exceptions raised by input streams that cannot be rewound
             # such as when using plain CGI under Apache
           end
diff --git a/actionpack/lib/action_controller/rewindable_input.rb b/actionpack/lib/action_controller/rewindable_input.rb
index 058453ea68..36f655c51e 100644
--- a/actionpack/lib/action_controller/rewindable_input.rb
+++ b/actionpack/lib/action_controller/rewindable_input.rb
@@ -3,33 +3,17 @@ module ActionController
     class RewindableIO < ActiveSupport::BasicObject
       def initialize(io)
         @io = io
-      end
-
-      def read(*args)
-        read_original_io
-        @io.read(*args)
-      end
-
-      def rewind
-        read_original_io
-        @io.rewind
-      end
-
-      def string
-        @string
+        @rewindable = io.is_a?(StringIO)
       end
 
       def method_missing(method, *args, &block)
-        @io.send(method, *args, &block)
-      end
-
-      private
-        def read_original_io
-          unless @string
-            @string = @io.read
-            @io = StringIO.new(@string)
-          end
+        unless @rewindable
+          @io = StringIO.new(@io.read)
+          @rewindable = true
         end
+
+        @io.__send__(method, *args, &block)
+      end
     end
 
     def initialize(app)
-- 
cgit v1.2.3


From ff0a2678c4bce9da348e1263915558795e3a3640 Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Sat, 17 Jan 2009 20:29:50 -0600
Subject: Build query string and POST params parser on top of Rack::Request.
 Also switch our multipart parser to use Racks. Moved XML, JSON, and YAML
 parsers into ActionController::ParamsParser middleware [#1661 state:resolved]

---
 actionpack/lib/action_controller.rb                |   2 +
 actionpack/lib/action_controller/base.rb           |   5 +-
 actionpack/lib/action_controller/middlewares.rb    |   1 +
 actionpack/lib/action_controller/params_parser.rb  |  71 +++++
 actionpack/lib/action_controller/rack_ext.rb       |   1 +
 .../lib/action_controller/rack_ext/parse_query.rb  |  18 ++
 actionpack/lib/action_controller/request.rb        |  34 ++-
 actionpack/lib/action_controller/request_parser.rb | 315 ---------------------
 actionpack/lib/action_controller/uploaded_file.rb  |   7 +
 .../action_controller/url_encoded_pair_parser.rb   |  61 ++++
 10 files changed, 186 insertions(+), 329 deletions(-)
 create mode 100644 actionpack/lib/action_controller/params_parser.rb
 create mode 100644 actionpack/lib/action_controller/rack_ext/parse_query.rb
 delete mode 100644 actionpack/lib/action_controller/request_parser.rb

(limited to 'actionpack/lib')

diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index 7a71c64695..5113a7b0cb 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -58,6 +58,7 @@ module ActionController
   autoload :Layout, 'action_controller/layout'
   autoload :MiddlewareStack, 'action_controller/middleware_stack'
   autoload :MimeResponds, 'action_controller/mime_responds'
+  autoload :ParamsParser, 'action_controller/params_parser'
   autoload :PolymorphicRoutes, 'action_controller/polymorphic_routes'
   autoload :RecordIdentifier, 'action_controller/record_identifier'
   autoload :Request, 'action_controller/request'
@@ -74,6 +75,7 @@ module ActionController
   autoload :TestCase, 'action_controller/test_case'
   autoload :TestProcess, 'action_controller/test_process'
   autoload :Translation, 'action_controller/translation'
+  autoload :UploadedFile, 'action_controller/uploaded_file'
   autoload :UploadedStringIO, 'action_controller/uploaded_file'
   autoload :UploadedTempfile, 'action_controller/uploaded_file'
   autoload :UrlEncodedPairParser, 'action_controller/url_encoded_pair_parser'
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index e22114195c..7a380bd1fb 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -301,10 +301,7 @@ module ActionController #:nodoc:
     # A YAML parser is also available and can be turned on with:
     #
     #   ActionController::Base.param_parsers[Mime::YAML] = :yaml
-    @@param_parsers = { Mime::MULTIPART_FORM   => :multipart_form,
-                        Mime::URL_ENCODED_FORM => :url_encoded_form,
-                        Mime::XML              => :xml_simple,
-                        Mime::JSON             => :json }
+    @@param_parsers = {}
     cattr_accessor :param_parsers
 
     # Controls the default charset for all renders.
diff --git a/actionpack/lib/action_controller/middlewares.rb b/actionpack/lib/action_controller/middlewares.rb
index cbcb5cb3e4..30dbc26f11 100644
--- a/actionpack/lib/action_controller/middlewares.rb
+++ b/actionpack/lib/action_controller/middlewares.rb
@@ -19,4 +19,5 @@ use "ActiveRecord::QueryCache", :if => lambda { defined?(ActiveRecord) }
 end
 
 use ActionController::RewindableInput
+use ActionController::ParamsParser
 use Rack::MethodOverride
diff --git a/actionpack/lib/action_controller/params_parser.rb b/actionpack/lib/action_controller/params_parser.rb
new file mode 100644
index 0000000000..d269fe07fa
--- /dev/null
+++ b/actionpack/lib/action_controller/params_parser.rb
@@ -0,0 +1,71 @@
+module ActionController
+  class ParamsParser
+    ActionController::Base.param_parsers[Mime::XML] = :xml_simple
+    ActionController::Base.param_parsers[Mime::JSON] = :json
+
+    def initialize(app)
+      @app = app
+    end
+
+    def call(env)
+      if params = parse_formatted_parameters(env)
+        env["action_controller.request.request_parameters"] = params
+      end
+
+      @app.call(env)
+    end
+
+    private
+      def parse_formatted_parameters(env)
+        request = Request.new(env)
+
+        return false if request.content_length.zero?
+
+        mime_type = content_type_from_legacy_post_data_format_header(env) || request.content_type
+        strategy = ActionController::Base.param_parsers[mime_type]
+
+        return false unless strategy
+
+        case strategy
+          when Proc
+            strategy.call(request.raw_post)
+          when :xml_simple, :xml_node
+            body = request.raw_post
+            body.blank? ? {} : Hash.from_xml(body).with_indifferent_access
+          when :yaml
+            YAML.load(request.raw_post)
+          when :json
+            body = request.raw_post
+            if body.blank?
+              {}
+            else
+              data = ActiveSupport::JSON.decode(body)
+              data = {:_json => data} unless data.is_a?(Hash)
+              data.with_indifferent_access
+            end
+          else
+            false
+        end
+      rescue Exception => e # YAML, XML or Ruby code block errors
+        raise
+          { "body" => request.raw_post,
+            "content_type" => request.content_type,
+            "content_length" => request.content_length,
+            "exception" => "#{e.message} (#{e.class})",
+            "backtrace" => e.backtrace }
+      end
+
+      def content_type_from_legacy_post_data_format_header(env)
+        if x_post_format = env['HTTP_X_POST_DATA_FORMAT']
+          case x_post_format.to_s.downcase
+            when 'yaml'
+              return Mime::YAML
+            when 'xml'
+              return Mime::XML
+          end
+        end
+
+        nil
+      end
+  end
+end
diff --git a/actionpack/lib/action_controller/rack_ext.rb b/actionpack/lib/action_controller/rack_ext.rb
index 17cd08f39a..2ba6654e3d 100644
--- a/actionpack/lib/action_controller/rack_ext.rb
+++ b/actionpack/lib/action_controller/rack_ext.rb
@@ -1,2 +1,3 @@
 require 'action_controller/rack_ext/lock'
 require 'action_controller/rack_ext/multipart'
+require 'action_controller/rack_ext/parse_query'
diff --git a/actionpack/lib/action_controller/rack_ext/parse_query.rb b/actionpack/lib/action_controller/rack_ext/parse_query.rb
new file mode 100644
index 0000000000..2f21a57770
--- /dev/null
+++ b/actionpack/lib/action_controller/rack_ext/parse_query.rb
@@ -0,0 +1,18 @@
+# Rack does not automatically cleanup Safari 2 AJAX POST body
+# This has not yet been commited to Rack, please +1 this ticket:
+# http://rack.lighthouseapp.com/projects/22435/tickets/19
+
+module Rack
+  module Utils
+    alias_method :parse_query_without_ajax_body_cleanup, :parse_query
+    module_function :parse_query_without_ajax_body_cleanup
+
+    def parse_query(qs, d = '&;')
+      qs = qs.dup
+      qs.chop! if qs[-1] == 0
+      qs.gsub!(/&_=$/, '')
+      parse_query_without_ajax_body_cleanup(qs, d)
+    end
+    module_function :parse_query
+  end
+end
diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb
index b4ab1ccda1..cbbfca41f6 100755
--- a/actionpack/lib/action_controller/request.rb
+++ b/actionpack/lib/action_controller/request.rb
@@ -9,11 +9,6 @@ module ActionController
   class Request < Rack::Request
     extend ActiveSupport::Memoizable
 
-    def initialize(env)
-      super
-      @parser = ActionController::RequestParser.new(env)
-    end
-
     %w[ AUTH_TYPE GATEWAY_INTERFACE
         PATH_TRANSLATED REMOTE_HOST
         REMOTE_IDENT REMOTE_USER REMOTE_ADDR
@@ -92,7 +87,11 @@ module ActionController
     # For backward compatibility, the post \format is extracted from the
     # X-Post-Data-Format HTTP header if present.
     def content_type
-      Mime::Type.lookup(@parser.content_type_without_parameters)
+      if @env['CONTENT_TYPE'] =~ /^([^,\;]*)/
+        Mime::Type.lookup($1.strip.downcase)
+      else
+        nil
+      end
     end
     memoize :content_type
 
@@ -380,7 +379,11 @@ EOM
     # Read the request \body. This is useful for web services that need to
     # work with raw requests directly.
     def raw_post
-      @parser.raw_post
+      unless @env.include? 'RAW_POST_DATA'
+        @env['RAW_POST_DATA'] = body.read(@env['CONTENT_LENGTH'].to_i)
+        body.rewind if body.respond_to?(:rewind)
+      end
+      @env['RAW_POST_DATA']
     end
 
     # Returns both GET and POST \parameters in a single hash.
@@ -409,19 +412,30 @@ EOM
       @env["rack.routing_args"] ||= {}
     end
 
+    # The request body is an IO input stream. If the RAW_POST_DATA environment
+    # variable is already set, wrap it in a StringIO.
     def body
-      @parser.body
+      if raw_post = @env['RAW_POST_DATA']
+        raw_post.force_encoding(Encoding::BINARY) if raw_post.respond_to?(:force_encoding)
+        StringIO.new(raw_post)
+      else
+        @env['rack.input']
+      end
+    end
+
+    def form_data?
+      FORM_DATA_MEDIA_TYPES.include?(content_type.to_s)
     end
 
     # Override Rack's GET method to support nested query strings
     def GET
-      @parser.query_parameters
+      @env["action_controller.request.query_parameters"] ||= UrlEncodedPairParser.parse_query_parameters(query_string)
     end
     alias_method :query_parameters, :GET
 
     # Override Rack's POST method to support nested query strings
     def POST
-      @parser.request_parameters
+      @env["action_controller.request.request_parameters"] ||= UrlEncodedPairParser.parse_hash_parameters(super)
     end
     alias_method :request_parameters, :POST
 
diff --git a/actionpack/lib/action_controller/request_parser.rb b/actionpack/lib/action_controller/request_parser.rb
deleted file mode 100644
index d1739ef4d0..0000000000
--- a/actionpack/lib/action_controller/request_parser.rb
+++ /dev/null
@@ -1,315 +0,0 @@
-module ActionController
-  class RequestParser
-    def initialize(env)
-      @env = env
-      freeze
-    end
-
-    def request_parameters
-      @env["action_controller.request_parser.request_parameters"] ||= parse_formatted_request_parameters
-    end
-
-    def query_parameters
-      @env["action_controller.request_parser.query_parameters"] ||= self.class.parse_query_parameters(query_string)
-    end
-
-    # Returns the query string, accounting for server idiosyncrasies.
-    def query_string
-      @env['QUERY_STRING'].present? ? @env['QUERY_STRING'] : (@env['REQUEST_URI'].split('?', 2)[1] || '')
-    end
-
-    # The request body is an IO input stream. If the RAW_POST_DATA environment
-    # variable is already set, wrap it in a StringIO.
-    def body
-      if raw_post = @env['RAW_POST_DATA']
-        raw_post.force_encoding(Encoding::BINARY) if raw_post.respond_to?(:force_encoding)
-        StringIO.new(raw_post)
-      else
-        @env['rack.input']
-      end
-    end
-
-    # The raw content type string with its parameters stripped off.
-    def content_type_without_parameters
-      self.class.extract_content_type_without_parameters(content_type_with_parameters)
-    end
-
-    def raw_post
-      unless @env.include? 'RAW_POST_DATA'
-        @env['RAW_POST_DATA'] = body.read(content_length)
-        body.rewind if body.respond_to?(:rewind)
-      end
-      @env['RAW_POST_DATA']
-    end
-
-    private
-
-    def parse_formatted_request_parameters
-      return {} if content_length.zero?
-
-      content_type, boundary = self.class.extract_multipart_boundary(content_type_with_parameters)
-
-      # Don't parse params for unknown requests.
-      return {} if content_type.blank?
-
-      mime_type = Mime::Type.lookup(content_type)
-      strategy = ActionController::Base.param_parsers[mime_type]
-
-      # Only multipart form parsing expects a stream.
-      body = (strategy && strategy != :multipart_form) ? raw_post : self.body
-
-      case strategy
-        when Proc
-          strategy.call(body)
-        when :url_encoded_form
-          self.class.clean_up_ajax_request_body! body
-          self.class.parse_query_parameters(body)
-        when :multipart_form
-          self.class.parse_multipart_form_parameters(body, boundary, content_length, @env)
-        when :xml_simple, :xml_node
-          body.blank? ? {} : Hash.from_xml(body).with_indifferent_access
-        when :yaml
-          YAML.load(body)
-        when :json
-          if body.blank?
-            {}
-          else
-            data = ActiveSupport::JSON.decode(body)
-            data = {:_json => data} unless data.is_a?(Hash)
-            data.with_indifferent_access
-          end
-        else
-          {}
-      end
-    rescue Exception => e # YAML, XML or Ruby code block errors
-      raise
-      { "body" => body,
-        "content_type" => content_type_with_parameters,
-        "content_length" => content_length,
-        "exception" => "#{e.message} (#{e.class})",
-        "backtrace" => e.backtrace }
-    end
-
-    def content_length
-      @env['CONTENT_LENGTH'].to_i
-    end
-
-    # The raw content type string. Use when you need parameters such as
-    # charset or boundary which aren't included in the content_type MIME type.
-    # Overridden by the X-POST_DATA_FORMAT header for backward compatibility.
-    def content_type_with_parameters
-      content_type_from_legacy_post_data_format_header || @env['CONTENT_TYPE'].to_s
-    end
-
-    def content_type_from_legacy_post_data_format_header
-      if x_post_format = @env['HTTP_X_POST_DATA_FORMAT']
-        case x_post_format.to_s.downcase
-          when 'yaml';  'application/x-yaml'
-          when 'xml';   'application/xml'
-        end
-      end
-    end
-
-    class << self
-      def parse_query_parameters(query_string)
-        return {} if query_string.blank?
-
-        pairs = query_string.split('&').collect do |chunk|
-          next if chunk.empty?
-          key, value = chunk.split('=', 2)
-          next if key.empty?
-          value = value.nil? ? nil : CGI.unescape(value)
-          [ CGI.unescape(key), value ]
-        end.compact
-
-        UrlEncodedPairParser.new(pairs).result
-      end
-
-      def parse_request_parameters(params)
-        parser = UrlEncodedPairParser.new
-
-        params = params.dup
-        until params.empty?
-          for key, value in params
-            if key.blank?
-              params.delete key
-            elsif !key.include?('[')
-              # much faster to test for the most common case first (GET)
-              # and avoid the call to build_deep_hash
-              parser.result[key] = get_typed_value(value[0])
-              params.delete key
-            elsif value.is_a?(Array)
-              parser.parse(key, get_typed_value(value.shift))
-              params.delete key if value.empty?
-            else
-              raise TypeError, "Expected array, found #{value.inspect}"
-            end
-          end
-        end
-
-        parser.result
-      end
-
-      def parse_multipart_form_parameters(body, boundary, body_size, env)
-        parse_request_parameters(read_multipart(body, boundary, body_size, env))
-      end
-
-      def extract_multipart_boundary(content_type_with_parameters)
-        if content_type_with_parameters =~ MULTIPART_BOUNDARY
-          ['multipart/form-data', $1.dup]
-        else
-          extract_content_type_without_parameters(content_type_with_parameters)
-        end
-      end
-
-      def extract_content_type_without_parameters(content_type_with_parameters)
-        $1.strip.downcase if content_type_with_parameters =~ /^([^,\;]*)/
-      end
-
-      def clean_up_ajax_request_body!(body)
-        body.chop! if body[-1] == 0
-        body.gsub!(/&_=$/, '')
-      end
-
-
-      private
-        def get_typed_value(value)
-          case value
-            when String
-              value
-            when NilClass
-              ''
-            when Array
-              value.map { |v| get_typed_value(v) }
-            else
-              if value.respond_to? :original_filename
-                # Uploaded file
-                if value.original_filename
-                  value
-                # Multipart param
-                else
-                  result = value.read
-                  value.rewind
-                  result
-                end
-              # Unknown value, neither string nor multipart.
-              else
-                raise "Unknown form value: #{value.inspect}"
-              end
-          end
-        end
-
-        MULTIPART_BOUNDARY = %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n
-
-        EOL = "\015\012"
-
-        def read_multipart(body, boundary, body_size, env)
-          params = Hash.new([])
-          boundary = "--" + boundary
-          quoted_boundary = Regexp.quote(boundary)
-          buf = ""
-          bufsize = 10 * 1024
-          boundary_end=""
-
-          # start multipart/form-data
-          body.binmode if defined? body.binmode
-          case body
-          when File
-            body.set_encoding(Encoding::BINARY) if body.respond_to?(:set_encoding)
-          when StringIO
-            body.string.force_encoding(Encoding::BINARY) if body.string.respond_to?(:force_encoding)
-          end
-          boundary_size = boundary.size + EOL.size
-          body_size -= boundary_size
-          status = body.read(boundary_size)
-          if nil == status
-            raise EOFError, "no content body"
-          elsif boundary + EOL != status
-            raise EOFError, "bad content body"
-          end
-
-          loop do
-            head = nil
-            content =
-              if 10240 < body_size
-                UploadedTempfile.new("CGI")
-              else
-                UploadedStringIO.new
-              end
-            content.binmode if defined? content.binmode
-
-            until head and /#{quoted_boundary}(?:#{EOL}|--)/n.match(buf)
-
-              if (not head) and /#{EOL}#{EOL}/n.match(buf)
-                buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
-                  head = $1.dup
-                  ""
-                end
-                next
-              end
-
-              if head and ( (EOL + boundary + EOL).size < buf.size )
-                content.print buf[0 ... (buf.size - (EOL + boundary + EOL).size)]
-                buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
-              end
-
-              c = if bufsize < body_size
-                    body.read(bufsize)
-                  else
-                    body.read(body_size)
-                  end
-              if c.nil? || c.empty?
-                raise EOFError, "bad content body"
-              end
-              buf.concat(c)
-              body_size -= c.size
-            end
-
-            buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do
-              content.print $1
-              if "--" == $2
-                body_size = -1
-              end
-              boundary_end = $2.dup
-              ""
-            end
-
-            content.rewind
-
-            head =~ /Content-Disposition:.* filename=(?:"((?:\\.|[^\"])*)"|([^;]*))/ni
-            if filename = $1 || $2
-              if /Mac/ni.match(env['HTTP_USER_AGENT']) and
-                  /Mozilla/ni.match(env['HTTP_USER_AGENT']) and
-                  (not /MSIE/ni.match(env['HTTP_USER_AGENT']))
-                filename = CGI.unescape(filename)
-              end
-              content.original_path = filename.dup
-            end
-
-            head =~ /Content-Type: ([^\r]*)/ni
-            content.content_type = $1.dup if $1
-
-            head =~ /Content-Disposition:.* name="?([^\";]*)"?/ni
-            name = $1.dup if $1
-
-            if params.has_key?(name)
-              params[name].push(content)
-            else
-              params[name] = [content]
-            end
-            break if body_size == -1
-          end
-          raise EOFError, "bad boundary end of body part" unless boundary_end=~/--/
-
-          begin
-            body.rewind if body.respond_to?(:rewind)
-          rescue Errno::ESPIPE
-            # Handles exceptions raised by input streams that cannot be rewound
-            # such as when using plain CGI under Apache
-          end
-
-          params
-        end
-    end # class << self
-  end
-end
diff --git a/actionpack/lib/action_controller/uploaded_file.rb b/actionpack/lib/action_controller/uploaded_file.rb
index ea4845c68f..376ba3621a 100644
--- a/actionpack/lib/action_controller/uploaded_file.rb
+++ b/actionpack/lib/action_controller/uploaded_file.rb
@@ -7,6 +7,13 @@ module ActionController
       end
     end
 
+    def self.extended(object)
+      object.class_eval do
+        attr_accessor :original_path, :content_type
+        alias_method :local_path, :path
+      end
+    end
+
     # Take the basename of the upload's original filename.
     # This handles the full Windows paths given by Internet Explorer
     # (and perhaps other broken user agents) without affecting
diff --git a/actionpack/lib/action_controller/url_encoded_pair_parser.rb b/actionpack/lib/action_controller/url_encoded_pair_parser.rb
index 9883ad0d85..b63dca987d 100644
--- a/actionpack/lib/action_controller/url_encoded_pair_parser.rb
+++ b/actionpack/lib/action_controller/url_encoded_pair_parser.rb
@@ -1,5 +1,66 @@
 module ActionController
   class UrlEncodedPairParser < StringScanner #:nodoc:
+    class << self
+      def parse_query_parameters(query_string)
+        return {} if query_string.blank?
+
+        pairs = query_string.split('&').collect do |chunk|
+          next if chunk.empty?
+          key, value = chunk.split('=', 2)
+          next if key.empty?
+          value = value.nil? ? nil : CGI.unescape(value)
+          [ CGI.unescape(key), value ]
+        end.compact
+
+        new(pairs).result
+      end
+
+      def parse_hash_parameters(params)
+        parser = new
+
+        params = params.dup
+        until params.empty?
+          for key, value in params
+            if key.blank?
+              params.delete(key)
+            elsif value.is_a?(Array)
+              parser.parse(key, get_typed_value(value.shift))
+              params.delete(key) if value.empty?
+            else
+              parser.parse(key, get_typed_value(value))
+              params.delete(key)
+            end
+          end
+        end
+
+        parser.result
+      end
+
+      private
+        def get_typed_value(value)
+          case value
+          when String
+            value
+          when NilClass
+            ''
+          when Array
+            value.map { |v| get_typed_value(v) }
+          when Hash
+            if value.has_key?(:tempfile)
+              upload = value[:tempfile]
+              upload.extend(UploadedFile)
+              upload.original_path = value[:filename]
+              upload.content_type = value[:type]
+              upload
+            else
+              nil
+            end
+          else
+            raise "Unknown form value: #{value.inspect}"
+          end
+        end
+    end
+
     attr_reader :top, :parent, :result
 
     def initialize(pairs = [])
-- 
cgit v1.2.3


From 41af606db385abe429888c5aca8b2e86c8830c24 Mon Sep 17 00:00:00 2001
From: Pratik Naik <pratiknaik@gmail.com>
Date: Sun, 18 Jan 2009 05:16:39 +0000
Subject: Remove script/performance/profiler in favour of performance
 integration tests.

To continue using script/performance/profiler, install the request_profiler plugin :

  script/plugin install git://github.com/rails/request_profiler.git
---
 .../lib/action_controller/request_profiler.rb      | 168 ---------------------
 1 file changed, 168 deletions(-)
 delete mode 100644 actionpack/lib/action_controller/request_profiler.rb

(limited to 'actionpack/lib')

diff --git a/actionpack/lib/action_controller/request_profiler.rb b/actionpack/lib/action_controller/request_profiler.rb
deleted file mode 100644
index 80cd55334f..0000000000
--- a/actionpack/lib/action_controller/request_profiler.rb
+++ /dev/null
@@ -1,168 +0,0 @@
-require 'optparse'
-
-module ActionController
-  class RequestProfiler
-    # Wrap up the integration session runner.
-    class Sandbox
-      include Integration::Runner
-
-      def self.benchmark(n, script)
-        new(script).benchmark(n)
-      end
-
-      def initialize(script_path)
-        @quiet = false
-        define_run_method(script_path)
-        reset!
-      end
-
-      def benchmark(n, profiling = false)
-        @quiet = true
-        print '  '
-
-        ms = Benchmark.ms do
-          n.times do |i|
-            run(profiling)
-            print_progress(i)
-          end
-        end
-
-        puts
-        ms
-      ensure
-        @quiet = false
-      end
-
-      def say(message)
-        puts "  #{message}" unless @quiet
-      end
-
-      private
-        def define_run_method(script_path)
-          script = File.read(script_path)
-
-          source = <<-end_source
-            def run(profiling = false)
-              if profiling
-                RubyProf.resume do
-                  #{script}
-                end
-              else
-                #{script}
-              end
-
-              old_request_count = request_count
-              reset!
-              self.request_count = old_request_count
-            end
-          end_source
-
-          instance_eval source, script_path, 1
-        end
-
-        def print_progress(i)
-          print "\n  " if i % 60 == 0
-          print ' ' if i % 10 == 0
-          print '.'
-          $stdout.flush
-        end
-    end
-
-
-    attr_reader :options
-
-    def initialize(options = {})
-      @options = default_options.merge(options)
-    end
-
-
-    def self.run(args = nil, options = {})
-      profiler = new(options)
-      profiler.parse_options(args) if args
-      profiler.run
-    end
-
-    def run
-      sandbox = Sandbox.new(options[:script])
-
-      puts 'Warming up once'
-
-      elapsed = warmup(sandbox)
-      puts '%.0f ms, %d requests, %d req/sec' % [elapsed, sandbox.request_count, 1000 * sandbox.request_count / elapsed]
-      puts "\n#{options[:benchmark] ? 'Benchmarking' : 'Profiling'} #{options[:n]}x"
-
-      options[:benchmark] ? benchmark(sandbox) : profile(sandbox)
-    end
-
-    def profile(sandbox)
-      load_ruby_prof
-
-      benchmark(sandbox, true)
-      results = RubyProf.stop
-
-      show_profile_results results
-      results
-    end
-
-    def benchmark(sandbox, profiling = false)
-      sandbox.request_count = 0
-      elapsed = sandbox.benchmark(options[:n], profiling)
-      count = sandbox.request_count.to_i
-      puts '%.0f ms, %d requests, %d req/sec' % [elapsed, count, 1000 * count / elapsed]
-    end
-
-    def warmup(sandbox)
-      Benchmark.ms { sandbox.run(false) }
-    end
-
-    def default_options
-      { :n => 100, :open => 'open %s &' }
-    end
-
-    # Parse command-line options
-    def parse_options(args)
-      OptionParser.new do |opt|
-        opt.banner = "USAGE: #{$0} [options] [session script path]"
-
-        opt.on('-n', '--times [100]', 'How many requests to process. Defaults to 100.') { |v| options[:n] = v.to_i if v }
-        opt.on('-b', '--benchmark', 'Benchmark instead of profiling') { |v| options[:benchmark] = v }
-        opt.on('-m', '--measure [mode]', 'Which ruby-prof measure mode to use: process_time, wall_time, cpu_time, allocations, or memory. Defaults to process_time.') { |v| options[:measure] = v }
-        opt.on('--open [CMD]', 'Command to open profile results. Defaults to "open %s &"') { |v| options[:open] = v }
-        opt.on('-h', '--help', 'Show this help') { puts opt; exit }
-
-        opt.parse args
-
-        if args.empty?
-          puts opt
-          exit
-        end
-        options[:script] = args.pop
-      end
-    end
-
-    protected
-      def load_ruby_prof
-        begin
-          gem 'ruby-prof', '>= 0.6.1'
-          require 'ruby-prof'
-          if mode = options[:measure]
-            RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
-          end
-        rescue LoadError
-          abort '`gem install ruby-prof` to use the profiler'
-        end
-      end
-
-      def show_profile_results(results)
-        File.open "#{RAILS_ROOT}/tmp/profile-graph.html", 'w' do |file|
-          RubyProf::GraphHtmlPrinter.new(results).print(file)
-          `#{options[:open] % file.path}` if options[:open]
-        end
-
-        File.open "#{RAILS_ROOT}/tmp/profile-flat.txt", 'w' do |file|
-          RubyProf::FlatPrinter.new(results).print(file)
-          `#{options[:open] % file.path}` if options[:open]
-        end
-      end
-  end
-end
-- 
cgit v1.2.3


From 085991891e610ed0ab616ce434eabf42a9437039 Mon Sep 17 00:00:00 2001
From: Pratik Naik <pratiknaik@gmail.com>
Date: Sun, 18 Jan 2009 05:28:21 +0000
Subject: Bump up the year in MIT license files

---
 actionpack/lib/action_controller.rb | 2 +-
 actionpack/lib/action_pack.rb       | 2 +-
 actionpack/lib/action_view.rb       | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'actionpack/lib')

diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index 5113a7b0cb..dca07a0afc 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -1,5 +1,5 @@
 #--
-# Copyright (c) 2004-2008 David Heinemeier Hansson
+# Copyright (c) 2004-2009 David Heinemeier Hansson
 #
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
diff --git a/actionpack/lib/action_pack.rb b/actionpack/lib/action_pack.rb
index c7fd3092e7..b90f89be39 100644
--- a/actionpack/lib/action_pack.rb
+++ b/actionpack/lib/action_pack.rb
@@ -1,5 +1,5 @@
 #--
-# Copyright (c) 2004-2008 David Heinemeier Hansson
+# Copyright (c) 2004-2009 David Heinemeier Hansson
 #
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index 210a5f1a93..0b710bd8d9 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -1,5 +1,5 @@
 #--
-# Copyright (c) 2004-2008 David Heinemeier Hansson
+# Copyright (c) 2004-2009 David Heinemeier Hansson
 #
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
-- 
cgit v1.2.3


From 01337e06dd3d58257eff7b46c7960461ae6c1cb1 Mon Sep 17 00:00:00 2001
From: Xavier Noria <fxn@hashref.com>
Date: Sun, 18 Jan 2009 14:30:03 +0100
Subject: in depth revision of AssetTagHelper rdoc

---
 .../lib/action_view/helpers/asset_tag_helper.rb    | 106 ++++++++++++---------
 1 file changed, 62 insertions(+), 44 deletions(-)

(limited to 'actionpack/lib')

diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index c6561f43a0..bd37f6fa0e 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -6,13 +6,19 @@ module ActionView
   module Helpers #:nodoc:
     # This module provides methods for generating HTML that links views to assets such
     # as images, javascripts, stylesheets, and feeds. These methods do not verify
-    # the assets exist before linking to them.
+    # the assets exist before linking to them:
+    #
+    #   image_tag("rails.png")
+    #   # => <img alt="Rails src="/images/rails.png?1230601161" />
+    #   stylesheet_link_tag("application")
+    #   # => <link href="/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />
     #
     # === Using asset hosts
     #
     # By default, Rails links to these assets on the current host in the public
-    # folder, but you can direct Rails to link to assets from a dedicated asset server by
-    # setting ActionController::Base.asset_host in your <tt>config/environment.rb</tt>.
+    # folder, but you can direct Rails to link to assets from a dedicated asset
+    # server by setting ActionController::Base.asset_host in the application
+    # configuration, typically in <tt>config/environments/production.rb</tt>.
     # For example, you'd define <tt>assets.example.com</tt> to be your asset
     # host this way:
     #
@@ -21,45 +27,49 @@ module ActionView
     # Helpers take that into account:
     #
     #   image_tag("rails.png")
-    #     => <img src="http://assets.example.com/images/rails.png" alt="Rails" />
+    #   # => <img alt="Rails" src="http://assets.example.com/images/rails.png?1230601161" />
     #   stylesheet_link_tag("application")
-    #     => <link href="http://assets.example.com/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
+    #   # => <link href="http://assets.example.com/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />
     #
-    # Browsers typically open at most two simultaneous connections to a single host,
-    # which means your assets often have to wait for other assets to finish downloading.
-    # You can alleviate this by using a <tt>%d</tt> wildcard in <tt>asset_host</tt>
-    # (for example, "assets%d.example.com") to automatically distribute asset requests
-    # among four hosts (e.g., "assets0.example.com" through "assets3.example.com") so
-    # browsers will open eight simultaneous connections rather than two.
+    # Browsers typically open at most two simultaneous connections to a single
+    # host, which means your assets often have to wait for other assets to finish
+    # downloading. You can alleviate this by using a <tt>%d</tt> wildcard in the
+    # +asset_host+. For example, "assets%d.example.com". If that wildcard is
+    # present Rails distributes asset requests among the corresponding four hosts
+    # "assets0.example.com", ..., "assets3.example.com". With this trick browsers
+    # will open eight simultaneous connections rather than two.
     #
     #   image_tag("rails.png")
-    #     => <img src="http://assets0.example.com/images/rails.png" alt="Rails" />
+    #   # => <img alt="Rails" src="http://assets0.example.com/images/rails.png?1230601161" />
     #   stylesheet_link_tag("application")
-    #     => <link href="http://assets3.example.com/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
+    #   # => <link href="http://assets2.example.com/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />
     #
-    # To do this, you can either setup 4 actual hosts, or you can use wildcard DNS to CNAME
-    # the wildcard to a single asset host.  You can read more about setting up your DNS CNAME records from
-    # your ISP.
+    # To do this, you can either setup four actual hosts, or you can use wildcard
+    # DNS to CNAME the wildcard to a single asset host. You can read more about
+    # setting up your DNS CNAME records from your ISP.
     #
     # Note: This is purely a browser performance optimization and is not meant
     # for server load balancing. See http://www.die.net/musings/page_load_time/
     # for background.
     #
-    # Alternatively, you can exert more control over the asset host by setting <tt>asset_host</tt> to a proc
-    # that takes a single source argument. This is useful if you are unable to setup 4 actual hosts or have
-    # fewer/more than 4 hosts. The example proc below generates http://assets1.example.com and
-    # http://assets2.example.com randomly.
+    # Alternatively, you can exert more control over the asset host by setting
+    # +asset_host+ to a proc like this:
     #
-    #   ActionController::Base.asset_host = Proc.new { |source| "http://assets#{rand(2) + 1}.example.com" }
+    #   ActionController::Base.asset_host = Proc.new { |source|
+    #     "http://assets#{rand(2) + 1}.example.com"
+    #   }
     #   image_tag("rails.png")
-    #     => <img src="http://assets2.example.com/images/rails.png" alt="Rails" />
+    #   # => <img alt="Rails" src="http://assets0.example.com/images/rails.png?1230601161" />
     #   stylesheet_link_tag("application")
-    #     => <link href="http://assets1.example.com/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
+    #   # => <link href="http://assets1.example.com/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />
+    #
+    # The example above generates http://assets1.example.com and
+    # http://assets2.example.com randomly. This option is useful for example if
+    # you need fewer/more than four hosts, custom host names, etc.
     #
-    # The proc takes a <tt>source</tt> parameter (which is the path of the source asset) and an optional
-    # <tt>request</tt> parameter (which is an entire instance of an <tt>ActionController::AbstractRequest</tt>
-    # subclass). This can be used to generate a particular asset host depending on the asset path and the particular
-    # request.
+    # As you see the proc takes a +source+ parameter. That's a string with the
+    # absolute path of the asset with any extensions and timestamps in place,
+    # for example "/images/rails.png?1230601161".
     #
     #    ActionController::Base.asset_host = Proc.new { |source|
     #      if source.starts_with?('/images')
@@ -69,14 +79,16 @@ module ActionView
     #      end
     #    }
     #   image_tag("rails.png")
-    #     => <img src="http://images.example.com/images/rails.png" alt="Rails" />
+    #   # => <img alt="Rails" src="http://images.example.com/images/rails.png?1230601161" />
     #   stylesheet_link_tag("application")
-    #     => <link href="http://assets.example.com/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
+    #   # => <link href="http://assets.example.com/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />
     #
-    # The optional <tt>request</tt> parameter to the proc is useful in particular for serving assets from an
-    # SSL-protected page. The example proc below disables asset hosting for HTTPS connections, while still sending
-    # assets for plain HTTP requests from asset hosts. This is useful for avoiding mixed media warnings when serving
-    # non-HTTP assets from HTTPS web pages when you don't have an SSL certificate for each of the asset hosts.
+    # Alternatively you may ask for a second parameter +request+. That one is
+    # particularly useful for serving assets from an SSL-protected page. The
+    # example proc below disables asset hosting for HTTPS connections, while
+    # still sending assets for plain HTTP requests from asset hosts. If you don't
+    # have SSL certificates for each of the asset hosts this technique allows you
+    # to avoid warnings in the client about mixed media.
     #
     #   ActionController::Base.asset_host = Proc.new { |source, request|
     #     if request.ssl?
@@ -86,7 +98,8 @@ module ActionView
     #     end
     #   }
     #
-    # You can also implement a custom asset host object that responds to the call method and tasks one or two parameters just like the proc.
+    # You can also implement a custom asset host object that responds to +call+
+    # and takes either one or two parameters just like the proc.
     #
     #   config.action_controller.asset_host = AssetHostingWithMinimumSsl.new(
     #     "http://asset%d.example.com", "https://asset1.example.com"
@@ -94,12 +107,15 @@ module ActionView
     #
     # === Using asset timestamps
     #
-    # By default, Rails will append all asset paths with that asset's timestamp. This allows you to set a cache-expiration date for the
-    # asset far into the future, but still be able to instantly invalidate it by simply updating the file (and hence updating the timestamp,
-    # which then updates the URL as the timestamp is part of that, which in turn busts the cache).
+    # By default, Rails appends asset's timestamps to all asset paths. This allows
+    # you to set a cache-expiration date for the asset far into the future, but
+    # still be able to instantly invalidate it by simply updating the file (and
+    # hence updating the timestamp, which then updates the URL as the timestamp
+    # is part of that, which in turn busts the cache).
     #
-    # It's the responsibility of the web server you use to set the far-future expiration date on cache assets that you need to take
-    # advantage of this feature. Here's an example for Apache:
+    # It's the responsibility of the web server you use to set the far-future
+    # expiration date on cache assets that you need to take advantage of this
+    # feature. Here's an example for Apache:
     #
     #   # Asset Expiration
     #   ExpiresActive On
@@ -107,11 +123,13 @@ module ActionView
     #     ExpiresDefault "access plus 1 year"
     #   </FilesMatch>
     #
-    # Also note that in order for this to work, all your application servers must return the same timestamps. This means that they must
-    # have their clocks synchronized. If one of them drift out of sync, you'll see different timestamps at random and the cache won't
-    # work. Which means that the browser will request the same assets over and over again even thought they didn't change. You can use
-    # something like Live HTTP Headers for Firefox to verify that the cache is indeed working (and that the assets are not being
-    # requested over and over).
+    # Also note that in order for this to work, all your application servers must
+    # return the same timestamps. This means that they must have their clocks
+    # synchronized. If one of them drifts out of sync, you'll see different
+    # timestamps at random and the cache won't work. In that case the browser
+    # will request the same assets over and over again even thought they didn't
+    # change. You can use something like Live HTTP Headers for Firefox to verify
+    # that the cache is indeed working.
     module AssetTagHelper
       ASSETS_DIR      = defined?(Rails.public_path) ? Rails.public_path : "public"
       JAVASCRIPTS_DIR = "#{ASSETS_DIR}/javascripts"
-- 
cgit v1.2.3


From e35e5ed2a4c87a10c70aa6b87a411182ce967c21 Mon Sep 17 00:00:00 2001
From: Xavier Noria <fxn@hashref.com>
Date: Sun, 18 Jan 2009 14:40:40 +0100
Subject: quoted a couple of strings

---
 actionpack/lib/action_view/helpers/asset_tag_helper.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'actionpack/lib')

diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index bd37f6fa0e..f6abea38ed 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -63,8 +63,8 @@ module ActionView
     #   stylesheet_link_tag("application")
     #   # => <link href="http://assets1.example.com/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />
     #
-    # The example above generates http://assets1.example.com and
-    # http://assets2.example.com randomly. This option is useful for example if
+    # The example above generates "http://assets1.example.com" and
+    # "http://assets2.example.com" randomly. This option is useful for example if
     # you need fewer/more than four hosts, custom host names, etc.
     #
     # As you see the proc takes a +source+ parameter. That's a string with the
-- 
cgit v1.2.3