From dd2ed32418a74ca9126834f98a1b0bca926c0c4f Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Fri, 24 Apr 2009 20:24:03 -0500 Subject: Start to integrate some of the features in Rack::Test. Eventually commit ActionDispatch::Test::MockRequest and ActionDispatch::Test:: UploadedFile upstream. --- .../lib/action_controller/testing/integration.rb | 175 +++------------------ .../lib/action_controller/testing/process.rb | 29 +--- actionpack/lib/action_dispatch.rb | 5 + actionpack/lib/action_dispatch/test/mock.rb | 127 +++++++++++++++ .../lib/action_dispatch/test/uploaded_file.rb | 33 ++++ actionpack/test/controller/integration_test.rb | 2 +- 6 files changed, 192 insertions(+), 179 deletions(-) create mode 100644 actionpack/lib/action_dispatch/test/mock.rb create mode 100644 actionpack/lib/action_dispatch/test/uploaded_file.rb diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb index d51b9b63ff..8bba6dfd59 100644 --- a/actionpack/lib/action_controller/testing/integration.rb +++ b/actionpack/lib/action_controller/testing/integration.rb @@ -17,9 +17,6 @@ module ActionController include ActionController::TestCase::Assertions include ActionController::TestProcess - # Rack application to use - attr_accessor :application - # The integer HTTP status code of the last request. attr_reader :status @@ -60,12 +57,9 @@ module ActionController # A running counter of the number of requests processed. attr_accessor :request_count - class MultiPartNeededException < Exception - end - # Create and initialize a new Session instance. def initialize(app = nil) - @application = app || ActionController::Dispatcher.new + @app = app || ActionController::Dispatcher.new reset! end @@ -255,103 +249,65 @@ module ActionController # Performs the actual request. def process(method, path, parameters = nil, headers = nil) - data = requestify(parameters) path = interpret_uri(path) if path =~ %r{://} - path = "/#{path}" unless path[0] == ?/ @path = path - env = {} - if method == :get - env["QUERY_STRING"] = data - data = nil + [ControllerCapture, ActionController::ProcessWithTest].each do |mod| + unless ActionController::Base < mod + ActionController::Base.class_eval { include mod } + end end - env["QUERY_STRING"] ||= "" + ActionController::Base.clear_last_instantiation! - data = data.is_a?(IO) ? data : StringIO.new(data || '') + opts = { + :method => method.to_s.upcase, + :params => parameters, + :headers => headers, - env.update( - "REQUEST_METHOD" => method.to_s.upcase, "SERVER_NAME" => host, "SERVER_PORT" => (https? ? "443" : "80"), "HTTPS" => https? ? "on" : "off", "rack.url_scheme" => https? ? "https" : "http", - "SCRIPT_NAME" => "", "REQUEST_URI" => path, "PATH_INFO" => path, "HTTP_HOST" => host, "REMOTE_ADDR" => remote_addr, "CONTENT_TYPE" => "application/x-www-form-urlencoded", - "CONTENT_LENGTH" => data ? data.length.to_s : nil, - "HTTP_COOKIE" => encode_cookies, "HTTP_ACCEPT" => accept, + "HTTP_COOKIE" => cookies.inject("") { |string, (name, value)| + string << "#{name}=#{value}; " + }, - "rack.version" => [0,1], - "rack.input" => data, - "rack.errors" => StringIO.new, - "rack.multithread" => true, - "rack.multiprocess" => true, - "rack.run_once" => false, - - "rack.test" => true - ) - - (headers || {}).each do |key, value| - key = key.to_s.upcase.gsub(/-/, "_") - key = "HTTP_#{key}" unless env.has_key?(key) || key =~ /^HTTP_/ - env[key] = value - end - - [ControllerCapture, ActionController::ProcessWithTest].each do |mod| - unless ActionController::Base < mod - ActionController::Base.class_eval { include mod } - end - end - - ActionController::Base.clear_last_instantiation! - - app = @application - # Rack::Lint doesn't accept String headers or bodies in Ruby 1.9 - unless RUBY_VERSION >= '1.9.0' && Rack.release <= '0.9.0' - app = Rack::Lint.new(app) - end + "rack.test" => true + } + env = ActionDispatch::Test::MockRequest.env_for(@path, opts) + app = Rack::Lint.new(@app) status, headers, body = app.call(env) + response = ::Rack::MockResponse.new(status, headers, body) @request_count += 1 @html_document = nil - @status = status.to_i + @status = response.status @status_message = ActionDispatch::StatusCodes::STATUS_CODES[@status] - - @headers = Rack::Utils::HeaderHash.new(headers) + @headers = response.headers + @body = response.body (@headers['Set-Cookie'] || "").split("\n").each do |cookie| name, value = cookie.match(/^([^=]*)=([^;]*);/)[1,2] @cookies[name] = value end - if body.is_a?(String) - @body_parts = [body] - @body = body - else - @body_parts = [] - body.each { |part| @body_parts << part.to_s } - @body = @body_parts.join - end - if @controller = ActionController::Base.last_instantiation @request = @controller.request @response = @controller.response @controller.send(:set_test_assigns) else - # Decorate responses from Rack Middleware and Rails Metal - # as an Response for the purposes of integration testing - @response = ActionDispatch::Response.new - @response.status = status.to_s - @response.headers.replace(@headers) - @response.body = @body_parts + @request = ::Rack::Request.new(env) + @response = response end # Decorate the response with the standard behavior of the @@ -360,21 +316,6 @@ module ActionController @response.extend(TestResponseBehavior) return @status - rescue MultiPartNeededException - boundary = "----------XnJLe9ZIbbGUYtzPQJ16u1" - status = process(method, path, - multipart_body(parameters, boundary), - (headers || {}).merge( - {"CONTENT_TYPE" => "multipart/form-data; boundary=#{boundary}"})) - return status - end - - # Encode the cookies hash in a format suitable for passing to a - # request. - def encode_cookies - cookies.inject("") do |string, (name, value)| - string << "#{name}=#{value}; " - end end # Get a temporary URL writer object @@ -389,72 +330,6 @@ module ActionController } UrlRewriter.new(ActionDispatch::Request.new(env), {}) end - - def name_with_prefix(prefix, name) - prefix ? "#{prefix}[#{name}]" : name.to_s - end - - # Convert the given parameters to a request string. The parameters may - # be a string, +nil+, or a Hash. - def requestify(parameters, prefix=nil) - if TestUploadedFile === parameters - raise MultiPartNeededException - elsif Hash === parameters - return nil if parameters.empty? - parameters.map { |k,v| - requestify(v, name_with_prefix(prefix, k)) - }.join("&") - elsif Array === parameters - parameters.map { |v| - requestify(v, name_with_prefix(prefix, "")) - }.join("&") - elsif prefix.nil? - parameters - else - "#{CGI.escape(prefix)}=#{CGI.escape(parameters.to_s)}" - end - end - - def multipart_requestify(params, first=true) - returning Hash.new do |p| - params.each do |key, value| - k = first ? CGI.escape(key.to_s) : "[#{CGI.escape(key.to_s)}]" - if Hash === value - multipart_requestify(value, false).each do |subkey, subvalue| - p[k + subkey] = subvalue - end - else - p[k] = value - end - end - end - end - - def multipart_body(params, boundary) - multipart_requestify(params).map do |key, value| - if value.respond_to?(:original_filename) - File.open(value.path, "rb") do |f| - f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding) - - <<-EOF ---#{boundary}\r -Content-Disposition: form-data; name="#{key}"; filename="#{CGI.escape(value.original_filename)}"\r -Content-Type: #{value.content_type}\r -Content-Length: #{File.stat(value.path).size}\r -\r -#{f.read}\r -EOF - end - else -<<-EOF ---#{boundary}\r -Content-Disposition: form-data; name="#{key}"\r -\r -#{value}\r -EOF - end - end.join("")+"--#{boundary}--\r" - end end # A module used to extend ActionController::Base, so that integration tests @@ -513,8 +388,8 @@ EOF # By default, a single session is automatically created for you, but you # can use this method to open multiple sessions that ought to be tested # simultaneously. - def open_session(application = nil) - session = Integration::Session.new(application) + def open_session(app = nil) + session = Integration::Session.new(app) # delegate the fixture accessors back to the test instance extras = Module.new { attr_accessor :delegate, :test_result } diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index 7e2857614c..f5742af472 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -363,34 +363,7 @@ module ActionController #:nodoc: # # Pass a true third parameter to ensure the uploaded file is opened in binary mode (only required for Windows): # post :change_avatar, :avatar => ActionController::TestUploadedFile.new(ActionController::TestCase.fixture_path + '/files/spongebob.png', 'image/png', :binary) - require 'tempfile' - class TestUploadedFile - # The filename, *not* including the path, of the "uploaded" file - attr_reader :original_filename - - # The content type of the "uploaded" file - attr_accessor :content_type - - def initialize(path, content_type = Mime::TEXT, binary = false) - raise "#{path} file does not exist" unless File.exist?(path) - @content_type = content_type - @original_filename = path.sub(/^.*#{File::SEPARATOR}([^#{File::SEPARATOR}]+)$/) { $1 } - @tempfile = Tempfile.new(@original_filename) - @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding) - @tempfile.binmode if binary - FileUtils.copy_file(path, @tempfile.path) - end - - def path #:nodoc: - @tempfile.path - end - - alias local_path path - - def method_missing(method_name, *args, &block) #:nodoc: - @tempfile.__send__(method_name, *args, &block) - end - end + TestUploadedFile = ActionDispatch::Test::UploadedFile module TestProcess def self.included(base) diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 5feb8a4863..13ce38e928 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -60,6 +60,11 @@ module ActionDispatch autoload :CookieStore, 'action_dispatch/middleware/session/cookie_store' autoload :MemCacheStore, 'action_dispatch/middleware/session/mem_cache_store' end + + module Test + autoload :UploadedFile, 'action_dispatch/test/uploaded_file' + autoload :MockRequest, 'action_dispatch/test/mock' + end end autoload :Mime, 'action_dispatch/http/mime_type' diff --git a/actionpack/lib/action_dispatch/test/mock.rb b/actionpack/lib/action_dispatch/test/mock.rb new file mode 100644 index 0000000000..86269fad01 --- /dev/null +++ b/actionpack/lib/action_dispatch/test/mock.rb @@ -0,0 +1,127 @@ +module ActionDispatch + module Test + class MockRequest < Rack::MockRequest + MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1" + + class << self + def env_for(path, opts) + headers = opts.delete(:headers) + + method = (opts[:method] || opts["REQUEST_METHOD"]).to_s.upcase + opts[:method] = opts["REQUEST_METHOD"] = method + + path = "/#{path}" unless path[0] == ?/ + uri = URI.parse(path) + uri.host ||= "example.org" + + if URI::HTTPS === uri + opts.update("SERVER_PORT" => "443", "HTTPS" => "on") + end + + if method == "POST" && !opts.has_key?(:input) + opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded" + + multipart = (opts[:params] || {}).any? do |k, v| + UploadedFile === v + end + + if multipart + opts[:input] = multipart_body(opts.delete(:params)) + opts["CONTENT_LENGTH"] ||= opts[:input].length.to_s + opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}" + else + params = opts.delete(:params) + opts[:input] = case params + when Hash then requestify(params) + when nil then "" + else params + end + end + end + + params = opts[:params] || {} + if params.is_a?(String) + if method == "GET" + uri.query = params + else + opts[:input] = params + end + else + params.update(::Rack::Utils.parse_query(uri.query)) + uri.query = requestify(params) + end + + env = ::Rack::MockRequest.env_for(uri.to_s, opts) + + (headers || {}).each do |key, value| + key = key.to_s.upcase.gsub(/-/, "_") + key = "HTTP_#{key}" unless env.has_key?(key) || key =~ /^HTTP_/ + env[key] = value + end + + env + end + + private + def requestify(value, prefix = nil) + case value + when Array + value.map do |v| + requestify(v, "#{prefix}[]") + end.join("&") + when Hash + value.map do |k, v| + requestify(v, prefix ? "#{prefix}[#{::Rack::Utils.escape(k)}]" : ::Rack::Utils.escape(k)) + end.join("&") + else + "#{prefix}=#{::Rack::Utils.escape(value)}" + end + end + + def multipart_requestify(params, first=true) + p = Hash.new + + params.each do |key, value| + k = first ? key.to_s : "[#{key}]" + + if Hash === value + multipart_requestify(value, false).each do |subkey, subvalue| + p[k + subkey] = subvalue + end + else + p[k] = value + end + end + + return p + end + + def multipart_body(params) + multipart_requestify(params).map do |key, value| + if value.respond_to?(:original_filename) + ::File.open(value.path, "rb") do |f| + f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding) + + <<-EOF +--#{MULTIPART_BOUNDARY}\r +Content-Disposition: form-data; name="#{key}"; filename="#{::Rack::Utils.escape(value.original_filename)}"\r +Content-Type: #{value.content_type}\r +Content-Length: #{::File.stat(value.path).size}\r +\r +#{f.read}\r +EOF + end + else +<<-EOF +--#{MULTIPART_BOUNDARY}\r +Content-Disposition: form-data; name="#{key}"\r +\r +#{value}\r +EOF + end + end.join("")+"--#{MULTIPART_BOUNDARY}--\r" + end + end + end + end +end diff --git a/actionpack/lib/action_dispatch/test/uploaded_file.rb b/actionpack/lib/action_dispatch/test/uploaded_file.rb new file mode 100644 index 0000000000..0ac7db4863 --- /dev/null +++ b/actionpack/lib/action_dispatch/test/uploaded_file.rb @@ -0,0 +1,33 @@ +require "tempfile" + +module ActionDispatch + module Test + class UploadedFile + # The filename, *not* including the path, of the "uploaded" file + attr_reader :original_filename + + # The content type of the "uploaded" file + attr_accessor :content_type + + def initialize(path, content_type = "text/plain", binary = false) + raise "#{path} file does not exist" unless ::File.exist?(path) + @content_type = content_type + @original_filename = ::File.basename(path) + @tempfile = Tempfile.new(@original_filename) + @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding) + @tempfile.binmode if binary + FileUtils.copy_file(path, @tempfile.path) + end + + def path + @tempfile.path + end + + alias_method :local_path, :path + + def method_missing(method_name, *args, &block) #:nodoc: + @tempfile.__send__(method_name, *args, &block) + end + end + end +end diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index e39a934c24..9eeaa7b4e1 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -337,7 +337,7 @@ class IntegrationProcessTest < ActionController::IntegrationTest get '/get_with_params?foo=bar' assert_equal '/get_with_params?foo=bar', request.env["REQUEST_URI"] assert_equal '/get_with_params?foo=bar', request.request_uri - assert_equal "", request.env["QUERY_STRING"] + assert_equal "foo=bar", request.env["QUERY_STRING"] assert_equal 'foo=bar', request.query_string assert_equal 'bar', request.parameters['foo'] -- cgit v1.2.3 From dc2caea9dc1535f30e8809b489c4ec1cf35febe6 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 24 Apr 2009 23:17:15 -0700 Subject: test uses Pathname --- actionpack/test/controller/render_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index bf72730bea..af7236ed26 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -1,5 +1,6 @@ require 'abstract_unit' require 'controller/fake_models' +require 'pathname' module Fun class GamesController < ActionController::Base -- cgit v1.2.3 From 044794fc9e1235981d20172b96f3b34b044ad19c Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 25 Apr 2009 13:41:30 -0500 Subject: Remove pending rack specifications until they are official --- actionpack/lib/action_controller/testing/integration.rb | 4 +--- actionpack/lib/action_dispatch/http/request.rb | 4 ++-- actionpack/lib/action_dispatch/middleware/failsafe.rb | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb index 8bba6dfd59..15d0603ac1 100644 --- a/actionpack/lib/action_controller/testing/integration.rb +++ b/actionpack/lib/action_controller/testing/integration.rb @@ -278,9 +278,7 @@ module ActionController "HTTP_ACCEPT" => accept, "HTTP_COOKIE" => cookies.inject("") { |string, (name, value)| string << "#{name}=#{value}; " - }, - - "rack.test" => true + } } env = ActionDispatch::Test::MockRequest.env_for(@path, opts) diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 523ab32b35..b8c547b696 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -397,7 +397,7 @@ EOM alias_method :params, :parameters def path_parameters=(parameters) #:nodoc: - @env["rack.routing_args"] = parameters + @env["action_dispatch.request.path_parameters"] = parameters @symbolized_path_parameters = @parameters = nil end @@ -413,7 +413,7 @@ EOM # # See symbolized_path_parameters for symbolized keys. def path_parameters - @env["rack.routing_args"] ||= {} + @env["action_dispatch.request.path_parameters"] ||= {} end # The request body is an IO input stream. If the RAW_POST_DATA environment diff --git a/actionpack/lib/action_dispatch/middleware/failsafe.rb b/actionpack/lib/action_dispatch/middleware/failsafe.rb index 7379a696aa..b5a3abcc92 100644 --- a/actionpack/lib/action_dispatch/middleware/failsafe.rb +++ b/actionpack/lib/action_dispatch/middleware/failsafe.rb @@ -11,7 +11,7 @@ module ActionDispatch @app.call(env) rescue Exception => exception # Reraise exception in test environment - if env["rack.test"] + if defined?(Rails) && Rails.test? raise exception else failsafe_response(exception) -- cgit v1.2.3 From b69da86ea545b342036fb37a472ec5abefaf3bd5 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 25 Apr 2009 13:56:37 -0500 Subject: Remove vendored version of Rack --- actionpack/lib/action_dispatch.rb | 9 +- actionpack/lib/action_dispatch/http/request.rb | 6 +- .../lib/action_dispatch/vendor/rack-1.0/rack.rb | 89 ---- .../vendor/rack-1.0/rack/adapter/camping.rb | 22 - .../vendor/rack-1.0/rack/auth/abstract/handler.rb | 37 -- .../vendor/rack-1.0/rack/auth/abstract/request.rb | 37 -- .../vendor/rack-1.0/rack/auth/basic.rb | 58 --- .../vendor/rack-1.0/rack/auth/digest/md5.rb | 124 ------ .../vendor/rack-1.0/rack/auth/digest/nonce.rb | 51 --- .../vendor/rack-1.0/rack/auth/digest/params.rb | 55 --- .../vendor/rack-1.0/rack/auth/digest/request.rb | 40 -- .../vendor/rack-1.0/rack/auth/openid.rb | 480 --------------------- .../vendor/rack-1.0/rack/builder.rb | 63 --- .../vendor/rack-1.0/rack/cascade.rb | 36 -- .../vendor/rack-1.0/rack/chunked.rb | 49 --- .../vendor/rack-1.0/rack/commonlogger.rb | 61 --- .../vendor/rack-1.0/rack/conditionalget.rb | 45 -- .../vendor/rack-1.0/rack/content_length.rb | 29 -- .../vendor/rack-1.0/rack/content_type.rb | 23 - .../vendor/rack-1.0/rack/deflater.rb | 85 ---- .../vendor/rack-1.0/rack/directory.rb | 153 ------- .../action_dispatch/vendor/rack-1.0/rack/file.rb | 88 ---- .../vendor/rack-1.0/rack/handler.rb | 48 --- .../vendor/rack-1.0/rack/handler/cgi.rb | 61 --- .../rack-1.0/rack/handler/evented_mongrel.rb | 8 - .../vendor/rack-1.0/rack/handler/fastcgi.rb | 89 ---- .../vendor/rack-1.0/rack/handler/lsws.rb | 55 --- .../vendor/rack-1.0/rack/handler/mongrel.rb | 84 ---- .../vendor/rack-1.0/rack/handler/scgi.rb | 59 --- .../rack-1.0/rack/handler/swiftiplied_mongrel.rb | 8 - .../vendor/rack-1.0/rack/handler/thin.rb | 18 - .../vendor/rack-1.0/rack/handler/webrick.rb | 67 --- .../action_dispatch/vendor/rack-1.0/rack/head.rb | 19 - .../action_dispatch/vendor/rack-1.0/rack/lint.rb | 462 -------------------- .../vendor/rack-1.0/rack/lobster.rb | 65 --- .../action_dispatch/vendor/rack-1.0/rack/lock.rb | 16 - .../vendor/rack-1.0/rack/methodoverride.rb | 27 -- .../action_dispatch/vendor/rack-1.0/rack/mime.rb | 204 --------- .../action_dispatch/vendor/rack-1.0/rack/mock.rb | 160 ------- .../vendor/rack-1.0/rack/recursive.rb | 57 --- .../vendor/rack-1.0/rack/reloader.rb | 64 --- .../vendor/rack-1.0/rack/request.rb | 241 ----------- .../vendor/rack-1.0/rack/response.rb | 179 -------- .../vendor/rack-1.0/rack/session/abstract/id.rb | 142 ------ .../vendor/rack-1.0/rack/session/cookie.rb | 91 ---- .../vendor/rack-1.0/rack/session/memcache.rb | 109 ----- .../vendor/rack-1.0/rack/session/pool.rb | 100 ----- .../vendor/rack-1.0/rack/showexceptions.rb | 349 --------------- .../vendor/rack-1.0/rack/showstatus.rb | 106 ----- .../action_dispatch/vendor/rack-1.0/rack/static.rb | 38 -- .../action_dispatch/vendor/rack-1.0/rack/urlmap.rb | 55 --- .../action_dispatch/vendor/rack-1.0/rack/utils.rb | 392 ----------------- .../request/multipart_params_parsing_test.rb | 2 +- 53 files changed, 8 insertions(+), 5007 deletions(-) delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/adapter/camping.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/abstract/handler.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/abstract/request.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/basic.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/md5.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/nonce.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/params.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/request.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/openid.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/builder.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/cascade.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/chunked.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/commonlogger.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/conditionalget.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/content_length.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/content_type.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/deflater.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/directory.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/file.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/cgi.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/evented_mongrel.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/fastcgi.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/lsws.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/mongrel.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/scgi.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/swiftiplied_mongrel.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/thin.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/webrick.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/head.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lint.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lobster.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lock.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/methodoverride.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/mime.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/mock.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/recursive.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/reloader.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/request.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/response.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/abstract/id.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/cookie.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/memcache.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/pool.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/showexceptions.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/showstatus.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/static.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/urlmap.rb delete mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/utils.rb diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 13ce38e928..0c915d9fd5 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -32,13 +32,8 @@ rescue LoadError end require 'active_support/core/all' -$:.unshift "#{File.dirname(__FILE__)}/action_dispatch/vendor/rack-1.0" -begin - gem 'rack', '~> 1.0.0' - require 'rack' -rescue Gem::LoadError - require 'action_dispatch/vendor/rack-1.0/rack' -end +gem 'rack', '~> 1.0.0' +require 'rack' module ActionDispatch autoload :Request, 'action_dispatch/http/request' diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index b8c547b696..ab654b9a50 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -93,7 +93,11 @@ module ActionDispatch end end end - + + def media_type + content_type.to_s + end + # Returns the accepted MIME type for the request. def accepts @accepts ||= begin diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack.rb deleted file mode 100644 index 6349b95094..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack.rb +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (C) 2007, 2008, 2009 Christian Neukirchen -# -# Rack is freely distributable under the terms of an MIT-style license. -# See COPYING or http://www.opensource.org/licenses/mit-license.php. - -$:.unshift(File.expand_path(File.dirname(__FILE__))) - - -# The Rack main module, serving as a namespace for all core Rack -# modules and classes. -# -# All modules meant for use in your application are autoloaded here, -# so it should be enough just to require rack.rb in your code. - -module Rack - # The Rack protocol version number implemented. - VERSION = [0,1] - - # Return the Rack protocol version as a dotted string. - def self.version - VERSION.join(".") - end - - # Return the Rack release as a dotted string. - def self.release - "1.0 bundled" - end - - autoload :Builder, "rack/builder" - autoload :Cascade, "rack/cascade" - autoload :Chunked, "rack/chunked" - autoload :CommonLogger, "rack/commonlogger" - autoload :ConditionalGet, "rack/conditionalget" - autoload :ContentLength, "rack/content_length" - autoload :ContentType, "rack/content_type" - autoload :File, "rack/file" - autoload :Deflater, "rack/deflater" - autoload :Directory, "rack/directory" - autoload :ForwardRequest, "rack/recursive" - autoload :Handler, "rack/handler" - autoload :Head, "rack/head" - autoload :Lint, "rack/lint" - autoload :Lock, "rack/lock" - autoload :MethodOverride, "rack/methodoverride" - autoload :Mime, "rack/mime" - autoload :Recursive, "rack/recursive" - autoload :Reloader, "rack/reloader" - autoload :ShowExceptions, "rack/showexceptions" - autoload :ShowStatus, "rack/showstatus" - autoload :Static, "rack/static" - autoload :URLMap, "rack/urlmap" - autoload :Utils, "rack/utils" - - autoload :MockRequest, "rack/mock" - autoload :MockResponse, "rack/mock" - - autoload :Request, "rack/request" - autoload :Response, "rack/response" - - module Auth - autoload :Basic, "rack/auth/basic" - autoload :AbstractRequest, "rack/auth/abstract/request" - autoload :AbstractHandler, "rack/auth/abstract/handler" - autoload :OpenID, "rack/auth/openid" - module Digest - autoload :MD5, "rack/auth/digest/md5" - autoload :Nonce, "rack/auth/digest/nonce" - autoload :Params, "rack/auth/digest/params" - autoload :Request, "rack/auth/digest/request" - end - end - - module Session - autoload :Cookie, "rack/session/cookie" - autoload :Pool, "rack/session/pool" - autoload :Memcache, "rack/session/memcache" - end - - # *Adapters* connect Rack with third party web frameworks. - # - # Rack includes an adapter for Camping, see README for other - # frameworks supporting Rack in their code bases. - # - # Refer to the submodules for framework-specific calling details. - - module Adapter - autoload :Camping, "rack/adapter/camping" - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/adapter/camping.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/adapter/camping.rb deleted file mode 100644 index 63bc787f54..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/adapter/camping.rb +++ /dev/null @@ -1,22 +0,0 @@ -module Rack - module Adapter - class Camping - def initialize(app) - @app = app - end - - def call(env) - env["PATH_INFO"] ||= "" - env["SCRIPT_NAME"] ||= "" - controller = @app.run(env['rack.input'], env) - h = controller.headers - h.each_pair do |k,v| - if v.kind_of? URI - h[k] = v.to_s - end - end - [controller.status, controller.headers, [controller.body.to_s]] - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/abstract/handler.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/abstract/handler.rb deleted file mode 100644 index 214df6299e..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/abstract/handler.rb +++ /dev/null @@ -1,37 +0,0 @@ -module Rack - module Auth - # Rack::Auth::AbstractHandler implements common authentication functionality. - # - # +realm+ should be set for all handlers. - - class AbstractHandler - - attr_accessor :realm - - def initialize(app, realm=nil, &authenticator) - @app, @realm, @authenticator = app, realm, authenticator - end - - - private - - def unauthorized(www_authenticate = challenge) - return [ 401, - { 'Content-Type' => 'text/plain', - 'Content-Length' => '0', - 'WWW-Authenticate' => www_authenticate.to_s }, - [] - ] - end - - def bad_request - return [ 400, - { 'Content-Type' => 'text/plain', - 'Content-Length' => '0' }, - [] - ] - end - - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/abstract/request.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/abstract/request.rb deleted file mode 100644 index 1d9ccec685..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/abstract/request.rb +++ /dev/null @@ -1,37 +0,0 @@ -module Rack - module Auth - class AbstractRequest - - def initialize(env) - @env = env - end - - def provided? - !authorization_key.nil? - end - - def parts - @parts ||= @env[authorization_key].split(' ', 2) - end - - def scheme - @scheme ||= parts.first.downcase.to_sym - end - - def params - @params ||= parts.last - end - - - private - - AUTHORIZATION_KEYS = ['HTTP_AUTHORIZATION', 'X-HTTP_AUTHORIZATION', 'X_HTTP_AUTHORIZATION'] - - def authorization_key - @authorization_key ||= AUTHORIZATION_KEYS.detect { |key| @env.has_key?(key) } - end - - end - - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/basic.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/basic.rb deleted file mode 100644 index 9557224648..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/basic.rb +++ /dev/null @@ -1,58 +0,0 @@ -require 'rack/auth/abstract/handler' -require 'rack/auth/abstract/request' - -module Rack - module Auth - # Rack::Auth::Basic implements HTTP Basic Authentication, as per RFC 2617. - # - # Initialize with the Rack application that you want protecting, - # and a block that checks if a username and password pair are valid. - # - # See also: example/protectedlobster.rb - - class Basic < AbstractHandler - - def call(env) - auth = Basic::Request.new(env) - - return unauthorized unless auth.provided? - - return bad_request unless auth.basic? - - if valid?(auth) - env['REMOTE_USER'] = auth.username - - return @app.call(env) - end - - unauthorized - end - - - private - - def challenge - 'Basic realm="%s"' % realm - end - - def valid?(auth) - @authenticator.call(*auth.credentials) - end - - class Request < Auth::AbstractRequest - def basic? - :basic == scheme - end - - def credentials - @credentials ||= params.unpack("m*").first.split(/:/, 2) - end - - def username - credentials.first - end - end - - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/md5.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/md5.rb deleted file mode 100644 index e579dc9632..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/md5.rb +++ /dev/null @@ -1,124 +0,0 @@ -require 'rack/auth/abstract/handler' -require 'rack/auth/digest/request' -require 'rack/auth/digest/params' -require 'rack/auth/digest/nonce' -require 'digest/md5' - -module Rack - module Auth - module Digest - # Rack::Auth::Digest::MD5 implements the MD5 algorithm version of - # HTTP Digest Authentication, as per RFC 2617. - # - # Initialize with the [Rack] application that you want protecting, - # and a block that looks up a plaintext password for a given username. - # - # +opaque+ needs to be set to a constant base64/hexadecimal string. - # - class MD5 < AbstractHandler - - attr_accessor :opaque - - attr_writer :passwords_hashed - - def initialize(*args) - super - @passwords_hashed = nil - end - - def passwords_hashed? - !!@passwords_hashed - end - - def call(env) - auth = Request.new(env) - - unless auth.provided? - return unauthorized - end - - if !auth.digest? || !auth.correct_uri? || !valid_qop?(auth) - return bad_request - end - - if valid?(auth) - if auth.nonce.stale? - return unauthorized(challenge(:stale => true)) - else - env['REMOTE_USER'] = auth.username - - return @app.call(env) - end - end - - unauthorized - end - - - private - - QOP = 'auth'.freeze - - def params(hash = {}) - Params.new do |params| - params['realm'] = realm - params['nonce'] = Nonce.new.to_s - params['opaque'] = H(opaque) - params['qop'] = QOP - - hash.each { |k, v| params[k] = v } - end - end - - def challenge(hash = {}) - "Digest #{params(hash)}" - end - - def valid?(auth) - valid_opaque?(auth) && valid_nonce?(auth) && valid_digest?(auth) - end - - def valid_qop?(auth) - QOP == auth.qop - end - - def valid_opaque?(auth) - H(opaque) == auth.opaque - end - - def valid_nonce?(auth) - auth.nonce.valid? - end - - def valid_digest?(auth) - digest(auth, @authenticator.call(auth.username)) == auth.response - end - - def md5(data) - ::Digest::MD5.hexdigest(data) - end - - alias :H :md5 - - def KD(secret, data) - H([secret, data] * ':') - end - - def A1(auth, password) - [ auth.username, auth.realm, password ] * ':' - end - - def A2(auth) - [ auth.method, auth.uri ] * ':' - end - - def digest(auth, password) - password_hash = passwords_hashed? ? password : H(A1(auth, password)) - - KD(password_hash, [ auth.nonce, auth.nc, auth.cnonce, QOP, H(A2(auth)) ] * ':') - end - - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/nonce.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/nonce.rb deleted file mode 100644 index dbe109f29a..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/nonce.rb +++ /dev/null @@ -1,51 +0,0 @@ -require 'digest/md5' - -module Rack - module Auth - module Digest - # Rack::Auth::Digest::Nonce is the default nonce generator for the - # Rack::Auth::Digest::MD5 authentication handler. - # - # +private_key+ needs to set to a constant string. - # - # +time_limit+ can be optionally set to an integer (number of seconds), - # to limit the validity of the generated nonces. - - class Nonce - - class << self - attr_accessor :private_key, :time_limit - end - - def self.parse(string) - new(*string.unpack("m*").first.split(' ', 2)) - end - - def initialize(timestamp = Time.now, given_digest = nil) - @timestamp, @given_digest = timestamp.to_i, given_digest - end - - def to_s - [([ @timestamp, digest ] * ' ')].pack("m*").strip - end - - def digest - ::Digest::MD5.hexdigest([ @timestamp, self.class.private_key ] * ':') - end - - def valid? - digest == @given_digest - end - - def stale? - !self.class.time_limit.nil? && (@timestamp - Time.now.to_i) < self.class.time_limit - end - - def fresh? - !stale? - end - - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/params.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/params.rb deleted file mode 100644 index 730e2efdc8..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/params.rb +++ /dev/null @@ -1,55 +0,0 @@ -module Rack - module Auth - module Digest - class Params < Hash - - def self.parse(str) - split_header_value(str).inject(new) do |header, param| - k, v = param.split('=', 2) - header[k] = dequote(v) - header - end - end - - def self.dequote(str) # From WEBrick::HTTPUtils - ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup - ret.gsub!(/\\(.)/, "\\1") - ret - end - - def self.split_header_value(str) - str.scan( /(\w+\=(?:"[^\"]+"|[^,]+))/n ).collect{ |v| v[0] } - end - - def initialize - super - - yield self if block_given? - end - - def [](k) - super k.to_s - end - - def []=(k, v) - super k.to_s, v.to_s - end - - UNQUOTED = ['qop', 'nc', 'stale'] - - def to_s - inject([]) do |parts, (k, v)| - parts << "#{k}=" + (UNQUOTED.include?(k) ? v.to_s : quote(v)) - parts - end.join(', ') - end - - def quote(str) # From WEBrick::HTTPUtils - '"' << str.gsub(/[\\\"]/o, "\\\1") << '"' - end - - end - end - end -end - diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/request.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/request.rb deleted file mode 100644 index a8aa3bf996..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/request.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'rack/auth/abstract/request' -require 'rack/auth/digest/params' -require 'rack/auth/digest/nonce' - -module Rack - module Auth - module Digest - class Request < Auth::AbstractRequest - - def method - @env['rack.methodoverride.original_method'] || @env['REQUEST_METHOD'] - end - - def digest? - :digest == scheme - end - - def correct_uri? - (@env['SCRIPT_NAME'].to_s + @env['PATH_INFO'].to_s) == uri - end - - def nonce - @nonce ||= Nonce.parse(params['nonce']) - end - - def params - @params ||= Params.parse(parts.last) - end - - def method_missing(sym) - if params.has_key? key = sym.to_s - return params[key] - end - super - end - - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/openid.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/openid.rb deleted file mode 100644 index c5f6a5143e..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/openid.rb +++ /dev/null @@ -1,480 +0,0 @@ -# AUTHOR: blink ; blink#ruby-lang@irc.freenode.net - -gem 'ruby-openid', '~> 2' if defined? Gem -require 'rack/request' -require 'rack/utils' -require 'rack/auth/abstract/handler' -require 'uri' -require 'openid' #gem -require 'openid/extension' #gem -require 'openid/store/memory' #gem - -module Rack - class Request - def openid_request - @env['rack.auth.openid.request'] - end - - def openid_response - @env['rack.auth.openid.response'] - end - end - - module Auth - - # Rack::Auth::OpenID provides a simple method for setting up an OpenID - # Consumer. It requires the ruby-openid library from janrain to operate, - # as well as a rack method of session management. - # - # The ruby-openid home page is at http://openidenabled.com/ruby-openid/. - # - # The OpenID specifications can be found at - # http://openid.net/specs/openid-authentication-1_1.html - # and - # http://openid.net/specs/openid-authentication-2_0.html. Documentation - # for published OpenID extensions and related topics can be found at - # http://openid.net/developers/specs/. - # - # It is recommended to read through the OpenID spec, as well as - # ruby-openid's documentation, to understand what exactly goes on. However - # a setup as simple as the presented examples is enough to provide - # Consumer functionality. - # - # This library strongly intends to utilize the OpenID 2.0 features of the - # ruby-openid library, which provides OpenID 1.0 compatiblity. - # - # NOTE: Due to the amount of data that this library stores in the - # session, Rack::Session::Cookie may fault. - - class OpenID - - class NoSession < RuntimeError; end - class BadExtension < RuntimeError; end - # Required for ruby-openid - ValidStatus = [:success, :setup_needed, :cancel, :failure] - - # = Arguments - # - # The first argument is the realm, identifying the site they are trusting - # with their identity. This is required, also treated as the trust_root - # in OpenID 1.x exchanges. - # - # The optional second argument is a hash of options. - # - # == Options - # - # :return_to defines the url to return to after the client - # authenticates with the openid service provider. This url should point - # to where Rack::Auth::OpenID is mounted. If :return_to is not - # provided, return_to will be the current url which allows flexibility - # with caveats. - # - # :session_key defines the key to the session hash in the env. - # It defaults to 'rack.session'. - # - # :openid_param defines at what key in the request parameters to - # find the identifier to resolve. As per the 2.0 spec, the default is - # 'openid_identifier'. - # - # :store defined what OpenID Store to use for persistant - # information. By default a Store::Memory will be used. - # - # :immediate as true will make initial requests to be of an - # immediate type. This is false by default. See OpenID specification - # documentation. - # - # :extensions should be a hash of openid extension - # implementations. The key should be the extension main module, the value - # should be an array of arguments for extension::Request.new. - # The hash is iterated over and passed to #add_extension for processing. - # Please see #add_extension for further documentation. - # - # == Examples - # - # simple_oid = OpenID.new('http://mysite.com/') - # - # return_oid = OpenID.new('http://mysite.com/', { - # :return_to => 'http://mysite.com/openid' - # }) - # - # complex_oid = OpenID.new('http://mysite.com/', - # :immediate => true, - # :extensions => { - # ::OpenID::SReg => [['email'],['nickname']] - # } - # ) - # - # = Advanced - # - # Most of the functionality of this library is encapsulated such that - # expansion and overriding functions isn't difficult nor tricky. - # Alternately, to avoid opening up singleton objects or subclassing, a - # wrapper rack middleware can be composed to act upon Auth::OpenID's - # responses. See #check and #finish for locations of pertinent data. - # - # == Responses - # - # To change the responses that Auth::OpenID returns, override the methods - # #redirect, #bad_request, #unauthorized, #access_denied, and - # #foreign_server_failure. - # - # Additionally #confirm_post_params is used when the URI would exceed - # length limits on a GET request when doing the initial verification - # request. - # - # == Processing - # - # To change methods of processing completed transactions, override the - # methods #success, #setup_needed, #cancel, and #failure. Please ensure - # the returned object is a rack compatible response. - # - # The first argument is an OpenID::Response, the second is a - # Rack::Request of the current request, the last is the hash used in - # ruby-openid handling, which can be found manually at - # env['rack.session'][:openid]. - # - # This is useful if you wanted to expand the processing done, such as - # setting up user accounts. - # - # oid_app = Rack::Auth::OpenID.new realm, :return_to => return_to - # def oid_app.success oid, request, session - # user = Models::User[oid.identity_url] - # user ||= Models::User.create_from_openid oid - # request['rack.session'][:user] = user.id - # redirect MyApp.site_home - # end - # - # site_map['/openid'] = oid_app - # map = Rack::URLMap.new site_map - # ... - - def initialize(realm, options={}) - realm = URI(realm) - raise ArgumentError, "Invalid realm: #{realm}" \ - unless realm.absolute? \ - and realm.fragment.nil? \ - and realm.scheme =~ /^https?$/ \ - and realm.host =~ /^(\*\.)?#{URI::REGEXP::PATTERN::URIC_NO_SLASH}+/ - realm.path = '/' if realm.path.empty? - @realm = realm.to_s - - if ruri = options[:return_to] - ruri = URI(ruri) - raise ArgumentError, "Invalid return_to: #{ruri}" \ - unless ruri.absolute? \ - and ruri.scheme =~ /^https?$/ \ - and ruri.fragment.nil? - raise ArgumentError, "return_to #{ruri} not within realm #{realm}" \ - unless self.within_realm?(ruri) - @return_to = ruri.to_s - end - - @session_key = options[:session_key] || 'rack.session' - @openid_param = options[:openid_param] || 'openid_identifier' - @store = options[:store] || ::OpenID::Store::Memory.new - @immediate = !!options[:immediate] - - @extensions = {} - if extensions = options.delete(:extensions) - extensions.each do |ext, args| - add_extension ext, *args - end - end - - # Undocumented, semi-experimental - @anonymous = !!options[:anonymous] - end - - attr_reader :realm, :return_to, :session_key, :openid_param, :store, - :immediate, :extensions - - # Sets up and uses session data at :openid within the session. - # Errors in this setup will raise a NoSession exception. - # - # If the parameter 'openid.mode' is set, which implies a followup from - # the openid server, processing is passed to #finish and the result is - # returned. However, if there is no appropriate openid information in the - # session, a 400 error is returned. - # - # If the parameter specified by options[:openid_param] is - # present, processing is passed to #check and the result is returned. - # - # If neither of these conditions are met, #unauthorized is called. - - def call(env) - env['rack.auth.openid'] = self - env_session = env[@session_key] - unless env_session and env_session.is_a?(Hash) - raise NoSession, 'No compatible session' - end - # let us work in our own namespace... - session = (env_session[:openid] ||= {}) - unless session and session.is_a?(Hash) - raise NoSession, 'Incompatible openid session' - end - - request = Rack::Request.new(env) - consumer = ::OpenID::Consumer.new(session, @store) - - if mode = request.GET['openid.mode'] - if session.key?(:openid_param) - finish(consumer, session, request) - else - bad_request - end - elsif request.GET[@openid_param] - check(consumer, session, request) - else - unauthorized - end - end - - # As the first part of OpenID consumer action, #check retrieves the data - # required for completion. - # - # If all parameters fit within the max length of a URI, a 303 redirect - # will be returned. Otherwise #confirm_post_params will be called. - # - # Any messages from OpenID's request are logged to env['rack.errors'] - # - # env['rack.auth.openid.request'] is the openid checkid request - # instance. - # - # session[:openid_param] is set to the openid identifier - # provided by the user. - # - # session[:return_to] is set to the return_to uri given to the - # identity provider. - - def check(consumer, session, req) - oid = consumer.begin(req.GET[@openid_param], @anonymous) - req.env['rack.auth.openid.request'] = oid - req.env['rack.errors'].puts(oid.message) - p oid if $DEBUG - - ## Extension support - extensions.each do |ext,args| - oid.add_extension(ext::Request.new(*args)) - end - - session[:openid_param] = req.GET[openid_param] - return_to_uri = return_to ? return_to : req.url - session[:return_to] = return_to_uri - immediate = session.key?(:setup_needed) ? false : immediate - - if oid.send_redirect?(realm, return_to_uri, immediate) - uri = oid.redirect_url(realm, return_to_uri, immediate) - redirect(uri) - else - confirm_post_params(oid, realm, return_to_uri, immediate) - end - rescue ::OpenID::DiscoveryFailure => e - # thrown from inside OpenID::Consumer#begin by yadis stuff - req.env['rack.errors'].puts([e.message, *e.backtrace]*"\n") - return foreign_server_failure - end - - # This is the final portion of authentication. - # If successful, a redirect to the realm is be returned. - # Data gathered from extensions are stored in session[:openid] with the - # extension's namespace uri as the key. - # - # Any messages from OpenID's response are logged to env['rack.errors'] - # - # env['rack.auth.openid.response'] will contain the openid - # response. - - def finish(consumer, session, req) - oid = consumer.complete(req.GET, req.url) - req.env['rack.auth.openid.response'] = oid - req.env['rack.errors'].puts(oid.message) - p oid if $DEBUG - - raise unless ValidStatus.include?(oid.status) - __send__(oid.status, oid, req, session) - end - - # The first argument should be the main extension module. - # The extension module should contain the constants: - # * class Request, should have OpenID::Extension as an ancestor - # * class Response, should have OpenID::Extension as an ancestor - # * string NS_URI, which defining the namespace of the extension - # - # All trailing arguments will be passed to extension::Request.new in - # #check. - # The openid response will be passed to - # extension::Response#from_success_response, #get_extension_args will be - # called on the result to attain the gathered data. - # - # This method returns the key at which the response data will be found in - # the session, which is the namespace uri by default. - - def add_extension(ext, *args) - raise BadExtension unless valid_extension?(ext) - extensions[ext] = args - return ext::NS_URI - end - - # Checks the validitity, in the context of usage, of a submitted - # extension. - - def valid_extension?(ext) - if not %w[NS_URI Request Response].all?{|c| ext.const_defined?(c) } - raise ArgumentError, 'Extension is missing constants.' - elsif not ext::Response.respond_to?(:from_success_response) - raise ArgumentError, 'Response is missing required method.' - end - return true - rescue - return false - end - - # Checks the provided uri to ensure it'd be considered within the realm. - # is currently not compatible with wildcard realms. - - def within_realm? uri - uri = URI.parse(uri.to_s) - realm = URI.parse(self.realm) - return false unless uri.absolute? - return false unless uri.path[0, realm.path.size] == realm.path - return false unless uri.host == realm.host or realm.host[/^\*\./] - # for wildcard support, is awkward with URI limitations - realm_match = Regexp.escape(realm.host). - sub(/^\*\./,"^#{URI::REGEXP::PATTERN::URIC_NO_SLASH}+.")+'$' - return false unless uri.host.match(realm_match) - return true - end - alias_method :include?, :within_realm? - - protected - - ### These methods define some of the boilerplate responses. - - # Returns an html form page for posting to an Identity Provider if the - # GET request would exceed the upper URI length limit. - - def confirm_post_params(oid, realm, return_to, immediate) - Rack::Response.new.finish do |r| - r.write 'Confirm...' - r.write oid.form_markup(realm, return_to, immediate) - r.write '' - end - end - - # Returns a 303 redirect with the destination of that provided by the - # argument. - - def redirect(uri) - [ 303, {'Content-Length'=>'0', 'Content-Type'=>'text/plain', - 'Location' => uri}, - [] ] - end - - # Returns an empty 400 response. - - def bad_request - [ 400, {'Content-Type'=>'text/plain', 'Content-Length'=>'0'}, - [''] ] - end - - # Returns a basic unauthorized 401 response. - - def unauthorized - [ 401, {'Content-Type' => 'text/plain', 'Content-Length' => '13'}, - ['Unauthorized.'] ] - end - - # Returns a basic access denied 403 response. - - def access_denied - [ 403, {'Content-Type' => 'text/plain', 'Content-Length' => '14'}, - ['Access denied.'] ] - end - - # Returns a 503 response to be used if communication with the remote - # OpenID server fails. - - def foreign_server_failure - [ 503, {'Content-Type'=>'text/plain', 'Content-Length' => '23'}, - ['Foreign server failure.'] ] - end - - private - - ### These methods are called after a transaction is completed, depending - # on its outcome. These should all return a rack compatible response. - # You'd want to override these to provide additional functionality. - - # Called to complete processing on a successful transaction. - # Within the openid session, :openid_identity and :openid_identifier are - # set to the user friendly and the standard representation of the - # validated identity. All other data in the openid session is cleared. - - def success(oid, request, session) - session.clear - session[:openid_identity] = oid.display_identifier - session[:openid_identifier] = oid.identity_url - extensions.keys.each do |ext| - label = ext.name[/[^:]+$/].downcase - response = ext::Response.from_success_response(oid) - session[label] = response.data - end - redirect(realm) - end - - # Called if the Identity Provider indicates further setup by the user is - # required. - # The identifier is retrived from the openid session at :openid_param. - # And :setup_needed is set to true to prevent looping. - - def setup_needed(oid, request, session) - identifier = session[:openid_param] - session[:setup_needed] = true - redirect req.script_name + '?' + openid_param + '=' + identifier - end - - # Called if the user indicates they wish to cancel identification. - # Data within openid session is cleared. - - def cancel(oid, request, session) - session.clear - access_denied - end - - # Called if the Identity Provider indicates the user is unable to confirm - # their identity. Data within the openid session is left alone, in case - # of swarm auth attacks. - - def failure(oid, request, session) - unauthorized - end - end - - # A class developed out of the request to use OpenID as an authentication - # middleware. The request will be sent to the OpenID instance unless the - # block evaluates to true. For example in rackup, you can use it as such: - # - # use Rack::Session::Pool - # use Rack::Auth::OpenIDAuth, realm, openid_options do |env| - # env['rack.session'][:authkey] == a_string - # end - # run RackApp - # - # Or simply: - # - # app = Rack::Auth::OpenIDAuth.new app, realm, openid_options, &auth - - class OpenIDAuth < Rack::Auth::AbstractHandler - attr_reader :oid - def initialize(app, realm, options={}, &auth) - @oid = OpenID.new(realm, options) - super(app, &auth) - end - - def call(env) - to = auth.call(env) ? @app : @oid - to.call env - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/builder.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/builder.rb deleted file mode 100644 index 295235e56a..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/builder.rb +++ /dev/null @@ -1,63 +0,0 @@ -module Rack - # Rack::Builder implements a small DSL to iteratively construct Rack - # applications. - # - # Example: - # - # app = Rack::Builder.new { - # use Rack::CommonLogger - # use Rack::ShowExceptions - # map "/lobster" do - # use Rack::Lint - # run Rack::Lobster.new - # end - # } - # - # Or - # - # app = Rack::Builder.app do - # use Rack::CommonLogger - # lambda { |env| [200, {'Content-Type' => 'text/plain'}, 'OK'] } - # end - # - # +use+ adds a middleware to the stack, +run+ dispatches to an application. - # You can use +map+ to construct a Rack::URLMap in a convenient way. - - class Builder - def initialize(&block) - @ins = [] - instance_eval(&block) if block_given? - end - - def self.app(&block) - self.new(&block).to_app - end - - def use(middleware, *args, &block) - @ins << lambda { |app| middleware.new(app, *args, &block) } - end - - def run(app) - @ins << app #lambda { |nothing| app } - end - - def map(path, &block) - if @ins.last.kind_of? Hash - @ins.last[path] = self.class.new(&block).to_app - else - @ins << {} - map(path, &block) - end - end - - def to_app - @ins[-1] = Rack::URLMap.new(@ins.last) if Hash === @ins.last - inner_app = @ins.last - @ins[0...-1].reverse.inject(inner_app) { |a, e| e.call(a) } - end - - def call(env) - to_app.call(env) - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/cascade.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/cascade.rb deleted file mode 100644 index a038aa1105..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/cascade.rb +++ /dev/null @@ -1,36 +0,0 @@ -module Rack - # Rack::Cascade tries an request on several apps, and returns the - # first response that is not 404 (or in a list of configurable - # status codes). - - class Cascade - attr_reader :apps - - def initialize(apps, catch=404) - @apps = apps - @catch = [*catch] - end - - def call(env) - status = headers = body = nil - raise ArgumentError, "empty cascade" if @apps.empty? - @apps.each { |app| - begin - status, headers, body = app.call(env) - break unless @catch.include?(status.to_i) - end - } - [status, headers, body] - end - - def add app - @apps << app - end - - def include? app - @apps.include? app - end - - alias_method :<<, :add - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/chunked.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/chunked.rb deleted file mode 100644 index 280d89dd65..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/chunked.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'rack/utils' - -module Rack - - # Middleware that applies chunked transfer encoding to response bodies - # when the response does not include a Content-Length header. - class Chunked - include Rack::Utils - - def initialize(app) - @app = app - end - - def call(env) - status, headers, body = @app.call(env) - headers = HeaderHash.new(headers) - - if env['HTTP_VERSION'] == 'HTTP/1.0' || - STATUS_WITH_NO_ENTITY_BODY.include?(status) || - headers['Content-Length'] || - headers['Transfer-Encoding'] - [status, headers.to_hash, body] - else - dup.chunk(status, headers, body) - end - end - - def chunk(status, headers, body) - @body = body - headers.delete('Content-Length') - headers['Transfer-Encoding'] = 'chunked' - [status, headers.to_hash, self] - end - - def each - term = "\r\n" - @body.each do |chunk| - size = bytesize(chunk) - next if size == 0 - yield [size.to_s(16), term, chunk, term].join - end - yield ["0", term, "", term].join - end - - def close - @body.close if @body.respond_to?(:close) - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/commonlogger.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/commonlogger.rb deleted file mode 100644 index 5e68ac626d..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/commonlogger.rb +++ /dev/null @@ -1,61 +0,0 @@ -module Rack - # Rack::CommonLogger forwards every request to an +app+ given, and - # logs a line in the Apache common log format to the +logger+, or - # rack.errors by default. - - class CommonLogger - def initialize(app, logger=nil) - @app = app - @logger = logger - end - - def call(env) - dup._call(env) - end - - def _call(env) - @env = env - @logger ||= self - @time = Time.now - @status, @header, @body = @app.call(env) - [@status, @header, self] - end - - def close - @body.close if @body.respond_to? :close - end - - # By default, log to rack.errors. - def <<(str) - @env["rack.errors"].write(str) - @env["rack.errors"].flush - end - - def each - length = 0 - @body.each { |part| - length += part.size - yield part - } - - @now = Time.now - - # Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common - # lilith.local - - [07/Aug/2006 23:58:02] "GET / HTTP/1.1" 500 - - # %{%s - %s [%s] "%s %s%s %s" %d %s\n} % - @logger << %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n} % - [ - @env['HTTP_X_FORWARDED_FOR'] || @env["REMOTE_ADDR"] || "-", - @env["REMOTE_USER"] || "-", - @now.strftime("%d/%b/%Y %H:%M:%S"), - @env["REQUEST_METHOD"], - @env["PATH_INFO"], - @env["QUERY_STRING"].empty? ? "" : "?"+@env["QUERY_STRING"], - @env["HTTP_VERSION"], - @status.to_s[0..3], - (length.zero? ? "-" : length.to_s), - @now - @time - ] - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/conditionalget.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/conditionalget.rb deleted file mode 100644 index 7bec824181..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/conditionalget.rb +++ /dev/null @@ -1,45 +0,0 @@ -require 'rack/utils' - -module Rack - - # Middleware that enables conditional GET using If-None-Match and - # If-Modified-Since. The application should set either or both of the - # Last-Modified or Etag response headers according to RFC 2616. When - # either of the conditions is met, the response body is set to be zero - # length and the response status is set to 304 Not Modified. - # - # Applications that defer response body generation until the body's each - # message is received will avoid response body generation completely when - # a conditional GET matches. - # - # Adapted from Michael Klishin's Merb implementation: - # http://github.com/wycats/merb-core/tree/master/lib/merb-core/rack/middleware/conditional_get.rb - class ConditionalGet - def initialize(app) - @app = app - end - - def call(env) - return @app.call(env) unless %w[GET HEAD].include?(env['REQUEST_METHOD']) - - status, headers, body = @app.call(env) - headers = Utils::HeaderHash.new(headers) - if etag_matches?(env, headers) || modified_since?(env, headers) - status = 304 - body = [] - end - [status, headers, body] - end - - private - def etag_matches?(env, headers) - etag = headers['Etag'] and etag == env['HTTP_IF_NONE_MATCH'] - end - - def modified_since?(env, headers) - last_modified = headers['Last-Modified'] and - last_modified == env['HTTP_IF_MODIFIED_SINCE'] - end - end - -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/content_length.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/content_length.rb deleted file mode 100644 index 1e56d43853..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/content_length.rb +++ /dev/null @@ -1,29 +0,0 @@ -require 'rack/utils' - -module Rack - # Sets the Content-Length header on responses with fixed-length bodies. - class ContentLength - include Rack::Utils - - def initialize(app) - @app = app - end - - def call(env) - status, headers, body = @app.call(env) - headers = HeaderHash.new(headers) - - if !STATUS_WITH_NO_ENTITY_BODY.include?(status) && - !headers['Content-Length'] && - !headers['Transfer-Encoding'] && - (body.respond_to?(:to_ary) || body.respond_to?(:to_str)) - - body = [body] if body.respond_to?(:to_str) # rack 0.4 compat - length = body.to_ary.inject(0) { |len, part| len + bytesize(part) } - headers['Content-Length'] = length.to_s - end - - [status, headers, body] - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/content_type.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/content_type.rb deleted file mode 100644 index 0c1e1ca3e1..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/content_type.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'rack/utils' - -module Rack - - # Sets the Content-Type header on responses which don't have one. - # - # Builder Usage: - # use Rack::ContentType, "text/plain" - # - # When no content type argument is provided, "text/html" is assumed. - class ContentType - def initialize(app, content_type = "text/html") - @app, @content_type = app, content_type - end - - def call(env) - status, headers, body = @app.call(env) - headers = Utils::HeaderHash.new(headers) - headers['Content-Type'] ||= @content_type - [status, headers.to_hash, body] - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/deflater.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/deflater.rb deleted file mode 100644 index a42b7477ae..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/deflater.rb +++ /dev/null @@ -1,85 +0,0 @@ -require "zlib" -require "stringio" -require "time" # for Time.httpdate -require 'rack/utils' - -module Rack - class Deflater - def initialize(app) - @app = app - end - - def call(env) - status, headers, body = @app.call(env) - headers = Utils::HeaderHash.new(headers) - - # Skip compressing empty entity body responses and responses with - # no-transform set. - if Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) || - headers['Cache-Control'].to_s =~ /\bno-transform\b/ - return [status, headers, body] - end - - request = Request.new(env) - - encoding = Utils.select_best_encoding(%w(gzip deflate identity), - request.accept_encoding) - - # Set the Vary HTTP header. - vary = headers["Vary"].to_s.split(",").map { |v| v.strip } - unless vary.include?("*") || vary.include?("Accept-Encoding") - headers["Vary"] = vary.push("Accept-Encoding").join(",") - end - - case encoding - when "gzip" - mtime = headers.key?("Last-Modified") ? - Time.httpdate(headers["Last-Modified"]) : Time.now - body = self.class.gzip(body, mtime) - size = Rack::Utils.bytesize(body) - headers = headers.merge("Content-Encoding" => "gzip", "Content-Length" => size.to_s) - [status, headers, [body]] - when "deflate" - body = self.class.deflate(body) - size = Rack::Utils.bytesize(body) - headers = headers.merge("Content-Encoding" => "deflate", "Content-Length" => size.to_s) - [status, headers, [body]] - when "identity" - [status, headers, body] - when nil - message = "An acceptable encoding for the requested resource #{request.fullpath} could not be found." - [406, {"Content-Type" => "text/plain", "Content-Length" => message.length.to_s}, [message]] - end - end - - def self.gzip(body, mtime) - io = StringIO.new - gzip = Zlib::GzipWriter.new(io) - gzip.mtime = mtime - - # TODO: Add streaming - body.each { |part| gzip << part } - - gzip.close - return io.string - end - - DEFLATE_ARGS = [ - Zlib::DEFAULT_COMPRESSION, - # drop the zlib header which causes both Safari and IE to choke - -Zlib::MAX_WBITS, - Zlib::DEF_MEM_LEVEL, - Zlib::DEFAULT_STRATEGY - ] - - # Loosely based on Mongrel's Deflate handler - def self.deflate(body) - deflater = Zlib::Deflate.new(*DEFLATE_ARGS) - - # TODO: Add streaming - body.each { |part| deflater << part } - - return deflater.finish - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/directory.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/directory.rb deleted file mode 100644 index acdd3029d3..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/directory.rb +++ /dev/null @@ -1,153 +0,0 @@ -require 'time' -require 'rack/utils' -require 'rack/mime' - -module Rack - # Rack::Directory serves entries below the +root+ given, according to the - # path info of the Rack request. If a directory is found, the file's contents - # will be presented in an html based index. If a file is found, the env will - # be passed to the specified +app+. - # - # If +app+ is not specified, a Rack::File of the same +root+ will be used. - - class Directory - DIR_FILE = "%s%s%s%s" - DIR_PAGE = <<-PAGE - - %s - - - -

%s

-
- - - - - - - -%s -
NameSizeTypeLast Modified
-
- - PAGE - - attr_reader :files - attr_accessor :root, :path - - def initialize(root, app=nil) - @root = F.expand_path(root) - @app = app || Rack::File.new(@root) - end - - def call(env) - dup._call(env) - end - - F = ::File - - def _call(env) - @env = env - @script_name = env['SCRIPT_NAME'] - @path_info = Utils.unescape(env['PATH_INFO']) - - if forbidden = check_forbidden - forbidden - else - @path = F.join(@root, @path_info) - list_path - end - end - - def check_forbidden - return unless @path_info.include? ".." - - body = "Forbidden\n" - size = Rack::Utils.bytesize(body) - return [403, {"Content-Type" => "text/plain","Content-Length" => size.to_s}, [body]] - end - - def list_directory - @files = [['../','Parent Directory','','','']] - glob = F.join(@path, '*') - - Dir[glob].sort.each do |node| - stat = stat(node) - next unless stat - basename = F.basename(node) - ext = F.extname(node) - - url = F.join(@script_name, @path_info, basename) - size = stat.size - type = stat.directory? ? 'directory' : Mime.mime_type(ext) - size = stat.directory? ? '-' : filesize_format(size) - mtime = stat.mtime.httpdate - url << '/' if stat.directory? - basename << '/' if stat.directory? - - @files << [ url, basename, size, type, mtime ] - end - - return [ 200, {'Content-Type'=>'text/html; charset=utf-8'}, self ] - end - - def stat(node, max = 10) - F.stat(node) - rescue Errno::ENOENT, Errno::ELOOP - return nil - end - - # TODO: add correct response if not readable, not sure if 404 is the best - # option - def list_path - @stat = F.stat(@path) - - if @stat.readable? - return @app.call(@env) if @stat.file? - return list_directory if @stat.directory? - else - raise Errno::ENOENT, 'No such file or directory' - end - - rescue Errno::ENOENT, Errno::ELOOP - return entity_not_found - end - - def entity_not_found - body = "Entity not found: #{@path_info}\n" - size = Rack::Utils.bytesize(body) - return [404, {"Content-Type" => "text/plain", "Content-Length" => size.to_s}, [body]] - end - - def each - show_path = @path.sub(/^#{@root}/,'') - files = @files.map{|f| DIR_FILE % f }*"\n" - page = DIR_PAGE % [ show_path, show_path , files ] - page.each_line{|l| yield l } - end - - # Stolen from Ramaze - - FILESIZE_FORMAT = [ - ['%.1fT', 1 << 40], - ['%.1fG', 1 << 30], - ['%.1fM', 1 << 20], - ['%.1fK', 1 << 10], - ] - - def filesize_format(int) - FILESIZE_FORMAT.each do |format, size| - return format % (int.to_f / size) if int >= size - end - - int.to_s + 'B' - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/file.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/file.rb deleted file mode 100644 index fe62bd6b86..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/file.rb +++ /dev/null @@ -1,88 +0,0 @@ -require 'time' -require 'rack/utils' -require 'rack/mime' - -module Rack - # Rack::File serves files below the +root+ given, according to the - # path info of the Rack request. - # - # Handlers can detect if bodies are a Rack::File, and use mechanisms - # like sendfile on the +path+. - - class File - attr_accessor :root - attr_accessor :path - - alias :to_path :path - - def initialize(root) - @root = root - end - - def call(env) - dup._call(env) - end - - F = ::File - - def _call(env) - @path_info = Utils.unescape(env["PATH_INFO"]) - return forbidden if @path_info.include? ".." - - @path = F.join(@root, @path_info) - - begin - if F.file?(@path) && F.readable?(@path) - serving - else - raise Errno::EPERM - end - rescue SystemCallError - not_found - end - end - - def forbidden - body = "Forbidden\n" - [403, {"Content-Type" => "text/plain", - "Content-Length" => body.size.to_s}, - [body]] - end - - # NOTE: - # We check via File::size? whether this file provides size info - # via stat (e.g. /proc files often don't), otherwise we have to - # figure it out by reading the whole file into memory. And while - # we're at it we also use this as body then. - - def serving - if size = F.size?(@path) - body = self - else - body = [F.read(@path)] - size = Utils.bytesize(body.first) - end - - [200, { - "Last-Modified" => F.mtime(@path).httpdate, - "Content-Type" => Mime.mime_type(F.extname(@path), 'text/plain'), - "Content-Length" => size.to_s - }, body] - end - - def not_found - body = "File not found: #{@path_info}\n" - [404, {"Content-Type" => "text/plain", - "Content-Length" => body.size.to_s}, - [body]] - end - - def each - F.open(@path, "rb") { |file| - while part = file.read(8192) - yield part - end - } - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler.rb deleted file mode 100644 index 1018af64c7..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler.rb +++ /dev/null @@ -1,48 +0,0 @@ -module Rack - # *Handlers* connect web servers with Rack. - # - # Rack includes Handlers for Mongrel, WEBrick, FastCGI, CGI, SCGI - # and LiteSpeed. - # - # Handlers usually are activated by calling MyHandler.run(myapp). - # A second optional hash can be passed to include server-specific - # configuration. - module Handler - def self.get(server) - return unless server - - if klass = @handlers[server] - obj = Object - klass.split("::").each { |x| obj = obj.const_get(x) } - obj - else - Rack::Handler.const_get(server.capitalize) - end - end - - def self.register(server, klass) - @handlers ||= {} - @handlers[server] = klass - end - - autoload :CGI, "rack/handler/cgi" - autoload :FastCGI, "rack/handler/fastcgi" - autoload :Mongrel, "rack/handler/mongrel" - autoload :EventedMongrel, "rack/handler/evented_mongrel" - autoload :SwiftipliedMongrel, "rack/handler/swiftiplied_mongrel" - autoload :WEBrick, "rack/handler/webrick" - autoload :LSWS, "rack/handler/lsws" - autoload :SCGI, "rack/handler/scgi" - autoload :Thin, "rack/handler/thin" - - register 'cgi', 'Rack::Handler::CGI' - register 'fastcgi', 'Rack::Handler::FastCGI' - register 'mongrel', 'Rack::Handler::Mongrel' - register 'emongrel', 'Rack::Handler::EventedMongrel' - register 'smongrel', 'Rack::Handler::SwiftipliedMongrel' - register 'webrick', 'Rack::Handler::WEBrick' - register 'lsws', 'Rack::Handler::LSWS' - register 'scgi', 'Rack::Handler::SCGI' - register 'thin', 'Rack::Handler::Thin' - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/cgi.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/cgi.rb deleted file mode 100644 index e38156c7f0..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/cgi.rb +++ /dev/null @@ -1,61 +0,0 @@ -require 'rack/content_length' - -module Rack - module Handler - class CGI - def self.run(app, options=nil) - serve app - end - - def self.serve(app) - app = ContentLength.new(app) - - env = ENV.to_hash - env.delete "HTTP_CONTENT_LENGTH" - - env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" - - env.update({"rack.version" => [0,1], - "rack.input" => $stdin, - "rack.errors" => $stderr, - - "rack.multithread" => false, - "rack.multiprocess" => true, - "rack.run_once" => true, - - "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" - }) - - env["QUERY_STRING"] ||= "" - env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] - env["REQUEST_PATH"] ||= "/" - - status, headers, body = app.call(env) - begin - send_headers status, headers - send_body body - ensure - body.close if body.respond_to? :close - end - end - - def self.send_headers(status, headers) - STDOUT.print "Status: #{status}\r\n" - headers.each { |k, vs| - vs.split("\n").each { |v| - STDOUT.print "#{k}: #{v}\r\n" - } - } - STDOUT.print "\r\n" - STDOUT.flush - end - - def self.send_body(body) - body.each { |part| - STDOUT.print part - STDOUT.flush - } - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/evented_mongrel.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/evented_mongrel.rb deleted file mode 100644 index 0f5cbf7293..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/evented_mongrel.rb +++ /dev/null @@ -1,8 +0,0 @@ -require 'swiftcore/evented_mongrel' - -module Rack - module Handler - class EventedMongrel < Handler::Mongrel - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/fastcgi.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/fastcgi.rb deleted file mode 100644 index 6324c7d274..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/fastcgi.rb +++ /dev/null @@ -1,89 +0,0 @@ -require 'fcgi' -require 'socket' -require 'rack/content_length' - -module Rack - module Handler - class FastCGI - def self.run(app, options={}) - file = options[:File] and STDIN.reopen(UNIXServer.new(file)) - port = options[:Port] and STDIN.reopen(TCPServer.new(port)) - FCGI.each { |request| - serve request, app - } - end - - module ProperStream # :nodoc: - def each # This is missing by default. - while line = gets - yield line - end - end - - def read(*args) - if args.empty? - super || "" # Empty string on EOF. - else - super - end - end - end - - def self.serve(request, app) - app = Rack::ContentLength.new(app) - - env = request.env - env.delete "HTTP_CONTENT_LENGTH" - - request.in.extend ProperStream - - env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" - - env.update({"rack.version" => [0,1], - "rack.input" => request.in, - "rack.errors" => request.err, - - "rack.multithread" => false, - "rack.multiprocess" => true, - "rack.run_once" => false, - - "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http" - }) - - env["QUERY_STRING"] ||= "" - env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] - env["REQUEST_PATH"] ||= "/" - env.delete "PATH_INFO" if env["PATH_INFO"] == "" - env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == "" - env.delete "CONTENT_LENGTH" if env["CONTENT_LENGTH"] == "" - - status, headers, body = app.call(env) - begin - send_headers request.out, status, headers - send_body request.out, body - ensure - body.close if body.respond_to? :close - request.finish - end - end - - def self.send_headers(out, status, headers) - out.print "Status: #{status}\r\n" - headers.each { |k, vs| - vs.split("\n").each { |v| - out.print "#{k}: #{v}\r\n" - } - } - out.print "\r\n" - out.flush - end - - def self.send_body(out, body) - body.each { |part| - out.print part - out.flush - } - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/lsws.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/lsws.rb deleted file mode 100644 index c65ba3ec8e..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/lsws.rb +++ /dev/null @@ -1,55 +0,0 @@ -require 'lsapi' -require 'rack/content_length' - -module Rack - module Handler - class LSWS - def self.run(app, options=nil) - while LSAPI.accept != nil - serve app - end - end - def self.serve(app) - app = Rack::ContentLength.new(app) - - env = ENV.to_hash - env.delete "HTTP_CONTENT_LENGTH" - env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" - env.update({"rack.version" => [0,1], - "rack.input" => StringIO.new($stdin.read.to_s), - "rack.errors" => $stderr, - "rack.multithread" => false, - "rack.multiprocess" => true, - "rack.run_once" => false, - "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" - }) - env["QUERY_STRING"] ||= "" - env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] - env["REQUEST_PATH"] ||= "/" - status, headers, body = app.call(env) - begin - send_headers status, headers - send_body body - ensure - body.close if body.respond_to? :close - end - end - def self.send_headers(status, headers) - print "Status: #{status}\r\n" - headers.each { |k, vs| - vs.split("\n").each { |v| - print "#{k}: #{v}\r\n" - } - } - print "\r\n" - STDOUT.flush - end - def self.send_body(body) - body.each { |part| - print part - STDOUT.flush - } - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/mongrel.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/mongrel.rb deleted file mode 100644 index f0c0d58330..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/mongrel.rb +++ /dev/null @@ -1,84 +0,0 @@ -require 'mongrel' -require 'stringio' -require 'rack/content_length' -require 'rack/chunked' - -module Rack - module Handler - class Mongrel < ::Mongrel::HttpHandler - def self.run(app, options={}) - server = ::Mongrel::HttpServer.new(options[:Host] || '0.0.0.0', - options[:Port] || 8080) - # Acts like Rack::URLMap, utilizing Mongrel's own path finding methods. - # Use is similar to #run, replacing the app argument with a hash of - # { path=>app, ... } or an instance of Rack::URLMap. - if options[:map] - if app.is_a? Hash - app.each do |path, appl| - path = '/'+path unless path[0] == ?/ - server.register(path, Rack::Handler::Mongrel.new(appl)) - end - elsif app.is_a? URLMap - app.instance_variable_get(:@mapping).each do |(host, path, appl)| - next if !host.nil? && !options[:Host].nil? && options[:Host] != host - path = '/'+path unless path[0] == ?/ - server.register(path, Rack::Handler::Mongrel.new(appl)) - end - else - raise ArgumentError, "first argument should be a Hash or URLMap" - end - else - server.register('/', Rack::Handler::Mongrel.new(app)) - end - yield server if block_given? - server.run.join - end - - def initialize(app) - @app = Rack::Chunked.new(Rack::ContentLength.new(app)) - end - - def process(request, response) - env = {}.replace(request.params) - env.delete "HTTP_CONTENT_TYPE" - env.delete "HTTP_CONTENT_LENGTH" - - env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" - - env.update({"rack.version" => [0,1], - "rack.input" => request.body || StringIO.new(""), - "rack.errors" => $stderr, - - "rack.multithread" => true, - "rack.multiprocess" => false, # ??? - "rack.run_once" => false, - - "rack.url_scheme" => "http", - }) - env["QUERY_STRING"] ||= "" - env.delete "PATH_INFO" if env["PATH_INFO"] == "" - - status, headers, body = @app.call(env) - - begin - response.status = status.to_i - response.send_status(nil) - - headers.each { |k, vs| - vs.split("\n").each { |v| - response.header[k] = v - } - } - response.send_header - - body.each { |part| - response.write part - response.socket.flush - } - ensure - body.close if body.respond_to? :close - end - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/scgi.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/scgi.rb deleted file mode 100644 index 9495c66374..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/scgi.rb +++ /dev/null @@ -1,59 +0,0 @@ -require 'scgi' -require 'stringio' -require 'rack/content_length' -require 'rack/chunked' - -module Rack - module Handler - class SCGI < ::SCGI::Processor - attr_accessor :app - - def self.run(app, options=nil) - new(options.merge(:app=>app, - :host=>options[:Host], - :port=>options[:Port], - :socket=>options[:Socket])).listen - end - - def initialize(settings = {}) - @app = Rack::Chunked.new(Rack::ContentLength.new(settings[:app])) - @log = Object.new - def @log.info(*args); end - def @log.error(*args); end - super(settings) - end - - def process_request(request, input_body, socket) - env = {}.replace(request) - env.delete "HTTP_CONTENT_TYPE" - env.delete "HTTP_CONTENT_LENGTH" - env["REQUEST_PATH"], env["QUERY_STRING"] = env["REQUEST_URI"].split('?', 2) - env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] - env["PATH_INFO"] = env["REQUEST_PATH"] - env["QUERY_STRING"] ||= "" - env["SCRIPT_NAME"] = "" - env.update({"rack.version" => [0,1], - "rack.input" => StringIO.new(input_body), - "rack.errors" => $stderr, - - "rack.multithread" => true, - "rack.multiprocess" => true, - "rack.run_once" => false, - - "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http" - }) - status, headers, body = app.call(env) - begin - socket.write("Status: #{status}\r\n") - headers.each do |k, vs| - vs.split("\n").each { |v| socket.write("#{k}: #{v}\r\n")} - end - socket.write("\r\n") - body.each {|s| socket.write(s)} - ensure - body.close if body.respond_to? :close - end - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/swiftiplied_mongrel.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/swiftiplied_mongrel.rb deleted file mode 100644 index 4bafd0b953..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/swiftiplied_mongrel.rb +++ /dev/null @@ -1,8 +0,0 @@ -require 'swiftcore/swiftiplied_mongrel' - -module Rack - module Handler - class SwiftipliedMongrel < Handler::Mongrel - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/thin.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/thin.rb deleted file mode 100644 index 3d4fedff75..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/thin.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "thin" -require "rack/content_length" -require "rack/chunked" - -module Rack - module Handler - class Thin - def self.run(app, options={}) - app = Rack::Chunked.new(Rack::ContentLength.new(app)) - server = ::Thin::Server.new(options[:Host] || '0.0.0.0', - options[:Port] || 8080, - app) - yield server if block_given? - server.start - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/webrick.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/webrick.rb deleted file mode 100644 index 829e7d6bf8..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/webrick.rb +++ /dev/null @@ -1,67 +0,0 @@ -require 'webrick' -require 'stringio' -require 'rack/content_length' - -module Rack - module Handler - class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet - def self.run(app, options={}) - server = ::WEBrick::HTTPServer.new(options) - server.mount "/", Rack::Handler::WEBrick, app - trap(:INT) { server.shutdown } - yield server if block_given? - server.start - end - - def initialize(server, app) - super server - @app = Rack::ContentLength.new(app) - end - - def service(req, res) - env = req.meta_vars - env.delete_if { |k, v| v.nil? } - - env.update({"rack.version" => [0,1], - "rack.input" => StringIO.new(req.body.to_s), - "rack.errors" => $stderr, - - "rack.multithread" => true, - "rack.multiprocess" => false, - "rack.run_once" => false, - - "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" - }) - - env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] - env["QUERY_STRING"] ||= "" - env["REQUEST_PATH"] ||= "/" - if env["PATH_INFO"] == "" - env.delete "PATH_INFO" - else - path, n = req.request_uri.path, env["SCRIPT_NAME"].length - env["PATH_INFO"] = path[n, path.length-n] - end - - status, headers, body = @app.call(env) - begin - res.status = status.to_i - headers.each { |k, vs| - if k.downcase == "set-cookie" - res.cookies.concat vs.split("\n") - else - vs.split("\n").each { |v| - res[k] = v - } - end - } - body.each { |part| - res.body << part - } - ensure - body.close if body.respond_to? :close - end - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/head.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/head.rb deleted file mode 100644 index deab822a99..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/head.rb +++ /dev/null @@ -1,19 +0,0 @@ -module Rack - -class Head - def initialize(app) - @app = app - end - - def call(env) - status, headers, body = @app.call(env) - - if env["REQUEST_METHOD"] == "HEAD" - [status, headers, []] - else - [status, headers, body] - end - end -end - -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lint.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lint.rb deleted file mode 100644 index 44a33ce36e..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lint.rb +++ /dev/null @@ -1,462 +0,0 @@ -require 'rack/utils' - -module Rack - # Rack::Lint validates your application and the requests and - # responses according to the Rack spec. - - class Lint - def initialize(app) - @app = app - end - - # :stopdoc: - - class LintError < RuntimeError; end - module Assertion - def assert(message, &block) - unless block.call - raise LintError, message - end - end - end - include Assertion - - ## This specification aims to formalize the Rack protocol. You - ## can (and should) use Rack::Lint to enforce it. - ## - ## When you develop middleware, be sure to add a Lint before and - ## after to catch all mistakes. - - ## = Rack applications - - ## A Rack application is an Ruby object (not a class) that - ## responds to +call+. - def call(env=nil) - dup._call(env) - end - - def _call(env) - ## It takes exactly one argument, the *environment* - assert("No env given") { env } - check_env env - - env['rack.input'] = InputWrapper.new(env['rack.input']) - env['rack.errors'] = ErrorWrapper.new(env['rack.errors']) - - ## and returns an Array of exactly three values: - status, headers, @body = @app.call(env) - ## The *status*, - check_status status - ## the *headers*, - check_headers headers - ## and the *body*. - check_content_type status, headers - check_content_length status, headers, env - [status, headers, self] - end - - ## == The Environment - def check_env(env) - ## The environment must be an true instance of Hash (no - ## subclassing allowed) that includes CGI-like headers. - ## The application is free to modify the environment. - assert("env #{env.inspect} is not a Hash, but #{env.class}") { - env.instance_of? Hash - } - - ## - ## The environment is required to include these variables - ## (adopted from PEP333), except when they'd be empty, but see - ## below. - - ## REQUEST_METHOD:: The HTTP request method, such as - ## "GET" or "POST". This cannot ever - ## be an empty string, and so is - ## always required. - - ## SCRIPT_NAME:: The initial portion of the request - ## URL's "path" that corresponds to the - ## application object, so that the - ## application knows its virtual - ## "location". This may be an empty - ## string, if the application corresponds - ## to the "root" of the server. - - ## PATH_INFO:: The remainder of the request URL's - ## "path", designating the virtual - ## "location" of the request's target - ## within the application. This may be an - ## empty string, if the request URL targets - ## the application root and does not have a - ## trailing slash. This information should be - ## decoded by the server if it comes from a - ## URL. - - ## QUERY_STRING:: The portion of the request URL that - ## follows the ?, if any. May be - ## empty, but is always required! - - ## SERVER_NAME, SERVER_PORT:: When combined with SCRIPT_NAME and PATH_INFO, these variables can be used to complete the URL. Note, however, that HTTP_HOST, if present, should be used in preference to SERVER_NAME for reconstructing the request URL. SERVER_NAME and SERVER_PORT can never be empty strings, and so are always required. - - ## HTTP_ Variables:: Variables corresponding to the - ## client-supplied HTTP request - ## headers (i.e., variables whose - ## names begin with HTTP_). The - ## presence or absence of these - ## variables should correspond with - ## the presence or absence of the - ## appropriate HTTP header in the - ## request. - - ## In addition to this, the Rack environment must include these - ## Rack-specific variables: - - ## rack.version:: The Array [0,1], representing this version of Rack. - ## rack.url_scheme:: +http+ or +https+, depending on the request URL. - ## rack.input:: See below, the input stream. - ## rack.errors:: See below, the error stream. - ## rack.multithread:: true if the application object may be simultaneously invoked by another thread in the same process, false otherwise. - ## rack.multiprocess:: true if an equivalent application object may be simultaneously invoked by another process, false otherwise. - ## rack.run_once:: true if the server expects (but does not guarantee!) that the application will only be invoked this one time during the life of its containing process. Normally, this will only be true for a server based on CGI (or something similar). - - ## The server or the application can store their own data in the - ## environment, too. The keys must contain at least one dot, - ## and should be prefixed uniquely. The prefix rack. - ## is reserved for use with the Rack core distribution and must - ## not be used otherwise. - ## - - %w[REQUEST_METHOD SERVER_NAME SERVER_PORT - QUERY_STRING - rack.version rack.input rack.errors - rack.multithread rack.multiprocess rack.run_once].each { |header| - assert("env missing required key #{header}") { env.include? header } - } - - ## The environment must not contain the keys - ## HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH - ## (use the versions without HTTP_). - %w[HTTP_CONTENT_TYPE HTTP_CONTENT_LENGTH].each { |header| - assert("env contains #{header}, must use #{header[5,-1]}") { - not env.include? header - } - } - - ## The CGI keys (named without a period) must have String values. - env.each { |key, value| - next if key.include? "." # Skip extensions - assert("env variable #{key} has non-string value #{value.inspect}") { - value.instance_of? String - } - } - - ## - ## There are the following restrictions: - - ## * rack.version must be an array of Integers. - assert("rack.version must be an Array, was #{env["rack.version"].class}") { - env["rack.version"].instance_of? Array - } - ## * rack.url_scheme must either be +http+ or +https+. - assert("rack.url_scheme unknown: #{env["rack.url_scheme"].inspect}") { - %w[http https].include? env["rack.url_scheme"] - } - - ## * There must be a valid input stream in rack.input. - check_input env["rack.input"] - ## * There must be a valid error stream in rack.errors. - check_error env["rack.errors"] - - ## * The REQUEST_METHOD must be a valid token. - assert("REQUEST_METHOD unknown: #{env["REQUEST_METHOD"]}") { - env["REQUEST_METHOD"] =~ /\A[0-9A-Za-z!\#$%&'*+.^_`|~-]+\z/ - } - - ## * The SCRIPT_NAME, if non-empty, must start with / - assert("SCRIPT_NAME must start with /") { - !env.include?("SCRIPT_NAME") || - env["SCRIPT_NAME"] == "" || - env["SCRIPT_NAME"] =~ /\A\// - } - ## * The PATH_INFO, if non-empty, must start with / - assert("PATH_INFO must start with /") { - !env.include?("PATH_INFO") || - env["PATH_INFO"] == "" || - env["PATH_INFO"] =~ /\A\// - } - ## * The CONTENT_LENGTH, if given, must consist of digits only. - assert("Invalid CONTENT_LENGTH: #{env["CONTENT_LENGTH"]}") { - !env.include?("CONTENT_LENGTH") || env["CONTENT_LENGTH"] =~ /\A\d+\z/ - } - - ## * One of SCRIPT_NAME or PATH_INFO must be - ## set. PATH_INFO should be / if - ## SCRIPT_NAME is empty. - assert("One of SCRIPT_NAME or PATH_INFO must be set (make PATH_INFO '/' if SCRIPT_NAME is empty)") { - env["SCRIPT_NAME"] || env["PATH_INFO"] - } - ## SCRIPT_NAME never should be /, but instead be empty. - assert("SCRIPT_NAME cannot be '/', make it '' and PATH_INFO '/'") { - env["SCRIPT_NAME"] != "/" - } - end - - ## === The Input Stream - def check_input(input) - ## The input stream must respond to +gets+, +each+ and +read+. - [:gets, :each, :read].each { |method| - assert("rack.input #{input} does not respond to ##{method}") { - input.respond_to? method - } - } - end - - class InputWrapper - include Assertion - - def initialize(input) - @input = input - end - - def size - @input.size - end - - def rewind - @input.rewind - end - - ## * +gets+ must be called without arguments and return a string, - ## or +nil+ on EOF. - def gets(*args) - assert("rack.input#gets called with arguments") { args.size == 0 } - v = @input.gets - assert("rack.input#gets didn't return a String") { - v.nil? or v.instance_of? String - } - v - end - - ## * +read+ must be called without or with one integer argument - ## and return a string, or +nil+ on EOF. - def read(*args) - assert("rack.input#read called with too many arguments") { - args.size <= 1 - } - if args.size == 1 - assert("rack.input#read called with non-integer argument") { - args.first.kind_of? Integer - } - end - v = @input.read(*args) - assert("rack.input#read didn't return a String") { - v.nil? or v.instance_of? String - } - v - end - - ## * +each+ must be called without arguments and only yield Strings. - def each(*args) - assert("rack.input#each called with arguments") { args.size == 0 } - @input.each { |line| - assert("rack.input#each didn't yield a String") { - line.instance_of? String - } - yield line - } - end - - ## * +close+ must never be called on the input stream. - def close(*args) - assert("rack.input#close must not be called") { false } - end - end - - ## === The Error Stream - def check_error(error) - ## The error stream must respond to +puts+, +write+ and +flush+. - [:puts, :write, :flush].each { |method| - assert("rack.error #{error} does not respond to ##{method}") { - error.respond_to? method - } - } - end - - class ErrorWrapper - include Assertion - - def initialize(error) - @error = error - end - - ## * +puts+ must be called with a single argument that responds to +to_s+. - def puts(str) - @error.puts str - end - - ## * +write+ must be called with a single argument that is a String. - def write(str) - assert("rack.errors#write not called with a String") { str.instance_of? String } - @error.write str - end - - ## * +flush+ must be called without arguments and must be called - ## in order to make the error appear for sure. - def flush - @error.flush - end - - ## * +close+ must never be called on the error stream. - def close(*args) - assert("rack.errors#close must not be called") { false } - end - end - - ## == The Response - - ## === The Status - def check_status(status) - ## The status, if parsed as integer (+to_i+), must be greater than or equal to 100. - assert("Status must be >=100 seen as integer") { status.to_i >= 100 } - end - - ## === The Headers - def check_headers(header) - ## The header must respond to each, and yield values of key and value. - assert("headers object should respond to #each, but doesn't (got #{header.class} as headers)") { - header.respond_to? :each - } - header.each { |key, value| - ## The header keys must be Strings. - assert("header key must be a string, was #{key.class}") { - key.instance_of? String - } - ## The header must not contain a +Status+ key, - assert("header must not contain Status") { key.downcase != "status" } - ## contain keys with : or newlines in their name, - assert("header names must not contain : or \\n") { key !~ /[:\n]/ } - ## contain keys names that end in - or _, - assert("header names must not end in - or _") { key !~ /[-_]\z/ } - ## but only contain keys that consist of - ## letters, digits, _ or - and start with a letter. - assert("invalid header name: #{key}") { key =~ /\A[a-zA-Z][a-zA-Z0-9_-]*\z/ } - - ## The values of the header must be Strings, - assert("a header value must be a String, but the value of " + - "'#{key}' is a #{value.class}") { value.kind_of? String } - ## consisting of lines (for multiple header values) seperated by "\n". - value.split("\n").each { |item| - ## The lines must not contain characters below 037. - assert("invalid header value #{key}: #{item.inspect}") { - item !~ /[\000-\037]/ - } - } - } - end - - ## === The Content-Type - def check_content_type(status, headers) - headers.each { |key, value| - ## There must be a Content-Type, except when the - ## +Status+ is 1xx, 204 or 304, in which case there must be none - ## given. - if key.downcase == "content-type" - assert("Content-Type header found in #{status} response, not allowed") { - not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i - } - return - end - } - assert("No Content-Type header found") { - Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i - } - end - - ## === The Content-Length - def check_content_length(status, headers, env) - headers.each { |key, value| - if key.downcase == 'content-length' - ## There must not be a Content-Length header when the - ## +Status+ is 1xx, 204 or 304. - assert("Content-Length header found in #{status} response, not allowed") { - not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i - } - - bytes = 0 - string_body = true - - if @body.respond_to?(:to_ary) - @body.each { |part| - unless part.kind_of?(String) - string_body = false - break - end - - bytes += Rack::Utils.bytesize(part) - } - - if env["REQUEST_METHOD"] == "HEAD" - assert("Response body was given for HEAD request, but should be empty") { - bytes == 0 - } - else - if string_body - assert("Content-Length header was #{value}, but should be #{bytes}") { - value == bytes.to_s - } - end - end - end - - return - end - } - end - - ## === The Body - def each - @closed = false - ## The Body must respond to #each - @body.each { |part| - ## and must only yield String values. - assert("Body yielded non-string value #{part.inspect}") { - part.instance_of? String - } - yield part - } - ## - ## If the Body responds to #close, it will be called after iteration. - # XXX howto: assert("Body has not been closed") { @closed } - - - ## - ## If the Body responds to #to_path, it must return a String - ## identifying the location of a file whose contents are identical - ## to that produced by calling #each. - - if @body.respond_to?(:to_path) - assert("The file identified by body.to_path does not exist") { - ::File.exist? @body.to_path - } - end - - ## - ## The Body commonly is an Array of Strings, the application - ## instance itself, or a File-like object. - end - - def close - @closed = true - @body.close if @body.respond_to?(:close) - end - - # :startdoc: - - end -end - -## == Thanks -## Some parts of this specification are adopted from PEP333: Python -## Web Server Gateway Interface -## v1.0 (http://www.python.org/dev/peps/pep-0333/). I'd like to thank -## everyone involved in that effort. diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lobster.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lobster.rb deleted file mode 100644 index f63f419a49..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lobster.rb +++ /dev/null @@ -1,65 +0,0 @@ -require 'zlib' - -require 'rack/request' -require 'rack/response' - -module Rack - # Paste has a Pony, Rack has a Lobster! - class Lobster - LobsterString = Zlib::Inflate.inflate("eJx9kEEOwyAMBO99xd7MAcytUhPlJyj2 - P6jy9i4k9EQyGAnBarEXeCBqSkntNXsi/ZCvC48zGQoZKikGrFMZvgS5ZHd+aGWVuWwhVF0 - t1drVmiR42HcWNz5w3QanT+2gIvTVCiE1lm1Y0eU4JGmIIbaKwextKn8rvW+p5PIwFl8ZWJ - I8jyiTlhTcYXkekJAzTyYN6E08A+dk8voBkAVTJQ==".delete("\n ").unpack("m*")[0]) - - LambdaLobster = lambda { |env| - if env["QUERY_STRING"].include?("flip") - lobster = LobsterString.split("\n"). - map { |line| line.ljust(42).reverse }. - join("\n") - href = "?" - else - lobster = LobsterString - href = "?flip" - end - - content = ["Lobstericious!", - "
", lobster, "
", - "flip!"] - length = content.inject(0) { |a,e| a+e.size }.to_s - [200, {"Content-Type" => "text/html", "Content-Length" => length}, content] - } - - def call(env) - req = Request.new(env) - if req.GET["flip"] == "left" - lobster = LobsterString.split("\n"). - map { |line| line.ljust(42).reverse }. - join("\n") - href = "?flip=right" - elsif req.GET["flip"] == "crash" - raise "Lobster crashed" - else - lobster = LobsterString - href = "?flip=left" - end - - res = Response.new - res.write "Lobstericious!" - res.write "
"
-      res.write lobster
-      res.write "
" - res.write "

flip!

" - res.write "

crash!

" - res.finish - end - - end -end - -if $0 == __FILE__ - require 'rack' - require 'rack/showexceptions' - Rack::Handler::WEBrick.run \ - Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), - :Port => 9292 -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lock.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lock.rb deleted file mode 100644 index 93238528c4..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lock.rb +++ /dev/null @@ -1,16 +0,0 @@ -module Rack - 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_dispatch/vendor/rack-1.0/rack/methodoverride.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/methodoverride.rb deleted file mode 100644 index 0eed29f471..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/methodoverride.rb +++ /dev/null @@ -1,27 +0,0 @@ -module Rack - class MethodOverride - HTTP_METHODS = %w(GET HEAD PUT POST DELETE OPTIONS) - - METHOD_OVERRIDE_PARAM_KEY = "_method".freeze - HTTP_METHOD_OVERRIDE_HEADER = "HTTP_X_HTTP_METHOD_OVERRIDE".freeze - - def initialize(app) - @app = app - end - - def call(env) - if env["REQUEST_METHOD"] == "POST" - req = Request.new(env) - method = req.POST[METHOD_OVERRIDE_PARAM_KEY] || - env[HTTP_METHOD_OVERRIDE_HEADER] - method = method.to_s.upcase - if HTTP_METHODS.include?(method) - env["rack.methodoverride.original_method"] = env["REQUEST_METHOD"] - env["REQUEST_METHOD"] = method - end - end - - @app.call(env) - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/mime.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/mime.rb deleted file mode 100644 index 5a6a73a97b..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/mime.rb +++ /dev/null @@ -1,204 +0,0 @@ -module Rack - module Mime - # Returns String with mime type if found, otherwise use +fallback+. - # +ext+ should be filename extension in the '.ext' format that - # File.extname(file) returns. - # +fallback+ may be any object - # - # Also see the documentation for MIME_TYPES - # - # Usage: - # Rack::Mime.mime_type('.foo') - # - # This is a shortcut for: - # Rack::Mime::MIME_TYPES.fetch('.foo', 'application/octet-stream') - - def mime_type(ext, fallback='application/octet-stream') - MIME_TYPES.fetch(ext, fallback) - end - module_function :mime_type - - # List of most common mime-types, selected various sources - # according to their usefulness in a webserving scope for Ruby - # users. - # - # To amend this list with your local mime.types list you can use: - # - # require 'webrick/httputils' - # list = WEBrick::HTTPUtils.load_mime_types('/etc/mime.types') - # Rack::Mime::MIME_TYPES.merge!(list) - # - # To add the list mongrel provides, use: - # - # require 'mongrel/handlers' - # Rack::Mime::MIME_TYPES.merge!(Mongrel::DirHandler::MIME_TYPES) - - MIME_TYPES = { - ".3gp" => "video/3gpp", - ".a" => "application/octet-stream", - ".ai" => "application/postscript", - ".aif" => "audio/x-aiff", - ".aiff" => "audio/x-aiff", - ".asc" => "application/pgp-signature", - ".asf" => "video/x-ms-asf", - ".asm" => "text/x-asm", - ".asx" => "video/x-ms-asf", - ".atom" => "application/atom+xml", - ".au" => "audio/basic", - ".avi" => "video/x-msvideo", - ".bat" => "application/x-msdownload", - ".bin" => "application/octet-stream", - ".bmp" => "image/bmp", - ".bz2" => "application/x-bzip2", - ".c" => "text/x-c", - ".cab" => "application/vnd.ms-cab-compressed", - ".cc" => "text/x-c", - ".chm" => "application/vnd.ms-htmlhelp", - ".class" => "application/octet-stream", - ".com" => "application/x-msdownload", - ".conf" => "text/plain", - ".cpp" => "text/x-c", - ".crt" => "application/x-x509-ca-cert", - ".css" => "text/css", - ".csv" => "text/csv", - ".cxx" => "text/x-c", - ".deb" => "application/x-debian-package", - ".der" => "application/x-x509-ca-cert", - ".diff" => "text/x-diff", - ".djv" => "image/vnd.djvu", - ".djvu" => "image/vnd.djvu", - ".dll" => "application/x-msdownload", - ".dmg" => "application/octet-stream", - ".doc" => "application/msword", - ".dot" => "application/msword", - ".dtd" => "application/xml-dtd", - ".dvi" => "application/x-dvi", - ".ear" => "application/java-archive", - ".eml" => "message/rfc822", - ".eps" => "application/postscript", - ".exe" => "application/x-msdownload", - ".f" => "text/x-fortran", - ".f77" => "text/x-fortran", - ".f90" => "text/x-fortran", - ".flv" => "video/x-flv", - ".for" => "text/x-fortran", - ".gem" => "application/octet-stream", - ".gemspec" => "text/x-script.ruby", - ".gif" => "image/gif", - ".gz" => "application/x-gzip", - ".h" => "text/x-c", - ".hh" => "text/x-c", - ".htm" => "text/html", - ".html" => "text/html", - ".ico" => "image/vnd.microsoft.icon", - ".ics" => "text/calendar", - ".ifb" => "text/calendar", - ".iso" => "application/octet-stream", - ".jar" => "application/java-archive", - ".java" => "text/x-java-source", - ".jnlp" => "application/x-java-jnlp-file", - ".jpeg" => "image/jpeg", - ".jpg" => "image/jpeg", - ".js" => "application/javascript", - ".json" => "application/json", - ".log" => "text/plain", - ".m3u" => "audio/x-mpegurl", - ".m4v" => "video/mp4", - ".man" => "text/troff", - ".mathml" => "application/mathml+xml", - ".mbox" => "application/mbox", - ".mdoc" => "text/troff", - ".me" => "text/troff", - ".mid" => "audio/midi", - ".midi" => "audio/midi", - ".mime" => "message/rfc822", - ".mml" => "application/mathml+xml", - ".mng" => "video/x-mng", - ".mov" => "video/quicktime", - ".mp3" => "audio/mpeg", - ".mp4" => "video/mp4", - ".mp4v" => "video/mp4", - ".mpeg" => "video/mpeg", - ".mpg" => "video/mpeg", - ".ms" => "text/troff", - ".msi" => "application/x-msdownload", - ".odp" => "application/vnd.oasis.opendocument.presentation", - ".ods" => "application/vnd.oasis.opendocument.spreadsheet", - ".odt" => "application/vnd.oasis.opendocument.text", - ".ogg" => "application/ogg", - ".p" => "text/x-pascal", - ".pas" => "text/x-pascal", - ".pbm" => "image/x-portable-bitmap", - ".pdf" => "application/pdf", - ".pem" => "application/x-x509-ca-cert", - ".pgm" => "image/x-portable-graymap", - ".pgp" => "application/pgp-encrypted", - ".pkg" => "application/octet-stream", - ".pl" => "text/x-script.perl", - ".pm" => "text/x-script.perl-module", - ".png" => "image/png", - ".pnm" => "image/x-portable-anymap", - ".ppm" => "image/x-portable-pixmap", - ".pps" => "application/vnd.ms-powerpoint", - ".ppt" => "application/vnd.ms-powerpoint", - ".ps" => "application/postscript", - ".psd" => "image/vnd.adobe.photoshop", - ".py" => "text/x-script.python", - ".qt" => "video/quicktime", - ".ra" => "audio/x-pn-realaudio", - ".rake" => "text/x-script.ruby", - ".ram" => "audio/x-pn-realaudio", - ".rar" => "application/x-rar-compressed", - ".rb" => "text/x-script.ruby", - ".rdf" => "application/rdf+xml", - ".roff" => "text/troff", - ".rpm" => "application/x-redhat-package-manager", - ".rss" => "application/rss+xml", - ".rtf" => "application/rtf", - ".ru" => "text/x-script.ruby", - ".s" => "text/x-asm", - ".sgm" => "text/sgml", - ".sgml" => "text/sgml", - ".sh" => "application/x-sh", - ".sig" => "application/pgp-signature", - ".snd" => "audio/basic", - ".so" => "application/octet-stream", - ".svg" => "image/svg+xml", - ".svgz" => "image/svg+xml", - ".swf" => "application/x-shockwave-flash", - ".t" => "text/troff", - ".tar" => "application/x-tar", - ".tbz" => "application/x-bzip-compressed-tar", - ".tcl" => "application/x-tcl", - ".tex" => "application/x-tex", - ".texi" => "application/x-texinfo", - ".texinfo" => "application/x-texinfo", - ".text" => "text/plain", - ".tif" => "image/tiff", - ".tiff" => "image/tiff", - ".torrent" => "application/x-bittorrent", - ".tr" => "text/troff", - ".txt" => "text/plain", - ".vcf" => "text/x-vcard", - ".vcs" => "text/x-vcalendar", - ".vrml" => "model/vrml", - ".war" => "application/java-archive", - ".wav" => "audio/x-wav", - ".wma" => "audio/x-ms-wma", - ".wmv" => "video/x-ms-wmv", - ".wmx" => "video/x-ms-wmx", - ".wrl" => "model/vrml", - ".wsdl" => "application/wsdl+xml", - ".xbm" => "image/x-xbitmap", - ".xhtml" => "application/xhtml+xml", - ".xls" => "application/vnd.ms-excel", - ".xml" => "application/xml", - ".xpm" => "image/x-xpixmap", - ".xsl" => "application/xml", - ".xslt" => "application/xslt+xml", - ".yaml" => "text/yaml", - ".yml" => "text/yaml", - ".zip" => "application/zip", - } - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/mock.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/mock.rb deleted file mode 100644 index 70852da3db..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/mock.rb +++ /dev/null @@ -1,160 +0,0 @@ -require 'uri' -require 'stringio' -require 'rack/lint' -require 'rack/utils' -require 'rack/response' - -module Rack - # Rack::MockRequest helps testing your Rack application without - # actually using HTTP. - # - # After performing a request on a URL with get/post/put/delete, it - # returns a MockResponse with useful helper methods for effective - # testing. - # - # You can pass a hash with additional configuration to the - # get/post/put/delete. - # :input:: A String or IO-like to be used as rack.input. - # :fatal:: Raise a FatalWarning if the app writes to rack.errors. - # :lint:: If true, wrap the application in a Rack::Lint. - - class MockRequest - class FatalWarning < RuntimeError - end - - class FatalWarner - def puts(warning) - raise FatalWarning, warning - end - - def write(warning) - raise FatalWarning, warning - end - - def flush - end - - def string - "" - end - end - - DEFAULT_ENV = { - "rack.version" => [0,1], - "rack.input" => StringIO.new, - "rack.errors" => StringIO.new, - "rack.multithread" => true, - "rack.multiprocess" => true, - "rack.run_once" => false, - } - - def initialize(app) - @app = app - end - - def get(uri, opts={}) request("GET", uri, opts) end - def post(uri, opts={}) request("POST", uri, opts) end - def put(uri, opts={}) request("PUT", uri, opts) end - def delete(uri, opts={}) request("DELETE", uri, opts) end - - def request(method="GET", uri="", opts={}) - env = self.class.env_for(uri, opts.merge(:method => method)) - - if opts[:lint] - app = Rack::Lint.new(@app) - else - app = @app - end - - errors = env["rack.errors"] - MockResponse.new(*(app.call(env) + [errors])) - end - - # Return the Rack environment used for a request to +uri+. - def self.env_for(uri="", opts={}) - uri = URI(uri) - env = DEFAULT_ENV.dup - - env["REQUEST_METHOD"] = opts[:method] || "GET" - env["SERVER_NAME"] = uri.host || "example.org" - env["SERVER_PORT"] = uri.port ? uri.port.to_s : "80" - env["QUERY_STRING"] = uri.query.to_s - env["PATH_INFO"] = (!uri.path || uri.path.empty?) ? "/" : uri.path - env["rack.url_scheme"] = uri.scheme || "http" - - env["SCRIPT_NAME"] = opts[:script_name] || "" - - if opts[:fatal] - env["rack.errors"] = FatalWarner.new - else - env["rack.errors"] = StringIO.new - end - - opts[:input] ||= "" - if String === opts[:input] - env["rack.input"] = StringIO.new(opts[:input]) - else - env["rack.input"] = opts[:input] - end - - env["CONTENT_LENGTH"] ||= env["rack.input"].length.to_s - - opts.each { |field, value| - env[field] = value if String === field - } - - env - end - end - - # Rack::MockResponse provides useful helpers for testing your apps. - # Usually, you don't create the MockResponse on your own, but use - # MockRequest. - - class MockResponse - def initialize(status, headers, body, errors=StringIO.new("")) - @status = status.to_i - - @original_headers = headers - @headers = Rack::Utils::HeaderHash.new - headers.each { |field, values| - @headers[field] = values - @headers[field] = "" if values.empty? - } - - @body = "" - body.each { |part| @body << part } - - @errors = errors.string - end - - # Status - attr_reader :status - - # Headers - attr_reader :headers, :original_headers - - def [](field) - headers[field] - end - - - # Body - attr_reader :body - - def =~(other) - @body =~ other - end - - def match(other) - @body.match other - end - - - # Errors - attr_accessor :errors - - - include Response::Helpers - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/recursive.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/recursive.rb deleted file mode 100644 index bf8b965925..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/recursive.rb +++ /dev/null @@ -1,57 +0,0 @@ -require 'uri' - -module Rack - # Rack::ForwardRequest gets caught by Rack::Recursive and redirects - # the current request to the app at +url+. - # - # raise ForwardRequest.new("/not-found") - # - - class ForwardRequest < Exception - attr_reader :url, :env - - def initialize(url, env={}) - @url = URI(url) - @env = env - - @env["PATH_INFO"] = @url.path - @env["QUERY_STRING"] = @url.query if @url.query - @env["HTTP_HOST"] = @url.host if @url.host - @env["HTTP_PORT"] = @url.port if @url.port - @env["rack.url_scheme"] = @url.scheme if @url.scheme - - super "forwarding to #{url}" - end - end - - # Rack::Recursive allows applications called down the chain to - # include data from other applications (by using - # rack['rack.recursive.include'][...] or raise a - # ForwardRequest to redirect internally. - - class Recursive - def initialize(app) - @app = app - end - - def call(env) - @script_name = env["SCRIPT_NAME"] - @app.call(env.merge('rack.recursive.include' => method(:include))) - rescue ForwardRequest => req - call(env.merge(req.env)) - end - - def include(env, path) - unless path.index(@script_name) == 0 && (path[@script_name.size] == ?/ || - path[@script_name.size].nil?) - raise ArgumentError, "can only include below #{@script_name}, not #{path}" - end - - env = env.merge("PATH_INFO" => path, "SCRIPT_NAME" => @script_name, - "REQUEST_METHOD" => "GET", - "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "", - "rack.input" => StringIO.new("")) - @app.call(env) - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/reloader.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/reloader.rb deleted file mode 100644 index b17d8c0926..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/reloader.rb +++ /dev/null @@ -1,64 +0,0 @@ -require 'thread' - -module Rack - # Rack::Reloader checks on every request, but at most every +secs+ - # seconds, if a file loaded changed, and reloads it, logging to - # rack.errors. - # - # It is recommended you use ShowExceptions to catch SyntaxErrors etc. - - class Reloader - def initialize(app, secs=10) - @app = app - @secs = secs # reload every @secs seconds max - @last = Time.now - end - - def call(env) - if Time.now > @last + @secs - Thread.exclusive { - reload!(env['rack.errors']) - @last = Time.now - } - end - - @app.call(env) - end - - def reload!(stderr=$stderr) - need_reload = $LOADED_FEATURES.find_all { |loaded| - begin - if loaded =~ /\A[.\/]/ # absolute filename or 1.9 - abs = loaded - else - abs = $LOAD_PATH.map { |path| ::File.join(path, loaded) }. - find { |file| ::File.exist? file } - end - - if abs - ::File.mtime(abs) > @last - @secs rescue false - else - false - end - end - } - - need_reload.each { |l| - $LOADED_FEATURES.delete l - } - - need_reload.each { |to_load| - begin - if require to_load - stderr.puts "#{self.class}: reloaded `#{to_load}'" - end - rescue LoadError, SyntaxError => e - raise e # Possibly ShowExceptions - end - } - - stderr.flush - need_reload - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/request.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/request.rb deleted file mode 100644 index d77fa26575..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/request.rb +++ /dev/null @@ -1,241 +0,0 @@ -require 'rack/utils' - -module Rack - # Rack::Request provides a convenient interface to a Rack - # environment. It is stateless, the environment +env+ passed to the - # constructor will be directly modified. - # - # req = Rack::Request.new(env) - # req.post? - # req.params["data"] - # - # The environment hash passed will store a reference to the Request object - # instantiated so that it will only instantiate if an instance of the Request - # object doesn't already exist. - - class Request - # The environment of the request. - attr_reader :env - - def self.new(env) - if self == Rack::Request - env["rack.request"] ||= super - else - super - end - end - - def initialize(env) - @env = env - end - - def body; @env["rack.input"] end - def scheme; @env["rack.url_scheme"] end - def script_name; @env["SCRIPT_NAME"].to_s end - def path_info; @env["PATH_INFO"].to_s end - def port; @env["SERVER_PORT"].to_i end - def request_method; @env["REQUEST_METHOD"] end - def query_string; @env["QUERY_STRING"].to_s end - def content_length; @env['CONTENT_LENGTH'] end - def content_type; @env['CONTENT_TYPE'] end - - # The media type (type/subtype) portion of the CONTENT_TYPE header - # without any media type parameters. e.g., when CONTENT_TYPE is - # "text/plain;charset=utf-8", the media-type is "text/plain". - # - # For more information on the use of media types in HTTP, see: - # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7 - def media_type - content_type && content_type.split(/\s*[;,]\s*/, 2)[0].downcase - end - - # The media type parameters provided in CONTENT_TYPE as a Hash, or - # an empty Hash if no CONTENT_TYPE or media-type parameters were - # provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8", - # this method responds with the following Hash: - # { 'charset' => 'utf-8' } - def media_type_params - return {} if content_type.nil? - content_type.split(/\s*[;,]\s*/)[1..-1]. - collect { |s| s.split('=', 2) }. - inject({}) { |hash,(k,v)| hash[k.downcase] = v ; hash } - end - - # The character set of the request body if a "charset" media type - # parameter was given, or nil if no "charset" was specified. Note - # that, per RFC2616, text/* media types that specify no explicit - # charset are to be considered ISO-8859-1. - def content_charset - media_type_params['charset'] - end - - def host - # Remove port number. - (@env["HTTP_HOST"] || @env["SERVER_NAME"]).gsub(/:\d+\z/, '') - end - - def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end - def path_info=(s); @env["PATH_INFO"] = s.to_s end - - def get?; request_method == "GET" end - def post?; request_method == "POST" end - def put?; request_method == "PUT" end - def delete?; request_method == "DELETE" end - def head?; request_method == "HEAD" end - - # The set of form-data media-types. Requests that do not indicate - # one of the media types presents in this list will not be eligible - # for form-data / param parsing. - FORM_DATA_MEDIA_TYPES = [ - nil, - 'application/x-www-form-urlencoded', - 'multipart/form-data' - ] - - # Determine whether the request body contains form-data by checking - # the request media_type against registered form-data media-types: - # "application/x-www-form-urlencoded" and "multipart/form-data". The - # list of form-data media types can be modified through the - # +FORM_DATA_MEDIA_TYPES+ array. - def form_data? - FORM_DATA_MEDIA_TYPES.include?(media_type) - end - - # Returns the data recieved in the query string. - def GET - if @env["rack.request.query_string"] == query_string - @env["rack.request.query_hash"] - else - @env["rack.request.query_string"] = query_string - @env["rack.request.query_hash"] = - Utils.parse_nested_query(query_string) - end - end - - # Returns the data recieved in the request body. - # - # This method support both application/x-www-form-urlencoded and - # multipart/form-data. - def POST - if @env["rack.request.form_input"].eql? @env["rack.input"] - @env["rack.request.form_hash"] - elsif form_data? - @env["rack.request.form_input"] = @env["rack.input"] - unless @env["rack.request.form_hash"] = - Utils::Multipart.parse_multipart(env) - form_vars = @env["rack.input"].read - - # Fix for Safari Ajax postings that always append \0 - form_vars.sub!(/\0\z/, '') - - @env["rack.request.form_vars"] = form_vars - @env["rack.request.form_hash"] = Utils.parse_nested_query(form_vars) - - begin - @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 - end - @env["rack.request.form_hash"] - else - {} - end - end - - # The union of GET and POST data. - def params - self.put? ? self.GET : self.GET.update(self.POST) - rescue EOFError => e - self.GET - end - - # shortcut for request.params[key] - def [](key) - params[key.to_s] - end - - # shortcut for request.params[key] = value - def []=(key, value) - params[key.to_s] = value - end - - # like Hash#values_at - def values_at(*keys) - keys.map{|key| params[key] } - end - - # the referer of the client or '/' - def referer - @env['HTTP_REFERER'] || '/' - end - alias referrer referer - - - def cookies - return {} unless @env["HTTP_COOKIE"] - - if @env["rack.request.cookie_string"] == @env["HTTP_COOKIE"] - @env["rack.request.cookie_hash"] - else - @env["rack.request.cookie_string"] = @env["HTTP_COOKIE"] - # According to RFC 2109: - # If multiple cookies satisfy the criteria above, they are ordered in - # the Cookie header such that those with more specific Path attributes - # precede those with less specific. Ordering with respect to other - # attributes (e.g., Domain) is unspecified. - @env["rack.request.cookie_hash"] = - Utils.parse_query(@env["rack.request.cookie_string"], ';,').inject({}) {|h,(k,v)| - h[k] = Array === v ? v.first : v - h - } - end - end - - def xhr? - @env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" - end - - # Tries to return a remake of the original request URL as a string. - def url - url = scheme + "://" - url << host - - if scheme == "https" && port != 443 || - scheme == "http" && port != 80 - url << ":#{port}" - end - - url << fullpath - - url - end - - def fullpath - path = script_name + path_info - path << "?" << query_string unless query_string.empty? - path - end - - def accept_encoding - @env["HTTP_ACCEPT_ENCODING"].to_s.split(/,\s*/).map do |part| - m = /^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$/.match(part) # From WEBrick - - if m - [m[1], (m[2] || 1.0).to_f] - else - raise "Invalid value for Accept-Encoding: #{part.inspect}" - end - end - end - - def ip - if addr = @env['HTTP_X_FORWARDED_FOR'] - addr.split(',').last.strip - else - @env['REMOTE_ADDR'] - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/response.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/response.rb deleted file mode 100644 index caf60d5b19..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/response.rb +++ /dev/null @@ -1,179 +0,0 @@ -require 'rack/request' -require 'rack/utils' - -module Rack - # Rack::Response provides a convenient interface to create a Rack - # response. - # - # It allows setting of headers and cookies, and provides useful - # defaults (a OK response containing HTML). - # - # You can use Response#write to iteratively generate your response, - # but note that this is buffered by Rack::Response until you call - # +finish+. +finish+ however can take a block inside which calls to - # +write+ are syncronous with the Rack response. - # - # Your application's +call+ should end returning Response#finish. - - class Response - attr_accessor :length - - def initialize(body=[], status=200, header={}, &block) - @status = status - @header = Utils::HeaderHash.new({"Content-Type" => "text/html"}. - merge(header)) - - @writer = lambda { |x| @body << x } - @block = nil - @length = 0 - - @body = [] - - if body.respond_to? :to_str - write body.to_str - elsif body.respond_to?(:each) - body.each { |part| - write part.to_s - } - else - raise TypeError, "stringable or iterable required" - end - - yield self if block_given? - end - - attr_reader :header - attr_accessor :status, :body - - def [](key) - header[key] - end - - def []=(key, value) - header[key] = value - end - - def set_cookie(key, value) - case value - when Hash - domain = "; domain=" + value[:domain] if value[:domain] - path = "; path=" + value[:path] if value[:path] - # According to RFC 2109, we need dashes here. - # N.B.: cgi.rb uses spaces... - expires = "; expires=" + value[:expires].clone.gmtime. - strftime("%a, %d-%b-%Y %H:%M:%S GMT") if value[:expires] - secure = "; secure" if value[:secure] - httponly = "; HttpOnly" if value[:httponly] - value = value[:value] - end - value = [value] unless Array === value - cookie = Utils.escape(key) + "=" + - value.map { |v| Utils.escape v }.join("&") + - "#{domain}#{path}#{expires}#{secure}#{httponly}" - - case self["Set-Cookie"] - when Array - self["Set-Cookie"] << cookie - when String - self["Set-Cookie"] = [self["Set-Cookie"], cookie] - when nil - self["Set-Cookie"] = cookie - end - end - - def delete_cookie(key, value={}) - unless Array === self["Set-Cookie"] - self["Set-Cookie"] = [self["Set-Cookie"]].compact - end - - self["Set-Cookie"].reject! { |cookie| - cookie =~ /\A#{Utils.escape(key)}=/ - } - - set_cookie(key, - {:value => '', :path => nil, :domain => nil, - :expires => Time.at(0) }.merge(value)) - end - - - def finish(&block) - @block = block - - if [204, 304].include?(status.to_i) - header.delete "Content-Type" - [status.to_i, header.to_hash, []] - else - [status.to_i, header.to_hash, self] - end - end - alias to_a finish # For *response - - def each(&callback) - @body.each(&callback) - @writer = callback - @block.call(self) if @block - end - - # Append to body and update Content-Length. - # - # NOTE: Do not mix #write and direct #body access! - # - def write(str) - s = str.to_s - @length += s.size - @writer.call s - - header["Content-Length"] = @length.to_s - str - end - - def close - body.close if body.respond_to?(:close) - end - - def empty? - @block == nil && @body.empty? - end - - alias headers header - - module Helpers - def invalid?; @status < 100 || @status >= 600; end - - def informational?; @status >= 100 && @status < 200; end - def successful?; @status >= 200 && @status < 300; end - def redirection?; @status >= 300 && @status < 400; end - def client_error?; @status >= 400 && @status < 500; end - def server_error?; @status >= 500 && @status < 600; end - - def ok?; @status == 200; end - def forbidden?; @status == 403; end - def not_found?; @status == 404; end - - def redirect?; [301, 302, 303, 307].include? @status; end - def empty?; [201, 204, 304].include? @status; end - - # Headers - attr_reader :headers, :original_headers - - def include?(header) - !!headers[header] - end - - def content_type - headers["Content-Type"] - end - - def content_length - cl = headers["Content-Length"] - cl ? cl.to_i : cl - end - - def location - headers["Location"] - end - end - - include Helpers - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/abstract/id.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/abstract/id.rb deleted file mode 100644 index 218144c17f..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/abstract/id.rb +++ /dev/null @@ -1,142 +0,0 @@ -# AUTHOR: blink ; blink#ruby-lang@irc.freenode.net -# bugrep: Andreas Zehnder - -require 'time' -require 'rack/request' -require 'rack/response' - -module Rack - - module Session - - module Abstract - - # ID sets up a basic framework for implementing an id based sessioning - # service. Cookies sent to the client for maintaining sessions will only - # contain an id reference. Only #get_session and #set_session are - # required to be overwritten. - # - # All parameters are optional. - # * :key determines the name of the cookie, by default it is - # 'rack.session' - # * :path, :domain, :expire_after, :secure, and :httponly set the related - # cookie options as by Rack::Response#add_cookie - # * :defer will not set a cookie in the response. - # * :renew (implementation dependent) will prompt the generation of a new - # session id, and migration of data to be referenced at the new id. If - # :defer is set, it will be overridden and the cookie will be set. - # * :sidbits sets the number of bits in length that a generated session - # id will be. - # - # These options can be set on a per request basis, at the location of - # env['rack.session.options']. Additionally the id of the session can be - # found within the options hash at the key :id. It is highly not - # recommended to change its value. - # - # Is Rack::Utils::Context compatible. - - class ID - DEFAULT_OPTIONS = { - :path => '/', - :domain => nil, - :expire_after => nil, - :secure => false, - :httponly => true, - :defer => false, - :renew => false, - :sidbits => 128 - } - - attr_reader :key, :default_options - def initialize(app, options={}) - @app = app - @key = options[:key] || "rack.session" - @default_options = self.class::DEFAULT_OPTIONS.merge(options) - end - - def call(env) - context(env) - end - - def context(env, app=@app) - load_session(env) - status, headers, body = app.call(env) - commit_session(env, status, headers, body) - end - - private - - # Generate a new session id using Ruby #rand. The size of the - # session id is controlled by the :sidbits option. - # Monkey patch this to use custom methods for session id generation. - - def generate_sid - "%0#{@default_options[:sidbits] / 4}x" % - rand(2**@default_options[:sidbits] - 1) - end - - # Extracts the session id from provided cookies and passes it and the - # environment to #get_session. It then sets the resulting session into - # 'rack.session', and places options and session metadata into - # 'rack.session.options'. - - def load_session(env) - request = Rack::Request.new(env) - session_id = request.cookies[@key] - - begin - session_id, session = get_session(env, session_id) - env['rack.session'] = session - rescue - env['rack.session'] = Hash.new - end - - env['rack.session.options'] = @default_options. - merge(:id => session_id) - end - - # Acquires the session from the environment and the session id from - # the session options and passes them to #set_session. If successful - # and the :defer option is not true, a cookie will be added to the - # response with the session's id. - - def commit_session(env, status, headers, body) - session = env['rack.session'] - options = env['rack.session.options'] - session_id = options[:id] - - if not session_id = set_session(env, session_id, session, options) - env["rack.errors"].puts("Warning! #{self.class.name} failed to save session. Content dropped.") - [status, headers, body] - elsif options[:defer] and not options[:renew] - env["rack.errors"].puts("Defering cookie for #{session_id}") if $VERBOSE - [status, headers, body] - else - cookie = Hash.new - cookie[:value] = session_id - cookie[:expires] = Time.now + options[:expire_after] unless options[:expire_after].nil? - response = Rack::Response.new(body, status, headers) - response.set_cookie(@key, cookie.merge(options)) - response.to_a - end - end - - # All thread safety and session retrival proceedures should occur here. - # Should return [session_id, session]. - # If nil is provided as the session id, generation of a new valid id - # should occur within. - - def get_session(env, sid) - raise '#get_session not implemented.' - end - - # All thread safety and session storage proceedures should occur here. - # Should return true or false dependant on whether or not the session - # was saved or not. - def set_session(env, sid, session, options) - raise '#set_session not implemented.' - end - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/cookie.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/cookie.rb deleted file mode 100644 index eace9bd0c6..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/cookie.rb +++ /dev/null @@ -1,91 +0,0 @@ -require 'openssl' -require 'rack/request' -require 'rack/response' - -module Rack - - module Session - - # Rack::Session::Cookie provides simple cookie based session management. - # The session is a Ruby Hash stored as base64 encoded marshalled data - # set to :key (default: rack.session). - # When the secret key is set, cookie data is checked for data integrity. - # - # Example: - # - # use Rack::Session::Cookie, :key => 'rack.session', - # :domain => 'foo.com', - # :path => '/', - # :expire_after => 2592000, - # :secret => 'change_me' - # - # All parameters are optional. - - class Cookie - - def initialize(app, options={}) - @app = app - @key = options[:key] || "rack.session" - @secret = options[:secret] - @default_options = {:domain => nil, - :path => "/", - :expire_after => nil}.merge(options) - end - - def call(env) - load_session(env) - status, headers, body = @app.call(env) - commit_session(env, status, headers, body) - end - - private - - def load_session(env) - request = Rack::Request.new(env) - session_data = request.cookies[@key] - - if @secret && session_data - session_data, digest = session_data.split("--") - session_data = nil unless digest == generate_hmac(session_data) - end - - begin - session_data = session_data.unpack("m*").first - session_data = Marshal.load(session_data) - env["rack.session"] = session_data - rescue - env["rack.session"] = Hash.new - end - - env["rack.session.options"] = @default_options.dup - end - - def commit_session(env, status, headers, body) - session_data = Marshal.dump(env["rack.session"]) - session_data = [session_data].pack("m*") - - if @secret - session_data = "#{session_data}--#{generate_hmac(session_data)}" - end - - if session_data.size > (4096 - @key.size) - env["rack.errors"].puts("Warning! Rack::Session::Cookie data size exceeds 4K. Content dropped.") - [status, headers, body] - else - options = env["rack.session.options"] - cookie = Hash.new - cookie[:value] = session_data - cookie[:expires] = Time.now + options[:expire_after] unless options[:expire_after].nil? - response = Rack::Response.new(body, status, headers) - response.set_cookie(@key, cookie.merge(options)) - response.to_a - end - end - - def generate_hmac(data) - OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, @secret, data) - end - - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/memcache.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/memcache.rb deleted file mode 100644 index 4a65cbf35d..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/memcache.rb +++ /dev/null @@ -1,109 +0,0 @@ -# AUTHOR: blink ; blink#ruby-lang@irc.freenode.net - -require 'rack/session/abstract/id' -require 'memcache' - -module Rack - module Session - # Rack::Session::Memcache provides simple cookie based session management. - # Session data is stored in memcached. The corresponding session key is - # maintained in the cookie. - # You may treat Session::Memcache as you would Session::Pool with the - # following caveats. - # - # * Setting :expire_after to 0 would note to the Memcache server to hang - # onto the session data until it would drop it according to it's own - # specifications. However, the cookie sent to the client would expire - # immediately. - # - # Note that memcache does drop data before it may be listed to expire. For - # a full description of behaviour, please see memcache's documentation. - - class Memcache < Abstract::ID - attr_reader :mutex, :pool - DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge \ - :namespace => 'rack:session', - :memcache_server => 'localhost:11211' - - def initialize(app, options={}) - super - - @mutex = Mutex.new - @pool = MemCache. - new @default_options[:memcache_server], @default_options - raise 'No memcache servers' unless @pool.servers.any?{|s|s.alive?} - end - - def generate_sid - loop do - sid = super - break sid unless @pool.get(sid, true) - end - end - - def get_session(env, sid) - session = @pool.get(sid) if sid - @mutex.lock if env['rack.multithread'] - unless sid and session - env['rack.errors'].puts("Session '#{sid.inspect}' not found, initializing...") if $VERBOSE and not sid.nil? - session = {} - sid = generate_sid - ret = @pool.add sid, session - raise "Session collision on '#{sid.inspect}'" unless /^STORED/ =~ ret - end - session.instance_variable_set('@old', {}.merge(session)) - return [sid, session] - rescue MemCache::MemCacheError, Errno::ECONNREFUSED # MemCache server cannot be contacted - warn "#{self} is unable to find server." - warn $!.inspect - return [ nil, {} ] - ensure - @mutex.unlock if env['rack.multithread'] - end - - def set_session(env, session_id, new_session, options) - expiry = options[:expire_after] - expiry = expiry.nil? ? 0 : expiry + 1 - - @mutex.lock if env['rack.multithread'] - session = @pool.get(session_id) || {} - if options[:renew] or options[:drop] - @pool.delete session_id - return false if options[:drop] - session_id = generate_sid - @pool.add session_id, 0 # so we don't worry about cache miss on #set - end - old_session = new_session.instance_variable_get('@old') || {} - session = merge_sessions session_id, old_session, new_session, session - @pool.set session_id, session, expiry - return session_id - rescue MemCache::MemCacheError, Errno::ECONNREFUSED # MemCache server cannot be contacted - warn "#{self} is unable to find server." - warn $!.inspect - return false - ensure - @mutex.unlock if env['rack.multithread'] - end - - private - - def merge_sessions sid, old, new, cur=nil - cur ||= {} - unless Hash === old and Hash === new - warn 'Bad old or new sessions provided.' - return cur - end - - delete = old.keys - new.keys - warn "//@#{sid}: delete #{delete*','}" if $VERBOSE and not delete.empty? - delete.each{|k| cur.delete k } - - update = new.keys.select{|k| new[k] != old[k] } - warn "//@#{sid}: update #{update*','}" if $VERBOSE and not update.empty? - update.each{|k| cur[k] = new[k] } - - cur - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/pool.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/pool.rb deleted file mode 100644 index f6f87408bb..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/pool.rb +++ /dev/null @@ -1,100 +0,0 @@ -# AUTHOR: blink ; blink#ruby-lang@irc.freenode.net -# THANKS: -# apeiros, for session id generation, expiry setup, and threadiness -# sergio, threadiness and bugreps - -require 'rack/session/abstract/id' -require 'thread' - -module Rack - module Session - # Rack::Session::Pool provides simple cookie based session management. - # Session data is stored in a hash held by @pool. - # In the context of a multithreaded environment, sessions being - # committed to the pool is done in a merging manner. - # - # The :drop option is available in rack.session.options if you with to - # explicitly remove the session from the session cache. - # - # Example: - # myapp = MyRackApp.new - # sessioned = Rack::Session::Pool.new(myapp, - # :domain => 'foo.com', - # :expire_after => 2592000 - # ) - # Rack::Handler::WEBrick.run sessioned - - class Pool < Abstract::ID - attr_reader :mutex, :pool - DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge :drop => false - - def initialize(app, options={}) - super - @pool = Hash.new - @mutex = Mutex.new - end - - def generate_sid - loop do - sid = super - break sid unless @pool.key? sid - end - end - - def get_session(env, sid) - session = @pool[sid] if sid - @mutex.lock if env['rack.multithread'] - unless sid and session - env['rack.errors'].puts("Session '#{sid.inspect}' not found, initializing...") if $VERBOSE and not sid.nil? - session = {} - sid = generate_sid - @pool.store sid, session - end - session.instance_variable_set('@old', {}.merge(session)) - return [sid, session] - ensure - @mutex.unlock if env['rack.multithread'] - end - - def set_session(env, session_id, new_session, options) - @mutex.lock if env['rack.multithread'] - session = @pool[session_id] - if options[:renew] or options[:drop] - @pool.delete session_id - return false if options[:drop] - session_id = generate_sid - @pool.store session_id, 0 - end - old_session = new_session.instance_variable_get('@old') || {} - session = merge_sessions session_id, old_session, new_session, session - @pool.store session_id, session - return session_id - rescue - warn "#{new_session.inspect} has been lost." - warn $!.inspect - ensure - @mutex.unlock if env['rack.multithread'] - end - - private - - def merge_sessions sid, old, new, cur=nil - cur ||= {} - unless Hash === old and Hash === new - warn 'Bad old or new sessions provided.' - return cur - end - - delete = old.keys - new.keys - warn "//@#{sid}: dropping #{delete*','}" if $DEBUG and not delete.empty? - delete.each{|k| cur.delete k } - - update = new.keys.select{|k| new[k] != old[k] } - warn "//@#{sid}: updating #{update*','}" if $DEBUG and not update.empty? - update.each{|k| cur[k] = new[k] } - - cur - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/showexceptions.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/showexceptions.rb deleted file mode 100644 index 697bc41fdb..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/showexceptions.rb +++ /dev/null @@ -1,349 +0,0 @@ -require 'ostruct' -require 'erb' -require 'rack/request' -require 'rack/utils' - -module Rack - # Rack::ShowExceptions catches all exceptions raised from the app it - # wraps. It shows a useful backtrace with the sourcefile and - # clickable context, the whole Rack environment and the request - # data. - # - # Be careful when you use this on public-facing sites as it could - # reveal information helpful to attackers. - - class ShowExceptions - CONTEXT = 7 - - def initialize(app) - @app = app - @template = ERB.new(TEMPLATE) - end - - def call(env) - @app.call(env) - rescue StandardError, LoadError, SyntaxError => e - backtrace = pretty(env, e) - [500, - {"Content-Type" => "text/html", - "Content-Length" => backtrace.join.size.to_s}, - backtrace] - end - - def pretty(env, exception) - req = Rack::Request.new(env) - path = (req.script_name + req.path_info).squeeze("/") - - frames = exception.backtrace.map { |line| - frame = OpenStruct.new - if line =~ /(.*?):(\d+)(:in `(.*)')?/ - frame.filename = $1 - frame.lineno = $2.to_i - frame.function = $4 - - begin - lineno = frame.lineno-1 - lines = ::File.readlines(frame.filename) - frame.pre_context_lineno = [lineno-CONTEXT, 0].max - frame.pre_context = lines[frame.pre_context_lineno...lineno] - frame.context_line = lines[lineno].chomp - frame.post_context_lineno = [lineno+CONTEXT, lines.size].min - frame.post_context = lines[lineno+1..frame.post_context_lineno] - rescue - end - - frame - else - nil - end - }.compact - - env["rack.errors"].puts "#{exception.class}: #{exception.message}" - env["rack.errors"].puts exception.backtrace.map { |l| "\t" + l } - env["rack.errors"].flush - - [@template.result(binding)] - end - - def h(obj) # :nodoc: - case obj - when String - Utils.escape_html(obj) - else - Utils.escape_html(obj.inspect) - end - end - - # :stopdoc: - -# adapted from Django -# Copyright (c) 2005, the Lawrence Journal-World -# Used under the modified BSD license: -# http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 -TEMPLATE = <<'HTML' - - - - - - <%=h exception.class %> at <%=h path %> - - - - - -
-

<%=h exception.class %> at <%=h path %>

-

<%=h exception.message %>

- - - - - - -
Ruby<%=h frames.first.filename %>: in <%=h frames.first.function %>, line <%=h frames.first.lineno %>
Web<%=h req.request_method %> <%=h(req.host + path)%>
- -

Jump to:

- -
- -
-

Traceback (innermost first)

-
    -<% frames.each { |frame| %> -
  • - <%=h frame.filename %>: in <%=h frame.function %> - - <% if frame.context_line %> -
    - <% if frame.pre_context %> -
      - <% frame.pre_context.each { |line| %> -
    1. <%=h line %>
    2. - <% } %> -
    - <% end %> - -
      -
    1. <%=h frame.context_line %>...
    - - <% if frame.post_context %> -
      - <% frame.post_context.each { |line| %> -
    1. <%=h line %>
    2. - <% } %> -
    - <% end %> -
    - <% end %> -
  • -<% } %> -
-
- -
-

Request information

- -

GET

- <% unless req.GET.empty? %> - - - - - - - - - <% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %> - - - - - <% } %> - -
VariableValue
<%=h key %>
<%=h val.inspect %>
- <% else %> -

No GET data.

- <% end %> - -

POST

- <% unless req.POST.empty? %> - - - - - - - - - <% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %> - - - - - <% } %> - -
VariableValue
<%=h key %>
<%=h val.inspect %>
- <% else %> -

No POST data.

- <% end %> - - - - <% unless req.cookies.empty? %> - - - - - - - - - <% req.cookies.each { |key, val| %> - - - - - <% } %> - -
VariableValue
<%=h key %>
<%=h val.inspect %>
- <% else %> -

No cookie data.

- <% end %> - -

Rack ENV

- - - - - - - - - <% env.sort_by { |k, v| k.to_s }.each { |key, val| %> - - - - - <% } %> - -
VariableValue
<%=h key %>
<%=h val %>
- -
- -
-

- You're seeing this error because you use Rack::ShowExceptions. -

-
- - - -HTML - - # :startdoc: - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/showstatus.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/showstatus.rb deleted file mode 100644 index 28258c7c89..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/showstatus.rb +++ /dev/null @@ -1,106 +0,0 @@ -require 'erb' -require 'rack/request' -require 'rack/utils' - -module Rack - # Rack::ShowStatus catches all empty responses the app it wraps and - # replaces them with a site explaining the error. - # - # Additional details can be put into rack.showstatus.detail - # and will be shown as HTML. If such details exist, the error page - # is always rendered, even if the reply was not empty. - - class ShowStatus - def initialize(app) - @app = app - @template = ERB.new(TEMPLATE) - end - - def call(env) - status, headers, body = @app.call(env) - headers = Utils::HeaderHash.new(headers) - empty = headers['Content-Length'].to_i <= 0 - - # client or server error, or explicit message - if (status.to_i >= 400 && empty) || env["rack.showstatus.detail"] - req = Rack::Request.new(env) - message = Rack::Utils::HTTP_STATUS_CODES[status.to_i] || status.to_s - detail = env["rack.showstatus.detail"] || message - body = @template.result(binding) - size = Rack::Utils.bytesize(body) - [status, headers.merge("Content-Type" => "text/html", "Content-Length" => size.to_s), [body]] - else - [status, headers, body] - end - end - - def h(obj) # :nodoc: - case obj - when String - Utils.escape_html(obj) - else - Utils.escape_html(obj.inspect) - end - end - - # :stopdoc: - -# adapted from Django -# Copyright (c) 2005, the Lawrence Journal-World -# Used under the modified BSD license: -# http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 -TEMPLATE = <<'HTML' - - - - - <%=h message %> at <%=h req.script_name + req.path_info %> - - - - -
-

<%=h message %> (<%= status.to_i %>)

- - - - - - - - - -
Request Method:<%=h req.request_method %>
Request URL:<%=h req.url %>
-
-
-

<%= detail %>

-
- -
-

- You're seeing this error because you use Rack::ShowStatus. -

-
- - -HTML - - # :startdoc: - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/static.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/static.rb deleted file mode 100644 index 168e8f83b2..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/static.rb +++ /dev/null @@ -1,38 +0,0 @@ -module Rack - - # The Rack::Static middleware intercepts requests for static files - # (javascript files, images, stylesheets, etc) based on the url prefixes - # passed in the options, and serves them using a Rack::File object. This - # allows a Rack stack to serve both static and dynamic content. - # - # Examples: - # use Rack::Static, :urls => ["/media"] - # will serve all requests beginning with /media from the "media" folder - # located in the current directory (ie media/*). - # - # use Rack::Static, :urls => ["/css", "/images"], :root => "public" - # will serve all requests beginning with /css or /images from the folder - # "public" in the current directory (ie public/css/* and public/images/*) - - class Static - - def initialize(app, options={}) - @app = app - @urls = options[:urls] || ["/favicon.ico"] - root = options[:root] || Dir.pwd - @file_server = Rack::File.new(root) - end - - def call(env) - path = env["PATH_INFO"] - can_serve = @urls.any? { |url| path.index(url) == 0 } - - if can_serve - @file_server.call(env) - else - @app.call(env) - end - end - - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/urlmap.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/urlmap.rb deleted file mode 100644 index 0ff32df181..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/urlmap.rb +++ /dev/null @@ -1,55 +0,0 @@ -module Rack - # Rack::URLMap takes a hash mapping urls or paths to apps, and - # dispatches accordingly. Support for HTTP/1.1 host names exists if - # the URLs start with http:// or https://. - # - # URLMap modifies the SCRIPT_NAME and PATH_INFO such that the part - # relevant for dispatch is in the SCRIPT_NAME, and the rest in the - # PATH_INFO. This should be taken care of when you need to - # reconstruct the URL in order to create links. - # - # URLMap dispatches in such a way that the longest paths are tried - # first, since they are most specific. - - class URLMap - def initialize(map = {}) - remap(map) - end - - def remap(map) - @mapping = map.map { |location, app| - if location =~ %r{\Ahttps?://(.*?)(/.*)} - host, location = $1, $2 - else - host = nil - end - - unless location[0] == ?/ - raise ArgumentError, "paths need to start with /" - end - location = location.chomp('/') - - [host, location, app] - }.sort_by { |(h, l, a)| [-l.size, h.to_s.size] } # Longest path first - end - - def call(env) - path = env["PATH_INFO"].to_s.squeeze("/") - script_name = env['SCRIPT_NAME'] - hHost, sName, sPort = env.values_at('HTTP_HOST','SERVER_NAME','SERVER_PORT') - @mapping.each { |host, location, app| - next unless (hHost == host || sName == host \ - || (host.nil? && (hHost == sName || hHost == sName+':'+sPort))) - next unless location == path[0, location.size] - next unless path[location.size] == nil || path[location.size] == ?/ - - return app.call( - env.merge( - 'SCRIPT_NAME' => (script_name + location), - 'PATH_INFO' => path[location.size..-1])) - } - [404, {"Content-Type" => "text/plain"}, ["Not Found: #{path}"]] - end - end -end - diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/utils.rb b/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/utils.rb deleted file mode 100644 index 0a61bce707..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/utils.rb +++ /dev/null @@ -1,392 +0,0 @@ -require 'set' -require 'tempfile' - -module Rack - # Rack::Utils contains a grab-bag of useful methods for writing web - # applications adopted from all kinds of Ruby libraries. - - module Utils - # Performs URI escaping so that you can construct proper - # query strings faster. Use this rather than the cgi.rb - # version since it's faster. (Stolen from Camping). - def escape(s) - s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) { - '%'+$1.unpack('H2'*$1.size).join('%').upcase - }.tr(' ', '+') - end - module_function :escape - - # Unescapes a URI escaped string. (Stolen from Camping). - def unescape(s) - s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){ - [$1.delete('%')].pack('H*') - } - end - module_function :unescape - - # Stolen from Mongrel, with some small modifications: - # Parses a query string by breaking it up at the '&' - # and ';' characters. You can also use this to parse - # cookies by changing the characters used in the second - # parameter (which defaults to '&;'). - def parse_query(qs, d = '&;') - params = {} - - (qs || '').split(/[#{d}] */n).each do |p| - k, v = unescape(p).split('=', 2) - - if cur = params[k] - if cur.class == Array - params[k] << v - else - params[k] = [cur, v] - end - else - params[k] = v - end - end - - return params - end - module_function :parse_query - - def parse_nested_query(qs, d = '&;') - params = {} - - (qs || '').split(/[#{d}] */n).each do |p| - k, v = unescape(p).split('=', 2) - normalize_params(params, k, v) - end - - return params - end - module_function :parse_nested_query - - def normalize_params(params, name, v = nil) - name =~ %r([\[\]]*([^\[\]]+)\]*) - k = $1 || '' - after = $' || '' - - return if k.empty? - - if after == "" - params[k] = v - elsif after == "[]" - params[k] ||= [] - raise TypeError unless params[k].is_a?(Array) - params[k] << v - elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$) - child_key = $1 - params[k] ||= [] - raise TypeError unless params[k].is_a?(Array) - if params[k].last.is_a?(Hash) && !params[k].last.key?(child_key) - normalize_params(params[k].last, child_key, v) - else - params[k] << normalize_params({}, child_key, v) - end - else - params[k] ||= {} - params[k] = normalize_params(params[k], after, v) - end - - return params - end - module_function :normalize_params - - def build_query(params) - params.map { |k, v| - if v.class == Array - build_query(v.map { |x| [k, x] }) - else - escape(k) + "=" + escape(v) - end - }.join("&") - end - module_function :build_query - - # Escape ampersands, brackets and quotes to their HTML/XML entities. - def escape_html(string) - string.to_s.gsub("&", "&"). - gsub("<", "<"). - gsub(">", ">"). - gsub("'", "'"). - gsub('"', """) - end - module_function :escape_html - - def select_best_encoding(available_encodings, accept_encoding) - # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html - - expanded_accept_encoding = - accept_encoding.map { |m, q| - if m == "*" - (available_encodings - accept_encoding.map { |m2, _| m2 }).map { |m2| [m2, q] } - else - [[m, q]] - end - }.inject([]) { |mem, list| - mem + list - } - - encoding_candidates = expanded_accept_encoding.sort_by { |_, q| -q }.map { |m, _| m } - - unless encoding_candidates.include?("identity") - encoding_candidates.push("identity") - end - - expanded_accept_encoding.find_all { |m, q| - q == 0.0 - }.each { |m, _| - encoding_candidates.delete(m) - } - - return (encoding_candidates & available_encodings)[0] - end - module_function :select_best_encoding - - # Return the bytesize of String; uses String#length under Ruby 1.8 and - # String#bytesize under 1.9. - if ''.respond_to?(:bytesize) - def bytesize(string) - string.bytesize - end - else - def bytesize(string) - string.size - end - end - module_function :bytesize - - # Context allows the use of a compatible middleware at different points - # in a request handling stack. A compatible middleware must define - # #context which should take the arguments env and app. The first of which - # would be the request environment. The second of which would be the rack - # application that the request would be forwarded to. - class Context - attr_reader :for, :app - - def initialize(app_f, app_r) - raise 'running context does not respond to #context' unless app_f.respond_to? :context - @for, @app = app_f, app_r - end - - def call(env) - @for.context(env, @app) - end - - def recontext(app) - self.class.new(@for, app) - end - - def context(env, app=@app) - recontext(app).call(env) - end - end - - # A case-insensitive Hash that preserves the original case of a - # header when set. - class HeaderHash < Hash - def initialize(hash={}) - @names = {} - hash.each { |k, v| self[k] = v } - end - - def to_hash - inject({}) do |hash, (k,v)| - if v.respond_to? :to_ary - hash[k] = v.to_ary.join("\n") - else - hash[k] = v - end - hash - end - end - - def [](k) - super @names[k.downcase] - end - - def []=(k, v) - delete k - @names[k.downcase] = k - super k, v - end - - def delete(k) - super @names.delete(k.downcase) - end - - def include?(k) - @names.has_key? k.downcase - end - - alias_method :has_key?, :include? - alias_method :member?, :include? - alias_method :key?, :include? - - def merge!(other) - other.each { |k, v| self[k] = v } - self - end - - def merge(other) - hash = dup - hash.merge! other - end - end - - # Every standard HTTP code mapped to the appropriate message. - # Stolen from Mongrel. - HTTP_STATUS_CODES = { - 100 => 'Continue', - 101 => 'Switching Protocols', - 200 => 'OK', - 201 => 'Created', - 202 => 'Accepted', - 203 => 'Non-Authoritative Information', - 204 => 'No Content', - 205 => 'Reset Content', - 206 => 'Partial Content', - 300 => 'Multiple Choices', - 301 => 'Moved Permanently', - 302 => 'Found', - 303 => 'See Other', - 304 => 'Not Modified', - 305 => 'Use Proxy', - 307 => 'Temporary Redirect', - 400 => 'Bad Request', - 401 => 'Unauthorized', - 402 => 'Payment Required', - 403 => 'Forbidden', - 404 => 'Not Found', - 405 => 'Method Not Allowed', - 406 => 'Not Acceptable', - 407 => 'Proxy Authentication Required', - 408 => 'Request Timeout', - 409 => 'Conflict', - 410 => 'Gone', - 411 => 'Length Required', - 412 => 'Precondition Failed', - 413 => 'Request Entity Too Large', - 414 => 'Request-URI Too Large', - 415 => 'Unsupported Media Type', - 416 => 'Requested Range Not Satisfiable', - 417 => 'Expectation Failed', - 500 => 'Internal Server Error', - 501 => 'Not Implemented', - 502 => 'Bad Gateway', - 503 => 'Service Unavailable', - 504 => 'Gateway Timeout', - 505 => 'HTTP Version Not Supported' - } - - # Responses with HTTP status codes that should not have an entity body - STATUS_WITH_NO_ENTITY_BODY = Set.new((100..199).to_a << 204 << 304) - - # A multipart form data parser, adapted from IOWA. - # - # Usually, Rack::Request#POST takes care of calling this. - - module Multipart - EOL = "\r\n" - - def self.parse_multipart(env) - unless env['CONTENT_TYPE'] =~ - %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n - nil - else - boundary = "--#{$1}" - - params = {} - buf = "" - content_length = env['CONTENT_LENGTH'].to_i - input = env['rack.input'] - - boundary_size = boundary.size + EOL.size - bufsize = 16384 - - content_length -= boundary_size - - status = input.read(boundary_size) - raise EOFError, "bad content body" unless status == boundary + EOL - - rx = /(?:#{EOL})?#{Regexp.quote boundary}(#{EOL}|--)/n - - loop { - head = nil - body = '' - filename = content_type = name = nil - - until head && buf =~ rx - if !head && i = buf.index("\r\n\r\n") - head = buf.slice!(0, i+2) # First \r\n - buf.slice!(0, 2) # Second \r\n - - filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1] - content_type = head[/Content-Type: (.*)\r\n/ni, 1] - name = head[/Content-Disposition:.* name="?([^\";]*)"?/ni, 1] - - if filename - body = Tempfile.new("RackMultipart") - body.binmode if body.respond_to?(:binmode) - end - - next - end - - # Save the read body part. - if head && (boundary_size+4 < buf.size) - body << buf.slice!(0, buf.size - (boundary_size+4)) - end - - c = input.read(bufsize < content_length ? bufsize : content_length) - raise EOFError, "bad content body" if c.nil? || c.empty? - buf << c - content_length -= c.size - end - - # Save the rest. - if i = buf.index(rx) - body << buf.slice!(0, i) - buf.slice!(0, boundary_size+2) - - content_length = -1 if $1 == "--" - end - - if filename == "" - # filename is blank which means no file has been selected - data = nil - elsif filename - body.rewind - - # 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 - # those which give the lone filename. - filename =~ /^(?:.*[:\\\/])?(.*)/m - filename = $1 - - data = {:filename => filename, :type => content_type, - :name => name, :tempfile => body, :head => head} - else - data = body - end - - Utils.normalize_params(params, name, data) unless data.nil? - - break if buf.empty? || content_length == -1 - } - - begin - input.rewind if 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 - - params - end - end - end - end -end diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb index 88b81dc493..6322cfc84a 100644 --- a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb @@ -96,7 +96,7 @@ class MultipartParamsParsingTest < ActionController::IntegrationTest # Ruby CGI doesn't handle multipart/mixed for us. files = params['files'] - assert_kind_of String, files + assert_kind_of Tempfile, files files.force_encoding('ASCII-8BIT') if files.respond_to?(:force_encoding) assert_equal 19756, files.size end -- cgit v1.2.3 From 4f412a10b6125831af34d874927f891f586d0101 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 25 Apr 2009 14:04:03 -0500 Subject: Remove RewindableInput middleware since all input MUST be rewindable according to a recent change in the Rack 1.0 SPEC --- .../lib/action_controller/dispatch/middlewares.rb | 1 - actionpack/lib/action_dispatch.rb | 1 - .../action_dispatch/middleware/rewindable_input.rb | 19 ------- .../request/multipart_params_parsing_test.rb | 61 ---------------------- .../request/url_encoded_params_parsing_test.rb | 38 -------------- 5 files changed, 120 deletions(-) delete mode 100644 actionpack/lib/action_dispatch/middleware/rewindable_input.rb diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb index b62b4f84a1..b5adbae746 100644 --- a/actionpack/lib/action_controller/dispatch/middlewares.rb +++ b/actionpack/lib/action_controller/dispatch/middlewares.rb @@ -7,7 +7,6 @@ use "ActionDispatch::Failsafe" use lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options } -use "ActionDispatch::RewindableInput" use "ActionDispatch::ParamsParser" use "Rack::MethodOverride" use "Rack::Head" diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 0c915d9fd5..4f65dcadee 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -43,7 +43,6 @@ module ActionDispatch autoload :Failsafe, 'action_dispatch/middleware/failsafe' autoload :ParamsParser, 'action_dispatch/middleware/params_parser' autoload :Reloader, 'action_dispatch/middleware/reloader' - autoload :RewindableInput, 'action_dispatch/middleware/rewindable_input' autoload :MiddlewareStack, 'action_dispatch/middleware/stack' module Http diff --git a/actionpack/lib/action_dispatch/middleware/rewindable_input.rb b/actionpack/lib/action_dispatch/middleware/rewindable_input.rb deleted file mode 100644 index c818f28cce..0000000000 --- a/actionpack/lib/action_dispatch/middleware/rewindable_input.rb +++ /dev/null @@ -1,19 +0,0 @@ -module ActionDispatch - class RewindableInput - def initialize(app) - @app = app - end - - def call(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 - env['rack.input'] = StringIO.new(env['rack.input'].read) - end - - @app.call(env) - end - end -end diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb index 6322cfc84a..cc81a87cb9 100644 --- a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb @@ -133,46 +133,6 @@ class MultipartParamsParsingTest < ActionController::IntegrationTest end end - # The lint wrapper is used in integration tests - # instead of a normal StringIO class - InputWrapper = Rack::Lint::InputWrapper - - test "parses unwindable stream" do - InputWrapper.any_instance.stubs(:rewind).raises(Errno::ESPIPE) - params = parse_multipart('large_text_file') - assert_equal %w(file foo), params.keys.sort - assert_equal 'bar', params['foo'] - end - - test "uploads and reads file with unwindable input" do - InputWrapper.any_instance.stubs(:rewind).raises(Errno::ESPIPE) - - with_test_routing do - post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain") - assert_equal "File: Hello", response.body - end - end - - test "passes through rack middleware and uploads file" do - with_muck_middleware do - with_test_routing do - post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain") - assert_equal "File: Hello", response.body - end - end - end - - test "passes through rack middleware and uploads file with unwindable input" do - InputWrapper.any_instance.stubs(:rewind).raises(Errno::ESPIPE) - - with_muck_middleware do - with_test_routing do - post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain") - assert_equal "File: Hello", response.body - end - end - end - private def fixture(name) File.open(File.join(FIXTURE_PATH, name), 'rb') do |file| @@ -199,25 +159,4 @@ class MultipartParamsParsingTest < ActionController::IntegrationTest yield end end - - class MuckMiddleware - def initialize(app) - @app = app - end - - def call(env) - env['rack.input'].read - env['rack.input'].rewind - @app.call(env) - end - end - - def with_muck_middleware - original_middleware = ActionController::Dispatcher.middleware - middleware = original_middleware.dup - middleware.insert_after ActionDispatch::RewindableInput, MuckMiddleware - ActionController::Dispatcher.middleware = middleware - yield - ActionController::Dispatcher.middleware = original_middleware - end end diff --git a/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb b/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb index 8de4a83d76..7167cdafac 100644 --- a/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb @@ -126,45 +126,7 @@ class UrlEncodedParamsParsingTest < ActionController::IntegrationTest assert_parses expected, query end - test "passes through rack middleware and parses params" do - with_muck_middleware do - assert_parses({ "a" => { "b" => "c" } }, "a[b]=c") - end - end - - # The lint wrapper is used in integration tests - # instead of a normal StringIO class - InputWrapper = Rack::Lint::InputWrapper - - test "passes through rack middleware and parses params with unwindable input" do - InputWrapper.any_instance.stubs(:rewind).raises(Errno::ESPIPE) - with_muck_middleware do - assert_parses({ "a" => { "b" => "c" } }, "a[b]=c") - end - end - private - class MuckMiddleware - def initialize(app) - @app = app - end - - def call(env) - env['rack.input'].read - env['rack.input'].rewind - @app.call(env) - end - end - - def with_muck_middleware - original_middleware = ActionController::Dispatcher.middleware - middleware = original_middleware.dup - middleware.insert_after ActionDispatch::RewindableInput, MuckMiddleware - ActionController::Dispatcher.middleware = middleware - yield - ActionController::Dispatcher.middleware = original_middleware - end - def with_test_routing with_routing do |set| set.draw do |map| -- cgit v1.2.3 From d0ace15c01c5092a128ffec816dd26636b5adefd Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sat, 25 Apr 2009 12:33:14 -0700 Subject: Updated for Rack 1.0 --- ci/geminstaller.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/geminstaller.yml b/ci/geminstaller.yml index 33f1e81179..387e370a6f 100644 --- a/ci/geminstaller.yml +++ b/ci/geminstaller.yml @@ -14,7 +14,7 @@ gems: - name: pg version: >= 0.7.9.2008.10.13 - name: rack - version: '~> 0.9.0' + version: '~> 1.0.0' - name: rake version: >= 0.8.1 - name: sqlite-ruby -- cgit v1.2.3 From dbbe2e74ff5b6363da74fe63045b043c24041b1a Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 26 Apr 2009 10:26:53 -0500 Subject: Create a new file for response tests --- actionpack/test/dispatch/rack_test.rb | 90 ------------------------------- actionpack/test/dispatch/response_test.rb | 83 ++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 90 deletions(-) create mode 100644 actionpack/test/dispatch/response_test.rb diff --git a/actionpack/test/dispatch/rack_test.rb b/actionpack/test/dispatch/rack_test.rb index 9fad4b22ee..94eba2a24f 100644 --- a/actionpack/test/dispatch/rack_test.rb +++ b/actionpack/test/dispatch/rack_test.rb @@ -201,93 +201,3 @@ class RackRequestNeedsRewoundTest < BaseRackTest assert_equal 0, request.body.pos end end - -class RackResponseTest < BaseRackTest - def setup - super - @response = ActionDispatch::Response.new - end - - test "simple output" do - @response.body = "Hello, World!" - @response.prepare! - - status, headers, body = @response.to_a - assert_equal 200, status - assert_equal({ - "Content-Type" => "text/html; charset=utf-8", - "Cache-Control" => "private, max-age=0, must-revalidate", - "ETag" => '"65a8e27d8879283831b664bd8b7f0ad4"', - "Set-Cookie" => "", - "Content-Length" => "13" - }, headers) - - parts = [] - body.each { |part| parts << part } - assert_equal ["Hello, World!"], parts - end - - def test_utf8_output - @response.body = [1090, 1077, 1089, 1090].pack("U*") - @response.prepare! - - status, headers, body = @response.to_a - assert_equal 200, status - assert_equal({ - "Content-Type" => "text/html; charset=utf-8", - "Cache-Control" => "private, max-age=0, must-revalidate", - "ETag" => '"ebb5e89e8a94e9dd22abf5d915d112b2"', - "Set-Cookie" => "", - "Content-Length" => "8" - }, headers) - end - - def test_streaming_block - @response.body = Proc.new do |response, output| - 5.times { |n| output.write(n) } - end - @response.prepare! - - status, headers, body = @response.to_a - assert_equal 200, status - assert_equal({ - "Content-Type" => "text/html; charset=utf-8", - "Cache-Control" => "no-cache", - "Set-Cookie" => "" - }, headers) - - parts = [] - body.each { |part| parts << part.to_s } - assert_equal ["0", "1", "2", "3", "4"], parts - end -end - -class RackResponseHeadersTest < BaseRackTest - def setup - super - @response = ActionDispatch::Response.new - @response.status = "200 OK" - end - - test "content type" do - [204, 304].each do |c| - @response.status = c.to_s - assert !response_headers.has_key?("Content-Type"), "#{c} should not have Content-Type header" - end - - [200, 302, 404, 500].each do |c| - @response.status = c.to_s - assert response_headers.has_key?("Content-Type"), "#{c} did not have Content-Type header" - end - end - - test "status" do - assert !response_headers.has_key?('Status') - end - - private - def response_headers - @response.prepare! - @response.to_a[1] - end -end diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb new file mode 100644 index 0000000000..fb593a6c31 --- /dev/null +++ b/actionpack/test/dispatch/response_test.rb @@ -0,0 +1,83 @@ +require 'abstract_unit' + +class ResponseTest < ActiveSupport::TestCase + def setup + @response = ActionDispatch::Response.new + end + + test "simple output" do + @response.body = "Hello, World!" + @response.prepare! + + status, headers, body = @response.to_a + assert_equal 200, status + assert_equal({ + "Content-Type" => "text/html; charset=utf-8", + "Cache-Control" => "private, max-age=0, must-revalidate", + "ETag" => '"65a8e27d8879283831b664bd8b7f0ad4"', + "Set-Cookie" => "", + "Content-Length" => "13" + }, headers) + + parts = [] + body.each { |part| parts << part } + assert_equal ["Hello, World!"], parts + end + + test "utf8 output" do + @response.body = [1090, 1077, 1089, 1090].pack("U*") + @response.prepare! + + status, headers, body = @response.to_a + assert_equal 200, status + assert_equal({ + "Content-Type" => "text/html; charset=utf-8", + "Cache-Control" => "private, max-age=0, must-revalidate", + "ETag" => '"ebb5e89e8a94e9dd22abf5d915d112b2"', + "Set-Cookie" => "", + "Content-Length" => "8" + }, headers) + end + + test "streaming block" do + @response.body = Proc.new do |response, output| + 5.times { |n| output.write(n) } + end + @response.prepare! + + status, headers, body = @response.to_a + assert_equal 200, status + assert_equal({ + "Content-Type" => "text/html; charset=utf-8", + "Cache-Control" => "no-cache", + "Set-Cookie" => "" + }, headers) + + parts = [] + body.each { |part| parts << part.to_s } + assert_equal ["0", "1", "2", "3", "4"], parts + end + + test "content type" do + [204, 304].each do |c| + @response.status = c.to_s + @response.prepare! + status, headers, body = @response.to_a + assert !headers.has_key?("Content-Type"), "#{c} should not have Content-Type header" + end + + [200, 302, 404, 500].each do |c| + @response.status = c.to_s + @response.prepare! + status, headers, body = @response.to_a + assert headers.has_key?("Content-Type"), "#{c} did not have Content-Type header" + end + end + + test "does not include Status header" do + @response.status = "200 OK" + @response.prepare! + status, headers, body = @response.to_a + assert !headers.has_key?('Status') + end +end -- cgit v1.2.3 From 5352a2417b9f6297d16a6baefd1994be4d1e4a12 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 26 Apr 2009 11:12:33 -0500 Subject: Move useful response test helpers into request --- .../lib/action_controller/testing/integration.rb | 7 ++- .../lib/action_controller/testing/process.rb | 61 +------------------- actionpack/lib/action_dispatch/http/response.rb | 65 +++++++++++++++++++++- actionpack/test/dispatch/response_test.rb | 47 ++++++++++++++++ 4 files changed, 116 insertions(+), 64 deletions(-) diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb index 15d0603ac1..10260d5af2 100644 --- a/actionpack/lib/action_controller/testing/integration.rb +++ b/actionpack/lib/action_controller/testing/integration.rb @@ -304,8 +304,11 @@ module ActionController @response = @controller.response @controller.send(:set_test_assigns) else - @request = ::Rack::Request.new(env) - @response = response + @request = Request.new(env) + @response = Response.new + @response.status = @status + @response.headers = @headers + @response.body = @body end # Decorate the response with the standard behavior of the diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index f5742af472..05b756fa4d 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -156,54 +156,7 @@ module ActionController #:nodoc: # A refactoring of TestResponse to allow the same behavior to be applied # to the "real" CgiResponse class in integration tests. module TestResponseBehavior #:nodoc: - # The response code of the request - def response_code - status.to_s[0,3].to_i rescue 0 - end - - # Returns a String to ensure compatibility with Net::HTTPResponse - def code - status.to_s.split(' ')[0] - end - - def message - status.to_s.split(' ',2)[1] - end - - # Was the response successful? - def success? - (200..299).include?(response_code) - end - - # Was the URL not found? - def missing? - response_code == 404 - end - - # Were we redirected? - def redirect? - (300..399).include?(response_code) - end - - # Was there a server-side error? - def error? - (500..599).include?(response_code) - end - - alias_method :server_error?, :error? - - # Was there a client client? - def client_error? - (400..499).include?(response_code) - end - - # Returns the redirection location or nil - def redirect_url - headers['Location'] - end - - # Does the redirect location match this regexp pattern? - def redirect_url_match?( pattern ) + def redirect_url_match?(pattern) return false if redirect_url.nil? p = Regexp.new(pattern) if pattern.class == String p = pattern if pattern.class == Regexp @@ -252,18 +205,6 @@ module ActionController #:nodoc: !template_objects[name].nil? end - # Returns the response cookies, converted to a Hash of (name => value) pairs - # - # assert_equal 'AuthorOfNewPage', r.cookies['author'] - def cookies - cookies = {} - Array(headers['Set-Cookie']).each do |cookie| - key, value = cookie.split(";").first.split("=").map {|val| Rack::Utils.unescape(val)} - cookies[key] = value - end - cookies - end - # Returns binary content (downloadable file), converted to a String def binary_content raise "Response body is not a Proc: #{body_parts.inspect}" unless body_parts.kind_of?(Proc) diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index ecf40b8103..7bc9c62e2c 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -37,6 +37,9 @@ module ActionDispatch # :nodoc: attr_accessor :session, :assigns, :template, :layout attr_accessor :redirected_to, :redirected_to_method_params + attr_writer :header + alias_method :headers=, :header= + delegate :default_charset, :to => 'ActionController::Base' def initialize @@ -45,6 +48,47 @@ module ActionDispatch # :nodoc: @session, @assigns = [], [] end + # The response code of the request + def response_code + status.to_s[0,3].to_i rescue 0 + end + + # Returns a String to ensure compatibility with Net::HTTPResponse + def code + status.to_s.split(' ')[0] + end + + def message + status.to_s.split(' ',2)[1] || StatusCodes::STATUS_CODES[response_code] + end + + # Was the response successful? + def success? + (200..299).include?(response_code) + end + + # Was the URL not found? + def missing? + response_code == 404 + end + + # Were we redirected? + def redirect? + (300..399).include?(response_code) + end + + # Was there a server-side error? + def error? + (500..599).include?(response_code) + end + + alias_method :server_error?, :error? + + # Was there a client client? + def client_error? + (400..499).include?(response_code) + end + def body str = '' each { |part| str << part.to_s } @@ -64,9 +108,14 @@ module ActionDispatch # :nodoc: @body end - def location; headers['Location'] end - def location=(url) headers['Location'] = url end + def location + headers['Location'] + end + alias_method :redirect_url, :location + def location=(url) + headers['Location'] = url + end # Sets the HTTP response's content MIME type. For example, in the controller # you could write this: @@ -192,6 +241,18 @@ module ActionDispatch # :nodoc: super(key, value) end + # Returns the response cookies, converted to a Hash of (name => value) pairs + # + # assert_equal 'AuthorOfNewPage', r.cookies['author'] + def cookies + cookies = {} + Array(headers['Set-Cookie']).each do |cookie| + key, value = cookie.split(";").first.split("=").map { |v| Rack::Utils.unescape(v) } + cookies[key] = value + end + cookies + end + private def handle_conditional_get! if etag? || last_modified? diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index fb593a6c31..2ddc6cb2b5 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -80,4 +80,51 @@ class ResponseTest < ActiveSupport::TestCase status, headers, body = @response.to_a assert !headers.has_key?('Status') end + + test "response code" do + @response.status = "200 OK" + assert_equal 200, @response.response_code + + @response.status = "200" + assert_equal 200, @response.response_code + + @response.status = 200 + assert_equal 200, @response.response_code + end + + test "code" do + @response.status = "200 OK" + assert_equal "200", @response.code + + @response.status = "200" + assert_equal "200", @response.code + + @response.status = 200 + assert_equal "200", @response.code + end + + test "message" do + @response.status = "200 OK" + assert_equal "OK", @response.message + + @response.status = "200" + assert_equal "OK", @response.message + + @response.status = 200 + assert_equal "OK", @response.message + end + + test "cookies" do + @response.set_cookie("user_name", :value => "david", :path => "/") + @response.prepare! + status, headers, body = @response.to_a + assert_equal "user_name=david; path=/", headers["Set-Cookie"] + assert_equal({"user_name" => "david"}, @response.cookies) + + @response.set_cookie("login", :value => "foo&bar", :path => "/", :expires => Time.utc(2005, 10, 10,5)) + @response.prepare! + status, headers, body = @response.to_a + assert_equal "user_name=david; path=/\nlogin=foo%26bar; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT", headers["Set-Cookie"] + assert_equal({"login" => "foo&bar", "user_name" => "david"}, @response.cookies) + end end -- cgit v1.2.3 From 5ea8d401569323a10592d68d29b293c1ae131a8b Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 26 Apr 2009 11:16:14 -0500 Subject: Deprecate response.redirect_url_match?, use assert_match instead. --- actionpack/lib/action_controller/testing/process.rb | 1 + actionpack/test/controller/action_pack_assertions_test.rb | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index 05b756fa4d..2ad0579a30 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -157,6 +157,7 @@ module ActionController #:nodoc: # to the "real" CgiResponse class in integration tests. module TestResponseBehavior #:nodoc: def redirect_url_match?(pattern) + ::ActiveSupport::Deprecation.warn("response.redirect_url_match? is deprecated. Use assert_match(/foo/, response.redirect_url) instead", caller) return false if redirect_url.nil? p = Regexp.new(pattern) if pattern.class == String p = pattern if pattern.class == Regexp diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index 96f7a42c9b..f091f9b87c 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -378,10 +378,12 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase def test_redirect_url_match process :redirect_external assert @response.redirect? - assert @response.redirect_url_match?("rubyonrails") - assert @response.redirect_url_match?(/rubyonrails/) - assert !@response.redirect_url_match?("phpoffrails") - assert !@response.redirect_url_match?(/perloffrails/) + assert_deprecated do + assert @response.redirect_url_match?("rubyonrails") + assert @response.redirect_url_match?(/rubyonrails/) + assert !@response.redirect_url_match?("phpoffrails") + assert !@response.redirect_url_match?(/perloffrails/) + end end # check for a redirection -- cgit v1.2.3 From 82bc768dad761df466e38ee9f1501aef766878c3 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 26 Apr 2009 11:19:42 -0500 Subject: Fix typo in stale session check [#2404 state:resolved] --- actionpack/lib/action_dispatch/middleware/session/abstract_store.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 6c039cf62d..211d373208 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -74,7 +74,7 @@ module ActionDispatch # Note that the regexp does not allow $1 to end with a ':' $1.constantize rescue LoadError, NameError => const_error - raise ActionController::SessionRestoreError, "Session contains objects whose class definition isn\\'t available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: \#{const_error.message} [\#{const_error.class}])\n" + raise ActionController::SessionRestoreError, "Session contains objects whose class definition isn't available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: #{const_error.message} [#{const_error.class}])\n" end retry -- cgit v1.2.3 From cd9bb88eefdbd8a43f0bb15934ae32985fd19b6e Mon Sep 17 00:00:00 2001 From: "Hongli Lai (Phusion)" Date: Sun, 26 Apr 2009 11:22:03 -0500 Subject: Remove reference to Rack::RewindableInput, which has been removed a while ago. Signed-off-by: Joshua Peek --- railties/lib/initializer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index a03be59a2b..b3b409dc4d 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -568,7 +568,7 @@ Run `rake gems:install` to install the missing gems. Rails::Rack::Metal.metal_paths += plugin_loader.engine_metal_paths configuration.middleware.insert_before( - :"ActionDispatch::RewindableInput", + :"ActionDispatch::ParamsParser", Rails::Rack::Metal, :if => Rails::Rack::Metal.metals.any?) end -- cgit v1.2.3 From 3cb97aeea8837b9d2b7ed3f9806f5727ceef0e3d Mon Sep 17 00:00:00 2001 From: "Hongli Lai (Phusion)" Date: Sun, 26 Apr 2009 11:23:10 -0500 Subject: Fix environment variable testing code in failsafe.rb. Signed-off-by: Joshua Peek --- actionpack/lib/action_dispatch/middleware/failsafe.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/failsafe.rb b/actionpack/lib/action_dispatch/middleware/failsafe.rb index b5a3abcc92..5e0c479fdd 100644 --- a/actionpack/lib/action_dispatch/middleware/failsafe.rb +++ b/actionpack/lib/action_dispatch/middleware/failsafe.rb @@ -11,7 +11,7 @@ module ActionDispatch @app.call(env) rescue Exception => exception # Reraise exception in test environment - if defined?(Rails) && Rails.test? + if defined?(Rails) && Rails.env.test? raise exception else failsafe_response(exception) -- cgit v1.2.3 From 6940c0de12eedcff6529ba0dfef533513cbcd389 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 26 Apr 2009 11:37:11 -0500 Subject: Unify functional and integration tests cookie helpers --- .../lib/action_controller/testing/integration.rb | 33 ++++++++-------------- actionpack/test/controller/integration_test.rb | 2 +- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb index 10260d5af2..be5f216e2b 100644 --- a/actionpack/lib/action_controller/testing/integration.rb +++ b/actionpack/lib/action_controller/testing/integration.rb @@ -285,37 +285,28 @@ module ActionController app = Rack::Lint.new(@app) status, headers, body = app.call(env) response = ::Rack::MockResponse.new(status, headers, body) + @request_count += 1 + @request = Request.new(env) - @html_document = nil + @response = Response.new + @response.status = @status = response.status + @response.headers = @headers = response.headers + @response.body = @body = response.body - @status = response.status @status_message = ActionDispatch::StatusCodes::STATUS_CODES[@status] - @headers = response.headers - @body = response.body - - (@headers['Set-Cookie'] || "").split("\n").each do |cookie| - name, value = cookie.match(/^([^=]*)=([^;]*);/)[1,2] - @cookies[name] = value - end - - if @controller = ActionController::Base.last_instantiation - @request = @controller.request - @response = @controller.response - @controller.send(:set_test_assigns) - else - @request = Request.new(env) - @response = Response.new - @response.status = @status - @response.headers = @headers - @response.body = @body - end + @cookies.merge!(@response.cookies) + @html_document = nil # Decorate the response with the standard behavior of the # TestResponse so that things like assert_response can be # used in integration tests. @response.extend(TestResponseBehavior) + if @controller = ActionController::Base.last_instantiation + @controller.send(:set_test_assigns) + end + return @status end diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index 9eeaa7b4e1..70fa41aded 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -297,7 +297,7 @@ class IntegrationProcessTest < ActionController::IntegrationTest assert_response 410 assert_response :gone assert_equal "cookie_1=; path=/\ncookie_3=chocolate; path=/", headers["Set-Cookie"] - assert_equal({"cookie_1"=>"", "cookie_2"=>"oatmeal", "cookie_3"=>"chocolate"}, cookies) + assert_equal({"cookie_1"=>nil, "cookie_2"=>"oatmeal", "cookie_3"=>"chocolate"}, cookies) assert_equal "Gone", response.body end end -- cgit v1.2.3 From c8919f4c7ca13ad78987ea0c8497abe85249975b Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 26 Apr 2009 11:52:45 -0500 Subject: Require an ActionDispatch::Request to use response assertions --- .../testing/assertions/response.rb | 24 ++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_controller/testing/assertions/response.rb b/actionpack/lib/action_controller/testing/assertions/response.rb index ca0a9bbf52..c57cbecc44 100644 --- a/actionpack/lib/action_controller/testing/assertions/response.rb +++ b/actionpack/lib/action_controller/testing/assertions/response.rb @@ -22,6 +22,8 @@ module ActionController # assert_response 401 # def assert_response(type, message = nil) + validate_response! + clean_backtrace do if [ :success, :missing, :redirect, :error ].include?(type) && @response.send("#{type}?") assert_block("") { true } # to count the assertion @@ -30,8 +32,8 @@ module ActionController elsif type.is_a?(Symbol) && @response.response_code == ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[type] assert_block("") { true } # to count the assertion else - if @response.error? - exception = @response.template.instance_variable_get(:@exception) + if @controller && @response.error? + exception = @controller.response.template.instance_variable_get(:@exception) exception_message = exception && exception.message assert_block(build_message(message, "Expected response to be a , but was \n", type, @response.response_code, exception_message.to_s)) { false } else @@ -57,6 +59,8 @@ module ActionController # assert_redirected_to @customer # def assert_redirected_to(options = {}, message=nil) + validate_response! + clean_backtrace do assert_response(:redirect, message) return true if options == @response.redirected_to @@ -89,23 +93,25 @@ module ActionController # assert_template :partial => false # def assert_template(options = {}, message = nil) + validate_response! + clean_backtrace do case options when NilClass, String - rendered = @response.rendered[:template].to_s + rendered = @controller.response.rendered[:template].to_s msg = build_message(message, "expecting but rendering with ", options, rendered) assert_block(msg) do if options.nil? - @response.rendered[:template].blank? + @controller.response.rendered[:template].blank? else rendered.to_s.match(options) end end when Hash if expected_partial = options[:partial] - partials = @response.rendered[:partials] + partials = @controller.response.rendered[:partials] if expected_count = options[:count] found = partials.detect { |p, _| p.to_s.match(expected_partial) } actual_count = found.nil? ? 0 : found.second @@ -120,7 +126,7 @@ module ActionController assert(partials.keys.any? { |p| p.to_s.match(expected_partial) }, msg) end else - assert @response.rendered[:partials].empty?, + assert @controller.response.rendered[:partials].empty?, "Expected no partials to be rendered" end end @@ -145,6 +151,12 @@ module ActionController @request.protocol + @request.host_with_port + after_routing end end + + def validate_response! + unless @request.is_a?(ActionDispatch::Request) + raise ArgumentError, "@request must be an ActionDispatch::Request" + end + end end end end -- cgit v1.2.3 From 04949096797a390105c7ab9fb9b99938d5921dd4 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 26 Apr 2009 14:33:57 -0500 Subject: Inherit TestSession from Session::AbstractStore and add indifferent access to Session::AbstractStore. --- actionpack/lib/action_controller/base/base.rb | 10 +-- .../lib/action_controller/testing/process.rb | 78 +++------------------- actionpack/lib/action_dispatch/http/request.rb | 14 +--- actionpack/lib/action_dispatch/http/response.rb | 3 +- .../middleware/session/abstract_store.rb | 28 +++++++- .../middleware/session/cookie_store.rb | 7 +- .../controller/http_digest_authentication_test.rb | 2 - .../test/controller/request/test_request_test.rb | 23 ++++--- .../test/dispatch/session/cookie_store_test.rb | 3 +- .../test/dispatch/session/test_session_test.rb | 24 +++---- 10 files changed, 67 insertions(+), 125 deletions(-) diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb index 3000b3d12f..afb9fb71cb 100644 --- a/actionpack/lib/action_controller/base/base.rb +++ b/actionpack/lib/action_controller/base/base.rb @@ -811,14 +811,8 @@ module ActionController #:nodoc: end def assign_shortcuts(request, response) - @_request, @_params = request, request.parameters - - @_response = response - @_response.session = request.session - - @_session = @_response.session - - @_headers = @_response.headers + @_request, @_response, @_params = request, response, request.parameters + @_session, @_headers = @_request.session, @_response.headers end def initialize_current_url diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index 2ad0579a30..16275371ad 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -1,8 +1,9 @@ require 'rack/session/abstract/id' + module ActionController #:nodoc: class TestRequest < ActionDispatch::Request #:nodoc: - attr_accessor :cookies, :session_options - attr_accessor :query_parameters, :path, :session + attr_accessor :cookies + attr_accessor :query_parameters, :path attr_accessor :host def self.new(env = {}) @@ -13,18 +14,13 @@ module ActionController #:nodoc: super(Rack::MockRequest.env_for("/").merge(env)) @query_parameters = {} - @session = TestSession.new - default_rack_options = Rack::Session::Abstract::ID::DEFAULT_OPTIONS - @session_options ||= {:id => generate_sid(default_rack_options[:sidbits])}.merge(default_rack_options) + @env['rack.session'] = TestSession.new + @env['rack.session.options'] = TestSession::DEFAULT_OPTIONS.merge(:id => ActiveSupport::SecureRandom.hex(16)) initialize_default_values initialize_containers end - def reset_session - @session.reset - end - # Wraps raw_post in a StringIO. def body_stream #:nodoc: StringIO.new(raw_post) @@ -124,10 +120,6 @@ module ActionController #:nodoc: end private - def generate_sid(sidbits) - "%0#{sidbits / 4}x" % rand(2**sidbits - 1) - end - def initialize_containers @cookies = {} end @@ -235,62 +227,12 @@ module ActionController #:nodoc: end end - class TestSession < Hash #:nodoc: - attr_accessor :session_id - - def initialize(attributes = nil) - reset_session_id - replace_attributes(attributes) - end - - def reset - reset_session_id - replace_attributes({ }) - end - - def data - to_hash - end - - def [](key) - super(key.to_s) - end - - def []=(key, value) - super(key.to_s, value) - end - - def update(hash = nil) - if hash.nil? - ActiveSupport::Deprecation.warn('use replace instead', caller) - replace({}) - else - super(hash) - end - end - - def delete(key = nil) - if key.nil? - ActiveSupport::Deprecation.warn('use clear instead', caller) - clear - else - super(key.to_s) - end - end - - def close - ActiveSupport::Deprecation.warn('sessions should no longer be closed', caller) - end - - private - - def reset_session_id - @session_id = '' - end + class TestSession < ActionDispatch::Session::AbstractStore::SessionHash #:nodoc: + DEFAULT_OPTIONS = ActionDispatch::Session::AbstractStore::DEFAULT_OPTIONS - def replace_attributes(attributes = nil) - attributes ||= {} - replace(attributes.stringify_keys) + def initialize(session = {}) + replace(session.stringify_keys) + @loaded = true end end diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index ab654b9a50..2602b344ca 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -451,23 +451,15 @@ EOM @env['rack.input'] end - def session - @env['rack.session'] ||= {} + def reset_session + self.session_options.delete(:id) + self.session = {} end def session=(session) #:nodoc: @env['rack.session'] = session end - def reset_session - @env['rack.session.options'].delete(:id) - @env['rack.session'] = {} - end - - def session_options - @env['rack.session.options'] ||= {} - end - def session_options=(options) @env['rack.session.options'] = options end diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 7bc9c62e2c..77c2dd0d7a 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -34,12 +34,13 @@ module ActionDispatch # :nodoc: DEFAULT_HEADERS = { "Cache-Control" => "no-cache" } attr_accessor :request - attr_accessor :session, :assigns, :template, :layout + attr_accessor :assigns, :template, :layout attr_accessor :redirected_to, :redirected_to_method_params attr_writer :header alias_method :headers=, :header= + delegate :session, :to => :request delegate :default_charset, :to => 'ActionController::Base' def initialize diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 211d373208..03761b10bd 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -26,12 +26,12 @@ module ActionDispatch def [](key) load! unless @loaded - super + super(key.to_s) end def []=(key, value) load! unless @loaded - super + super(key.to_s, value) end def to_hash @@ -40,6 +40,24 @@ module ActionDispatch h end + def update(hash = nil) + if hash.nil? + ActiveSupport::Deprecation.warn('use replace instead', caller) + replace({}) + else + super(hash.stringify_keys) + end + end + + def delete(key = nil) + if key.nil? + ActiveSupport::Deprecation.warn('use clear instead', caller) + clear + else + super(key.to_s) + end + end + def data ActiveSupport::Deprecation.warn( "ActionController::Session::AbstractStore::SessionHash#data " + @@ -47,6 +65,10 @@ module ActionDispatch to_hash end + def close + ActiveSupport::Deprecation.warn('sessions should no longer be closed', caller) + end + def inspect load! unless @loaded super @@ -61,7 +83,7 @@ module ActionDispatch stale_session_check! do id, session = @by.send(:load_session, @env) (@env[ENV_SESSION_OPTIONS_KEY] ||= {})[:id] = id - replace(session) + replace(session.stringify_keys) @loaded = true end end diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index 433c4cc070..547a2d2062 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -143,7 +143,8 @@ module ActionDispatch request = Rack::Request.new(env) session_data = request.cookies[@key] data = unmarshal(session_data) || persistent_session_id!({}) - [data[:session_id], data] + data.stringify_keys! + [data["session_id"], data] end # Marshal a session hash into safe cookie data. Include an integrity hash. @@ -206,12 +207,12 @@ module ActionDispatch end def inject_persistent_session_id(data) - requires_session_id?(data) ? { :session_id => generate_sid } : {} + requires_session_id?(data) ? { "session_id" => generate_sid } : {} end def requires_session_id?(data) if data - data.respond_to?(:key?) && !data.key?(:session_id) + data.respond_to?(:key?) && !data.key?("session_id") else true end diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb index 00789eea38..7bebc8cd2a 100644 --- a/actionpack/test/controller/http_digest_authentication_test.rb +++ b/actionpack/test/controller/http_digest_authentication_test.rb @@ -111,8 +111,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase test "authentication request with valid credential and nil session" do @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please') - # session_id = "" in functional test, but is +nil+ in real life - @request.session.session_id = nil get :display assert_response :success diff --git a/actionpack/test/controller/request/test_request_test.rb b/actionpack/test/controller/request/test_request_test.rb index 81551b4ba7..0a39feb7fe 100644 --- a/actionpack/test/controller/request/test_request_test.rb +++ b/actionpack/test/controller/request/test_request_test.rb @@ -10,26 +10,27 @@ class ActionController::TestRequestTest < ActiveSupport::TestCase def test_test_request_has_session_options_initialized assert @request.session_options end - - Rack::Session::Abstract::ID::DEFAULT_OPTIONS.each_key do |option| - test "test_rack_default_session_options_#{option}_exists_in_session_options_and_is_default" do - assert_equal(Rack::Session::Abstract::ID::DEFAULT_OPTIONS[option], - @request.session_options[option], + + ActionDispatch::Session::AbstractStore::DEFAULT_OPTIONS.each_key do |option| + test "rack default session options #{option} exists in session options and is default" do + assert_equal(ActionDispatch::Session::AbstractStore::DEFAULT_OPTIONS[option], + @request.session_options[option], "Missing rack session default option #{option} in request.session_options") end - test "test_rack_default_session_options_#{option}_exists_in_session_options" do - assert(@request.session_options.has_key?(option), + + test "rack default session options #{option} exists in session options" do + assert(@request.session_options.has_key?(option), "Missing rack session option #{option} in request.session_options") end end - + def test_session_id_exists_by_default assert_not_nil(@request.session_options[:id]) end - + def test_session_id_different_on_each_call - prev_id = + prev_id = assert_not_equal(@request.session_options[:id], ActionController::TestRequest.new.session_options[:id]) end - + end \ No newline at end of file diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index b9bf8cf411..3090a70244 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -10,8 +10,7 @@ class CookieStoreTest < ActionController::IntegrationTest :key => SessionKey, :secret => SessionSecret) Verifier = ActiveSupport::MessageVerifier.new(SessionSecret, 'SHA1') - - SignedBar = "BAh7BjoIZm9vIghiYXI%3D--fef868465920f415f2c0652d6910d3af288a0367" + SignedBar = Verifier.generate(:foo => "bar", :session_id => ActiveSupport::SecureRandom.hex(16)) class TestController < ActionController::Base def no_session_access diff --git a/actionpack/test/dispatch/session/test_session_test.rb b/actionpack/test/dispatch/session/test_session_test.rb index de6539e1cc..0ff93f1c5d 100644 --- a/actionpack/test/dispatch/session/test_session_test.rb +++ b/actionpack/test/dispatch/session/test_session_test.rb @@ -2,37 +2,30 @@ require 'abstract_unit' require 'stringio' class ActionController::TestSessionTest < ActiveSupport::TestCase - def test_calling_delete_without_parameters_raises_deprecation_warning_and_calls_to_clear_test_session assert_deprecated(/use clear instead/){ ActionController::TestSession.new.delete } end - + def test_calling_update_without_parameters_raises_deprecation_warning_and_calls_to_clear_test_session assert_deprecated(/use replace instead/){ ActionController::TestSession.new.update } end - + def test_calling_close_raises_deprecation_warning assert_deprecated(/sessions should no longer be closed/){ ActionController::TestSession.new.close } end - - def test_defaults - session = ActionController::TestSession.new - assert_equal({}, session.data) - assert_equal('', session.session_id) - end - + def test_ctor_allows_setting session = ActionController::TestSession.new({:one => 'one', :two => 'two'}) assert_equal('one', session[:one]) assert_equal('two', session[:two]) end - + def test_setting_session_item_sets_item session = ActionController::TestSession.new session[:key] = 'value' assert_equal('value', session[:key]) end - + def test_calling_delete_removes_item session = ActionController::TestSession.new session[:key] = 'value' @@ -40,13 +33,13 @@ class ActionController::TestSessionTest < ActiveSupport::TestCase session.delete(:key) assert_nil(session[:key]) end - + def test_calling_update_with_params_passes_to_attributes session = ActionController::TestSession.new() session.update('key' => 'value') assert_equal('value', session[:key]) end - + def test_clear_emptys_session params = {:one => 'one', :two => 'two'} session = ActionController::TestSession.new({:one => 'one', :two => 'two'}) @@ -54,5 +47,4 @@ class ActionController::TestSessionTest < ActiveSupport::TestCase assert_nil(session[:one]) assert_nil(session[:two]) end - -end \ No newline at end of file +end -- cgit v1.2.3 From da3a80dd4fadde9b3bd671c72b5bee737fb70e39 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 15:04:02 -0700 Subject: Track object ids so the objects needn't respond to == --- activesupport/lib/active_support/json/encoding.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index 42a217cedc..e8e9308495 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -6,8 +6,8 @@ module ActiveSupport # Converts a Ruby object into a JSON string. def self.encode(value, options = {}) seen = (options[:seen] ||= []) - raise CircularReferenceError, 'object references itself' if seen.include?(value) - seen << value + raise CircularReferenceError, 'object references itself' if seen.include?(value.object_id) + seen << value.object_id value.send(:rails_to_json, options) ensure seen.pop -- cgit v1.2.3 From be7e21a85c487b6f3bfc2e393387ada5cc52290d Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 15:05:50 -0700 Subject: Qualify toplevel constant references since we're in a BasicObject --- actionpack/lib/action_view/helpers/prototype_helper.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index fb8122af35..868c8226c4 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -686,7 +686,7 @@ module ActionView # Returns an object whose to_json evaluates to +code+. Use this to pass a literal JavaScript # expression as an argument to another JavaScriptGenerator method. def literal(code) - ActiveSupport::JSON::Variable.new(code.to_s) + ::ActiveSupport::JSON::Variable.new(code.to_s) end # Returns a collection reference by finding it through a CSS +pattern+ in the DOM. This collection can then be @@ -973,7 +973,7 @@ module ActionView def loop_on_multiple_args(method, ids) record(ids.size>1 ? "#{javascript_object_for(ids)}.each(#{method})" : - "#{method}(#{ActiveSupport::JSON.encode(ids.first)})") + "#{method}(#{::ActiveSupport::JSON.encode(ids.first)})") end def page @@ -997,7 +997,7 @@ module ActionView end def javascript_object_for(object) - ActiveSupport::JSON.encode(object) + ::ActiveSupport::JSON.encode(object) end def arguments_for_call(arguments, block = nil) @@ -1139,7 +1139,7 @@ module ActionView class JavaScriptElementProxy < JavaScriptProxy #:nodoc: def initialize(generator, id) @id = id - super(generator, "$(#{ActiveSupport::JSON.encode(id)})") + super(generator, "$(#{::ActiveSupport::JSON.encode(id)})") end # Allows access of element attributes through +attribute+. Examples: @@ -1213,7 +1213,7 @@ module ActionView enumerate :eachSlice, :variable => variable, :method_args => [number], :yield_args => %w(value index), :return => true, &block else add_variable_assignment!(variable) - append_enumerable_function!("eachSlice(#{ActiveSupport::JSON.encode(number)});") + append_enumerable_function!("eachSlice(#{::ActiveSupport::JSON.encode(number)});") end end @@ -1234,7 +1234,7 @@ module ActionView def pluck(variable, property) add_variable_assignment!(variable) - append_enumerable_function!("pluck(#{ActiveSupport::JSON.encode(property)});") + append_enumerable_function!("pluck(#{::ActiveSupport::JSON.encode(property)});") end def zip(variable, *arguments, &block) @@ -1298,7 +1298,7 @@ module ActionView class JavaScriptElementCollectionProxy < JavaScriptCollectionProxy #:nodoc:\ def initialize(generator, pattern) - super(generator, "$$(#{ActiveSupport::JSON.encode(pattern)})") + super(generator, "$$(#{::ActiveSupport::JSON.encode(pattern)})") end end end -- cgit v1.2.3 From 8d64085138b1a2ff36b94267d0236868b287610e Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 15:18:33 -0700 Subject: Only Object to_json alias is needed. Prefer nil options. --- actionpack/lib/action_view/helpers/prototype_helper.rb | 2 -- activesupport/lib/active_support/json/encoders/date.rb | 2 -- .../lib/active_support/json/encoders/date_time.rb | 2 -- .../lib/active_support/json/encoders/enumerable.rb | 4 +--- .../lib/active_support/json/encoders/false_class.rb | 2 -- activesupport/lib/active_support/json/encoders/hash.rb | 14 +++++++------- .../lib/active_support/json/encoders/nil_class.rb | 2 -- activesupport/lib/active_support/json/encoders/numeric.rb | 2 -- activesupport/lib/active_support/json/encoders/object.rb | 2 +- activesupport/lib/active_support/json/encoders/regexp.rb | 2 -- activesupport/lib/active_support/json/encoders/string.rb | 2 -- activesupport/lib/active_support/json/encoders/symbol.rb | 4 +--- activesupport/lib/active_support/json/encoders/time.rb | 2 -- .../lib/active_support/json/encoders/true_class.rb | 2 -- activesupport/lib/active_support/json/encoding.rb | 3 ++- 15 files changed, 12 insertions(+), 35 deletions(-) diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index 868c8226c4..9cafd17004 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -1188,8 +1188,6 @@ module ActionView @variable end - alias to_json rails_to_json - private def append_to_function_chain!(call) @generator << @variable if @empty diff --git a/activesupport/lib/active_support/json/encoders/date.rb b/activesupport/lib/active_support/json/encoders/date.rb index 79c3957362..1aebdd2764 100644 --- a/activesupport/lib/active_support/json/encoders/date.rb +++ b/activesupport/lib/active_support/json/encoders/date.rb @@ -18,6 +18,4 @@ class Date %("#{strftime("%Y/%m/%d")}") end end - - alias to_json rails_to_json end diff --git a/activesupport/lib/active_support/json/encoders/date_time.rb b/activesupport/lib/active_support/json/encoders/date_time.rb index cdfc39b9f3..096e0dd36b 100644 --- a/activesupport/lib/active_support/json/encoders/date_time.rb +++ b/activesupport/lib/active_support/json/encoders/date_time.rb @@ -18,6 +18,4 @@ class DateTime strftime('"%Y/%m/%d %H:%M:%S %z"') end end - - alias to_json rails_to_json end diff --git a/activesupport/lib/active_support/json/encoders/enumerable.rb b/activesupport/lib/active_support/json/encoders/enumerable.rb index e1c3ec249d..6e0c3b6b9c 100644 --- a/activesupport/lib/active_support/json/encoders/enumerable.rb +++ b/activesupport/lib/active_support/json/encoders/enumerable.rb @@ -6,9 +6,7 @@ module Enumerable # # => users.to_json(:only => :name) # # will pass the :only => :name option to each user. - def rails_to_json(options = {}) #:nodoc: + def rails_to_json(options = nil) #:nodoc: "[#{map { |value| ActiveSupport::JSON.encode(value, options) } * ','}]" end - - alias to_json rails_to_json end diff --git a/activesupport/lib/active_support/json/encoders/false_class.rb b/activesupport/lib/active_support/json/encoders/false_class.rb index a7657cca37..4c47b3372e 100644 --- a/activesupport/lib/active_support/json/encoders/false_class.rb +++ b/activesupport/lib/active_support/json/encoders/false_class.rb @@ -2,6 +2,4 @@ class FalseClass def rails_to_json(options = nil) #:nodoc: 'false' end - - alias to_json rails_to_json end diff --git a/activesupport/lib/active_support/json/encoders/hash.rb b/activesupport/lib/active_support/json/encoders/hash.rb index 19b97d7b8c..cd8639c1dd 100644 --- a/activesupport/lib/active_support/json/encoders/hash.rb +++ b/activesupport/lib/active_support/json/encoders/hash.rb @@ -30,13 +30,15 @@ class Hash # would pass the :include => :posts option to users, # allowing the posts association in the User model to be converted to JSON # as well. - def rails_to_json(options = {}) #:nodoc: + def rails_to_json(options = nil) #:nodoc: hash_keys = self.keys - if except = options[:except] - hash_keys = hash_keys - Array.wrap(except) - elsif only = options[:only] - hash_keys = hash_keys & Array.wrap(only) + if options + if except = options[:except] + hash_keys = hash_keys - Array.wrap(except) + elsif only = options[:only] + hash_keys = hash_keys & Array.wrap(only) + end end result = '{' @@ -45,6 +47,4 @@ class Hash end * ',' result << '}' end - - alias to_json rails_to_json end diff --git a/activesupport/lib/active_support/json/encoders/nil_class.rb b/activesupport/lib/active_support/json/encoders/nil_class.rb index b31e1dd249..b7b63e26d5 100644 --- a/activesupport/lib/active_support/json/encoders/nil_class.rb +++ b/activesupport/lib/active_support/json/encoders/nil_class.rb @@ -2,6 +2,4 @@ class NilClass def rails_to_json(options = nil) #:nodoc: 'null' end - - alias to_json rails_to_json end diff --git a/activesupport/lib/active_support/json/encoders/numeric.rb b/activesupport/lib/active_support/json/encoders/numeric.rb index 491b330c39..b969902da0 100644 --- a/activesupport/lib/active_support/json/encoders/numeric.rb +++ b/activesupport/lib/active_support/json/encoders/numeric.rb @@ -2,6 +2,4 @@ class Numeric def rails_to_json(options = nil) #:nodoc: to_s end - - alias to_json rails_to_json end diff --git a/activesupport/lib/active_support/json/encoders/object.rb b/activesupport/lib/active_support/json/encoders/object.rb index d68f50562e..57603bd1e6 100644 --- a/activesupport/lib/active_support/json/encoders/object.rb +++ b/activesupport/lib/active_support/json/encoders/object.rb @@ -2,7 +2,7 @@ require 'active_support/core_ext/object/instance_variables' class Object # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info. - def rails_to_json(options = {}) + def rails_to_json(options = nil) ActiveSupport::JSON.encode(instance_values, options) end diff --git a/activesupport/lib/active_support/json/encoders/regexp.rb b/activesupport/lib/active_support/json/encoders/regexp.rb index 63ccd7c490..ff7dd67544 100644 --- a/activesupport/lib/active_support/json/encoders/regexp.rb +++ b/activesupport/lib/active_support/json/encoders/regexp.rb @@ -2,6 +2,4 @@ class Regexp def rails_to_json(options = nil) #:nodoc: inspect end - - alias to_json rails_to_json end diff --git a/activesupport/lib/active_support/json/encoders/string.rb b/activesupport/lib/active_support/json/encoders/string.rb index 27bef3b9cc..da16111fd5 100644 --- a/activesupport/lib/active_support/json/encoders/string.rb +++ b/activesupport/lib/active_support/json/encoders/string.rb @@ -33,6 +33,4 @@ class String s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/, '\\\\u\&') } + '"' end - - alias to_json rails_to_json end diff --git a/activesupport/lib/active_support/json/encoders/symbol.rb b/activesupport/lib/active_support/json/encoders/symbol.rb index 6487bf8cb7..c39eda81c1 100644 --- a/activesupport/lib/active_support/json/encoders/symbol.rb +++ b/activesupport/lib/active_support/json/encoders/symbol.rb @@ -1,7 +1,5 @@ class Symbol - def rails_to_json(options = {}) #:nodoc: + def rails_to_json(options = nil) #:nodoc: ActiveSupport::JSON.encode(to_s, options) end - - alias to_json rails_to_json end diff --git a/activesupport/lib/active_support/json/encoders/time.rb b/activesupport/lib/active_support/json/encoders/time.rb index 2699672949..1cb0808490 100644 --- a/activesupport/lib/active_support/json/encoders/time.rb +++ b/activesupport/lib/active_support/json/encoders/time.rb @@ -20,6 +20,4 @@ class Time %("#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)}") end end - - alias to_json rails_to_json end diff --git a/activesupport/lib/active_support/json/encoders/true_class.rb b/activesupport/lib/active_support/json/encoders/true_class.rb index ac7c7d1e87..a22c487a93 100644 --- a/activesupport/lib/active_support/json/encoders/true_class.rb +++ b/activesupport/lib/active_support/json/encoders/true_class.rb @@ -2,6 +2,4 @@ class TrueClass def rails_to_json(options = nil) #:nodoc: 'true' end - - alias to_json rails_to_json end diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index e8e9308495..acccb62aea 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -4,7 +4,8 @@ module ActiveSupport end # Converts a Ruby object into a JSON string. - def self.encode(value, options = {}) + def self.encode(value, options = nil) + options ||= {} seen = (options[:seen] ||= []) raise CircularReferenceError, 'object references itself' if seen.include?(value.object_id) seen << value.object_id -- cgit v1.2.3 From 4a8d2ef0a552e04d6cb35b91e23dd3979783b586 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 15:53:32 -0700 Subject: Extract json string escaping --- activesupport/lib/active_support/json.rb | 38 ++++++++++++++++++---- .../lib/active_support/json/encoders/string.rb | 33 +------------------ 2 files changed, 33 insertions(+), 38 deletions(-) diff --git a/activesupport/lib/active_support/json.rb b/activesupport/lib/active_support/json.rb index fc433de582..b2ebe9adc8 100644 --- a/activesupport/lib/active_support/json.rb +++ b/activesupport/lib/active_support/json.rb @@ -11,6 +11,33 @@ module ActiveSupport # matches YAML-formatted dates DATE_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[ \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?))$/ + module Encoding #:nodoc: + mattr_accessor :escape_regex + + ESCAPED_CHARS = { + "\010" => '\b', + "\f" => '\f', + "\n" => '\n', + "\r" => '\r', + "\t" => '\t', + '"' => '\"', + '\\' => '\\\\', + '>' => '\u003E', + '<' => '\u003C', + '&' => '\u0026' + } + + def self.escape(string) + json = '"' + string.gsub(escape_regex) { |s| ESCAPED_CHARS[s] } + json.force_encoding('ascii-8bit') if respond_to?(:force_encoding) + json.gsub(/([\xC0-\xDF][\x80-\xBF]| + [\xE0-\xEF][\x80-\xBF]{2}| + [\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s| + s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/, '\\\\u\&') + } + '"' + end + end + class << self attr_reader :backend delegate :decode, :to => :backend @@ -34,9 +61,7 @@ module ActiveSupport end class << self - def escape_html_entities_in_json - @escape_html_entities_in_json - end + attr_reader :escape_html_entities_in_json def escape_html_entities_in_json=(value) ActiveSupport::JSON::Encoding.escape_regex = \ @@ -48,8 +73,9 @@ module ActiveSupport @escape_html_entities_in_json = value end end - - JSON.backend = 'Yaml' end -require 'active_support/json/encoding' \ No newline at end of file +ActiveSupport.escape_html_entities_in_json = true +ActiveSupport::JSON.backend = 'Yaml' + +require 'active_support/json/encoding' diff --git a/activesupport/lib/active_support/json/encoders/string.rb b/activesupport/lib/active_support/json/encoders/string.rb index da16111fd5..ea82ca29fb 100644 --- a/activesupport/lib/active_support/json/encoders/string.rb +++ b/activesupport/lib/active_support/json/encoders/string.rb @@ -1,36 +1,5 @@ -module ActiveSupport - module JSON - module Encoding - mattr_accessor :escape_regex - - ESCAPED_CHARS = { - "\010" => '\b', - "\f" => '\f', - "\n" => '\n', - "\r" => '\r', - "\t" => '\t', - '"' => '\"', - '\\' => '\\\\', - '>' => '\u003E', - '<' => '\u003C', - '&' => '\u0026' - } - end - end -end - -ActiveSupport.escape_html_entities_in_json = true - class String def rails_to_json(options = nil) #:nodoc: - json = '"' + gsub(ActiveSupport::JSON::Encoding.escape_regex) { |s| - ActiveSupport::JSON::Encoding::ESCAPED_CHARS[s] - } - json.force_encoding('ascii-8bit') if respond_to?(:force_encoding) - json.gsub(/([\xC0-\xDF][\x80-\xBF]| - [\xE0-\xEF][\x80-\xBF]{2}| - [\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s| - s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/, '\\\\u\&') - } + '"' + ActiveSupport::JSON::Encoding.escape(self) end end -- cgit v1.2.3 From 3bd32754e24c4894abd2316eb0be3aeed08cf906 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 15:54:28 -0700 Subject: Privatize rails_to_json --- .../lib/active_support/json/encoders/date.rb | 37 ++++----- .../lib/active_support/json/encoders/date_time.rb | 37 ++++----- .../lib/active_support/json/encoders/enumerable.rb | 21 +++--- .../active_support/json/encoders/false_class.rb | 7 +- .../lib/active_support/json/encoders/hash.rb | 87 +++++++++++----------- .../lib/active_support/json/encoders/nil_class.rb | 7 +- .../lib/active_support/json/encoders/numeric.rb | 7 +- .../lib/active_support/json/encoders/object.rb | 9 ++- .../lib/active_support/json/encoders/regexp.rb | 7 +- .../lib/active_support/json/encoders/string.rb | 7 +- .../lib/active_support/json/encoders/symbol.rb | 7 +- .../lib/active_support/json/encoders/time.rb | 37 ++++----- .../lib/active_support/json/encoders/true_class.rb | 7 +- activesupport/lib/active_support/json/variable.rb | 7 +- activesupport/lib/active_support/time_with_zone.rb | 42 +++++------ activesupport/test/json/encoding_test.rb | 2 +- 16 files changed, 171 insertions(+), 157 deletions(-) diff --git a/activesupport/lib/active_support/json/encoders/date.rb b/activesupport/lib/active_support/json/encoders/date.rb index 1aebdd2764..f1479e11e0 100644 --- a/activesupport/lib/active_support/json/encoders/date.rb +++ b/activesupport/lib/active_support/json/encoders/date.rb @@ -1,21 +1,22 @@ class Date - # Returns a JSON string representing the date. If ActiveSupport.use_standard_json_time_format is set to true, the - # ISO 8601 format is used. - # - # ==== Examples - # - # # With ActiveSupport.use_standard_json_time_format = true - # Date.new(2005,2,1).to_json - # # => "2005-02-01" - # - # # With ActiveSupport.use_standard_json_time_format = false - # Date.new(2005,2,1).to_json - # # => "2005/02/01" - def rails_to_json(options = nil) - if ActiveSupport.use_standard_json_time_format - %("#{strftime("%Y-%m-%d")}") - else - %("#{strftime("%Y/%m/%d")}") + private + # Returns a JSON string representing the date. If ActiveSupport.use_standard_json_time_format is set to true, the + # ISO 8601 format is used. + # + # ==== Examples + # + # # With ActiveSupport.use_standard_json_time_format = true + # Date.new(2005,2,1).to_json + # # => "2005-02-01" + # + # # With ActiveSupport.use_standard_json_time_format = false + # Date.new(2005,2,1).to_json + # # => "2005/02/01" + def rails_to_json(options = nil) + if ActiveSupport.use_standard_json_time_format + %("#{strftime("%Y-%m-%d")}") + else + %("#{strftime("%Y/%m/%d")}") + end end - end end diff --git a/activesupport/lib/active_support/json/encoders/date_time.rb b/activesupport/lib/active_support/json/encoders/date_time.rb index 096e0dd36b..343612afe9 100644 --- a/activesupport/lib/active_support/json/encoders/date_time.rb +++ b/activesupport/lib/active_support/json/encoders/date_time.rb @@ -1,21 +1,22 @@ class DateTime - # Returns a JSON string representing the datetime. If ActiveSupport.use_standard_json_time_format is set to true, the - # ISO 8601 format is used. - # - # ==== Examples - # - # # With ActiveSupport.use_standard_json_time_format = true - # DateTime.civil(2005,2,1,15,15,10).to_json - # # => "2005-02-01T15:15:10+00:00" - # - # # With ActiveSupport.use_standard_json_time_format = false - # DateTime.civil(2005,2,1,15,15,10).to_json - # # => "2005/02/01 15:15:10 +0000" - def rails_to_json(options = nil) - if ActiveSupport.use_standard_json_time_format - xmlschema.inspect - else - strftime('"%Y/%m/%d %H:%M:%S %z"') + private + # Returns a JSON string representing the datetime. If ActiveSupport.use_standard_json_time_format is set to true, the + # ISO 8601 format is used. + # + # ==== Examples + # + # # With ActiveSupport.use_standard_json_time_format = true + # DateTime.civil(2005,2,1,15,15,10).to_json + # # => "2005-02-01T15:15:10+00:00" + # + # # With ActiveSupport.use_standard_json_time_format = false + # DateTime.civil(2005,2,1,15,15,10).to_json + # # => "2005/02/01 15:15:10 +0000" + def rails_to_json(options = nil) + if ActiveSupport.use_standard_json_time_format + xmlschema.inspect + else + strftime('"%Y/%m/%d %H:%M:%S %z"') + end end - end end diff --git a/activesupport/lib/active_support/json/encoders/enumerable.rb b/activesupport/lib/active_support/json/encoders/enumerable.rb index 6e0c3b6b9c..adde7445b3 100644 --- a/activesupport/lib/active_support/json/encoders/enumerable.rb +++ b/activesupport/lib/active_support/json/encoders/enumerable.rb @@ -1,12 +1,13 @@ module Enumerable - # Returns a JSON string representing the enumerable. Any +options+ - # given will be passed on to its elements. For example: - # - # users = User.find(:all) - # # => users.to_json(:only => :name) - # - # will pass the :only => :name option to each user. - def rails_to_json(options = nil) #:nodoc: - "[#{map { |value| ActiveSupport::JSON.encode(value, options) } * ','}]" - end + private + # Returns a JSON string representing the enumerable. Any +options+ + # given will be passed on to its elements. For example: + # + # users = User.find(:all) + # # => users.to_json(:only => :name) + # + # will pass the :only => :name option to each user. + def rails_to_json(options = nil) #:nodoc: + "[#{map { |value| ActiveSupport::JSON.encode(value, options) } * ','}]" + end end diff --git a/activesupport/lib/active_support/json/encoders/false_class.rb b/activesupport/lib/active_support/json/encoders/false_class.rb index 4c47b3372e..673465860a 100644 --- a/activesupport/lib/active_support/json/encoders/false_class.rb +++ b/activesupport/lib/active_support/json/encoders/false_class.rb @@ -1,5 +1,6 @@ class FalseClass - def rails_to_json(options = nil) #:nodoc: - 'false' - end + private + def rails_to_json(options = nil) + 'false' + end end diff --git a/activesupport/lib/active_support/json/encoders/hash.rb b/activesupport/lib/active_support/json/encoders/hash.rb index cd8639c1dd..5aec547b9b 100644 --- a/activesupport/lib/active_support/json/encoders/hash.rb +++ b/activesupport/lib/active_support/json/encoders/hash.rb @@ -1,50 +1,51 @@ require 'active_support/core_ext/array/wrap' class Hash - # Returns a JSON string representing the hash. - # - # Without any +options+, the returned JSON string will include all - # the hash keys. For example: - # - # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json - # # => {"name": "Konata Izumi", "1": 2, "age": 16} - # - # The keys in the JSON string are unordered due to the nature of hashes. - # - # The :only and :except options can be used to limit the - # attributes included, and will accept 1 or more hash keys to include/exclude. - # - # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json(:only => [:name, 'age']) - # # => {"name": "Konata Izumi", "age": 16} - # - # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json(:except => 1) - # # => {"name": "Konata Izumi", "age": 16} - # - # The +options+ also filter down to any hash values. This is particularly - # useful for converting hashes containing ActiveRecord objects or any object - # that responds to options in their to_json method. For example: - # - # users = User.find(:all) - # { :users => users, :count => users.size }.to_json(:include => :posts) - # - # would pass the :include => :posts option to users, - # allowing the posts association in the User model to be converted to JSON - # as well. - def rails_to_json(options = nil) #:nodoc: - hash_keys = self.keys + private + # Returns a JSON string representing the hash. + # + # Without any +options+, the returned JSON string will include all + # the hash keys. For example: + # + # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json + # # => {"name": "Konata Izumi", "1": 2, "age": 16} + # + # The keys in the JSON string are unordered due to the nature of hashes. + # + # The :only and :except options can be used to limit the + # attributes included, and will accept 1 or more hash keys to include/exclude. + # + # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json(:only => [:name, 'age']) + # # => {"name": "Konata Izumi", "age": 16} + # + # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json(:except => 1) + # # => {"name": "Konata Izumi", "age": 16} + # + # The +options+ also filter down to any hash values. This is particularly + # useful for converting hashes containing ActiveRecord objects or any object + # that responds to options in their to_json method. For example: + # + # users = User.find(:all) + # { :users => users, :count => users.size }.to_json(:include => :posts) + # + # would pass the :include => :posts option to users, + # allowing the posts association in the User model to be converted to JSON + # as well. + def rails_to_json(options = nil) #:nodoc: + hash_keys = self.keys - if options - if except = options[:except] - hash_keys = hash_keys - Array.wrap(except) - elsif only = options[:only] - hash_keys = hash_keys & Array.wrap(only) + if options + if except = options[:except] + hash_keys = hash_keys - Array.wrap(except) + elsif only = options[:only] + hash_keys = hash_keys & Array.wrap(only) + end end - end - result = '{' - result << hash_keys.map do |key| - "#{ActiveSupport::JSON.encode(key.to_s)}:#{ActiveSupport::JSON.encode(self[key], options)}" - end * ',' - result << '}' - end + result = '{' + result << hash_keys.map do |key| + "#{ActiveSupport::JSON.encode(key.to_s)}:#{ActiveSupport::JSON.encode(self[key], options)}" + end * ',' + result << '}' + end end diff --git a/activesupport/lib/active_support/json/encoders/nil_class.rb b/activesupport/lib/active_support/json/encoders/nil_class.rb index b7b63e26d5..5343badc9c 100644 --- a/activesupport/lib/active_support/json/encoders/nil_class.rb +++ b/activesupport/lib/active_support/json/encoders/nil_class.rb @@ -1,5 +1,6 @@ class NilClass - def rails_to_json(options = nil) #:nodoc: - 'null' - end + private + def rails_to_json(options = nil) + 'null' + end end diff --git a/activesupport/lib/active_support/json/encoders/numeric.rb b/activesupport/lib/active_support/json/encoders/numeric.rb index b969902da0..42de2f4ea7 100644 --- a/activesupport/lib/active_support/json/encoders/numeric.rb +++ b/activesupport/lib/active_support/json/encoders/numeric.rb @@ -1,5 +1,6 @@ class Numeric - def rails_to_json(options = nil) #:nodoc: - to_s - end + private + def rails_to_json(options = nil) + to_s + end end diff --git a/activesupport/lib/active_support/json/encoders/object.rb b/activesupport/lib/active_support/json/encoders/object.rb index 57603bd1e6..4722feb7db 100644 --- a/activesupport/lib/active_support/json/encoders/object.rb +++ b/activesupport/lib/active_support/json/encoders/object.rb @@ -2,9 +2,12 @@ require 'active_support/core_ext/object/instance_variables' class Object # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info. - def rails_to_json(options = nil) - ActiveSupport::JSON.encode(instance_values, options) + def to_json(options = nil) + rails_to_json(options) end - alias to_json rails_to_json + private + def rails_to_json(options = nil) + ActiveSupport::JSON.encode(instance_values, options) + end end diff --git a/activesupport/lib/active_support/json/encoders/regexp.rb b/activesupport/lib/active_support/json/encoders/regexp.rb index ff7dd67544..62be810be5 100644 --- a/activesupport/lib/active_support/json/encoders/regexp.rb +++ b/activesupport/lib/active_support/json/encoders/regexp.rb @@ -1,5 +1,6 @@ class Regexp - def rails_to_json(options = nil) #:nodoc: - inspect - end + private + def rails_to_json(options = nil) + inspect + end end diff --git a/activesupport/lib/active_support/json/encoders/string.rb b/activesupport/lib/active_support/json/encoders/string.rb index ea82ca29fb..6b9dcd97bf 100644 --- a/activesupport/lib/active_support/json/encoders/string.rb +++ b/activesupport/lib/active_support/json/encoders/string.rb @@ -1,5 +1,6 @@ class String - def rails_to_json(options = nil) #:nodoc: - ActiveSupport::JSON::Encoding.escape(self) - end + private + def rails_to_json(options = nil) + ActiveSupport::JSON::Encoding.escape(self) + end end diff --git a/activesupport/lib/active_support/json/encoders/symbol.rb b/activesupport/lib/active_support/json/encoders/symbol.rb index c39eda81c1..333cf773c1 100644 --- a/activesupport/lib/active_support/json/encoders/symbol.rb +++ b/activesupport/lib/active_support/json/encoders/symbol.rb @@ -1,5 +1,6 @@ class Symbol - def rails_to_json(options = nil) #:nodoc: - ActiveSupport::JSON.encode(to_s, options) - end + private + def rails_to_json(options = nil) + ActiveSupport::JSON.encode(to_s, options) + end end diff --git a/activesupport/lib/active_support/json/encoders/time.rb b/activesupport/lib/active_support/json/encoders/time.rb index 1cb0808490..c1cf3398c2 100644 --- a/activesupport/lib/active_support/json/encoders/time.rb +++ b/activesupport/lib/active_support/json/encoders/time.rb @@ -1,23 +1,24 @@ require 'active_support/core_ext/time/conversions' class Time - # Returns a JSON string representing the time. If ActiveSupport.use_standard_json_time_format is set to true, the - # ISO 8601 format is used. - # - # ==== Examples - # - # # With ActiveSupport.use_standard_json_time_format = true - # Time.utc(2005,2,1,15,15,10).to_json - # # => "2005-02-01T15:15:10Z" - # - # # With ActiveSupport.use_standard_json_time_format = false - # Time.utc(2005,2,1,15,15,10).to_json - # # => "2005/02/01 15:15:10 +0000" - def rails_to_json(options = nil) - if ActiveSupport.use_standard_json_time_format - xmlschema.inspect - else - %("#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)}") + private + # Returns a JSON string representing the time. If ActiveSupport.use_standard_json_time_format is set to true, the + # ISO 8601 format is used. + # + # ==== Examples + # + # # With ActiveSupport.use_standard_json_time_format = true + # Time.utc(2005,2,1,15,15,10).to_json + # # => "2005-02-01T15:15:10Z" + # + # # With ActiveSupport.use_standard_json_time_format = false + # Time.utc(2005,2,1,15,15,10).to_json + # # => "2005/02/01 15:15:10 +0000" + def rails_to_json(options = nil) + if ActiveSupport.use_standard_json_time_format + xmlschema.inspect + else + %("#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)}") + end end - end end diff --git a/activesupport/lib/active_support/json/encoders/true_class.rb b/activesupport/lib/active_support/json/encoders/true_class.rb index a22c487a93..6d5d063254 100644 --- a/activesupport/lib/active_support/json/encoders/true_class.rb +++ b/activesupport/lib/active_support/json/encoders/true_class.rb @@ -1,5 +1,6 @@ class TrueClass - def rails_to_json(options = nil) #:nodoc: - 'true' - end + private + def rails_to_json(options = nil) + 'true' + end end diff --git a/activesupport/lib/active_support/json/variable.rb b/activesupport/lib/active_support/json/variable.rb index 3ee152ee3c..2c7b449a50 100644 --- a/activesupport/lib/active_support/json/variable.rb +++ b/activesupport/lib/active_support/json/variable.rb @@ -2,9 +2,10 @@ module ActiveSupport module JSON # A string that returns itself as its JSON-encoded form. class Variable < String - def rails_to_json(options=nil) - self - end + private + def rails_to_json(options = nil) + self + end end end end diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 1949ce0ad3..c02ee1a524 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -118,28 +118,6 @@ module ActiveSupport end alias_method :iso8601, :xmlschema - # Returns a JSON string representing the TimeWithZone. If ActiveSupport.use_standard_json_time_format is set to - # true, the ISO 8601 format is used. - # - # ==== Examples - # - # # With ActiveSupport.use_standard_json_time_format = true - # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json - # # => "2005-02-01T15:15:10Z" - # - # # With ActiveSupport.use_standard_json_time_format = false - # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json - # # => "2005/02/01 15:15:10 +0000" - def rails_to_json(options = nil) - if !ActiveSupport.respond_to?(:use_standard_json_time_format) || ActiveSupport.use_standard_json_time_format - xmlschema.inspect - else - %("#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)}") - end - end - - alias to_json rails_to_json - def to_yaml(options = {}) if options.kind_of?(YAML::Emitter) utc.to_yaml(options) @@ -323,6 +301,26 @@ module ActiveSupport end private + # Returns a JSON string representing the TimeWithZone. If ActiveSupport.use_standard_json_time_format is set to + # true, the ISO 8601 format is used. + # + # ==== Examples + # + # # With ActiveSupport.use_standard_json_time_format = true + # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json + # # => "2005-02-01T15:15:10Z" + # + # # With ActiveSupport.use_standard_json_time_format = false + # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json + # # => "2005/02/01 15:15:10 +0000" + def rails_to_json(options = nil) + if !ActiveSupport.respond_to?(:use_standard_json_time_format) || ActiveSupport.use_standard_json_time_format + xmlschema.inspect + else + %("#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)}") + end + end + def get_period_and_ensure_valid_local_time # we don't want a Time.local instance enforcing its own DST rules as well, # so transfer time values to a utc constructor if necessary diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index db24b3d96a..1a0e6d543c 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -134,6 +134,6 @@ class JsonOptionsTests < Test::Unit::TestCase ActiveSupport::JSON.expects(:encode).with(2, json_options) ActiveSupport::JSON.expects(:encode).with('foo', json_options) - [1, 2, 'foo'].rails_to_json(json_options) + [1, 2, 'foo'].send(:rails_to_json, json_options) end end -- cgit v1.2.3 From ea712364e202816ce99f53824f01d0aa6f178247 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 15:56:08 -0700 Subject: Don't undefine object_id --- activesupport/lib/active_support/deprecation/proxy_wrappers.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb index ec54efe08e..dec56715be 100644 --- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb +++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb @@ -3,7 +3,7 @@ require 'active_support/inflector' module ActiveSupport module Deprecation class DeprecationProxy #:nodoc: - instance_methods.each { |m| undef_method m unless m =~ /^__/ } + instance_methods.each { |m| undef_method m unless m =~ /^__|^object_id$/ } # Don't give a deprecation warning on inspect since test/unit and error # logs rely on it for diagnostics. -- cgit v1.2.3 From c9d9bd7227b687f2162bd485b891aa2c2499adf0 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 16:04:11 -0700 Subject: Check for to_str rather than String --- actionpack/lib/action_dispatch/http/response.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 77c2dd0d7a..c2add1272e 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -98,7 +98,7 @@ module ActionDispatch # :nodoc: def body=(body) @body = - if body.is_a?(String) + if body.respond_to?(:to_str) [body] else body @@ -215,8 +215,6 @@ module ActionDispatch # :nodoc: if @body.respond_to?(:call) @writer = lambda { |x| callback.call(x) } @body.call(self, self) - elsif @body.is_a?(String) - callback.call(@body) else @body.each(&callback) end -- cgit v1.2.3 From 3f632027819ab331187ca58c014458dfcfd57a89 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 16:04:29 -0700 Subject: Don't assume :params is a Hash --- actionpack/lib/action_dispatch/test/mock.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/actionpack/lib/action_dispatch/test/mock.rb b/actionpack/lib/action_dispatch/test/mock.rb index 86269fad01..8dc048af11 100644 --- a/actionpack/lib/action_dispatch/test/mock.rb +++ b/actionpack/lib/action_dispatch/test/mock.rb @@ -21,10 +21,7 @@ module ActionDispatch if method == "POST" && !opts.has_key?(:input) opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded" - multipart = (opts[:params] || {}).any? do |k, v| - UploadedFile === v - end - + multipart = opts[:params].respond_to?(:any?) && opts[:params].any? { |k, v| UploadedFile === v } if multipart opts[:input] = multipart_body(opts.delete(:params)) opts["CONTENT_LENGTH"] ||= opts[:input].length.to_s -- cgit v1.2.3 From 1d71a34afa206e611d2dc5368c55cc4aed25ba01 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Sun, 15 Mar 2009 06:32:29 -0400 Subject: add JRuby-JDOM backend for XmlMini Signed-off-by: Jeremy Kemper --- activesupport/lib/active_support/xml_mini/jdom.rb | 162 ++++++++++++++++++++++ activesupport/test/xml_mini/jdom_engine_test.rb | 153 ++++++++++++++++++++ 2 files changed, 315 insertions(+) create mode 100644 activesupport/lib/active_support/xml_mini/jdom.rb create mode 100644 activesupport/test/xml_mini/jdom_engine_test.rb diff --git a/activesupport/lib/active_support/xml_mini/jdom.rb b/activesupport/lib/active_support/xml_mini/jdom.rb new file mode 100644 index 0000000000..d795d55690 --- /dev/null +++ b/activesupport/lib/active_support/xml_mini/jdom.rb @@ -0,0 +1,162 @@ +raise "JRuby is required to use the JDOM backend for XmlMini" unless RUBY_PLATFORM =~ /java/ + +require 'jruby' +include Java + +import javax.xml.parsers.DocumentBuilder unless defined? DocumentBuilder +import javax.xml.parsers.DocumentBuilderFactory unless defined? DocumentBuilderFactory +import java.io.StringReader unless defined? StringReader +import org.xml.sax.InputSource unless defined? InputSource +import org.xml.sax.Attributes unless defined? Attributes +import org.w3c.dom.Node unless defined? Node + +# = XmlMini JRuby JDOM implementation +module ActiveSupport + module XmlMini_JDOM #:nodoc: + extend self + + CONTENT_KEY = '__content__'.freeze + + NODE_TYPE_NAMES = %w{ATTRIBUTE_NODE CDATA_SECTION_NODE COMMENT_NODE DOCUMENT_FRAGMENT_NODE + DOCUMENT_NODE DOCUMENT_TYPE_NODE ELEMENT_NODE ENTITY_NODE ENTITY_REFERENCE_NODE NOTATION_NODE + PROCESSING_INSTRUCTION_NODE TEXT_NODE} + + node_type_map = {} + NODE_TYPE_NAMES.each { |type| node_type_map[Node.send(type)] = type } + + # Parse an XML Document string into a simple hash using Java's jdom. + # string:: + # XML Document string to parse + def parse(string) + if string.blank? + {} + else + @dbf = DocumentBuilderFactory.new_instance + xml_string_reader = StringReader.new(string) + xml_input_source = InputSource.new(xml_string_reader) + doc = @dbf.new_document_builder.parse(xml_input_source) + merge_element!({}, doc.document_element) + end + end + + private + + # Convert an XML element and merge into the hash + # + # hash:: + # Hash to merge the converted element into. + # element:: + # XML element to merge into hash + def merge_element!(hash, element) + merge!(hash, element.tag_name, collapse(element)) + end + + # Actually converts an XML document element into a data structure. + # + # element:: + # The document element to be collapsed. + def collapse(element) + hash = get_attributes(element) + + child_nodes = element.child_nodes + if child_nodes.length > 0 + for i in 0...child_nodes.length + child = child_nodes.item(i) + merge_element!(hash, child) unless child.node_type == Node.TEXT_NODE + end + merge_texts!(hash, element) unless empty_content?(element) + hash + else + merge_texts!(hash, element) + end + end + + # Merge all the texts of an element into the hash + # + # hash:: + # Hash to add the converted emement to. + # element:: + # XML element whose texts are to me merged into the hash + def merge_texts!(hash, element) + text_children = texts(element) + if text_children.join.empty? + hash + else + # must use value to prevent double-escaping + merge!(hash, CONTENT_KEY, text_children.join) + end + end + + # Adds a new key/value pair to an existing Hash. If the key to be added + # already exists and the existing value associated with key is not + # an Array, it will be wrapped in an Array. Then the new value is + # appended to that Array. + # + # hash:: + # Hash to add key/value pair to. + # key:: + # Key to be added. + # value:: + # Value to be associated with key. + def merge!(hash, key, value) + if hash.has_key?(key) + if hash[key].instance_of?(Array) + hash[key] << value + else + hash[key] = [hash[key], value] + end + elsif value.instance_of?(Array) + hash[key] = [value] + else + hash[key] = value + end + hash + end + + # Converts the attributes array of an XML element into a hash. + # Returns an empty Hash if node has no attributes. + # + # element:: + # XML element to extract attributes from. + def get_attributes(element) + attribute_hash = {} + attributes = element.attributes + for i in 0...attributes.length + attribute_hash[attributes.item(i).name] = attributes.item(i).value + end + attribute_hash + end + + # Determines if a document element has text content + # + # element:: + # XML element to be checked. + def texts(element) + texts = [] + child_nodes = element.child_nodes + for i in 0...child_nodes.length + item = child_nodes.item(i) + if item.node_type == Node.TEXT_NODE + texts << item.get_data + end + end + texts + end + + # Determines if a document element has text content + # + # element:: + # XML element to be checked. + def empty_content?(element) + text = '' + child_nodes = element.child_nodes + for i in 0...child_nodes.length + item = child_nodes.item(i) + if item.node_type == Node.TEXT_NODE + text << item.get_data.strip + end + end + text.strip.length == 0 + end + end +end diff --git a/activesupport/test/xml_mini/jdom_engine_test.rb b/activesupport/test/xml_mini/jdom_engine_test.rb new file mode 100644 index 0000000000..b745228994 --- /dev/null +++ b/activesupport/test/xml_mini/jdom_engine_test.rb @@ -0,0 +1,153 @@ +require 'abstract_unit' +require 'active_support/xml_mini' + +if RUBY_PLATFORM =~ /java/ + +class JDOMEngineTest < Test::Unit::TestCase + include ActiveSupport + + def setup + @default_backend = XmlMini.backend + XmlMini.backend = 'JDOM' + end + + def teardown + XmlMini.backend = @default_backend + end + + # def test_file_from_xml + # hash = Hash.from_xml(<<-eoxml) + # + # + # + # + # eoxml + # assert hash.has_key?('blog') + # assert hash['blog'].has_key?('logo') + # + # file = hash['blog']['logo'] + # assert_equal 'logo.png', file.original_filename + # assert_equal 'image/png', file.content_type + # end + + def test_exception_thrown_on_expansion_attack + assert_raise NativeException do + attack_xml = <<-EOT + + + + + + + + + ]> + + &a; + + EOT + Hash.from_xml(attack_xml) + end + end + + def test_setting_JDOM_as_backend + XmlMini.backend = 'JDOM' + assert_equal XmlMini_JDOM, XmlMini.backend + end + + def test_blank_returns_empty_hash + assert_equal({}, XmlMini.parse(nil)) + assert_equal({}, XmlMini.parse('')) + end + + def test_array_type_makes_an_array + assert_equal_rexml(<<-eoxml) + + + a post + another post + + + eoxml + end + + def test_one_node_document_as_hash + assert_equal_rexml(<<-eoxml) + + eoxml + end + + def test_one_node_with_attributes_document_as_hash + assert_equal_rexml(<<-eoxml) + + eoxml + end + + def test_products_node_with_book_node_as_hash + assert_equal_rexml(<<-eoxml) + + + + eoxml + end + + def test_products_node_with_two_book_nodes_as_hash + assert_equal_rexml(<<-eoxml) + + + + + eoxml + end + + def test_single_node_with_content_as_hash + assert_equal_rexml(<<-eoxml) + + hello world + + eoxml + end + + def test_children_with_children + assert_equal_rexml(<<-eoxml) + + + + + + eoxml + end + + def test_children_with_text + assert_equal_rexml(<<-eoxml) + + + hello everyone + + + eoxml + end + + def test_children_with_non_adjacent_text + assert_equal_rexml(<<-eoxml) + + good + + hello everyone + + morning + + eoxml + end + + private + def assert_equal_rexml(xml) + hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) } + assert_equal(hash, XmlMini.parse(xml)) + end +end + +else + # don't run these test because we aren't running in JRuby +end -- cgit v1.2.3 From 8aaed3d456bad8a0bdf4789b69b41f7d817f981c Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 16:21:57 -0700 Subject: Convert encoding before escaping --- activesupport/lib/active_support/json.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/activesupport/lib/active_support/json.rb b/activesupport/lib/active_support/json.rb index b2ebe9adc8..5072992cdf 100644 --- a/activesupport/lib/active_support/json.rb +++ b/activesupport/lib/active_support/json.rb @@ -28,13 +28,14 @@ module ActiveSupport } def self.escape(string) - json = '"' + string.gsub(escape_regex) { |s| ESCAPED_CHARS[s] } - json.force_encoding('ascii-8bit') if respond_to?(:force_encoding) - json.gsub(/([\xC0-\xDF][\x80-\xBF]| + string = string.dup.force_encoding(::Encoding::BINARY) if string.respond_to?(:force_encoding) + json = string.gsub(escape_regex) { |s| ESCAPED_CHARS[s] }. + gsub(/([\xC0-\xDF][\x80-\xBF]| [\xE0-\xEF][\x80-\xBF]{2}| [\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s| - s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/, '\\\\u\&') - } + '"' + s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/, '\\\\u\&') + } + %("#{json}") end end -- cgit v1.2.3 From f7d7dc5aa8a5facc357ed291819db23e3f3df9b6 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 17:19:14 -0700 Subject: Use session= writer methods --- actionpack/lib/action_controller/testing/process.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index 16275371ad..c532a67e78 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -14,8 +14,8 @@ module ActionController #:nodoc: super(Rack::MockRequest.env_for("/").merge(env)) @query_parameters = {} - @env['rack.session'] = TestSession.new - @env['rack.session.options'] = TestSession::DEFAULT_OPTIONS.merge(:id => ActiveSupport::SecureRandom.hex(16)) + self.session = TestSession.new + self.session_options = TestSession::DEFAULT_OPTIONS.merge(:id => ActiveSupport::SecureRandom.hex(16)) initialize_default_values initialize_containers -- cgit v1.2.3 From 1850aea7fc9a1353de8e87adadf5230269b358c1 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 18:26:06 -0700 Subject: Not sure why Request#session is missing --- actionpack/lib/action_dispatch/http/request.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 2602b344ca..0b8909ced7 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -451,6 +451,14 @@ EOM @env['rack.input'] end + def session + @env['rack.session'] + end + + def session_options + @env['rack.session.options'] + end + def reset_session self.session_options.delete(:id) self.session = {} -- cgit v1.2.3 From f5b4a9d02bc2292bae59e7b4fc028cce6edb91f7 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 18:27:41 -0700 Subject: Array splitting strings on newlines is deprecated --- actionpack/lib/action_dispatch/http/response.rb | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index c2add1272e..6c92fb9713 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -245,9 +245,14 @@ module ActionDispatch # :nodoc: # assert_equal 'AuthorOfNewPage', r.cookies['author'] def cookies cookies = {} - Array(headers['Set-Cookie']).each do |cookie| - key, value = cookie.split(";").first.split("=").map { |v| Rack::Utils.unescape(v) } - cookies[key] = value + if header = headers['Set-Cookie'] + header = header.split("\n") if header.respond_to?(:to_str) + header.each do |cookie| + if pair = cookie.split(';').first + key, value = pair.split("=").map { |v| Rack::Utils.unescape(v) } + cookies[key] = value + end + end end cookies end @@ -305,7 +310,13 @@ module ActionDispatch # :nodoc: end def convert_cookies! - headers['Set-Cookie'] = Array(headers['Set-Cookie']).compact + headers['Set-Cookie'] = + if header = headers['Set-Cookie'] + header = header.split("\n") if header.respond_to?(:to_str) + header.compact + else + [] + end end end end -- cgit v1.2.3 From 5cef0cbad2d1df013c74ab96c16cf7fd84040f46 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 19:08:04 -0700 Subject: Check for to_str rather than String --- actionpack/lib/action_controller/base/render.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_controller/base/render.rb b/actionpack/lib/action_controller/base/render.rb index 33695cd78e..601c5429c3 100644 --- a/actionpack/lib/action_controller/base/render.rb +++ b/actionpack/lib/action_controller/base/render.rb @@ -254,7 +254,7 @@ module ActionController render_for_text(js) elsif json = options[:json] - json = ActiveSupport::JSON.encode(json) unless json.is_a?(String) + json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str) json = "#{options[:callback]}(#{json})" unless options[:callback].blank? response.content_type ||= Mime::JSON render_for_text(json) -- cgit v1.2.3 From 678385d307559b2b5737bb2b07f633d2b9a0802c Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 19:59:22 -0700 Subject: Use javascript_object_for --- actionpack/lib/action_view/helpers/prototype_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index 9cafd17004..a44c144d53 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -973,7 +973,7 @@ module ActionView def loop_on_multiple_args(method, ids) record(ids.size>1 ? "#{javascript_object_for(ids)}.each(#{method})" : - "#{method}(#{::ActiveSupport::JSON.encode(ids.first)})") + "#{method}(#{javascript_object_for(ids.first)})") end def page -- cgit v1.2.3 From ee46ffedb88f812467485167036c7d254d0ce757 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 20:04:47 -0700 Subject: Now that we have a separate internal rails_to_json, use a separate circular reference stack instead of sticking it in the options hash --- actionpack/lib/action_view/helpers/prototype_helper.rb | 4 ++-- activesupport/lib/active_support/json/encoders/date.rb | 2 +- activesupport/lib/active_support/json/encoders/date_time.rb | 2 +- .../lib/active_support/json/encoders/enumerable.rb | 4 ++-- .../lib/active_support/json/encoders/false_class.rb | 2 +- activesupport/lib/active_support/json/encoders/hash.rb | 4 ++-- activesupport/lib/active_support/json/encoders/nil_class.rb | 2 +- activesupport/lib/active_support/json/encoders/numeric.rb | 2 +- activesupport/lib/active_support/json/encoders/object.rb | 6 +++--- activesupport/lib/active_support/json/encoders/regexp.rb | 2 +- activesupport/lib/active_support/json/encoders/string.rb | 2 +- activesupport/lib/active_support/json/encoders/symbol.rb | 4 ++-- activesupport/lib/active_support/json/encoders/time.rb | 2 +- .../lib/active_support/json/encoders/true_class.rb | 2 +- activesupport/lib/active_support/json/encoding.rb | 13 +++++++------ activesupport/lib/active_support/json/variable.rb | 2 +- activesupport/lib/active_support/time_with_zone.rb | 2 +- 17 files changed, 29 insertions(+), 28 deletions(-) diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index a44c144d53..1fbe012a95 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -1180,11 +1180,11 @@ module ActionView # The JSON Encoder calls this to check for the +to_json+ method # Since it's a blank slate object, I suppose it responds to anything. - def respond_to?(method) + def respond_to?(*) true end - def rails_to_json(options = nil) + def rails_to_json(*) @variable end diff --git a/activesupport/lib/active_support/json/encoders/date.rb b/activesupport/lib/active_support/json/encoders/date.rb index f1479e11e0..9adb3c20e2 100644 --- a/activesupport/lib/active_support/json/encoders/date.rb +++ b/activesupport/lib/active_support/json/encoders/date.rb @@ -12,7 +12,7 @@ class Date # # With ActiveSupport.use_standard_json_time_format = false # Date.new(2005,2,1).to_json # # => "2005/02/01" - def rails_to_json(options = nil) + def rails_to_json(*) if ActiveSupport.use_standard_json_time_format %("#{strftime("%Y-%m-%d")}") else diff --git a/activesupport/lib/active_support/json/encoders/date_time.rb b/activesupport/lib/active_support/json/encoders/date_time.rb index 343612afe9..3a29292b24 100644 --- a/activesupport/lib/active_support/json/encoders/date_time.rb +++ b/activesupport/lib/active_support/json/encoders/date_time.rb @@ -12,7 +12,7 @@ class DateTime # # With ActiveSupport.use_standard_json_time_format = false # DateTime.civil(2005,2,1,15,15,10).to_json # # => "2005/02/01 15:15:10 +0000" - def rails_to_json(options = nil) + def rails_to_json(*) if ActiveSupport.use_standard_json_time_format xmlschema.inspect else diff --git a/activesupport/lib/active_support/json/encoders/enumerable.rb b/activesupport/lib/active_support/json/encoders/enumerable.rb index adde7445b3..898990a59c 100644 --- a/activesupport/lib/active_support/json/encoders/enumerable.rb +++ b/activesupport/lib/active_support/json/encoders/enumerable.rb @@ -7,7 +7,7 @@ module Enumerable # # => users.to_json(:only => :name) # # will pass the :only => :name option to each user. - def rails_to_json(options = nil) #:nodoc: - "[#{map { |value| ActiveSupport::JSON.encode(value, options) } * ','}]" + def rails_to_json(options = nil, *args) #:nodoc: + "[#{map { |value| ActiveSupport::JSON.encode(value, options, *args) } * ','}]" end end diff --git a/activesupport/lib/active_support/json/encoders/false_class.rb b/activesupport/lib/active_support/json/encoders/false_class.rb index 673465860a..eb975fe542 100644 --- a/activesupport/lib/active_support/json/encoders/false_class.rb +++ b/activesupport/lib/active_support/json/encoders/false_class.rb @@ -1,6 +1,6 @@ class FalseClass private - def rails_to_json(options = nil) + def rails_to_json(*) 'false' end end diff --git a/activesupport/lib/active_support/json/encoders/hash.rb b/activesupport/lib/active_support/json/encoders/hash.rb index 5aec547b9b..4771484843 100644 --- a/activesupport/lib/active_support/json/encoders/hash.rb +++ b/activesupport/lib/active_support/json/encoders/hash.rb @@ -31,7 +31,7 @@ class Hash # would pass the :include => :posts option to users, # allowing the posts association in the User model to be converted to JSON # as well. - def rails_to_json(options = nil) #:nodoc: + def rails_to_json(options = nil, *args) #:nodoc: hash_keys = self.keys if options @@ -44,7 +44,7 @@ class Hash result = '{' result << hash_keys.map do |key| - "#{ActiveSupport::JSON.encode(key.to_s)}:#{ActiveSupport::JSON.encode(self[key], options)}" + "#{ActiveSupport::JSON.encode(key.to_s)}:#{ActiveSupport::JSON.encode(self[key], options, *args)}" end * ',' result << '}' end diff --git a/activesupport/lib/active_support/json/encoders/nil_class.rb b/activesupport/lib/active_support/json/encoders/nil_class.rb index 5343badc9c..8c51dba384 100644 --- a/activesupport/lib/active_support/json/encoders/nil_class.rb +++ b/activesupport/lib/active_support/json/encoders/nil_class.rb @@ -1,6 +1,6 @@ class NilClass private - def rails_to_json(options = nil) + def rails_to_json(*) 'null' end end diff --git a/activesupport/lib/active_support/json/encoders/numeric.rb b/activesupport/lib/active_support/json/encoders/numeric.rb index 42de2f4ea7..c7cd0df1d7 100644 --- a/activesupport/lib/active_support/json/encoders/numeric.rb +++ b/activesupport/lib/active_support/json/encoders/numeric.rb @@ -1,6 +1,6 @@ class Numeric private - def rails_to_json(options = nil) + def rails_to_json(*) to_s end end diff --git a/activesupport/lib/active_support/json/encoders/object.rb b/activesupport/lib/active_support/json/encoders/object.rb index 4722feb7db..9cc12d91ac 100644 --- a/activesupport/lib/active_support/json/encoders/object.rb +++ b/activesupport/lib/active_support/json/encoders/object.rb @@ -3,11 +3,11 @@ require 'active_support/core_ext/object/instance_variables' class Object # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info. def to_json(options = nil) - rails_to_json(options) + ActiveSupport::JSON.encode(self, options) end private - def rails_to_json(options = nil) - ActiveSupport::JSON.encode(instance_values, options) + def rails_to_json(*args) + ActiveSupport::JSON.encode(instance_values, *args) end end diff --git a/activesupport/lib/active_support/json/encoders/regexp.rb b/activesupport/lib/active_support/json/encoders/regexp.rb index 62be810be5..ee42db4d02 100644 --- a/activesupport/lib/active_support/json/encoders/regexp.rb +++ b/activesupport/lib/active_support/json/encoders/regexp.rb @@ -1,6 +1,6 @@ class Regexp private - def rails_to_json(options = nil) + def rails_to_json(*) inspect end end diff --git a/activesupport/lib/active_support/json/encoders/string.rb b/activesupport/lib/active_support/json/encoders/string.rb index 6b9dcd97bf..4a6b21c1c0 100644 --- a/activesupport/lib/active_support/json/encoders/string.rb +++ b/activesupport/lib/active_support/json/encoders/string.rb @@ -1,6 +1,6 @@ class String private - def rails_to_json(options = nil) + def rails_to_json(*) ActiveSupport::JSON::Encoding.escape(self) end end diff --git a/activesupport/lib/active_support/json/encoders/symbol.rb b/activesupport/lib/active_support/json/encoders/symbol.rb index 333cf773c1..d575350a4e 100644 --- a/activesupport/lib/active_support/json/encoders/symbol.rb +++ b/activesupport/lib/active_support/json/encoders/symbol.rb @@ -1,6 +1,6 @@ class Symbol private - def rails_to_json(options = nil) - ActiveSupport::JSON.encode(to_s, options) + def rails_to_json(*args) + ActiveSupport::JSON.encode(to_s, *args) end end diff --git a/activesupport/lib/active_support/json/encoders/time.rb b/activesupport/lib/active_support/json/encoders/time.rb index c1cf3398c2..d434b9aace 100644 --- a/activesupport/lib/active_support/json/encoders/time.rb +++ b/activesupport/lib/active_support/json/encoders/time.rb @@ -14,7 +14,7 @@ class Time # # With ActiveSupport.use_standard_json_time_format = false # Time.utc(2005,2,1,15,15,10).to_json # # => "2005/02/01 15:15:10 +0000" - def rails_to_json(options = nil) + def rails_to_json(*) if ActiveSupport.use_standard_json_time_format xmlschema.inspect else diff --git a/activesupport/lib/active_support/json/encoders/true_class.rb b/activesupport/lib/active_support/json/encoders/true_class.rb index 6d5d063254..bc25a6db78 100644 --- a/activesupport/lib/active_support/json/encoders/true_class.rb +++ b/activesupport/lib/active_support/json/encoders/true_class.rb @@ -1,6 +1,6 @@ class TrueClass private - def rails_to_json(options = nil) + def rails_to_json(*) 'true' end end diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index acccb62aea..5441145dfd 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -4,12 +4,13 @@ module ActiveSupport end # Converts a Ruby object into a JSON string. - def self.encode(value, options = nil) - options ||= {} - seen = (options[:seen] ||= []) - raise CircularReferenceError, 'object references itself' if seen.include?(value.object_id) - seen << value.object_id - value.send(:rails_to_json, options) + def self.encode(value, options = nil, seen = nil) + seen ||= [] + if seen.any? { |object| object.equal?(value) } + raise CircularReferenceError, 'object references itself' + end + seen << value + value.send(:rails_to_json, options, seen) ensure seen.pop end diff --git a/activesupport/lib/active_support/json/variable.rb b/activesupport/lib/active_support/json/variable.rb index 2c7b449a50..daa7449b71 100644 --- a/activesupport/lib/active_support/json/variable.rb +++ b/activesupport/lib/active_support/json/variable.rb @@ -3,7 +3,7 @@ module ActiveSupport # A string that returns itself as its JSON-encoded form. class Variable < String private - def rails_to_json(options = nil) + def rails_to_json(*) self end end diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index c02ee1a524..069842c6c3 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -313,7 +313,7 @@ module ActiveSupport # # With ActiveSupport.use_standard_json_time_format = false # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json # # => "2005/02/01 15:15:10 +0000" - def rails_to_json(options = nil) + def rails_to_json(*) if !ActiveSupport.respond_to?(:use_standard_json_time_format) || ActiveSupport.use_standard_json_time_format xmlschema.inspect else -- cgit v1.2.3 From f58c322e7e08003b2bb4d2281b2db1e78930e8ff Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 20:05:17 -0700 Subject: Use __send__ for BasicObject friendliness --- activesupport/lib/active_support/json/encoding.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index 5441145dfd..5fefe5b88b 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -10,7 +10,7 @@ module ActiveSupport raise CircularReferenceError, 'object references itself' end seen << value - value.send(:rails_to_json, options, seen) + value.__send__(:rails_to_json, options, seen) ensure seen.pop end -- cgit v1.2.3 From 706f31323162ab8bdc5b10180bcd2740c0c9b6c3 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 20:24:45 -0700 Subject: Use Array.wrap --- activerecord/lib/active_record/serialization.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/serialization.rb b/activerecord/lib/active_record/serialization.rb index 870b4b2dd4..78f66c3a73 100644 --- a/activerecord/lib/active_record/serialization.rb +++ b/activerecord/lib/active_record/serialization.rb @@ -20,9 +20,9 @@ module ActiveRecord #:nodoc: if options[:only] options.delete(:except) - attribute_names = attribute_names & Array(options[:only]).collect { |n| n.to_s } + attribute_names = attribute_names & Array.wrap(options[:only]).collect { |n| n.to_s } else - options[:except] = Array(options[:except]) | Array(@record.class.inheritance_column) + options[:except] = Array.wrap(options[:except]) | Array.wrap(@record.class.inheritance_column) attribute_names = attribute_names - options[:except].collect { |n| n.to_s } end @@ -30,7 +30,7 @@ module ActiveRecord #:nodoc: end def serializable_method_names - Array(options[:methods]).inject([]) do |method_attributes, name| + Array.wrap(options[:methods]).inject([]) do |method_attributes, name| method_attributes << name if @record.respond_to?(name.to_s) method_attributes end @@ -51,7 +51,7 @@ module ActiveRecord #:nodoc: :only => options[:only] } include_has_options = include_associations.is_a?(Hash) - associations = include_has_options ? include_associations.keys : Array(include_associations) + associations = include_has_options ? include_associations.keys : Array.wrap(include_associations) for association in associations records = case @record.class.reflect_on_association(association).macro -- cgit v1.2.3 From 6e3e00219b6910ec39b84844c845e0e237ff15a6 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 20:25:36 -0700 Subject: Fix differing rails_to_json arity --- activerecord/lib/active_record/serializers/json_serializer.rb | 9 ++++++--- activeresource/lib/active_resource/base.rb | 8 +++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/activerecord/lib/active_record/serializers/json_serializer.rb b/activerecord/lib/active_record/serializers/json_serializer.rb index e9cb8bfca9..48df15d2c0 100644 --- a/activerecord/lib/active_record/serializers/json_serializer.rb +++ b/activerecord/lib/active_record/serializers/json_serializer.rb @@ -82,14 +82,17 @@ module ActiveRecord #:nodoc: end end - # For compatibility with ActiveSupport::JSON.encode - alias rails_to_json to_json - def from_json(json) self.attributes = ActiveSupport::JSON.decode(json) self end + private + # For compatibility with ActiveSupport::JSON.encode + def rails_to_json(options, *args) + to_json(options) + end + class JsonSerializer < ActiveRecord::Serialization::Serializer #:nodoc: def serialize ActiveSupport::JSON.encode(serializable_record) diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index 2e742267ba..f9a461d02e 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -890,9 +890,6 @@ module ActiveResource ActiveSupport::JSON.encode(attributes, options) end - # For compatibility with ActiveSupport::JSON.encode - alias rails_to_json to_json - # Returns the serialized string representation of the resource in the configured # serialization format specified in ActiveResource::Base.format. The options # applicable depend on the configured encoding format. @@ -1064,6 +1061,11 @@ module ActiveResource self.class.__send__(:split_options, options) end + # For compatibility with ActiveSupport::JSON.encode + def rails_to_json(options, *args) + to_json(options) + end + def method_missing(method_symbol, *arguments) #:nodoc: method_name = method_symbol.to_s -- cgit v1.2.3 From e44cd416208241cd96f75574d6c454fc2101e789 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 26 Apr 2009 23:59:17 -0700 Subject: Make it clearer that session is nil --- actionpack/test/activerecord/active_record_store_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/actionpack/test/activerecord/active_record_store_test.rb b/actionpack/test/activerecord/active_record_store_test.rb index 34f18806a2..663cd259c8 100644 --- a/actionpack/test/activerecord/active_record_store_test.rb +++ b/actionpack/test/activerecord/active_record_store_test.rb @@ -13,6 +13,7 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest end def set_session_value + raise "missing session!" unless session session[:foo] = params[:foo] || "bar" head :ok end -- cgit v1.2.3 From a88ddf8cc327279258cd68b0ad4091a5d54e3507 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 27 Apr 2009 00:00:03 -0700 Subject: Don't return bare string as rack body --- actionpack/lib/action_dispatch/middleware/failsafe.rb | 4 ++-- actionpack/test/controller/dispatcher_test.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/failsafe.rb b/actionpack/lib/action_dispatch/middleware/failsafe.rb index 5e0c479fdd..836098482c 100644 --- a/actionpack/lib/action_dispatch/middleware/failsafe.rb +++ b/actionpack/lib/action_dispatch/middleware/failsafe.rb @@ -29,9 +29,9 @@ module ActionDispatch def failsafe_response_body error_path = "#{self.class.error_file_path}/500.html" if File.exist?(error_path) - File.read(error_path) + [File.read(error_path)] else - "

500 Internal Server Error

" + ["

500 Internal Server Error

"] end end diff --git a/actionpack/test/controller/dispatcher_test.rb b/actionpack/test/controller/dispatcher_test.rb index 569d698a03..c3bd113b86 100644 --- a/actionpack/test/controller/dispatcher_test.rb +++ b/actionpack/test/controller/dispatcher_test.rb @@ -53,7 +53,7 @@ class DispatcherTest < Test::Unit::TestCase assert_equal [ 500, {"Content-Type" => "text/html"}, - "

500 Internal Server Error

" + ["

500 Internal Server Error

"] ], dispatch end end -- cgit v1.2.3 From c2b4da1c425dd8e1cc6606d49aea53e4f7521b91 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 27 Apr 2009 00:17:02 -0700 Subject: Sufficient to test that multipart/mixed wasn't parsed to a hash --- actionpack/test/dispatch/request/multipart_params_parsing_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb index cc81a87cb9..aaf647e45a 100644 --- a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb @@ -96,7 +96,7 @@ class MultipartParamsParsingTest < ActionController::IntegrationTest # Ruby CGI doesn't handle multipart/mixed for us. files = params['files'] - assert_kind_of Tempfile, files + assert_not_kind_of Hash, files files.force_encoding('ASCII-8BIT') if files.respond_to?(:force_encoding) assert_equal 19756, files.size end -- cgit v1.2.3 From dde063507ac40fda1a67f06a54c1a57d237f57b2 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 27 Apr 2009 09:29:01 -0700 Subject: Can't please them all --- actionpack/test/dispatch/request/multipart_params_parsing_test.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb index aaf647e45a..9e008a9ae8 100644 --- a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb @@ -94,9 +94,8 @@ class MultipartParamsParsingTest < ActionController::IntegrationTest assert_equal %w(files foo), params.keys.sort assert_equal 'bar', params['foo'] - # Ruby CGI doesn't handle multipart/mixed for us. + # Rack doesn't handle multipart/mixed for us. files = params['files'] - assert_not_kind_of Hash, files files.force_encoding('ASCII-8BIT') if files.respond_to?(:force_encoding) assert_equal 19756, files.size end -- cgit v1.2.3 From 21aa32692caf91f56d1c5c411baae635fa398344 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 27 Apr 2009 13:11:17 -0500 Subject: Delegate controller.session to request.session and deprecate response session --- actionpack/lib/action_controller/base/base.rb | 14 +++++--------- actionpack/lib/action_controller/testing/process.rb | 2 +- actionpack/lib/action_dispatch/http/request.rb | 8 -------- actionpack/lib/action_dispatch/http/response.rb | 6 +++++- actionpack/test/controller/test_test.rb | 6 ------ 5 files changed, 11 insertions(+), 25 deletions(-) diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb index afb9fb71cb..1d0738588d 100644 --- a/actionpack/lib/action_controller/base/base.rb +++ b/actionpack/lib/action_controller/base/base.rb @@ -238,7 +238,7 @@ module ActionController #:nodoc: cattr_reader :protected_instance_variables # Controller specific instance variables which will not be accessible inside views. @@protected_instance_variables = %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller - @action_name @before_filter_chain_aborted @action_cache_path @_session @_headers @_params + @action_name @before_filter_chain_aborted @action_cache_path @_headers @_params @_flash @_response) # Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets, @@ -356,7 +356,9 @@ module ActionController #:nodoc: # Holds a hash of objects in the session. Accessed like session[:person] to get the object tied to the "person" # key. The session will hold any type of object as values, but the key should be a string or symbol. - attr_internal :session + def session + request.session + end # Holds a hash of header names and values. Accessed like headers["Cache-Control"] to get the value of the Cache-Control # directive. Values should always be specified as strings. @@ -787,7 +789,6 @@ module ActionController #:nodoc: # Resets the session by clearing out all the objects stored within and initializing a new session object. def reset_session #:doc: request.reset_session - @_session = request.session end private @@ -812,7 +813,7 @@ module ActionController #:nodoc: def assign_shortcuts(request, response) @_request, @_response, @_params = request, response, request.parameters - @_session, @_headers = @_request.session, @_response.headers + @_headers = @_response.headers end def initialize_current_url @@ -888,10 +889,6 @@ module ActionController #:nodoc: "#{request.protocol}#{request.host}#{request.request_uri}" end - def close_session - # @_session.close if @_session && @_session.respond_to?(:close) - end - def default_template(action_name = self.action_name) self.view_paths.find_template(default_template_name(action_name), default_template_format) end @@ -915,7 +912,6 @@ module ActionController #:nodoc: end def process_cleanup - close_session end end diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index c532a67e78..d073d06b19 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -165,7 +165,7 @@ module ActionController #:nodoc: # A shortcut to the flash. Returns an empty hash if no session flash exists. def flash - session['flash'] || {} + request.session['flash'] || {} end # Do we have a flash? diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 0b8909ced7..2602b344ca 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -451,14 +451,6 @@ EOM @env['rack.input'] end - def session - @env['rack.session'] - end - - def session_options - @env['rack.session.options'] - end - def reset_session self.session_options.delete(:id) self.session = {} diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 6c92fb9713..ebba4eefa0 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -40,7 +40,11 @@ module ActionDispatch # :nodoc: attr_writer :header alias_method :headers=, :header= - delegate :session, :to => :request + def session + ActiveSupport::Deprecation.warn("response.session has been deprecated. Use request.session instead", caller) + request.session + end + delegate :default_charset, :to => 'ActionController::Base' def initialize diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb index 124e259ef6..f68ffc7a2a 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_test.rb @@ -184,12 +184,6 @@ XML assert_equal Hash.new, @controller.session.to_hash end - def test_session_is_cleared_from_response_after_reset_session - process :set_session - process :reset_the_session - assert_equal Hash.new, @response.session.to_hash - end - def test_session_is_cleared_from_request_after_reset_session process :set_session process :reset_the_session -- cgit v1.2.3 From da3c21ead59cb47b8f4c69c6bd95f225a9c8b479 Mon Sep 17 00:00:00 2001 From: Eloy Duran Date: Tue, 17 Mar 2009 01:04:47 +0100 Subject: Ensure the parent record is always saved when the child is invalid. [#2249 state:resolved] Signed-off-by: Pratik Naik --- .../lib/active_record/autosave_association.rb | 14 +++++++++----- .../test/cases/autosave_association_test.rb | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index 741aa2acbe..9717ca3d8b 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -311,11 +311,13 @@ module ActiveRecord # ActiveRecord::Base after the AutosaveAssociation module, which it does by default. def save_has_one_association(reflection) if (association = association_instance_get(reflection.name)) && !association.target.nil? - if reflection.options[:autosave] && association.marked_for_destruction? + autosave = reflection.options[:autosave] + + if autosave && association.marked_for_destruction? association.destroy - elsif new_record? || association.new_record? || association[reflection.primary_key_name] != id || reflection.options[:autosave] + elsif new_record? || association.new_record? || association[reflection.primary_key_name] != id || autosave association[reflection.primary_key_name] = id - association.save(false) + association.save(!autosave) end end end @@ -330,10 +332,12 @@ module ActiveRecord # ActiveRecord::Base after the AutosaveAssociation module, which it does by default. def save_belongs_to_association(reflection) if association = association_instance_get(reflection.name) - if reflection.options[:autosave] && association.marked_for_destruction? + autosave = reflection.options[:autosave] + + if autosave && association.marked_for_destruction? association.destroy else - association.save(false) if association.new_record? || reflection.options[:autosave] + association.save(!autosave) if association.new_record? || autosave if association.updated? self[reflection.primary_key_name] = association.id diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 436f50d395..919b6f857c 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -38,6 +38,17 @@ class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase end class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase + def test_should_save_parent_but_not_invalid_child + firm = Firm.new(:name => 'GlobalMegaCorp') + assert firm.valid? + + firm.build_account_using_primary_key + assert !firm.build_account_using_primary_key.valid? + + assert firm.save + assert firm.account_using_primary_key.new_record? + end + def test_save_fails_for_invalid_has_one firm = Firm.find(:first) assert firm.valid? @@ -126,6 +137,17 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas end class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase + def test_should_save_parent_but_not_invalid_child + client = Client.new(:name => 'Joe (the Plumber)') + assert client.valid? + + client.build_firm + assert !client.firm.valid? + + assert client.save + assert client.firm.new_record? + end + def test_save_fails_for_invalid_belongs_to assert log = AuditLog.create(:developer_id => 0, :message => "") -- cgit v1.2.3 From cecafc52ee0a4a53c903ddbaba95683261f88e5f Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Thu, 23 Apr 2009 15:58:38 -0700 Subject: Refactor ActionView::Template ActionView::Template is now completely independent from template storage, which allows different back ends such as the database. ActionView::Template's only responsibility is to take in the template source (passed in from ActionView::Path), compile it, and render it. --- actionpack/lib/action_controller/base/base.rb | 20 +- actionpack/lib/action_controller/base/render.rb | 7 +- .../testing/assertions/response.rb | 10 +- actionpack/lib/action_view/base.rb | 4 +- actionpack/lib/action_view/paths.rb | 12 +- actionpack/lib/action_view/render/rendering.rb | 13 +- actionpack/lib/action_view/template/error.rb | 4 +- actionpack/lib/action_view/template/handlers.rb | 2 +- actionpack/lib/action_view/template/path.rb | 68 +++-- actionpack/lib/action_view/template/template.rb | 336 ++++++++++++--------- actionpack/lib/action_view/test_case.rb | 7 +- .../abstract_controller_test.rb | 2 +- actionpack/test/controller/helper_test.rb | 2 +- actionpack/test/controller/layout_test.rb | 24 +- actionpack/test/controller/render_test.rb | 6 +- actionpack/test/controller/view_paths_test.rb | 49 +-- actionpack/test/fixtures/layouts/standard.erb | 1 - actionpack/test/fixtures/layouts/standard.html.erb | 1 + .../test/render_file_with_locals_and_default.erb | 1 + .../test/template/compiled_templates_test.rb | 36 +-- actionpack/test/template/render_test.rb | 14 +- .../active_support/core_ext/module/delegation.rb | 4 +- railties/test/plugin_loader_test.rb | 4 +- railties/test/plugin_test_helper.rb | 2 +- 24 files changed, 344 insertions(+), 285 deletions(-) delete mode 100644 actionpack/test/fixtures/layouts/standard.erb create mode 100644 actionpack/test/fixtures/layouts/standard.html.erb create mode 100644 actionpack/test/fixtures/test/render_file_with_locals_and_default.erb diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb index 1d0738588d..2063df54b4 100644 --- a/actionpack/lib/action_controller/base/base.rb +++ b/actionpack/lib/action_controller/base/base.rb @@ -494,8 +494,18 @@ module ActionController #:nodoc: end protected :filter_parameters end + + @@exempt_from_layout = [ActionView::TemplateHandlers::RJS] + + def exempt_from_layout(*types) + types.each do |type| + @@exempt_from_layout << + ActionView::Template.handler_class_for_extension(type) + end + + @@exempt_from_layout + end - delegate :exempt_from_layout, :to => 'ActionView::Template' end public @@ -856,13 +866,13 @@ module ActionController #:nodoc: return (performed? ? ret : default_render) if called begin - default_render - rescue ActionView::MissingTemplate => e - raise e unless e.action_name == action_name - # If the path is the same as the action_name, the action is completely missing + view_paths.find_by_parts(action_name, {:formats => formats, :locales => [I18n.locale]}, controller_path) + rescue => e raise UnknownAction, "No action responded to #{action_name}. Actions: " + "#{action_methods.sort.to_sentence}", caller end + + default_render end # Returns true if a render or redirect has already been performed. diff --git a/actionpack/lib/action_controller/base/render.rb b/actionpack/lib/action_controller/base/render.rb index 601c5429c3..4286577ec5 100644 --- a/actionpack/lib/action_controller/base/render.rb +++ b/actionpack/lib/action_controller/base/render.rb @@ -378,13 +378,14 @@ module ActionController # ==== Arguments # parts:: # Example: ["show", [:html, :xml], "users", false] - def render_for_parts(parts, layout, options = {}) + def render_for_parts(parts, layout_details, options = {}) parts[1] = {:formats => parts[1], :locales => [I18n.locale]} tmp = view_paths.find_by_parts(*parts) - layout = _pick_layout(*layout) unless tmp.exempt_from_layout? - + layout = _pick_layout(*layout_details) unless + self.class.exempt_from_layout.include?(tmp.handler) + render_for_text( @template._render_template_with_layout(tmp, layout, options, parts[3])) end diff --git a/actionpack/lib/action_controller/testing/assertions/response.rb b/actionpack/lib/action_controller/testing/assertions/response.rb index c57cbecc44..574b8d6825 100644 --- a/actionpack/lib/action_controller/testing/assertions/response.rb +++ b/actionpack/lib/action_controller/testing/assertions/response.rb @@ -98,22 +98,22 @@ module ActionController clean_backtrace do case options when NilClass, String - rendered = @controller.response.rendered[:template].to_s + rendered = (@controller.response.rendered[:template] || []).map { |t| t.identifier } msg = build_message(message, "expecting but rendering with ", - options, rendered) + options, rendered.join(', ')) assert_block(msg) do if options.nil? @controller.response.rendered[:template].blank? else - rendered.to_s.match(options) + rendered.any? { |t| t.match(options) } end end when Hash if expected_partial = options[:partial] partials = @controller.response.rendered[:partials] if expected_count = options[:count] - found = partials.detect { |p, _| p.to_s.match(expected_partial) } + found = partials.detect { |p, _| p.identifier.match(expected_partial) } actual_count = found.nil? ? 0 : found.second msg = build_message(message, "expecting ? to be rendered ? time(s) but rendered ? time(s)", @@ -123,7 +123,7 @@ module ActionController msg = build_message(message, "expecting partial but action rendered ", options[:partial], partials.keys) - assert(partials.keys.any? { |p| p.to_s.match(expected_partial) }, msg) + assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg) end else assert @controller.response.rendered[:partials].empty?, diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index efed19a21d..d087395361 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -196,7 +196,9 @@ module ActionView #:nodoc: delegate :controller_path, :to => :controller, :allow_nil => true delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers, - :flash, :logger, :action_name, :controller_name, :to => :controller + :flash, :action_name, :controller_name, :to => :controller + + delegate :logger, :to => :controller, :allow_nil => true delegate :find_by_parts, :to => :view_paths diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index e48088f344..f6d021c92a 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -3,7 +3,7 @@ module ActionView #:nodoc: def self.type_cast(obj) if obj.is_a?(String) cache = !Object.const_defined?(:Rails) || Rails.configuration.cache_classes - Template::FileSystemPath.new(obj, :cache => cache) + Template::FileSystemPathWithFallback.new(obj, :cache => cache) else obj end @@ -34,18 +34,18 @@ module ActionView #:nodoc: end def find_by_parts(path, details = {}, prefix = nil, partial = false) - template_path = path.sub(/^\//, '') + # template_path = path.sub(/^\//, '') + template_path = path each do |load_path| if template = load_path.find_by_parts(template_path, details, prefix, partial) return template end end - - Template.new(path, self) - rescue ActionView::MissingTemplate => e + + # TODO: Have a fallback absolute path? extension = details[:formats] || [] - raise ActionView::MissingTemplate.new(self, "#{prefix}/#{path}.{#{extension.join(",")}}") + raise ActionView::MissingTemplate.new(self, "#{prefix}/#{path} - #{details.inspect} - partial: #{!!partial}") end def find_by_parts?(path, extension = nil, prefix = nil, partial = false) diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 4213b09e48..f174053b86 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -46,8 +46,8 @@ module ActionView locals ||= {} if controller && layout - response.layout = layout.path_without_format_and_extension if controller.respond_to?(:response) - logger.info("Rendering template within #{layout.path_without_format_and_extension}") if logger + response.layout = layout.identifier if controller.respond_to?(:response) + logger.info("Rendering template within #{layout.identifier}") if logger end begin @@ -76,7 +76,6 @@ module ActionView end end rescue Exception => e - raise e if template.is_a?(InlineTemplate) || !template.filename if TemplateError === e e.sub_template_of(template) raise e @@ -86,7 +85,9 @@ module ActionView end def _render_inline(inline, layout, options) - content = _render_template(InlineTemplate.new(options[:inline], options[:type]), options[:locals] || {}) + handler = Template.handler_class_for_extension(options[:type] || "erb") + template = Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {}) + content = _render_template(template, options[:locals] || {}) layout ? _render_content_with_layout(content, layout, options[:locals]) : content end @@ -96,7 +97,7 @@ module ActionView def _render_template_with_layout(template, layout = nil, options = {}, partial = false) if controller && logger - logger.info("Rendering #{template.path_without_extension}" + + logger.info("Rendering #{template.identifier}" + (options[:status] ? " (#{options[:status]})" : '')) end @@ -107,7 +108,7 @@ module ActionView _render_template(template, options[:locals] || {}) end - return content unless layout && !template.exempt_from_layout? + return content unless layout _render_content_with_layout(content, layout, options[:locals] || {}) end end diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb index 37cb1c7c6c..a06e80b294 100644 --- a/actionpack/lib/action_view/template/error.rb +++ b/actionpack/lib/action_view/template/error.rb @@ -12,7 +12,7 @@ module ActionView end def file_name - @template.relative_path + @template.identifier end def message @@ -30,7 +30,7 @@ module ActionView def sub_template_message if @sub_templates "Trace of template inclusion: " + - @sub_templates.collect { |template| template.relative_path }.join(", ") + @sub_templates.collect { |template| template.identifier }.join(", ") else "" end diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb index 448ab6731b..0590372d09 100644 --- a/actionpack/lib/action_view/template/handlers.rb +++ b/actionpack/lib/action_view/template/handlers.rb @@ -46,7 +46,7 @@ module ActionView #:nodoc: end def handler_class_for_extension(extension) - registered_template_handler(extension) || @@default_template_handlers + (extension && registered_template_handler(extension.to_sym)) || @@default_template_handlers end end end diff --git a/actionpack/lib/action_view/template/path.rb b/actionpack/lib/action_view/template/path.rb index 660a7e91a2..478bf96c9a 100644 --- a/actionpack/lib/action_view/template/path.rb +++ b/actionpack/lib/action_view/template/path.rb @@ -1,3 +1,5 @@ +require "pathname" + module ActionView class Template # Abstract super class @@ -26,13 +28,6 @@ module ActionView def find_templates(name, details, prefix, partial) raise NotImplementedError end - - # TODO: Refactor this to abstract out the file system - def initialize_template(file) - t = Template.new(file.split("#{self}/").last, self) - t.load! - t - end def valid_handlers @valid_handlers ||= TemplateHandlers.extensions @@ -44,10 +39,10 @@ module ActionView /\.(?:#{e})$/ end end - + def handler_glob - e = TemplateHandlers.extensions.join(',') - ".{#{e}}" + e = TemplateHandlers.extensions.map{|h| ".#{h},"}.join + "{#{e}}" end def formats_glob @@ -69,23 +64,19 @@ module ActionView def initialize(path, options = {}) raise ArgumentError, "path already is a Path class" if path.is_a?(Path) super(options) - @path = path + @path = Pathname.new(path).expand_path end - + # TODO: This is the currently needed API. Make this suck less # ==== attr_reader :path def to_s - if defined?(RAILS_ROOT) - path.to_s.sub(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '') - else - path.to_s - end + path.to_s end def to_str - path.to_str + path.to_s end def ==(path) @@ -97,11 +88,15 @@ module ActionView end # ==== - def find_templates(name, details, prefix, partial) - if glob = parts_to_glob(name, details, prefix, partial) + def find_templates(name, details, prefix, partial, root = "#{@path}/") + if glob = details_to_glob(name, details, prefix, partial, root) cached(glob) do Dir[glob].map do |path| - initialize_template(path) unless File.directory?(path) + next if File.directory?(path) + source = File.read(path) + identifier = Pathname.new(path).expand_path.to_s + + Template.new(source, identifier, *path_to_details(path)) end.compact end end @@ -109,7 +104,8 @@ module ActionView private - def parts_to_glob(name, details, prefix, partial) + # :api: plugin + def details_to_glob(name, details, prefix, partial, root) path = "" path << "#{prefix}/" unless prefix.empty? path << (partial ? "_#{name}" : name) @@ -123,8 +119,34 @@ module ActionView end end - "#{@path}/#{path}#{extensions}#{handler_glob}" + "#{root}#{path}#{extensions}#{handler_glob}" + 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[1] == '_' + details = (m[2]||"").split('.').reject { |e| e.empty? } + handler = Template.handler_class_for_extension(m[3]) + + format = Mime[details.last] && details.pop.to_sym + locale = details.last && details.pop.to_sym + + return handler, :format => format, :locale => locale, :partial => partial + end end end + + class FileSystemPathWithFallback < FileSystemPath + + def find_templates(name, details, prefix, partial) + templates = super + return super(name, details, prefix, partial, '') if templates.empty? + templates + end + + end end end \ No newline at end of file diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb index e541336613..ce6268729a 100644 --- a/actionpack/lib/action_view/template/template.rb +++ b/actionpack/lib/action_view/template/template.rb @@ -1,188 +1,230 @@ +# encoding: utf-8 +# This is so that templates compiled in this file are UTF-8 + require 'set' require "action_view/template/path" -module ActionView #:nodoc: +module ActionView class Template extend TemplateHandlers - extend ActiveSupport::Memoizable + attr_reader :source, :identifier, :handler - module Loading - def load! - @cached = true - # freeze - end + def initialize(source, identifier, handler, details) + @source = source + @identifier = identifier + @handler = handler + @details = details end - include Loading - include Renderable - - # Templates that are exempt from layouts - @@exempt_from_layout = Set.new([/\.rjs$/]) - - # Don't render layouts for templates with the given extensions. - def self.exempt_from_layout(*extensions) - regexps = extensions.collect do |extension| - extension.is_a?(Regexp) ? extension : /\.#{Regexp.escape(extension.to_s)}$/ - end - @@exempt_from_layout.merge(regexps) + def render(view, locals, &blk) + method_name = compile(locals, view) + view.send(method_name, locals, &blk) + end + + # TODO: Figure out how to abstract this + def variable_name + identifier[%r'_?(\w+)(\.\w+)*$', 1].to_sym end - attr_accessor :template_path, :filename, :load_path, :base_path - attr_accessor :locale, :name, :format, :extension - delegate :to_s, :to => :path + # TODO: Figure out how to abstract this + def counter_name + "#{variable_name}_counter".to_sym + end + + # TODO: kill hax + def partial? + @details[:partial] + end + + # TODO: Move out of Template + def mime_type + Mime::Type.lookup_by_extension(@details[:format]) if @details[:format] + end + + private - def initialize(template_path, load_paths = []) - template_path = template_path.dup - @load_path, @filename = find_full_path(template_path, load_paths) - @base_path, @name, @locale, @format, @extension = split(template_path) - @base_path.to_s.gsub!(/\/$/, '') # Push to split method + def compile(locals, view) + method_name = build_method_name(locals) + + return method_name if view.respond_to?(method_name) + + locals_code = locals.keys.map! { |key| "#{key} = local_assigns[:#{key}];" }.join + + source = <<-end_src + def #{method_name}(local_assigns) + old_output_buffer = output_buffer;#{locals_code};#{@handler.call(self)} + ensure + self.output_buffer = old_output_buffer + end + end_src + + begin + ActionView::Base::CompiledTemplates.module_eval(source, identifier, 0) + method_name + rescue Exception => e # errors from template code + if logger = (view && view.logger) + logger.debug "ERROR: compiling #{method_name} RAISED #{e}" + logger.debug "Function body: #{source}" + logger.debug "Backtrace: #{e.backtrace.join("\n")}" + end - # Extend with partial super powers - extend RenderablePartial if @name =~ /^_/ + raise ActionView::TemplateError.new(self, {}, e) + end + end + + def build_method_name(locals) + # TODO: is locals.keys.hash reliably the same? + "_render_template_#{@identifier.hash}_#{__id__}_#{locals.keys.hash}".gsub('-', "_") end + end +end + +if false + module ActionView #:nodoc: + class Template + extend TemplateHandlers + extend ActiveSupport::Memoizable - def accessible_paths - paths = [] + module Loading + def load! + @cached = true + # freeze + end + end + include Loading + + include Renderable - if valid_extension?(extension) - paths << path - paths << path_without_extension - if multipart? - formats = format.split(".") - paths << "#{path_without_format_and_extension}.#{formats.first}" - paths << "#{path_without_format_and_extension}.#{formats.second}" + # Templates that are exempt from layouts + @@exempt_from_layout = Set.new([/\.rjs$/]) + + # Don't render layouts for templates with the given extensions. + def self.exempt_from_layout(*extensions) + regexps = extensions.collect do |extension| + extension.is_a?(Regexp) ? extension : /\.#{Regexp.escape(extension.to_s)}$/ end - else - # template without explicit template handler should only be reachable through its exact path - paths << template_path + @@exempt_from_layout.merge(regexps) end - paths - end + attr_accessor :template_path, :filename, :load_path, :base_path + attr_accessor :locale, :name, :format, :extension + delegate :to_s, :to => :path + + def initialize(template_path, load_paths = []) + template_path = template_path.dup + @load_path, @filename = find_full_path(template_path, load_paths) + @name = template_path.to_s.split("/").last.split(".").first + # @base_path, @name, @locale, @format, @extension = split(template_path) + @base_path.to_s.gsub!(/\/$/, '') # Push to split method + + # Extend with partial super powers + extend RenderablePartial if @name =~ /^_/ + end - def relative_path - path = File.expand_path(filename) - path.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '') if defined?(RAILS_ROOT) - path - end - memoize :relative_path + def accessible_paths + paths = [] + + if valid_extension?(extension) + paths << path + paths << path_without_extension + if multipart? + formats = format.split(".") + paths << "#{path_without_format_and_extension}.#{formats.first}" + paths << "#{path_without_format_and_extension}.#{formats.second}" + end + else + # template without explicit template handler should only be reachable through its exact path + paths << template_path + end + + paths + end - def source - File.read(filename) - end - memoize :source + def relative_path + path = File.expand_path(filename) + path.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '') if defined?(RAILS_ROOT) + path + end + memoize :relative_path - def exempt_from_layout? - @@exempt_from_layout.any? { |exempted| path =~ exempted } - end + def source + File.read(filename) + end + memoize :source - def path_without_extension - [base_path, [name, locale, format].compact.join('.')].compact.join('/') - end - memoize :path_without_extension + def exempt_from_layout? + @@exempt_from_layout.any? { |exempted| path =~ exempted } + end + + def path_without_extension + [base_path, [name, locale, format].compact.join('.')].compact.join('/') + end + memoize :path_without_extension - def path_without_format_and_extension - [base_path, [name, locale].compact.join('.')].compact.join('/') - end - memoize :path_without_format_and_extension + def path_without_format_and_extension + [base_path, [name, locale].compact.join('.')].compact.join('/') + end + memoize :path_without_format_and_extension - def path - [base_path, [name, locale, format, extension].compact.join('.')].compact.join('/') - end - memoize :path + def path + [base_path, [name, locale, format, extension].compact.join('.')].compact.join('/') + end + memoize :path - def mime_type - Mime::Type.lookup_by_extension(format) if format && defined?(::Mime) - end - memoize :mime_type + def mime_type + Mime::Type.lookup_by_extension(format) if format && defined?(::Mime) + end + memoize :mime_type - def multipart? - format && format.include?('.') - end + def multipart? + format && format.include?('.') + end - def content_type - format && format.gsub('.', '/') - end + def content_type + format && format.gsub('.', '/') + end - private + private - def format_and_extension - (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions - end - memoize :format_and_extension - - def mtime - File.mtime(filename) - end - memoize :mtime + def format_and_extension + (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions + end + memoize :format_and_extension - def method_segment - relative_path.to_s.gsub(/([^a-zA-Z0-9_])/) { $1.ord } - end - memoize :method_segment + def mtime + File.mtime(filename) + end + memoize :mtime - def stale? - File.mtime(filename) > mtime - end + def method_segment + relative_path.to_s.gsub(/([^a-zA-Z0-9_])/) { $1.ord } + end + memoize :method_segment - def recompile? - !@cached - end + def stale? + File.mtime(filename) > mtime + end - def valid_extension?(extension) - !Template.registered_template_handler(extension).nil? - end + def recompile? + !@cached + end - def valid_locale?(locale) - I18n.available_locales.include?(locale.to_sym) - end + def valid_extension?(extension) + !Template.registered_template_handler(extension).nil? + end - def find_full_path(path, load_paths) - load_paths = Array(load_paths) + [nil] - load_paths.each do |load_path| - file = load_path ? "#{load_path.to_str}/#{path}" : path - return load_path, file if File.file?(file) + def valid_locale?(locale) + I18n.available_locales.include?(locale.to_sym) end - raise MissingTemplate.new(load_paths, path) - end - # Returns file split into an array - # [base_path, name, locale, format, extension] - def split(file) - if m = file.to_s.match(/^(.*\/)?([^\.]+)\.(.*)$/) - base_path = m[1] - name = m[2] - extensions = m[3] - else - return - end - - locale = nil - format = nil - extension = nil - - if m = extensions.split(".") - if valid_locale?(m[0]) && m[1] && valid_extension?(m[2]) # All three - locale = m[0] - format = m[1] - extension = m[2] - elsif m[0] && m[1] && valid_extension?(m[2]) # Multipart formats - format = "#{m[0]}.#{m[1]}" - extension = m[2] - elsif valid_locale?(m[0]) && valid_extension?(m[1]) # locale and extension - locale = m[0] - extension = m[1] - elsif valid_extension?(m[1]) # format and extension - format = m[0] - extension = m[1] - elsif valid_extension?(m[0]) # Just extension - extension = m[0] - else # No extension - format = m[0] + def find_full_path(path, load_paths) + load_paths = Array(load_paths) + [nil] + load_paths.each do |load_path| + file = load_path ? "#{load_path.to_str}/#{path}" : path + return load_path, file if File.file?(file) end + raise MissingTemplate.new(load_paths, path) end - - [base_path, name, locale, format, extension] end end -end +end \ No newline at end of file diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index c8f204046b..dddd671812 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -10,9 +10,10 @@ module ActionView alias_method :_render_template_without_template_tracking, :_render_template def _render_template(template, local_assigns = {}) - if template.respond_to?(:path) && !template.is_a?(InlineTemplate) - @_rendered[:partials][template] += 1 if template.is_a?(RenderablePartial) - @_rendered[:template] ||= template + if template.respond_to?(:identifier) + @_rendered[:partials][template] += 1 if template.partial? + @_rendered[:template] ||= [] + @_rendered[:template] << template end _render_template_without_template_tracking(template, local_assigns) end diff --git a/actionpack/test/abstract_controller/abstract_controller_test.rb b/actionpack/test/abstract_controller/abstract_controller_test.rb index f1dcb39ef1..331797afcf 100644 --- a/actionpack/test/abstract_controller/abstract_controller_test.rb +++ b/actionpack/test/abstract_controller/abstract_controller_test.rb @@ -139,7 +139,7 @@ module AbstractController private def self.layout(formats) begin - view_paths.find_by_parts(name.underscore, {:formats => formats}t, "layouts") + view_paths.find_by_parts(name.underscore, {:formats => formats}, "layouts") rescue ActionView::MissingTemplate begin view_paths.find_by_parts("application", {:formats => formats}, "layouts") diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb index 5f36461b89..58addc123d 100644 --- a/actionpack/test/controller/helper_test.rb +++ b/actionpack/test/controller/helper_test.rb @@ -211,7 +211,7 @@ class IsolatedHelpersTest < Test::Unit::TestCase end def test_helper_in_a - assert_raise(NameError) { A.process(@request, @response) } + assert_raise(ActionView::TemplateError) { A.process(@request, @response) } end def test_helper_in_b diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb index f2721e274d..11559b4071 100644 --- a/actionpack/test/controller/layout_test.rb +++ b/actionpack/test/controller/layout_test.rb @@ -56,8 +56,8 @@ class LayoutAutoDiscoveryTest < ActionController::TestCase def test_third_party_template_library_auto_discovers_layout @controller = ThirdPartyTemplateLibraryController.new get :hello - assert_equal 'layouts/third_party_template_library.mab', @controller.active_layout(true).to_s - assert_equal 'layouts/third_party_template_library', @response.layout + assert @controller.active_layout(true).identifier.include?('layouts/third_party_template_library.mab') + assert @response.layout.include?('layouts/third_party_template_library') assert_response :success assert_equal 'Mab', @response.body end @@ -72,7 +72,7 @@ class LayoutAutoDiscoveryTest < ActionController::TestCase def test_namespaced_controllers_auto_detect_layouts @controller = MultipleExtensions.new get :hello - assert_equal 'layouts/multiple_extensions.html.erb', @controller.active_layout(true).to_s + assert @controller.active_layout(true).identifier.include?('layouts/multiple_extensions.html.erb') assert_equal 'multiple_extensions.html.erb hello.rhtml', @response.body.strip end end @@ -116,22 +116,24 @@ class RendersNoLayoutController < LayoutTest end class LayoutSetInResponseTest < ActionController::TestCase + include ActionView::TemplateHandlers + def test_layout_set_when_using_default_layout @controller = DefaultLayoutController.new get :hello - assert_equal 'layouts/layout_test', @response.layout + assert @response.layout.include?('layouts/layout_test') end def test_layout_set_when_set_in_controller @controller = HasOwnLayoutController.new get :hello - assert_equal 'layouts/item', @response.layout + assert @response.layout.include?('layouts/item') end def test_layout_only_exception_when_included @controller = OnlyLayoutController.new get :hello - assert_equal 'layouts/item', @response.layout + assert @response.layout.include?('layouts/item') end def test_layout_only_exception_when_excepted @@ -143,7 +145,7 @@ class LayoutSetInResponseTest < ActionController::TestCase def test_layout_except_exception_when_included @controller = ExceptLayoutController.new get :hello - assert_equal 'layouts/item', @response.layout + assert @response.layout.include?('layouts/item') end def test_layout_except_exception_when_excepted @@ -155,7 +157,7 @@ class LayoutSetInResponseTest < ActionController::TestCase def test_layout_set_when_using_render @controller = SetsLayoutInRenderController.new get :hello - assert_equal 'layouts/third_party_template_library', @response.layout + assert @response.layout.include?('layouts/third_party_template_library') end def test_layout_is_not_set_when_none_rendered @@ -165,14 +167,14 @@ class LayoutSetInResponseTest < ActionController::TestCase end def test_exempt_from_layout_honored_by_render_template - ActionController::Base.exempt_from_layout :rhtml + ActionController::Base.exempt_from_layout :erb @controller = RenderWithTemplateOptionController.new get :hello assert_equal "alt/hello.rhtml", @response.body.strip ensure - ActionController::Base.exempt_from_layout.delete(/\.rhtml$/) + ActionController::Base.exempt_from_layout.delete(ERB) end def test_layout_is_picked_from_the_controller_instances_view_path @@ -232,7 +234,7 @@ unless RUBY_PLATFORM =~ /(:?mswin|mingw|bccwin)/ @controller = LayoutSymlinkedTest.new get :hello assert_response 200 - assert_equal "layouts/symlinked/symlinked_layout", @response.layout + assert @response.layout.include?("layouts/symlinked/symlinked_layout") end end end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index af7236ed26..da063710a9 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -773,7 +773,7 @@ class RenderTest < ActionController::TestCase begin get :render_line_offset flunk "the action should have raised an exception" - rescue RuntimeError => exc + rescue StandardError => exc line = exc.backtrace.first assert(line =~ %r{:(\d+):}) assert_equal "1", $1, @@ -1736,7 +1736,7 @@ class RenderingLoggingTest < ActionController::TestCase @controller.logger = MockLogger.new get :layout_test logged = @controller.logger.logged.find_all {|l| l =~ /render/i } - assert_equal "Rendering test/hello_world", logged[0] - assert_equal "Rendering template within layouts/standard", logged[1] + assert logged[0] =~ %r{Rendering.*test/hello_world} + assert logged[1] =~ %r{Rendering template within.*layouts/standard} end end diff --git a/actionpack/test/controller/view_paths_test.rb b/actionpack/test/controller/view_paths_test.rb index 1539f8f506..0ac10634b2 100644 --- a/actionpack/test/controller/view_paths_test.rb +++ b/actionpack/test/controller/view_paths_test.rb @@ -20,7 +20,7 @@ class ViewLoadPathsTest < ActionController::TestCase layout 'test/sub' def hello_world; render(:template => 'test/hello_world'); end end - + def setup TestController.view_paths = nil @@ -42,30 +42,39 @@ class ViewLoadPathsTest < ActionController::TestCase ActiveSupport::Deprecation.behavior = @old_behavior end + def expand(array) + array.map {|x| File.expand_path(x)} + end + + def assert_paths(*paths) + controller = paths.first.is_a?(Class) ? paths.shift : @controller + assert_equal expand(paths), controller.view_paths.map(&:to_s) + end + def test_template_load_path_was_set_correctly - assert_equal [FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s) + assert_paths FIXTURE_LOAD_PATH end def test_controller_appends_view_path_correctly @controller.append_view_path 'foo' - assert_equal [FIXTURE_LOAD_PATH, 'foo'], @controller.view_paths.map(&:to_s) + assert_paths(FIXTURE_LOAD_PATH, "foo") @controller.append_view_path(%w(bar baz)) - assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz'], @controller.view_paths.map(&:to_s) - + assert_paths(FIXTURE_LOAD_PATH, "foo", "bar", "baz") + @controller.append_view_path(FIXTURE_LOAD_PATH) - assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s) + assert_paths(FIXTURE_LOAD_PATH, "foo", "bar", "baz", FIXTURE_LOAD_PATH) end def test_controller_prepends_view_path_correctly @controller.prepend_view_path 'baz' - assert_equal ['baz', FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s) + assert_paths("baz", FIXTURE_LOAD_PATH) @controller.prepend_view_path(%w(foo bar)) - assert_equal ['foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s) + assert_paths "foo", "bar", "baz", FIXTURE_LOAD_PATH @controller.prepend_view_path(FIXTURE_LOAD_PATH) - assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s) + assert_paths FIXTURE_LOAD_PATH, "foo", "bar", "baz", FIXTURE_LOAD_PATH end def test_template_appends_view_path_correctly @@ -73,11 +82,11 @@ class ViewLoadPathsTest < ActionController::TestCase class_view_paths = TestController.view_paths @controller.append_view_path 'foo' - assert_equal [FIXTURE_LOAD_PATH, 'foo'], @controller.view_paths.map(&:to_s) + assert_paths FIXTURE_LOAD_PATH, "foo" @controller.append_view_path(%w(bar baz)) - assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz'], @controller.view_paths.map(&:to_s) - assert_equal class_view_paths, TestController.view_paths + assert_paths FIXTURE_LOAD_PATH, "foo", "bar", "baz" + assert_paths TestController, *class_view_paths end def test_template_prepends_view_path_correctly @@ -85,11 +94,11 @@ class ViewLoadPathsTest < ActionController::TestCase class_view_paths = TestController.view_paths @controller.prepend_view_path 'baz' - assert_equal ['baz', FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s) + assert_paths "baz", FIXTURE_LOAD_PATH @controller.prepend_view_path(%w(foo bar)) - assert_equal ['foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s) - assert_equal class_view_paths, TestController.view_paths + assert_paths "foo", "bar", "baz", FIXTURE_LOAD_PATH + assert_paths TestController, *class_view_paths end def test_view_paths @@ -130,12 +139,12 @@ class ViewLoadPathsTest < ActionController::TestCase A.view_paths = ['a/path'] - assert_equal ['a/path'], A.view_paths.map(&:to_s) - assert_equal A.view_paths, B.view_paths - assert_equal original_load_paths, C.view_paths - + assert_paths A, "a/path" + assert_paths A, *B.view_paths + assert_paths C, *original_load_paths + C.view_paths = [] assert_nothing_raised { C.view_paths << 'c/path' } - assert_equal ['c/path'], C.view_paths.map(&:to_s) + assert_paths C, "c/path" end end diff --git a/actionpack/test/fixtures/layouts/standard.erb b/actionpack/test/fixtures/layouts/standard.erb deleted file mode 100644 index 368764e6f4..0000000000 --- a/actionpack/test/fixtures/layouts/standard.erb +++ /dev/null @@ -1 +0,0 @@ -<%= @content_for_layout %><%= @variable_for_layout %> \ No newline at end of file diff --git a/actionpack/test/fixtures/layouts/standard.html.erb b/actionpack/test/fixtures/layouts/standard.html.erb new file mode 100644 index 0000000000..368764e6f4 --- /dev/null +++ b/actionpack/test/fixtures/layouts/standard.html.erb @@ -0,0 +1 @@ +<%= @content_for_layout %><%= @variable_for_layout %> \ No newline at end of file diff --git a/actionpack/test/fixtures/test/render_file_with_locals_and_default.erb b/actionpack/test/fixtures/test/render_file_with_locals_and_default.erb new file mode 100644 index 0000000000..9b4900acc5 --- /dev/null +++ b/actionpack/test/fixtures/test/render_file_with_locals_and_default.erb @@ -0,0 +1 @@ +<%= secret ||= 'one' %> \ No newline at end of file diff --git a/actionpack/test/template/compiled_templates_test.rb b/actionpack/test/template/compiled_templates_test.rb index c75e29ed9a..b29b03f99d 100644 --- a/actionpack/test/template/compiled_templates_test.rb +++ b/actionpack/test/template/compiled_templates_test.rb @@ -5,37 +5,13 @@ class CompiledTemplatesTest < Test::Unit::TestCase def setup @compiled_templates = ActionView::Base::CompiledTemplates @compiled_templates.instance_methods.each do |m| - @compiled_templates.send(:remove_method, m) if m =~ /^_run_/ + @compiled_templates.send(:remove_method, m) if m =~ /^_render_template_/ end end - - def test_template_gets_compiled - assert_equal 0, @compiled_templates.instance_methods.size - assert_equal "Hello world!", render(:file => "test/hello_world.erb") - assert_equal 1, @compiled_templates.instance_methods.size - end - + def test_template_gets_recompiled_when_using_different_keys_in_local_assigns - assert_equal 0, @compiled_templates.instance_methods.size - assert_equal "Hello world!", render(:file => "test/hello_world.erb") - assert_equal "Hello world!", render(:file => "test/hello_world.erb", :locals => {:foo => "bar"}) - assert_equal 2, @compiled_templates.instance_methods.size - end - - def test_compiled_template_will_not_be_recompiled_when_rendered_with_identical_local_assigns - assert_equal 0, @compiled_templates.instance_methods.size - assert_equal "Hello world!", render(:file => "test/hello_world.erb") - ActionView::Template.any_instance.expects(:compile!).never - assert_equal "Hello world!", render(:file => "test/hello_world.erb") - end - - def test_compiled_template_will_always_be_recompiled_when_template_is_not_cached - ActionView::Template.any_instance.expects(:recompile?).times(3).returns(true) - assert_equal 0, @compiled_templates.instance_methods.size - assert_equal "Hello world!", render(:file => "#{FIXTURE_LOAD_PATH}/test/hello_world.erb") - ActionView::Template.any_instance.expects(:compile!).times(3) - 3.times { assert_equal "Hello world!", render(:file => "#{FIXTURE_LOAD_PATH}/test/hello_world.erb") } - assert_equal 1, @compiled_templates.instance_methods.size + assert_equal "one", render(:file => "test/render_file_with_locals_and_default.erb") + assert_equal "two", render(:file => "test/render_file_with_locals_and_default.erb", :locals => { :secret => "two" }) end def test_template_changes_are_not_reflected_with_cached_templates @@ -61,14 +37,12 @@ class CompiledTemplatesTest < Test::Unit::TestCase def render_with_cache(*args) view_paths = ActionController::Base.view_paths - assert_equal ActionView::Template::FileSystemPath, view_paths.first.class ActionView::Base.new(view_paths, {}).render(*args) end def render_without_cache(*args) - path = ActionView::Template::FileSystemPath.new(FIXTURE_LOAD_PATH) + path = ActionView::Template::FileSystemPathWithFallback.new(FIXTURE_LOAD_PATH) view_paths = ActionView::Base.process_view_paths(path) - assert_equal ActionView::Template::FileSystemPath, view_paths.first.class ActionView::Base.new(view_paths, {}).render(*args) end diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 7191df0dfd..71291f009c 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -91,10 +91,6 @@ module RenderTestCases assert_equal "The secret is in the sauce\n", @view.render(:file => "test/dot.directory/render_file_with_ivar") end - def test_render_has_access_current_template - assert_equal "test/template.erb", @view.render(:file => "test/template.erb") - end - def test_render_update # TODO: You should not have to stub out template because template is self! @view.instance_variable_set(:@template, @view) @@ -240,10 +236,6 @@ module RenderTestCases end end - def test_template_with_malformed_template_handler_is_reachable_through_its_exact_filename - assert_equal "Don't render me!", @view.render(:file => 'test/malformed/malformed.html.erb~') - end - def test_render_with_layout assert_equal %(\nHello world!\n), @view.render(:file => "test/hello_world.erb", :layout => "layouts/yield") @@ -269,7 +261,7 @@ class CachedViewRenderTest < ActiveSupport::TestCase # Ensure view path cache is primed def setup view_paths = ActionController::Base.view_paths - assert_equal ActionView::Template::FileSystemPath, view_paths.first.class + assert_equal ActionView::Template::FileSystemPathWithFallback, view_paths.first.class setup_view(view_paths) end end @@ -280,9 +272,9 @@ class LazyViewRenderTest < ActiveSupport::TestCase # Test the same thing as above, but make sure the view path # is not eager loaded def setup - path = ActionView::Template::FileSystemPath.new(FIXTURE_LOAD_PATH) + path = ActionView::Template::FileSystemPathWithFallback.new(FIXTURE_LOAD_PATH) view_paths = ActionView::Base.process_view_paths(path) - assert_equal ActionView::Template::FileSystemPath, view_paths.first.class + assert_equal ActionView::Template::FileSystemPathWithFallback, view_paths.first.class setup_view(view_paths) end end diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb index fb4b5f0f3c..a44344806d 100644 --- a/activesupport/lib/active_support/core_ext/module/delegation.rb +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -110,8 +110,10 @@ class Module allow_nil = options[:allow_nil] && "#{to} && " + file, line = caller[0].split(":") + methods.each do |method| - module_eval(<<-EOS, "(__DELEGATION__)", 1) + module_eval(<<-EOS, file, line.to_i) def #{prefix}#{method}(*args, &block) # def customer_name(*args, &block) #{allow_nil}#{to}.__send__(#{method.inspect}, *args, &block) # client && client.__send__(:name, *args, &block) end # end diff --git a/railties/test/plugin_loader_test.rb b/railties/test/plugin_loader_test.rb index b270748dd6..c647d7b478 100644 --- a/railties/test/plugin_loader_test.rb +++ b/railties/test/plugin_loader_test.rb @@ -132,8 +132,8 @@ class TestPluginLoader < Test::Unit::TestCase @loader.send :add_engine_view_paths - assert_equal [ File.join(plugin_fixture_path('engines/engine'), 'app', 'views') ], ActionController::Base.view_paths - assert_equal [ File.join(plugin_fixture_path('engines/engine'), 'app', 'views') ], ActionMailer::Base.view_paths + assert_equal [ File.join(plugin_fixture_path('engines/engine'), 'app', 'views') ], ActionController::Base.view_paths.map { |p| p.to_s } + assert_equal [ File.join(plugin_fixture_path('engines/engine'), 'app', 'views') ], ActionMailer::Base.view_paths.map { |p| p.to_s } end def test_should_add_plugin_load_paths_to_Dependencies_load_once_paths diff --git a/railties/test/plugin_test_helper.rb b/railties/test/plugin_test_helper.rb index 93d50dc07f..55d1a1fa96 100644 --- a/railties/test/plugin_test_helper.rb +++ b/railties/test/plugin_test_helper.rb @@ -12,7 +12,7 @@ RAILS_ROOT = '.' unless defined?(RAILS_ROOT) class Test::Unit::TestCase private def plugin_fixture_root_path - File.join(File.dirname(__FILE__), 'fixtures', 'plugins') + File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'plugins')) end def only_load_the_following_plugins!(plugins) -- cgit v1.2.3 From ab83db9d069dea643eeb3588eeee634a780b6735 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Mon, 27 Apr 2009 12:34:25 -0700 Subject: Fixes ActionMailer to work with the ActionView refactoring --- actionmailer/lib/action_mailer/base.rb | 11 +- actionmailer/test/mail_service_test.rb | 4 +- actionpack/lib/action_view/template/template.rb | 152 +----------------------- 3 files changed, 9 insertions(+), 158 deletions(-) diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 69e77871b0..af2cc2ee24 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -475,7 +475,7 @@ module ActionMailer #:nodoc: # if @parts.empty? template_root.find_all_by_parts(@template, {}, template_path).each do |template| @parts << Part.new( - :content_type => Mime::Type.lookup_by_extension(template.content_type || "text").to_s, + :content_type => template.mime_type ? template.mime_type.to_s : "text/plain", :disposition => "inline", :charset => charset, :body => render_template(template, @body) @@ -555,12 +555,13 @@ module ActionMailer #:nodoc: end def render_template(template, body) - if template.respond_to?(:content_type) - @current_template_content_type = template.content_type + if template.respond_to?(:mime_type) + @current_template_content_type = template.mime_type && template.mime_type.to_sym.to_s end @template = initialize_template_class(body) - layout = _pick_layout(layout, true) unless template.exempt_from_layout? + layout = _pick_layout(layout, true) unless + ActionController::Base.exempt_from_layout.include?(template.handler) @template._render_template_with_layout(template, layout, {}) ensure @current_template_content_type = nil @@ -584,7 +585,7 @@ module ActionMailer #:nodoc: end layout = _pick_layout(layout, - !template || !template.exempt_from_layout?) + !template || ActionController::Base.exempt_from_layout.include?(template.handler)) if template @template._render_template_with_layout(template, layout, opts) diff --git a/actionmailer/test/mail_service_test.rb b/actionmailer/test/mail_service_test.rb index b27bda49be..919ab5de94 100644 --- a/actionmailer/test/mail_service_test.rb +++ b/actionmailer/test/mail_service_test.rb @@ -994,13 +994,13 @@ end class InheritableTemplateRootTest < Test::Unit::TestCase def test_attr - expected = "#{File.dirname(__FILE__)}/fixtures/path.with.dots" + expected = File.expand_path("#{File.dirname(__FILE__)}/fixtures/path.with.dots") assert_equal expected, FunkyPathMailer.template_root.to_s sub = Class.new(FunkyPathMailer) sub.template_root = 'test/path' - assert_equal 'test/path', sub.template_root.to_s + assert_equal File.expand_path('test/path'), sub.template_root.to_s assert_equal expected, FunkyPathMailer.template_root.to_s end end diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb index ce6268729a..dcc5006103 100644 --- a/actionpack/lib/action_view/template/template.rb +++ b/actionpack/lib/action_view/template/template.rb @@ -38,7 +38,7 @@ module ActionView # TODO: Move out of Template def mime_type - Mime::Type.lookup_by_extension(@details[:format]) if @details[:format] + Mime::Type.lookup_by_extension(@details[:format].to_s) if @details[:format] end private @@ -77,154 +77,4 @@ module ActionView "_render_template_#{@identifier.hash}_#{__id__}_#{locals.keys.hash}".gsub('-', "_") end end -end - -if false - module ActionView #:nodoc: - class Template - extend TemplateHandlers - extend ActiveSupport::Memoizable - - module Loading - def load! - @cached = true - # freeze - end - end - include Loading - - include Renderable - - # Templates that are exempt from layouts - @@exempt_from_layout = Set.new([/\.rjs$/]) - - # Don't render layouts for templates with the given extensions. - def self.exempt_from_layout(*extensions) - regexps = extensions.collect do |extension| - extension.is_a?(Regexp) ? extension : /\.#{Regexp.escape(extension.to_s)}$/ - end - @@exempt_from_layout.merge(regexps) - end - - attr_accessor :template_path, :filename, :load_path, :base_path - attr_accessor :locale, :name, :format, :extension - delegate :to_s, :to => :path - - def initialize(template_path, load_paths = []) - template_path = template_path.dup - @load_path, @filename = find_full_path(template_path, load_paths) - @name = template_path.to_s.split("/").last.split(".").first - # @base_path, @name, @locale, @format, @extension = split(template_path) - @base_path.to_s.gsub!(/\/$/, '') # Push to split method - - # Extend with partial super powers - extend RenderablePartial if @name =~ /^_/ - end - - def accessible_paths - paths = [] - - if valid_extension?(extension) - paths << path - paths << path_without_extension - if multipart? - formats = format.split(".") - paths << "#{path_without_format_and_extension}.#{formats.first}" - paths << "#{path_without_format_and_extension}.#{formats.second}" - end - else - # template without explicit template handler should only be reachable through its exact path - paths << template_path - end - - paths - end - - def relative_path - path = File.expand_path(filename) - path.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '') if defined?(RAILS_ROOT) - path - end - memoize :relative_path - - def source - File.read(filename) - end - memoize :source - - def exempt_from_layout? - @@exempt_from_layout.any? { |exempted| path =~ exempted } - end - - def path_without_extension - [base_path, [name, locale, format].compact.join('.')].compact.join('/') - end - memoize :path_without_extension - - def path_without_format_and_extension - [base_path, [name, locale].compact.join('.')].compact.join('/') - end - memoize :path_without_format_and_extension - - def path - [base_path, [name, locale, format, extension].compact.join('.')].compact.join('/') - end - memoize :path - - def mime_type - Mime::Type.lookup_by_extension(format) if format && defined?(::Mime) - end - memoize :mime_type - - def multipart? - format && format.include?('.') - end - - def content_type - format && format.gsub('.', '/') - end - - private - - def format_and_extension - (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions - end - memoize :format_and_extension - - def mtime - File.mtime(filename) - end - memoize :mtime - - def method_segment - relative_path.to_s.gsub(/([^a-zA-Z0-9_])/) { $1.ord } - end - memoize :method_segment - - def stale? - File.mtime(filename) > mtime - end - - def recompile? - !@cached - end - - def valid_extension?(extension) - !Template.registered_template_handler(extension).nil? - end - - def valid_locale?(locale) - I18n.available_locales.include?(locale.to_sym) - end - - def find_full_path(path, load_paths) - load_paths = Array(load_paths) + [nil] - load_paths.each do |load_path| - file = load_path ? "#{load_path.to_str}/#{path}" : path - return load_path, file if File.file?(file) - end - raise MissingTemplate.new(load_paths, path) - end - end - end end \ No newline at end of file -- cgit v1.2.3 From 4246a79a991af6c4c5a9473d01e805a5ac04624a Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Mon, 27 Apr 2009 17:28:36 -0300 Subject: Show executed queries when assert_sql assertion fails [#2573 state:resolved] Signed-off-by: Pratik Naik --- activerecord/lib/active_record/test_case.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/test_case.rb b/activerecord/lib/active_record/test_case.rb index 8c6abaaccb..2dfe2c09ea 100644 --- a/activerecord/lib/active_record/test_case.rb +++ b/activerecord/lib/active_record/test_case.rb @@ -20,7 +20,7 @@ module ActiveRecord patterns_to_match.each do |pattern| failed_patterns << pattern unless $queries_executed.any?{ |sql| pattern === sql } end - assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} not found." + assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} not found.#{$queries_executed.size == 0 ? '' : "\nQueries:\n#{$queries_executed.join("\n")}"}" end def assert_queries(num = 1) -- cgit v1.2.3 From b825bef74cdde2a29ee050a5ddf4034633abcfe0 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 28 Apr 2009 17:58:51 -0700 Subject: Fix missing core extension dependencies --- railties/lib/commands/server.rb | 1 - railties/lib/console_app.rb | 2 ++ railties/lib/rails/plugin.rb | 1 + railties/lib/tasks/misc.rake | 6 +++++- railties/test/abstract_unit.rb | 1 + railties/test/plugin_test_helper.rb | 1 + 6 files changed, 10 insertions(+), 2 deletions(-) diff --git a/railties/lib/commands/server.rb b/railties/lib/commands/server.rb index ebe34a42cd..91ac7752ef 100644 --- a/railties/lib/commands/server.rb +++ b/railties/lib/commands/server.rb @@ -1,4 +1,3 @@ -require 'active_support' require 'action_controller' require 'fileutils' diff --git a/railties/lib/console_app.rb b/railties/lib/console_app.rb index d7d01d703f..5c8302634a 100644 --- a/railties/lib/console_app.rb +++ b/railties/lib/console_app.rb @@ -1,3 +1,5 @@ +require 'active_support' +require 'active_support/core/all' require 'active_support/test_case' require 'action_controller' diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index 63864058ee..bc28bec57e 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -1,3 +1,4 @@ +require 'active_support' require 'active_support/core_ext/kernel/reporting' require 'active_support/core_ext/symbol' require 'active_support/dependencies' diff --git a/railties/lib/tasks/misc.rake b/railties/lib/tasks/misc.rake index 9e6f96db5b..a2c338aa5b 100644 --- a/railties/lib/tasks/misc.rake +++ b/railties/lib/tasks/misc.rake @@ -12,10 +12,10 @@ end desc 'Generate a crytographically secure secret key. This is typically used to generate a secret for cookie sessions.' task :secret do + require 'active_support/secure_random' puts ActiveSupport::SecureRandom.hex(64) end -require 'active_support' namespace :time do namespace :zones do desc 'Displays names of all time zones recognized by the Rails TimeZone class, grouped by offset. Results can be filtered with optional OFFSET parameter, e.g., OFFSET=-6' @@ -30,6 +30,8 @@ namespace :time do desc 'Displays names of time zones recognized by the Rails TimeZone class with the same offset as the system local time' task :local do + require 'active_support' + require 'active_support/core/time' jan_offset = Time.now.beginning_of_year.utc_offset jul_offset = Time.now.beginning_of_year.change(:month => 7).utc_offset offset = jan_offset < jul_offset ? jan_offset : jul_offset @@ -38,6 +40,8 @@ namespace :time do # to find UTC -06:00 zones, OFFSET can be set to either -6, -6:00 or 21600 def build_time_zone_list(method, offset = ENV['OFFSET']) + require 'active_support' + require 'active_support/core/time' if offset offset = if offset.to_s.match(/(\+|-)?(\d+):(\d+)/) sign = $1 == '-' ? -1 : 1 diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb index 0addcb8bf3..ffd60ee662 100644 --- a/railties/test/abstract_unit.rb +++ b/railties/test/abstract_unit.rb @@ -13,6 +13,7 @@ gem 'mocha', '>= 0.9.5' require 'mocha' require 'active_support' +require 'active_support/core/all' require 'active_support/test_case' if defined?(RAILS_ROOT) diff --git a/railties/test/plugin_test_helper.rb b/railties/test/plugin_test_helper.rb index 55d1a1fa96..adb62de665 100644 --- a/railties/test/plugin_test_helper.rb +++ b/railties/test/plugin_test_helper.rb @@ -3,6 +3,7 @@ $:.unshift File.dirname(__FILE__) + "/../../activesupport/lib" require 'test/unit' require 'active_support' +require 'active_support/core/all' require 'initializer' require File.join(File.dirname(__FILE__), 'abstract_unit') -- cgit v1.2.3 From acd5db300b755d5abae2748f239441fb865c6b62 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 28 Apr 2009 18:21:03 -0700 Subject: Rejig active support dependencies to behave better with the boot process --- railties/lib/initializer.rb | 10 +++++++--- railties/lib/rails/backtrace_cleaner.rb | 3 +++ railties/lib/rails/plugin.rb | 5 ----- railties/test/boot_test.rb | 1 + railties/test/gem_dependency_test.rb | 1 + 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index b3b409dc4d..1bd7baed62 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -5,12 +5,9 @@ require 'pathname' $LOAD_PATH.unshift File.dirname(__FILE__) require 'railties_path' require 'rails/version' -require 'rails/plugin/locator' -require 'rails/plugin/loader' require 'rails/gem_dependency' require 'rails/rack' - RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV) module Rails @@ -244,6 +241,7 @@ module Rails # Set the paths from which Rails will automatically load source files, and # the load_once paths. def set_autoload_paths + require 'active_support/dependencies' ActiveSupport::Dependencies.load_paths = configuration.load_paths.uniq ActiveSupport::Dependencies.load_once_paths = configuration.load_once_paths.uniq @@ -263,6 +261,8 @@ module Rails # list. By default, all frameworks (Active Record, Active Support, # Action Pack, Action Mailer, and Active Resource) are loaded. def require_frameworks + require 'active_support' + require 'active_support/core/all' configuration.frameworks.each { |framework| require(framework.to_s) } rescue LoadError => e # Re-raise as RuntimeError because Mongrel would swallow LoadError. @@ -289,10 +289,12 @@ module Rails # Adds all load paths from plugins to the global set of load paths, so that # code from plugins can be required (explicitly or automatically via ActiveSupport::Dependencies). def add_plugin_load_paths + require 'active_support/dependencies' plugin_loader.add_plugin_load_paths end def add_gem_load_paths + require 'rails/gem_dependency' Rails::GemDependency.add_frozen_gem_path unless @configuration.gems.empty? require "rubygems" @@ -1037,12 +1039,14 @@ Run `rake gems:install` to install the missing gems. end def default_plugin_locators + require 'rails/plugin/locator' locators = [] locators << Plugin::GemLocator if defined? Gem locators << Plugin::FileSystemLocator end def default_plugin_loader + require 'rails/plugin/loader' Plugin::Loader end diff --git a/railties/lib/rails/backtrace_cleaner.rb b/railties/lib/rails/backtrace_cleaner.rb index 923ed8b31d..1605429e8b 100644 --- a/railties/lib/rails/backtrace_cleaner.rb +++ b/railties/lib/rails/backtrace_cleaner.rb @@ -1,3 +1,6 @@ +require 'active_support/backtrace_cleaner' +require 'rails/gem_dependency' + module Rails class BacktraceCleaner < ActiveSupport::BacktraceCleaner ERB_METHOD_SIG = /:in `_run_erb_.*/ diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index bc28bec57e..0f924724cd 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -1,8 +1,3 @@ -require 'active_support' -require 'active_support/core_ext/kernel/reporting' -require 'active_support/core_ext/symbol' -require 'active_support/dependencies' - module Rails # The Plugin class should be an object which provides the following methods: # diff --git a/railties/test/boot_test.rb b/railties/test/boot_test.rb index 08fcc82e6f..2dd68857c3 100644 --- a/railties/test/boot_test.rb +++ b/railties/test/boot_test.rb @@ -1,6 +1,7 @@ require 'abstract_unit' require 'initializer' require "#{File.dirname(__FILE__)}/../environments/boot" +require 'rails/gem_dependency' class BootTest < Test::Unit::TestCase def test_boot_returns_if_booted diff --git a/railties/test/gem_dependency_test.rb b/railties/test/gem_dependency_test.rb index d9cd5148a3..da7bda9bee 100644 --- a/railties/test/gem_dependency_test.rb +++ b/railties/test/gem_dependency_test.rb @@ -1,4 +1,5 @@ require 'plugin_test_helper' +require 'rails/gem_dependency' class Rails::GemDependency public :install_command, :unpack_command -- cgit v1.2.3 From afa7d7ff05a0d4787b216d50d609084649f21669 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 28 Apr 2009 16:15:17 -0500 Subject: Fix validate_request method name --- actionpack/lib/action_controller/testing/assertions/response.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/action_controller/testing/assertions/response.rb b/actionpack/lib/action_controller/testing/assertions/response.rb index 574b8d6825..a4a3dcdec8 100644 --- a/actionpack/lib/action_controller/testing/assertions/response.rb +++ b/actionpack/lib/action_controller/testing/assertions/response.rb @@ -22,7 +22,7 @@ module ActionController # assert_response 401 # def assert_response(type, message = nil) - validate_response! + validate_request! clean_backtrace do if [ :success, :missing, :redirect, :error ].include?(type) && @response.send("#{type}?") @@ -59,7 +59,7 @@ module ActionController # assert_redirected_to @customer # def assert_redirected_to(options = {}, message=nil) - validate_response! + validate_request! clean_backtrace do assert_response(:redirect, message) @@ -93,7 +93,7 @@ module ActionController # assert_template :partial => false # def assert_template(options = {}, message = nil) - validate_response! + validate_request! clean_backtrace do case options @@ -152,7 +152,7 @@ module ActionController end end - def validate_response! + def validate_request! unless @request.is_a?(ActionDispatch::Request) raise ArgumentError, "@request must be an ActionDispatch::Request" end -- cgit v1.2.3 From d63b42da362d696398fd371815734cb0caed48df Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 28 Apr 2009 16:25:04 -0500 Subject: Move header injection back into integration tests --- actionpack/lib/action_controller/testing/integration.rb | 7 ++++++- actionpack/lib/action_dispatch/test/mock.rb | 12 +----------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb index be5f216e2b..037463e489 100644 --- a/actionpack/lib/action_controller/testing/integration.rb +++ b/actionpack/lib/action_controller/testing/integration.rb @@ -263,7 +263,6 @@ module ActionController opts = { :method => method.to_s.upcase, :params => parameters, - :headers => headers, "SERVER_NAME" => host, "SERVER_PORT" => (https? ? "443" : "80"), @@ -282,6 +281,12 @@ module ActionController } env = ActionDispatch::Test::MockRequest.env_for(@path, opts) + (headers || {}).each do |key, value| + key = key.to_s.upcase.gsub(/-/, "_") + key = "HTTP_#{key}" unless env.has_key?(key) || key =~ /^HTTP_/ + env[key] = value + end + app = Rack::Lint.new(@app) status, headers, body = app.call(env) response = ::Rack::MockResponse.new(status, headers, body) diff --git a/actionpack/lib/action_dispatch/test/mock.rb b/actionpack/lib/action_dispatch/test/mock.rb index 8dc048af11..4042f9fbc8 100644 --- a/actionpack/lib/action_dispatch/test/mock.rb +++ b/actionpack/lib/action_dispatch/test/mock.rb @@ -5,8 +5,6 @@ module ActionDispatch class << self def env_for(path, opts) - headers = opts.delete(:headers) - method = (opts[:method] || opts["REQUEST_METHOD"]).to_s.upcase opts[:method] = opts["REQUEST_METHOD"] = method @@ -48,15 +46,7 @@ module ActionDispatch uri.query = requestify(params) end - env = ::Rack::MockRequest.env_for(uri.to_s, opts) - - (headers || {}).each do |key, value| - key = key.to_s.upcase.gsub(/-/, "_") - key = "HTTP_#{key}" unless env.has_key?(key) || key =~ /^HTTP_/ - env[key] = value - end - - env + ::Rack::MockRequest.env_for(uri.to_s, opts) end private -- cgit v1.2.3 From 8925e89c6307b8b7c8aeb0277ae5e059904b2fc6 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 28 Apr 2009 16:32:26 -0500 Subject: Deprecate response.assigns --- actionpack/lib/action_dispatch/http/response.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index ebba4eefa0..f570b8e8ed 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -34,7 +34,7 @@ module ActionDispatch # :nodoc: DEFAULT_HEADERS = { "Cache-Control" => "no-cache" } attr_accessor :request - attr_accessor :assigns, :template, :layout + attr_accessor :template, :layout attr_accessor :redirected_to, :redirected_to_method_params attr_writer :header @@ -45,12 +45,16 @@ module ActionDispatch # :nodoc: request.session end + def assigns + ActiveSupport::Deprecation.warn("response.assigns has been deprecated. Use controller.assigns instead", caller) + template.assigns + end + delegate :default_charset, :to => 'ActionController::Base' def initialize super @header = Rack::Utils::HeaderHash.new(DEFAULT_HEADERS) - @session, @assigns = [], [] end # The response code of the request -- cgit v1.2.3 From c0a372ba87f556769b98a6d06e8c684c3c3156df Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 28 Apr 2009 23:29:29 -0500 Subject: Deprecate template, session, assigns, and layout accessors on response object. Instead access them through the controller instance. This mainly affects functional test assertions. --- actionpack/lib/action_controller/base/base.rb | 4 +- .../lib/action_controller/base/mime_responds.rb | 2 +- .../lib/action_controller/caching/actions.rb | 2 +- .../testing/assertions/response.rb | 10 +- .../lib/action_controller/testing/process.rb | 13 +- actionpack/lib/action_dispatch/http/response.rb | 16 +- actionpack/lib/action_view/base.rb | 2 +- actionpack/lib/action_view/render/rendering.rb | 2 +- actionpack/lib/action_view/test_case.rb | 5 +- .../test/controller/action_pack_assertions_test.rb | 12 +- actionpack/test/controller/filters_test.rb | 177 +++++++++++++-------- actionpack/test/controller/flash_test.rb | 48 +++--- actionpack/test/controller/layout_test.rb | 24 +-- actionpack/test/template/body_parts_test.rb | 2 +- actionpack/test/template/output_buffer_test.rb | 18 +-- 15 files changed, 195 insertions(+), 142 deletions(-) diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb index 2063df54b4..14c4339c94 100644 --- a/actionpack/lib/action_controller/base/base.rb +++ b/actionpack/lib/action_controller/base/base.rb @@ -367,6 +367,8 @@ module ActionController #:nodoc: # Returns the name of the action this controller is processing. attr_accessor :action_name + attr_reader :template + class << self def call(env) # HACK: For global rescue to have access to the original request and response @@ -816,7 +818,7 @@ module ActionController #:nodoc: def initialize_template_class(response) @template = response.template = ActionView::Base.new(self.class.view_paths, {}, self, formats) - response.template.helpers.send :include, self.class.master_helper_module + @template.helpers.send :include, self.class.master_helper_module response.redirected_to = nil @performed_render = @performed_redirect = false end diff --git a/actionpack/lib/action_controller/base/mime_responds.rb b/actionpack/lib/action_controller/base/mime_responds.rb index bac225ab2a..1003e61a0b 100644 --- a/actionpack/lib/action_controller/base/mime_responds.rb +++ b/actionpack/lib/action_controller/base/mime_responds.rb @@ -127,7 +127,7 @@ module ActionController #:nodoc: @order << mime_type @responses[mime_type] ||= Proc.new do - @response.template.formats = [mime_type.to_sym] + @controller.template.formats = [mime_type.to_sym] @response.content_type = mime_type.to_s block_given? ? block.call : @controller.send(:render, :action => @controller.action_name) end diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb index b99feddf77..d95a346862 100644 --- a/actionpack/lib/action_controller/caching/actions.rb +++ b/actionpack/lib/action_controller/caching/actions.rb @@ -121,7 +121,7 @@ module ActionController #:nodoc: end def content_for_layout(controller) - controller.response.layout && controller.response.template.instance_variable_get('@cached_content_for_layout') + controller.template.layout && controller.template.instance_variable_get('@cached_content_for_layout') end end diff --git a/actionpack/lib/action_controller/testing/assertions/response.rb b/actionpack/lib/action_controller/testing/assertions/response.rb index a4a3dcdec8..684fe1ffe0 100644 --- a/actionpack/lib/action_controller/testing/assertions/response.rb +++ b/actionpack/lib/action_controller/testing/assertions/response.rb @@ -33,7 +33,7 @@ module ActionController assert_block("") { true } # to count the assertion else if @controller && @response.error? - exception = @controller.response.template.instance_variable_get(:@exception) + exception = @controller.template.instance_variable_get(:@exception) exception_message = exception && exception.message assert_block(build_message(message, "Expected response to be a , but was \n", type, @response.response_code, exception_message.to_s)) { false } else @@ -98,20 +98,20 @@ module ActionController clean_backtrace do case options when NilClass, String - rendered = (@controller.response.rendered[:template] || []).map { |t| t.identifier } + rendered = (@controller.template.rendered[:template] || []).map { |t| t.identifier } msg = build_message(message, "expecting but rendering with ", options, rendered.join(', ')) assert_block(msg) do if options.nil? - @controller.response.rendered[:template].blank? + @controller.template.rendered[:template].blank? else rendered.any? { |t| t.match(options) } end end when Hash if expected_partial = options[:partial] - partials = @controller.response.rendered[:partials] + partials = @controller.template.rendered[:partials] if expected_count = options[:count] found = partials.detect { |p, _| p.identifier.match(expected_partial) } actual_count = found.nil? ? 0 : found.second @@ -126,7 +126,7 @@ module ActionController assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg) end else - assert @controller.response.rendered[:partials].empty?, + assert @controller.template.rendered[:partials].empty?, "Expected no partials to be rendered" end end diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index d073d06b19..16a8f66bc4 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -160,7 +160,8 @@ module ActionController #:nodoc: # Returns the template of the file which was used to # render this response (or nil) def rendered - template.instance_variable_get(:@_rendered) + ActiveSupport::Deprecation.warn("response.rendered has been deprecated. Use tempate.rendered instead", caller) + @template.instance_variable_get(:@_rendered) end # A shortcut to the flash. Returns an empty hash if no session flash exists. @@ -190,11 +191,13 @@ module ActionController #:nodoc: # A shortcut to the template.assigns def template_objects - template.assigns || {} + ActiveSupport::Deprecation.warn("response.template_objects has been deprecated. Use tempate.assigns instead", caller) + @template.assigns || {} end # Does the specified template object exist? def has_template_object?(name=nil) + ActiveSupport::Deprecation.warn("response.has_template_object? has been deprecated. Use tempate.assigns[name].nil? instead", caller) !template_objects[name].nil? end @@ -317,9 +320,9 @@ module ActionController #:nodoc: def assigns(key = nil) if key.nil? - @response.template.assigns + @controller.template.assigns else - @response.template.assigns[key.to_s] + @controller.template.assigns[key.to_s] end end @@ -431,7 +434,7 @@ module ActionController #:nodoc: (instance_variable_names - self.class.protected_instance_variables).each do |var| name, value = var[1..-1], instance_variable_get(var) @assigns[name] = value - response.template.assigns[name] = value if response + @template.assigns[name] = value if response end end end diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index f570b8e8ed..d104dcb8a0 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -34,20 +34,30 @@ module ActionDispatch # :nodoc: DEFAULT_HEADERS = { "Cache-Control" => "no-cache" } attr_accessor :request - attr_accessor :template, :layout attr_accessor :redirected_to, :redirected_to_method_params attr_writer :header alias_method :headers=, :header= + def template + ActiveSupport::Deprecation.warn("response.template has been deprecated. Use controller.template instead", caller) + @template + end + attr_writer :template + def session ActiveSupport::Deprecation.warn("response.session has been deprecated. Use request.session instead", caller) - request.session + @request.session end def assigns ActiveSupport::Deprecation.warn("response.assigns has been deprecated. Use controller.assigns instead", caller) - template.assigns + @template.controller.assigns + end + + def layout + ActiveSupport::Deprecation.warn("response.layout has been deprecated. Use template.layout instead", caller) + @template.layout end delegate :default_charset, :to => 'ActionController::Base' diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index d087395361..44bd401631 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -191,7 +191,7 @@ module ActionView #:nodoc: ActionController::Base.allow_concurrency || (cache_template_loading.nil? ? !ActiveSupport::Dependencies.load? : cache_template_loading) end - attr_internal :request + attr_internal :request, :layout delegate :controller_path, :to => :controller, :allow_nil => true diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index f174053b86..6e368f27eb 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -46,7 +46,7 @@ module ActionView locals ||= {} if controller && layout - response.layout = layout.identifier if controller.respond_to?(:response) + @_layout = layout.identifier logger.info("Rendering template within #{layout.identifier}") if logger end diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index dddd671812..50bed67f7d 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -7,7 +7,8 @@ module ActionView @_rendered = { :template => nil, :partials => Hash.new(0) } initialize_without_template_tracking(*args) end - + + attr_internal :rendered alias_method :_render_template_without_template_tracking, :_render_template def _render_template(template, local_assigns = {}) if template.respond_to?(:identifier) @@ -16,7 +17,7 @@ module ActionView @_rendered[:template] << template end _render_template_without_template_tracking(template, local_assigns) - end + end end class TestCase < ActiveSupport::TestCase diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index f091f9b87c..dd59999a0c 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -292,14 +292,14 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase # make sure that the template objects exist def test_template_objects_alive process :assign_this - assert !@response.has_template_object?('hi') - assert @response.has_template_object?('howdy') + assert !@controller.template.assigns['hi'] + assert @controller.template.assigns['howdy'] end # make sure we don't have template objects when we shouldn't def test_template_object_missing process :nothing - assert_nil @response.template_objects['howdy'] + assert_nil @controller.template.assigns['howdy'] end # check the empty flashing @@ -328,11 +328,11 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase # check if we were rendered by a file-based template? def test_rendered_action process :nothing - assert_nil @response.rendered[:template] + assert_nil @controller.template.rendered[:template] process :hello_world - assert @response.rendered[:template] - assert 'hello_world', @response.rendered[:template].to_s + assert @controller.template.rendered[:template] + assert 'hello_world', @controller.template.rendered[:template].to_s end # check the redirection location diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index e83fde2349..aca7a821c8 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -165,11 +165,11 @@ class FilterTest < Test::Unit::TestCase def index render :text => 'ok' end - + def public end end - + class SkippingAndReorderingController < TestController skip_before_filter :ensure_login before_filter :find_record @@ -450,7 +450,8 @@ class FilterTest < Test::Unit::TestCase def test_empty_filter_chain assert_equal 0, EmptyFilterChainController.filter_chain.size - assert test_process(EmptyFilterChainController).template.assigns['action_executed'] + test_process(EmptyFilterChainController) + assert @controller.template.assigns['action_executed'] end def test_added_filter_to_inheritance_graph @@ -466,88 +467,109 @@ class FilterTest < Test::Unit::TestCase end def test_running_filters - assert_equal %w( wonderful_life ensure_login ), test_process(PrependingController).template.assigns["ran_filter"] + test_process(PrependingController) + assert_equal %w( wonderful_life ensure_login ), @controller.template.assigns["ran_filter"] end def test_running_filters_with_proc - assert test_process(ProcController).template.assigns["ran_proc_filter"] + test_process(ProcController) + assert @controller.template.assigns["ran_proc_filter"] end def test_running_filters_with_implicit_proc - assert test_process(ImplicitProcController).template.assigns["ran_proc_filter"] + test_process(ImplicitProcController) + assert @controller.template.assigns["ran_proc_filter"] end def test_running_filters_with_class - assert test_process(AuditController).template.assigns["was_audited"] + test_process(AuditController) + assert @controller.template.assigns["was_audited"] end def test_running_anomolous_yet_valid_condition_filters - response = test_process(AnomolousYetValidConditionController) - assert_equal %w( ensure_login ), response.template.assigns["ran_filter"] - assert response.template.assigns["ran_class_filter"] - assert response.template.assigns["ran_proc_filter1"] - assert response.template.assigns["ran_proc_filter2"] + test_process(AnomolousYetValidConditionController) + assert_equal %w( ensure_login ), @controller.template.assigns["ran_filter"] + assert @controller.template.assigns["ran_class_filter"] + assert @controller.template.assigns["ran_proc_filter1"] + assert @controller.template.assigns["ran_proc_filter2"] - response = test_process(AnomolousYetValidConditionController, "show_without_filter") - assert_equal nil, response.template.assigns["ran_filter"] - assert !response.template.assigns["ran_class_filter"] - assert !response.template.assigns["ran_proc_filter1"] - assert !response.template.assigns["ran_proc_filter2"] + test_process(AnomolousYetValidConditionController, "show_without_filter") + assert_equal nil, @controller.template.assigns["ran_filter"] + assert !@controller.template.assigns["ran_class_filter"] + assert !@controller.template.assigns["ran_proc_filter1"] + assert !@controller.template.assigns["ran_proc_filter2"] end def test_running_conditional_options - response = test_process(ConditionalOptionsFilter) - assert_equal %w( ensure_login ), response.template.assigns["ran_filter"] + test_process(ConditionalOptionsFilter) + assert_equal %w( ensure_login ), @controller.template.assigns["ran_filter"] end def test_running_collection_condition_filters - assert_equal %w( ensure_login ), test_process(ConditionalCollectionFilterController).template.assigns["ran_filter"] - assert_equal nil, test_process(ConditionalCollectionFilterController, "show_without_filter").template.assigns["ran_filter"] - assert_equal nil, test_process(ConditionalCollectionFilterController, "another_action").template.assigns["ran_filter"] + test_process(ConditionalCollectionFilterController) + assert_equal %w( ensure_login ), @controller.template.assigns["ran_filter"] + test_process(ConditionalCollectionFilterController, "show_without_filter") + assert_equal nil, @controller.template.assigns["ran_filter"] + test_process(ConditionalCollectionFilterController, "another_action") + assert_equal nil, @controller.template.assigns["ran_filter"] end def test_running_only_condition_filters - assert_equal %w( ensure_login ), test_process(OnlyConditionSymController).template.assigns["ran_filter"] - assert_equal nil, test_process(OnlyConditionSymController, "show_without_filter").template.assigns["ran_filter"] + test_process(OnlyConditionSymController) + assert_equal %w( ensure_login ), @controller.template.assigns["ran_filter"] + test_process(OnlyConditionSymController, "show_without_filter") + assert_equal nil, @controller.template.assigns["ran_filter"] - assert test_process(OnlyConditionProcController).template.assigns["ran_proc_filter"] - assert !test_process(OnlyConditionProcController, "show_without_filter").template.assigns["ran_proc_filter"] + test_process(OnlyConditionProcController) + assert @controller.template.assigns["ran_proc_filter"] + test_process(OnlyConditionProcController, "show_without_filter") + assert !@controller.template.assigns["ran_proc_filter"] - assert test_process(OnlyConditionClassController).template.assigns["ran_class_filter"] - assert !test_process(OnlyConditionClassController, "show_without_filter").template.assigns["ran_class_filter"] + test_process(OnlyConditionClassController) + assert @controller.template.assigns["ran_class_filter"] + test_process(OnlyConditionClassController, "show_without_filter") + assert !@controller.template.assigns["ran_class_filter"] end def test_running_except_condition_filters - assert_equal %w( ensure_login ), test_process(ExceptConditionSymController).template.assigns["ran_filter"] - assert_equal nil, test_process(ExceptConditionSymController, "show_without_filter").template.assigns["ran_filter"] + test_process(ExceptConditionSymController) + assert_equal %w( ensure_login ), @controller.template.assigns["ran_filter"] + test_process(ExceptConditionSymController, "show_without_filter") + assert_equal nil, @controller.template.assigns["ran_filter"] - assert test_process(ExceptConditionProcController).template.assigns["ran_proc_filter"] - assert !test_process(ExceptConditionProcController, "show_without_filter").template.assigns["ran_proc_filter"] + test_process(ExceptConditionProcController) + assert @controller.template.assigns["ran_proc_filter"] + test_process(ExceptConditionProcController, "show_without_filter") + assert !@controller.template.assigns["ran_proc_filter"] - assert test_process(ExceptConditionClassController).template.assigns["ran_class_filter"] - assert !test_process(ExceptConditionClassController, "show_without_filter").template.assigns["ran_class_filter"] + test_process(ExceptConditionClassController) + assert @controller.template.assigns["ran_class_filter"] + test_process(ExceptConditionClassController, "show_without_filter") + assert !@controller.template.assigns["ran_class_filter"] end def test_running_before_and_after_condition_filters - assert_equal %w( ensure_login clean_up_tmp), test_process(BeforeAndAfterConditionController).template.assigns["ran_filter"] - assert_equal nil, test_process(BeforeAndAfterConditionController, "show_without_filter").template.assigns["ran_filter"] + test_process(BeforeAndAfterConditionController) + assert_equal %w( ensure_login clean_up_tmp), @controller.template.assigns["ran_filter"] + test_process(BeforeAndAfterConditionController, "show_without_filter") + assert_equal nil, @controller.template.assigns["ran_filter"] end def test_around_filter - controller = test_process(AroundFilterController) - assert controller.template.assigns["before_ran"] - assert controller.template.assigns["after_ran"] + test_process(AroundFilterController) + assert @controller.template.assigns["before_ran"] + assert @controller.template.assigns["after_ran"] end def test_before_after_class_filter - controller = test_process(BeforeAfterClassFilterController) - assert controller.template.assigns["before_ran"] - assert controller.template.assigns["after_ran"] + test_process(BeforeAfterClassFilterController) + assert @controller.template.assigns["before_ran"] + assert @controller.template.assigns["after_ran"] end def test_having_properties_in_around_filter - controller = test_process(AroundFilterController) - assert_equal "before and after", controller.template.assigns["execution_log"] + test_process(AroundFilterController) + assert_equal "before and after", @controller.template.assigns["execution_log"] end def test_prepending_and_appending_around_filter @@ -560,7 +582,7 @@ class FilterTest < Test::Unit::TestCase def test_rendering_breaks_filtering_chain response = test_process(RenderingController) assert_equal "something else", response.body - assert !response.template.assigns["ran_action"] + assert !@controller.template.assigns["ran_action"] end def test_filters_with_mixed_specialization_run_in_order @@ -586,40 +608,53 @@ class FilterTest < Test::Unit::TestCase def test_running_prepended_before_and_after_filter assert_equal 3, PrependingBeforeAndAfterController.filter_chain.length - response = test_process(PrependingBeforeAndAfterController) - assert_equal %w( before_all between_before_all_and_after_all after_all ), response.template.assigns["ran_filter"] + test_process(PrependingBeforeAndAfterController) + assert_equal %w( before_all between_before_all_and_after_all after_all ), @controller.template.assigns["ran_filter"] end - + def test_skipping_and_limiting_controller - assert_equal %w( ensure_login ), test_process(SkippingAndLimitedController, "index").template.assigns["ran_filter"] - assert_nil test_process(SkippingAndLimitedController, "public").template.assigns["ran_filter"] + test_process(SkippingAndLimitedController, "index") + assert_equal %w( ensure_login ), @controller.template.assigns["ran_filter"] + test_process(SkippingAndLimitedController, "public") + assert_nil @controller.template.assigns["ran_filter"] end def test_skipping_and_reordering_controller - assert_equal %w( find_record ensure_login ), test_process(SkippingAndReorderingController, "index").template.assigns["ran_filter"] + test_process(SkippingAndReorderingController, "index") + assert_equal %w( find_record ensure_login ), @controller.template.assigns["ran_filter"] end def test_conditional_skipping_of_filters - assert_nil test_process(ConditionalSkippingController, "login").template.assigns["ran_filter"] - assert_equal %w( ensure_login find_user ), test_process(ConditionalSkippingController, "change_password").template.assigns["ran_filter"] + test_process(ConditionalSkippingController, "login") + assert_nil @controller.template.assigns["ran_filter"] + test_process(ConditionalSkippingController, "change_password") + assert_equal %w( ensure_login find_user ), @controller.template.assigns["ran_filter"] - assert_nil test_process(ConditionalSkippingController, "login").template.controller.instance_variable_get("@ran_after_filter") - assert_equal %w( clean_up ), test_process(ConditionalSkippingController, "change_password").template.controller.instance_variable_get("@ran_after_filter") + test_process(ConditionalSkippingController, "login") + assert_nil @controller.template.controller.instance_variable_get("@ran_after_filter") + test_process(ConditionalSkippingController, "change_password") + assert_equal %w( clean_up ), @controller.template.controller.instance_variable_get("@ran_after_filter") end def test_conditional_skipping_of_filters_when_parent_filter_is_also_conditional - assert_equal %w( conditional_in_parent conditional_in_parent ), test_process(ChildOfConditionalParentController).template.assigns['ran_filter'] - assert_nil test_process(ChildOfConditionalParentController, 'another_action').template.assigns['ran_filter'] + test_process(ChildOfConditionalParentController) + assert_equal %w( conditional_in_parent conditional_in_parent ), @controller.template.assigns['ran_filter'] + test_process(ChildOfConditionalParentController, 'another_action') + assert_nil @controller.template.assigns['ran_filter'] end def test_condition_skipping_of_filters_when_siblings_also_have_conditions - assert_equal %w( conditional_in_parent conditional_in_parent ), test_process(ChildOfConditionalParentController).template.assigns['ran_filter'], "1" - assert_equal nil, test_process(AnotherChildOfConditionalParentController).template.assigns['ran_filter'] - assert_equal %w( conditional_in_parent conditional_in_parent ), test_process(ChildOfConditionalParentController).template.assigns['ran_filter'] + test_process(ChildOfConditionalParentController) + assert_equal %w( conditional_in_parent conditional_in_parent ), @controller.template.assigns['ran_filter'], "1" + test_process(AnotherChildOfConditionalParentController) + assert_equal nil, @controller.template.assigns['ran_filter'] + test_process(ChildOfConditionalParentController) + assert_equal %w( conditional_in_parent conditional_in_parent ), @controller.template.assigns['ran_filter'] end def test_changing_the_requirements - assert_equal nil, test_process(ChangingTheRequirementsController, "go_wild").template.assigns['ran_filter'] + test_process(ChangingTheRequirementsController, "go_wild") + assert_equal nil, @controller.template.assigns['ran_filter'] end def test_a_rescuing_around_filter @@ -638,7 +673,8 @@ class FilterTest < Test::Unit::TestCase request = ActionController::TestRequest.new request.action = action controller = controller.new if controller.is_a?(Class) - controller.process_with_test(request, ActionController::TestResponse.new) + @controller = controller + @controller.process_with_test(request, ActionController::TestResponse.new) end end @@ -819,9 +855,9 @@ class YieldingAroundFiltersTest < Test::Unit::TestCase end def test_with_proc - controller = test_process(ControllerWithProcFilter,'no_raise') - assert controller.template.assigns['before'] - assert controller.template.assigns['after'] + test_process(ControllerWithProcFilter,'no_raise') + assert @controller.template.assigns['before'] + assert @controller.template.assigns['after'] end def test_nested_filters @@ -841,13 +877,13 @@ class YieldingAroundFiltersTest < Test::Unit::TestCase end def test_filter_order_with_all_filter_types - controller = test_process(ControllerWithAllTypesOfFilters,'no_raise') - assert_equal 'before around (before yield) around_again (before yield) around_again (after yield) around (after yield) after',controller.template.assigns['ran_filter'].join(' ') + test_process(ControllerWithAllTypesOfFilters,'no_raise') + assert_equal 'before around (before yield) around_again (before yield) around_again (after yield) around (after yield) after', @controller.template.assigns['ran_filter'].join(' ') end def test_filter_order_with_skip_filter_method - controller = test_process(ControllerWithTwoLessFilters,'no_raise') - assert_equal 'before around (before yield) around (after yield)',controller.template.assigns['ran_filter'].join(' ') + test_process(ControllerWithTwoLessFilters,'no_raise') + assert_equal 'before around (before yield) around (after yield)', @controller.template.assigns['ran_filter'].join(' ') end def test_first_filter_in_multiple_before_filter_chain_halts @@ -880,6 +916,7 @@ class YieldingAroundFiltersTest < Test::Unit::TestCase request = ActionController::TestRequest.new request.action = action controller = controller.new if controller.is_a?(Class) - controller.process_with_test(request, ActionController::TestResponse.new) + @controller = controller + @controller.process_with_test(request, ActionController::TestResponse.new) end end diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb index d8a892811e..ef60cae0ff 100644 --- a/actionpack/test/controller/flash_test.rb +++ b/actionpack/test/controller/flash_test.rb @@ -79,64 +79,64 @@ class FlashTest < ActionController::TestCase get :set_flash get :use_flash - assert_equal "hello", @response.template.assigns["flash_copy"]["that"] - assert_equal "hello", @response.template.assigns["flashy"] + assert_equal "hello", @controller.template.assigns["flash_copy"]["that"] + assert_equal "hello", @controller.template.assigns["flashy"] get :use_flash - assert_nil @response.template.assigns["flash_copy"]["that"], "On second flash" + assert_nil @controller.template.assigns["flash_copy"]["that"], "On second flash" end def test_keep_flash get :set_flash get :use_flash_and_keep_it - assert_equal "hello", @response.template.assigns["flash_copy"]["that"] - assert_equal "hello", @response.template.assigns["flashy"] + assert_equal "hello", @controller.template.assigns["flash_copy"]["that"] + assert_equal "hello", @controller.template.assigns["flashy"] get :use_flash - assert_equal "hello", @response.template.assigns["flash_copy"]["that"], "On second flash" + assert_equal "hello", @controller.template.assigns["flash_copy"]["that"], "On second flash" get :use_flash - assert_nil @response.template.assigns["flash_copy"]["that"], "On third flash" + assert_nil @controller.template.assigns["flash_copy"]["that"], "On third flash" end def test_flash_now get :set_flash_now - assert_equal "hello", @response.template.assigns["flash_copy"]["that"] - assert_equal "bar" , @response.template.assigns["flash_copy"]["foo"] - assert_equal "hello", @response.template.assigns["flashy"] + assert_equal "hello", @controller.template.assigns["flash_copy"]["that"] + assert_equal "bar" , @controller.template.assigns["flash_copy"]["foo"] + assert_equal "hello", @controller.template.assigns["flashy"] get :attempt_to_use_flash_now - assert_nil @response.template.assigns["flash_copy"]["that"] - assert_nil @response.template.assigns["flash_copy"]["foo"] - assert_nil @response.template.assigns["flashy"] + assert_nil @controller.template.assigns["flash_copy"]["that"] + assert_nil @controller.template.assigns["flash_copy"]["foo"] + assert_nil @controller.template.assigns["flashy"] end def test_update_flash get :set_flash get :use_flash_and_update_it - assert_equal "hello", @response.template.assigns["flash_copy"]["that"] - assert_equal "hello again", @response.template.assigns["flash_copy"]["this"] + assert_equal "hello", @controller.template.assigns["flash_copy"]["that"] + assert_equal "hello again", @controller.template.assigns["flash_copy"]["this"] get :use_flash - assert_nil @response.template.assigns["flash_copy"]["that"], "On second flash" - assert_equal "hello again", @response.template.assigns["flash_copy"]["this"], "On second flash" + assert_nil @controller.template.assigns["flash_copy"]["that"], "On second flash" + assert_equal "hello again", @controller.template.assigns["flash_copy"]["this"], "On second flash" end def test_flash_after_reset_session get :use_flash_after_reset_session - assert_equal "hello", @response.template.assigns["flashy_that"] - assert_equal "good-bye", @response.template.assigns["flashy_this"] - assert_nil @response.template.assigns["flashy_that_reset"] + assert_equal "hello", @controller.template.assigns["flashy_that"] + assert_equal "good-bye", @controller.template.assigns["flashy_this"] + assert_nil @controller.template.assigns["flashy_that_reset"] end def test_sweep_after_halted_filter_chain get :std_action - assert_nil @response.template.assigns["flash_copy"]["foo"] + assert_nil @controller.template.assigns["flash_copy"]["foo"] get :filter_halting_action - assert_equal "bar", @response.template.assigns["flash_copy"]["foo"] + assert_equal "bar", @controller.template.assigns["flash_copy"]["foo"] get :std_action # follow redirection - assert_equal "bar", @response.template.assigns["flash_copy"]["foo"] + assert_equal "bar", @controller.template.assigns["flash_copy"]["foo"] get :std_action - assert_nil @response.template.assigns["flash_copy"]["foo"] + assert_nil @controller.template.assigns["flash_copy"]["foo"] end end diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb index 11559b4071..da3f7b0cb8 100644 --- a/actionpack/test/controller/layout_test.rb +++ b/actionpack/test/controller/layout_test.rb @@ -57,7 +57,7 @@ class LayoutAutoDiscoveryTest < ActionController::TestCase @controller = ThirdPartyTemplateLibraryController.new get :hello assert @controller.active_layout(true).identifier.include?('layouts/third_party_template_library.mab') - assert @response.layout.include?('layouts/third_party_template_library') + assert @controller.template.layout.include?('layouts/third_party_template_library') assert_response :success assert_equal 'Mab', @response.body end @@ -121,49 +121,49 @@ class LayoutSetInResponseTest < ActionController::TestCase def test_layout_set_when_using_default_layout @controller = DefaultLayoutController.new get :hello - assert @response.layout.include?('layouts/layout_test') + assert @controller.template.layout.include?('layouts/layout_test') end def test_layout_set_when_set_in_controller @controller = HasOwnLayoutController.new get :hello - assert @response.layout.include?('layouts/item') + assert @controller.template.layout.include?('layouts/item') end def test_layout_only_exception_when_included @controller = OnlyLayoutController.new get :hello - assert @response.layout.include?('layouts/item') + assert @controller.template.layout.include?('layouts/item') end def test_layout_only_exception_when_excepted @controller = OnlyLayoutController.new get :goodbye - assert_equal nil, @response.layout + assert_equal nil, @controller.template.layout end def test_layout_except_exception_when_included @controller = ExceptLayoutController.new get :hello - assert @response.layout.include?('layouts/item') + assert @controller.template.layout.include?('layouts/item') end def test_layout_except_exception_when_excepted @controller = ExceptLayoutController.new get :goodbye - assert_equal nil, @response.layout + assert_equal nil, @controller.template.layout end def test_layout_set_when_using_render @controller = SetsLayoutInRenderController.new get :hello - assert @response.layout.include?('layouts/third_party_template_library') + assert @controller.template.layout.include?('layouts/third_party_template_library') end def test_layout_is_not_set_when_none_rendered @controller = RendersNoLayoutController.new get :hello - assert_nil @response.layout + assert_nil @controller.template.layout end def test_exempt_from_layout_honored_by_render_template @@ -181,7 +181,7 @@ class LayoutSetInResponseTest < ActionController::TestCase pending do @controller = PrependsViewPathController.new get :hello - assert_equal 'layouts/alt', @response.layout + assert_equal 'layouts/alt', @controller.template.layout end end @@ -206,7 +206,7 @@ class LayoutExceptionRaised < ActionController::TestCase def test_exception_raised_when_layout_file_not_found @controller = SetsNonExistentLayoutFile.new get :hello - assert_kind_of ActionView::MissingTemplate, @response.template.instance_eval { @exception } + assert_kind_of ActionView::MissingTemplate, @controller.template.instance_eval { @exception } end end @@ -234,7 +234,7 @@ unless RUBY_PLATFORM =~ /(:?mswin|mingw|bccwin)/ @controller = LayoutSymlinkedTest.new get :hello assert_response 200 - assert @response.layout.include?("layouts/symlinked/symlinked_layout") + assert @controller.template.layout.include?("layouts/symlinked/symlinked_layout") end end end diff --git a/actionpack/test/template/body_parts_test.rb b/actionpack/test/template/body_parts_test.rb index 4c82b75cdc..5be8533293 100644 --- a/actionpack/test/template/body_parts_test.rb +++ b/actionpack/test/template/body_parts_test.rb @@ -6,7 +6,7 @@ class BodyPartsTest < ActionController::TestCase class TestController < ActionController::Base def index RENDERINGS.each do |rendering| - response.template.punctuate_body! rendering + @template.punctuate_body! rendering end @performed_render = true end diff --git a/actionpack/test/template/output_buffer_test.rb b/actionpack/test/template/output_buffer_test.rb index 6d8eab63dc..bc17f36783 100644 --- a/actionpack/test/template/output_buffer_test.rb +++ b/actionpack/test/template/output_buffer_test.rb @@ -13,23 +13,23 @@ class OutputBufferTest < ActionController::TestCase # Start with the default body parts get :index assert_equal ['foo'], @response.body_parts - assert_nil @response.template.output_buffer + assert_nil @controller.template.output_buffer # Nil output buffer is skipped - @response.template.flush_output_buffer - assert_nil @response.template.output_buffer + @controller.template.flush_output_buffer + assert_nil @controller.template.output_buffer assert_equal ['foo'], @response.body_parts # Empty output buffer is skipped - @response.template.output_buffer = '' - @response.template.flush_output_buffer - assert_equal '', @response.template.output_buffer + @controller.template.output_buffer = '' + @controller.template.flush_output_buffer + assert_equal '', @controller.template.output_buffer assert_equal ['foo'], @response.body_parts # Flushing appends the output buffer to the body parts - @response.template.output_buffer = 'bar' - @response.template.flush_output_buffer - assert_equal '', @response.template.output_buffer + @controller.template.output_buffer = 'bar' + @controller.template.flush_output_buffer + assert_equal '', @controller.template.output_buffer assert_equal ['foo', 'bar'], @response.body_parts end end -- cgit v1.2.3 From 599f2cfb4a0e0ec4135265bf5c56b83f1450beea Mon Sep 17 00:00:00 2001 From: David Dollar Date: Wed, 29 Apr 2009 01:22:54 -0400 Subject: Attempt to deal with more cases of gems with native components. This commit adds a rudimentary check for 'unbuilt' gems, so that we can abort the application load if there are any gems that have native components that have not yet been built. The rake task gems:build has now only builds 'unbuilt' gems as a result. The rake task gems:build:force has been added to deal with cases of incomplete builds, or any case where you need to force the build of all of your gems. Changes the gems:build task to get its gem list by parsing directory entries in vendor/gems, which sidesteps the chicken/egg issues involved with having a gem unpacked into vendor/gems without before its native bits are compiled. [#2266 state:committed] Signed-off-by: Jeremy Kemper --- railties/lib/initializer.rb | 21 +++++++++++ railties/lib/rails/gem_dependency.rb | 21 ++++++++--- railties/lib/tasks/gems.rake | 18 ++++++++-- railties/test/gem_dependency_test.rb | 21 +++++++++++ .../vendor/gems/dummy-gem-i-1.0.0/.specification | 41 ++++++++++++++++++++++ .../dummy-gem-i-1.0.0/ext/dummy-gem-i/Makefile | 0 .../gems/dummy-gem-i-1.0.0/lib/dummy-gem-i.rb | 1 + .../vendor/gems/dummy-gem-j-1.0.0/.specification | 41 ++++++++++++++++++++++ .../gems/dummy-gem-j-1.0.0/lib/dummy-gem-j.rb | 1 + 9 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 railties/test/vendor/gems/dummy-gem-i-1.0.0/.specification create mode 100644 railties/test/vendor/gems/dummy-gem-i-1.0.0/ext/dummy-gem-i/Makefile create mode 100644 railties/test/vendor/gems/dummy-gem-i-1.0.0/lib/dummy-gem-i.rb create mode 100644 railties/test/vendor/gems/dummy-gem-j-1.0.0/.specification create mode 100644 railties/test/vendor/gems/dummy-gem-j-1.0.0/lib/dummy-gem-j.rb diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 1bd7baed62..71366a4480 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -156,6 +156,8 @@ module Rails add_support_load_paths + check_for_unbuilt_gems + load_gems load_plugins @@ -308,6 +310,25 @@ module Rails end end + def check_for_unbuilt_gems + unbuilt_gems = @configuration.gems.select(&:frozen?).reject(&:built?) + if unbuilt_gems.size > 0 + # don't print if the gems:build rake tasks are being run + unless $gems_build_rake_task + abort <<-end_error +The following gems have native components that need to be built + #{unbuilt_gems.map { |gem| "#{gem.name} #{gem.requirement}" } * "\n "} + +You're running: + ruby #{Gem.ruby_version} at #{Gem.ruby} + rubygems #{Gem::RubyGemsVersion} at #{Gem.path * ', '} + +Run `rake gems:build` to build the unbuilt gems. + end_error + end + end + end + def check_gem_dependencies unloaded_gems = @configuration.gems.reject { |g| g.loaded? } if unloaded_gems.size > 0 diff --git a/railties/lib/rails/gem_dependency.rb b/railties/lib/rails/gem_dependency.rb index 3062a77104..ee3d0d81ba 100644 --- a/railties/lib/rails/gem_dependency.rb +++ b/railties/lib/rails/gem_dependency.rb @@ -29,6 +29,15 @@ module Rails end end + def self.from_directory_name(directory_name) + directory_name_parts = File.basename(directory_name).split('-') + name = directory_name_parts[0..-2].join('-') + version = directory_name_parts.last + self.new(name, :version => version) + rescue ArgumentError => e + raise "Unable to determine gem name and version from '#{directory_name}'" + end + def initialize(name, options = {}) require 'rubygems' unless Object.const_defined?(:Gem) @@ -101,8 +110,12 @@ module Rails end def built? - # TODO: If Rubygems ever gives us a way to detect this, we should use it - false + return false unless frozen? + specification.extensions.each do |ext| + makefile = File.join(unpacked_gem_directory, File.dirname(ext), 'Makefile') + return false unless File.exists?(makefile) + end + true end def framework_gem? @@ -155,9 +168,9 @@ module Rails specification && File.exists?(unpacked_gem_directory) end - def build + def build(options={}) require 'rails/gem_builder' - unless built? + if options[:force] || !built? return unless File.exists?(unpacked_specification_filename) spec = YAML::load_file(unpacked_specification_filename) Rails::GemBuilder.new(spec, unpacked_gem_directory).build_extensions diff --git a/railties/lib/tasks/gems.rake b/railties/lib/tasks/gems.rake index ed07bf2016..efadb1da3b 100644 --- a/railties/lib/tasks/gems.rake +++ b/railties/lib/tasks/gems.rake @@ -20,8 +20,16 @@ namespace :gems do desc "Build any native extensions for unpacked gems" task :build do $gems_build_rake_task = true - Rake::Task['gems:unpack'].invoke - current_gems.each &:build + frozen_gems.each &:build + end + + namespace :build do + desc "Force the build of all gems" + task :force do + $gems_build_rake_task = true + Rake::Task['gems:unpack'].invoke + current_gems.each { |gem| gem.build(:force => true) } + end end desc "Installs all required gems." @@ -53,6 +61,12 @@ def current_gems gems end +def frozen_gems + Dir[File.join(RAILS_ROOT, 'vendor', 'gems', '*-*')].map do |gem_dir| + Rails::GemDependency.from_directory_name(gem_dir) + end +end + def print_gem_status(gem, indent=1) code = case when gem.framework_gem? then 'R' diff --git a/railties/test/gem_dependency_test.rb b/railties/test/gem_dependency_test.rb index da7bda9bee..4ff4fe8d43 100644 --- a/railties/test/gem_dependency_test.rb +++ b/railties/test/gem_dependency_test.rb @@ -145,4 +145,25 @@ class GemDependencyTest < Test::Unit::TestCase end end + def test_gem_from_directory_name + dummy_gem = Rails::GemDependency.from_directory_name('dummy-gem-1.1') + assert_equal 'dummy-gem', dummy_gem.name + assert_equal '= 1.1', dummy_gem.version_requirements.to_s + end + + def test_gem_from_invalid_directory_name + assert_raises RuntimeError do + dummy_gem = Rails::GemDependency.from_directory_name('dummy-gem') + end + assert_raises RuntimeError do + dummy_gem = Rails::GemDependency.from_directory_name('dummy') + end + end + + def test_gem_determines_build_status + assert_equal true, Rails::GemDependency.new("dummy-gem-a").built? + assert_equal true, Rails::GemDependency.new("dummy-gem-i").built? + assert_equal false, Rails::GemDependency.new("dummy-gem-j").built? + end + end diff --git a/railties/test/vendor/gems/dummy-gem-i-1.0.0/.specification b/railties/test/vendor/gems/dummy-gem-i-1.0.0/.specification new file mode 100644 index 0000000000..50b4969da5 --- /dev/null +++ b/railties/test/vendor/gems/dummy-gem-i-1.0.0/.specification @@ -0,0 +1,41 @@ +--- !ruby/object:Gem::Specification +name: dummy-gem-i +version: !ruby/object:Gem::Version + version: 1.3.0 +platform: ruby +authors: +- "Nobody" +date: 2008-10-03 00:00:00 -04:00 +dependencies: +- !ruby/object:Gem::Dependency + name: dummy-gem-i + type: :runtime + version_requirement: + version_requirements: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: 1.0.0 + version: +extensions: +- ext/dummy-gem-i/extconf.rb +files: +- lib +- lib/dummy-gem-i.rb +require_paths: +- lib +required_ruby_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +required_rubygems_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +requirements: [] +specification_version: 2 +summary: Dummy Gem G diff --git a/railties/test/vendor/gems/dummy-gem-i-1.0.0/ext/dummy-gem-i/Makefile b/railties/test/vendor/gems/dummy-gem-i-1.0.0/ext/dummy-gem-i/Makefile new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/test/vendor/gems/dummy-gem-i-1.0.0/lib/dummy-gem-i.rb b/railties/test/vendor/gems/dummy-gem-i-1.0.0/lib/dummy-gem-i.rb new file mode 100644 index 0000000000..2f9a376c2c --- /dev/null +++ b/railties/test/vendor/gems/dummy-gem-i-1.0.0/lib/dummy-gem-i.rb @@ -0,0 +1 @@ +DUMMY_GEM_I_VERSION="1.0.0" diff --git a/railties/test/vendor/gems/dummy-gem-j-1.0.0/.specification b/railties/test/vendor/gems/dummy-gem-j-1.0.0/.specification new file mode 100644 index 0000000000..2c456546fc --- /dev/null +++ b/railties/test/vendor/gems/dummy-gem-j-1.0.0/.specification @@ -0,0 +1,41 @@ +--- !ruby/object:Gem::Specification +name: dummy-gem-j +version: !ruby/object:Gem::Version + version: 1.3.0 +platform: ruby +authors: +- "Nobody" +date: 2008-10-03 00:00:00 -04:00 +dependencies: +- !ruby/object:Gem::Dependency + name: dummy-gem-j + type: :runtime + version_requirement: + version_requirements: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: 1.0.0 + version: +extensions: +- ext/dummy-gem-j/extconf.rb +files: +- lib +- lib/dummy-gem-j.rb +require_paths: +- lib +required_ruby_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +required_rubygems_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +requirements: [] +specification_version: 2 +summary: Dummy Gem G diff --git a/railties/test/vendor/gems/dummy-gem-j-1.0.0/lib/dummy-gem-j.rb b/railties/test/vendor/gems/dummy-gem-j-1.0.0/lib/dummy-gem-j.rb new file mode 100644 index 0000000000..8ecd363ff8 --- /dev/null +++ b/railties/test/vendor/gems/dummy-gem-j-1.0.0/lib/dummy-gem-j.rb @@ -0,0 +1 @@ +DUMMY_GEM_J_VERSION="1.0.0" -- cgit v1.2.3 From 7149ddd2a109345f8c48c787b5541b9b31a8a6fa Mon Sep 17 00:00:00 2001 From: David Dollar Date: Wed, 29 Apr 2009 10:04:17 -0400 Subject: Additional tests for the gem subsystem * test_gem_ignores_development_dependencies * test_gem_guards_against_duplicate_unpacks * test_gem_does_not_unpack_framework_gems [#2236 state:committed] Signed-off-by: Jeremy Kemper --- railties/test/gem_dependency_test.rb | 21 ++++++++++ .../vendor/gems/dummy-gem-h-1.0.0/.specification | 29 +++++++++++++ .../gems/dummy-gem-h-1.0.0/lib/dummy-gem-h.rb | 1 + .../vendor/gems/dummy-gem-k-1.0.0/.specification | 49 ++++++++++++++++++++++ .../gems/dummy-gem-k-1.0.0/lib/dummy-gem-k.rb | 1 + 5 files changed, 101 insertions(+) create mode 100644 railties/test/vendor/gems/dummy-gem-h-1.0.0/.specification create mode 100644 railties/test/vendor/gems/dummy-gem-h-1.0.0/lib/dummy-gem-h.rb create mode 100644 railties/test/vendor/gems/dummy-gem-k-1.0.0/.specification create mode 100644 railties/test/vendor/gems/dummy-gem-k-1.0.0/lib/dummy-gem-k.rb diff --git a/railties/test/gem_dependency_test.rb b/railties/test/gem_dependency_test.rb index 4ff4fe8d43..ff27af5572 100644 --- a/railties/test/gem_dependency_test.rb +++ b/railties/test/gem_dependency_test.rb @@ -145,6 +145,27 @@ class GemDependencyTest < Test::Unit::TestCase end end + def test_gem_ignores_development_dependencies + dummy_gem = Rails::GemDependency.new "dummy-gem-k" + dummy_gem.add_load_paths + dummy_gem.load + assert_equal 1, dummy_gem.dependencies.size + end + + def test_gem_guards_against_duplicate_unpacks + dummy_gem = Rails::GemDependency.new "dummy-gem-a" + dummy_gem.stubs(:frozen?).returns(true) + dummy_gem.expects(:unpack_base).never + dummy_gem.unpack + end + + def test_gem_does_not_unpack_framework_gems + dummy_gem = Rails::GemDependency.new "dummy-gem-a" + dummy_gem.stubs(:framework_gem?).returns(true) + dummy_gem.expects(:unpack_base).never + dummy_gem.unpack + end + def test_gem_from_directory_name dummy_gem = Rails::GemDependency.from_directory_name('dummy-gem-1.1') assert_equal 'dummy-gem', dummy_gem.name diff --git a/railties/test/vendor/gems/dummy-gem-h-1.0.0/.specification b/railties/test/vendor/gems/dummy-gem-h-1.0.0/.specification new file mode 100644 index 0000000000..b3f7930948 --- /dev/null +++ b/railties/test/vendor/gems/dummy-gem-h-1.0.0/.specification @@ -0,0 +1,29 @@ +--- !ruby/object:Gem::Specification +name: dummy-gem-h +version: !ruby/object:Gem::Version + version: 1.3.0 +platform: ruby +authors: +- "Nobody" +date: 2008-10-03 00:00:00 -04:00 +dependencies: +files: +- lib +- lib/dummy-gem-h.rb +require_paths: +- lib +required_ruby_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +required_rubygems_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +requirements: [] +specification_version: 2 +summary: Dummy Gem H diff --git a/railties/test/vendor/gems/dummy-gem-h-1.0.0/lib/dummy-gem-h.rb b/railties/test/vendor/gems/dummy-gem-h-1.0.0/lib/dummy-gem-h.rb new file mode 100644 index 0000000000..0f91234936 --- /dev/null +++ b/railties/test/vendor/gems/dummy-gem-h-1.0.0/lib/dummy-gem-h.rb @@ -0,0 +1 @@ +DUMMY_GEM_H_VERSION="1.0.0" diff --git a/railties/test/vendor/gems/dummy-gem-k-1.0.0/.specification b/railties/test/vendor/gems/dummy-gem-k-1.0.0/.specification new file mode 100644 index 0000000000..20edd0f856 --- /dev/null +++ b/railties/test/vendor/gems/dummy-gem-k-1.0.0/.specification @@ -0,0 +1,49 @@ +--- !ruby/object:Gem::Specification +name: dummy-gem-k +version: !ruby/object:Gem::Version + version: 1.3.0 +platform: ruby +authors: +- "Nobody" +date: 2008-10-03 00:00:00 -04:00 +dependencies: +- !ruby/object:Gem::Dependency + name: dummy-gem-k + type: :runtime + version_requirement: + version_requirements: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: 1.0.0 + version: +- !ruby/object:Gem::Dependency + name: dummy-gem-h + type: :development + version_requirement: + version_requirements: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: 1.0.0 + version: +files: +- lib +- lib/dummy-gem-k.rb +require_paths: +- lib +required_ruby_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +required_rubygems_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +requirements: [] +specification_version: 2 +summary: Dummy Gem I diff --git a/railties/test/vendor/gems/dummy-gem-k-1.0.0/lib/dummy-gem-k.rb b/railties/test/vendor/gems/dummy-gem-k-1.0.0/lib/dummy-gem-k.rb new file mode 100644 index 0000000000..97fb1d69ce --- /dev/null +++ b/railties/test/vendor/gems/dummy-gem-k-1.0.0/lib/dummy-gem-k.rb @@ -0,0 +1 @@ +DUMMY_GEM_K_VERSION="1.0.0" -- cgit v1.2.3 From db892ea77563dadb6fbbd242be78ff87321d0bd1 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Wed, 29 Apr 2009 19:35:21 -0300 Subject: Fix duplicated test name [#2581 state:committed] Signed-off-by: Jeremy Kemper --- activerecord/test/cases/calculations_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 56dcdea110..fd455e0864 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -233,7 +233,7 @@ class CalculationsTest < ActiveRecord::TestCase assert_equal 8, c['Jadedpixel'] end - def test_should_group_by_summed_field_with_conditions_and_having + def test_should_group_by_summed_field_through_association_and_having c = companies(:rails_core).companies.sum(:id, :group => :name, :having => 'sum(id) > 7') assert_nil c['Leetsoft'] -- cgit v1.2.3