From 42a06d2d6253eed3b9f4fb4edfa251c9508a2e20 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 22 Apr 2009 09:10:14 -0700
Subject: stdlib autoloads were hanging on 1.9.1
---
activesupport/lib/active_support/core_ext/string/iterators.rb | 5 ++---
activesupport/lib/active_support/json/decoding.rb | 6 ++----
activesupport/test/json/decoding_test.rb | 4 ++--
3 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/activesupport/lib/active_support/core_ext/string/iterators.rb b/activesupport/lib/active_support/core_ext/string/iterators.rb
index 472de7bc24..2f8aa84024 100644
--- a/activesupport/lib/active_support/core_ext/string/iterators.rb
+++ b/activesupport/lib/active_support/core_ext/string/iterators.rb
@@ -1,11 +1,10 @@
unless '1.9'.respond_to?(:each_char)
- autoload :StringScanner, 'strscan' unless defined? :StringScanner
-
class String
# Yields a single-character string for each character in the string.
# When $KCODE = 'UTF8', multi-byte characters are yielded appropriately.
def each_char
- scanner, char = StringScanner.new(self), /./mu
+ require 'strscan' unless defined? ::StringScanner
+ scanner, char = ::StringScanner.new(self), /./mu
while c = scanner.scan(char)
yield c
end
diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb
index c66500aa9c..70e9f40fc7 100644
--- a/activesupport/lib/active_support/json/decoding.rb
+++ b/activesupport/lib/active_support/json/decoding.rb
@@ -1,6 +1,3 @@
-autoload :YAML, 'yaml' unless defined? YAML
-autoload :StringScanner, 'strscan' unless defined? StringScanner
-
require 'active_support/core_ext/string/starts_ends_with'
module ActiveSupport
@@ -22,7 +19,8 @@ module ActiveSupport
# Ensure that ":" and "," are always followed by a space
def convert_json_to_yaml(json) #:nodoc:
- scanner, quoting, marks, pos, times = StringScanner.new(json), false, [], nil, []
+ require 'strscan' unless defined? ::StringScanner
+ scanner, quoting, marks, pos, times = ::StringScanner.new(json), false, [], nil, []
while scanner.scan_until(/(\\['"]|['":,\\]|\\.)/)
case char = scanner[1]
when '"', "'"
diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb
index 8fe40557d6..7d8a07654d 100644
--- a/activesupport/test/json/decoding_test.rb
+++ b/activesupport/test/json/decoding_test.rb
@@ -1,7 +1,7 @@
# encoding: UTF-8
require 'abstract_unit'
-class TestJSONDecoding < Test::Unit::TestCase
+class TestJSONDecoding < ActiveSupport::TestCase
TESTS = {
%q({"returnTo":{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
%q({returnTo:{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
@@ -36,7 +36,7 @@ class TestJSONDecoding < Test::Unit::TestCase
}
TESTS.each do |json, expected|
- define_method :"test_json_decoding_#{json}" do
+ test "json decodes #{json}" do
assert_nothing_raised do
assert_equal expected, ActiveSupport::JSON.decode(json)
end
--
cgit v1.2.3
From ab321268f86d9013cbd4ecd0b5f46e7b05ec55a9 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 22 Apr 2009 16:10:49 -0700
Subject: No more free lunch
---
actionpack/lib/action_controller.rb | 1 +
actionpack/lib/action_dispatch.rb | 1 +
actionpack/lib/action_view.rb | 1 +
activemodel/lib/active_model/core.rb | 15 ++++++++++-----
activerecord/lib/active_record.rb | 1 +
activeresource/lib/active_resource.rb | 1 +
activesupport/CHANGELOG | 2 ++
activesupport/lib/active_support.rb | 3 ---
activesupport/lib/active_support/core/all.rb | 1 +
.../lib/active_support/core_ext/kernel/requires.rb | 4 +++-
railties/Rakefile | 4 ++--
railties/lib/rails/plugin.rb | 10 ++++++----
railties/lib/rails/rack/metal.rb | 1 +
railties/lib/rails_generator.rb | 14 ++++++++------
14 files changed, 38 insertions(+), 21 deletions(-)
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index 100a0be1db..aee6b9dc9f 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -30,6 +30,7 @@ rescue LoadError
require 'active_support'
end
end
+require 'active_support/core/all'
require File.join(File.dirname(__FILE__), "action_pack")
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index bd5a38cc82..5feb8a4863 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -30,6 +30,7 @@ rescue LoadError
require 'active_support'
end
end
+require 'active_support/core/all'
$:.unshift "#{File.dirname(__FILE__)}/action_dispatch/vendor/rack-1.0"
begin
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index e604c2a581..dd352f9ce0 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -30,6 +30,7 @@ rescue LoadError
require 'active_support'
end
end
+require 'active_support/core/all'
require File.join(File.dirname(__FILE__), "action_pack")
diff --git a/activemodel/lib/active_model/core.rb b/activemodel/lib/active_model/core.rb
index 47b968e121..6b2bee53d9 100644
--- a/activemodel/lib/active_model/core.rb
+++ b/activemodel/lib/active_model/core.rb
@@ -1,7 +1,12 @@
-# This file is required by each major ActiveModel component for the core requirements. This allows you to
-# load individual pieces of ActiveModel as needed.
-$LOAD_PATH << File.join(File.dirname(__FILE__), '..', '..', '..', 'activesupport', 'lib')
+begin
+ require 'active_support'
+rescue LoadError
+ activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
+ if File.directory?(activesupport_path)
+ $:.unshift activesupport_path
+ require 'active_support'
+ end
+end
-# premature optimization?
# So far, we only need the string inflections and not the rest of ActiveSupport.
-require 'active_support/inflector'
\ No newline at end of file
+require 'active_support/inflector'
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 2f8c5c712f..500a90d6cb 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -30,6 +30,7 @@ rescue LoadError
require 'active_support'
end
end
+require 'active_support/core/all'
module ActiveRecord
# TODO: Review explicit loads to see if they will automatically be handled by the initilizer.
diff --git a/activeresource/lib/active_resource.rb b/activeresource/lib/active_resource.rb
index db9007060f..2f0c8d1a8e 100644
--- a/activeresource/lib/active_resource.rb
+++ b/activeresource/lib/active_resource.rb
@@ -30,6 +30,7 @@ rescue LoadError
require 'active_support'
end
end
+require 'active_support/core/all'
require 'active_resource/formats'
require 'active_resource/base'
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index e208f56455..cd7b47d780 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* require 'active_support' no longer orders the whole menu of core extensions. Ask for just what you need: e.g. require 'active_support/core/time' to use timezones, durations, and stdlib date/time extensions. [Jeremy Kemper]
+
* Removed rarely-used DRb cache store. [Jeremy Kemper]
* TimeWithZone.name returns 'Time', to further thwart type checking [Geoff Buesing]
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 21b730fa0c..84bf372163 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -50,10 +50,7 @@ module ActiveSupport
autoload :XmlMini, 'active_support/xml_mini'
end
-require 'active_support/core/all'
-
require 'active_support/vendor'
-require 'active_support/core_ext'
require 'active_support/dependencies'
require 'active_support/json'
diff --git a/activesupport/lib/active_support/core/all.rb b/activesupport/lib/active_support/core/all.rb
index f397f48e9c..55e8b4cfac 100644
--- a/activesupport/lib/active_support/core/all.rb
+++ b/activesupport/lib/active_support/core/all.rb
@@ -1,3 +1,4 @@
+require 'active_support/core_ext'
require 'active_support/core'
Dir["#{File.dirname(__FILE__)}/*.rb"].sort.each do |path|
require "active_support/core/#{File.basename(path, '.rb')}"
diff --git a/activesupport/lib/active_support/core_ext/kernel/requires.rb b/activesupport/lib/active_support/core_ext/kernel/requires.rb
index 323fea49fe..d2238898d6 100644
--- a/activesupport/lib/active_support/core_ext/kernel/requires.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/requires.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/kernel/reporting'
+
module Kernel
# Require a library with fallback to RubyGems. Warnings during library
# loading are silenced to increase signal/noise for application warnings.
@@ -21,4 +23,4 @@ module Kernel
end
end
end
-end
\ No newline at end of file
+end
diff --git a/railties/Rakefile b/railties/Rakefile
index a9adbda0b5..9cd102df0f 100644
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -29,12 +29,12 @@ task :default => :test
task :test do
Dir['test/**/*_test.rb'].all? do |file|
ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
- system(ruby, '-Itest', file)
+ system(ruby, '-Itest', "-I#{File.dirname(__FILE__)}/../activesupport/lib", file)
end or raise "Failures"
end
Rake::TestTask.new("regular_test") do |t|
- t.libs << 'test'
+ t.libs << 'test' << "#{File.dirname(__FILE__)}/../activesupport/lib"
t.pattern = 'test/**/*_test.rb'
t.warning = true
t.verbose = true
diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb
index 80deb73bbb..e66166306a 100644
--- a/railties/lib/rails/plugin.rb
+++ b/railties/lib/rails/plugin.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/kernel/reporting'
+
module Rails
# The Plugin class should be an object which provides the following methods:
#
@@ -35,10 +37,10 @@ module Rails
def load_paths
report_nonexistant_or_empty_plugin! unless valid?
- returning [] do |load_paths|
- load_paths << lib_path if has_lib_directory?
- load_paths << app_paths if has_app_directory?
- end.flatten
+ load_paths = []
+ load_paths << lib_path if has_lib_directory?
+ load_paths << app_paths if has_app_directory?
+ load_paths.flatten
end
# Evaluates a plugin's init.rb file.
diff --git a/railties/lib/rails/rack/metal.rb b/railties/lib/rails/rack/metal.rb
index adc43da864..7a616c7911 100644
--- a/railties/lib/rails/rack/metal.rb
+++ b/railties/lib/rails/rack/metal.rb
@@ -1,4 +1,5 @@
require 'active_support/ordered_hash'
+require 'active_support/core_ext/class/attribute_accessors'
module Rails
module Rack
diff --git a/railties/lib/rails_generator.rb b/railties/lib/rails_generator.rb
index 9f0ffc1562..201a9e0f91 100644
--- a/railties/lib/rails_generator.rb
+++ b/railties/lib/rails_generator.rb
@@ -21,16 +21,18 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
-$:.unshift(File.dirname(__FILE__))
-$:.unshift(File.dirname(__FILE__) + "/../../activesupport/lib")
-
begin
- require 'active_support'
+ require 'active_support'
rescue LoadError
- require 'rubygems'
- gem 'activesupport'
+ activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
+ if File.directory?(activesupport_path)
+ $:.unshift activesupport_path
+ require 'active_support'
+ end
end
+require 'active_support/core/all'
+$:.unshift(File.dirname(__FILE__))
require 'rails_generator/base'
require 'rails_generator/lookup'
require 'rails_generator/commands'
--
cgit v1.2.3
From f5d720fb96f2e085acc4ed17f63272c4d38e567e Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 22 Apr 2009 16:41:06 -0700
Subject: Opt in to Dependencies
---
actionpack/lib/action_view/template/template.rb | 1 +
activerecord/lib/active_record/base.rb | 1 +
activesupport/lib/active_support.rb | 1 -
.../core_ext/class/delegating_attributes.rb | 2 ++
activesupport/lib/active_support/dependencies.rb | 1 +
activesupport/lib/active_support/json.rb | 2 ++
.../lib/active_support/testing/deprecation.rb | 18 +++++++++---------
.../test/core_ext/module/attribute_aliasing_test.rb | 1 +
activesupport/test/dependencies_test.rb | 1 +
railties/lib/rails/plugin.rb | 1 +
10 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb
index 0d2f201458..b6967a2013 100644
--- a/actionpack/lib/action_view/template/template.rb
+++ b/actionpack/lib/action_view/template/template.rb
@@ -1,3 +1,4 @@
+require 'set'
require "action_view/template/path"
module ActionView #:nodoc:
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 251d5000f5..97c36a675d 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1,5 +1,6 @@
require 'yaml'
require 'set'
+require 'active_support/dependencies'
module ActiveRecord #:nodoc:
# Generic Active Record exception class.
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 84bf372163..f240cbf5e4 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -51,7 +51,6 @@ module ActiveSupport
end
require 'active_support/vendor'
-require 'active_support/dependencies'
require 'active_support/json'
I18n.load_path << "#{File.dirname(__FILE__)}/active_support/locale/en.yml"
diff --git a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
index da798c67e7..b0784d8416 100644
--- a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
+++ b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/blank'
+
class Class
def superclass_delegating_reader(*names)
class_name_to_stop_searching_on = superclass.name.blank? ? "Object" : superclass.name
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 41b7e00c0c..1804c14618 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -1,4 +1,5 @@
require 'set'
+require 'thread'
require 'active_support/inflector'
require 'active_support/core_ext/name_error'
require 'active_support/core_ext/object/blank'
diff --git a/activesupport/lib/active_support/json.rb b/activesupport/lib/active_support/json.rb
index 2bdb4a7b11..91f19f8a70 100644
--- a/activesupport/lib/active_support/json.rb
+++ b/activesupport/lib/active_support/json.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/module/attribute_accessors'
+
module ActiveSupport
# If true, use ISO 8601 format for dates and times. Otherwise, fall back to the Active Support legacy format.
mattr_accessor :use_standard_json_time_format
diff --git a/activesupport/lib/active_support/testing/deprecation.rb b/activesupport/lib/active_support/testing/deprecation.rb
index e9220605bd..0135185a47 100644
--- a/activesupport/lib/active_support/testing/deprecation.rb
+++ b/activesupport/lib/active_support/testing/deprecation.rb
@@ -1,3 +1,5 @@
+require 'active_support/deprecation'
+
module ActiveSupport
module Testing
module Deprecation #:nodoc:
@@ -35,21 +37,19 @@ end
begin
require 'test/unit/error'
-
+rescue LoadError
+ # Using miniunit, ignore.
+else
module Test
module Unit
- class Error # :nodoc:
+ class Error #:nodoc:
# Silence warnings when reporting test errors.
def message_with_silenced_deprecation
- ActiveSupport::Deprecation.silence do
- message_without_silenced_deprecation
- end
+ ActiveSupport::Deprecation.silence { message_without_silenced_deprecation }
end
-
- alias_method_chain :message, :silenced_deprecation
+ alias_method :message_without_silenced_deprecation, :message
+ alias_method :message, :message_with_silenced_deprecation
end
end
end
-rescue LoadError
- # Using miniunit, ignore.
end
diff --git a/activesupport/test/core_ext/module/attribute_aliasing_test.rb b/activesupport/test/core_ext/module/attribute_aliasing_test.rb
index 570ac3b8d5..f17d031662 100644
--- a/activesupport/test/core_ext/module/attribute_aliasing_test.rb
+++ b/activesupport/test/core_ext/module/attribute_aliasing_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/module/aliasing'
module AttributeAliasing
class Content
diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb
index a21f09403f..01c1d67f4c 100644
--- a/activesupport/test/dependencies_test.rb
+++ b/activesupport/test/dependencies_test.rb
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'pp'
+require 'active_support/dependencies'
module ModuleWithMissing
mattr_accessor :missing_count
diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb
index e66166306a..dd840ef058 100644
--- a/railties/lib/rails/plugin.rb
+++ b/railties/lib/rails/plugin.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/kernel/reporting'
+require 'active_support/dependencies'
module Rails
# The Plugin class should be an object which provides the following methods:
--
cgit v1.2.3
From 6fee981fa4ea2654f825c58b58327fc15fddf3a6 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 22 Apr 2009 16:48:58 -0700
Subject: Opt in to JSON
---
actionpack/lib/action_dispatch/middleware/params_parser.rb | 2 ++
activerecord/lib/active_record/serializers/json_serializer.rb | 2 ++
activeresource/lib/active_resource/formats/json_format.rb | 2 ++
activesupport/lib/active_support.rb | 1 -
activesupport/test/json/decoding_test.rb | 1 +
5 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index 6df572268c..abaee2829e 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -1,3 +1,5 @@
+require 'active_support/json'
+
module ActionDispatch
class ParamsParser
ActionController::Base.param_parsers[Mime::XML] = :xml_simple
diff --git a/activerecord/lib/active_record/serializers/json_serializer.rb b/activerecord/lib/active_record/serializers/json_serializer.rb
index 1fd65ed006..c709c3f1eb 100644
--- a/activerecord/lib/active_record/serializers/json_serializer.rb
+++ b/activerecord/lib/active_record/serializers/json_serializer.rb
@@ -1,3 +1,5 @@
+require 'active_support/json'
+
module ActiveRecord #:nodoc:
module Serialization
def self.included(base)
diff --git a/activeresource/lib/active_resource/formats/json_format.rb b/activeresource/lib/active_resource/formats/json_format.rb
index 1d88fc5f16..101027d99e 100644
--- a/activeresource/lib/active_resource/formats/json_format.rb
+++ b/activeresource/lib/active_resource/formats/json_format.rb
@@ -1,3 +1,5 @@
+require 'active_support/json'
+
module ActiveResource
module Formats
module JsonFormat
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 84bf372163..5392faa993 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -52,6 +52,5 @@ end
require 'active_support/vendor'
require 'active_support/dependencies'
-require 'active_support/json'
I18n.load_path << "#{File.dirname(__FILE__)}/active_support/locale/en.yml"
diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb
index 7d8a07654d..9b4b207c88 100644
--- a/activesupport/test/json/decoding_test.rb
+++ b/activesupport/test/json/decoding_test.rb
@@ -1,5 +1,6 @@
# encoding: UTF-8
require 'abstract_unit'
+require 'active_support/json'
class TestJSONDecoding < ActiveSupport::TestCase
TESTS = {
--
cgit v1.2.3
From b2d6fdae353be4fca41d7ac1839f30d9737162fd Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 22 Apr 2009 17:00:33 -0700
Subject: Fix tests on 1.9
---
actionpack/lib/action_view/helpers/number_helper.rb | 2 ++
activemodel/lib/active_model/core.rb | 2 +-
activesupport/lib/active_support/core_ext/class/attribute_accessors.rb | 2 ++
.../lib/active_support/core_ext/class/delegating_attributes.rb | 2 +-
4 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index dea958deaf..c02692b09a 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/float/rounding'
+
module ActionView
module Helpers #:nodoc:
# Provides methods for converting numbers into formatted strings.
diff --git a/activemodel/lib/active_model/core.rb b/activemodel/lib/active_model/core.rb
index 6b2bee53d9..b4b020defc 100644
--- a/activemodel/lib/active_model/core.rb
+++ b/activemodel/lib/active_model/core.rb
@@ -1,7 +1,7 @@
begin
require 'active_support'
rescue LoadError
- activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
+ activesupport_path = "#{File.dirname(__FILE__)}/../../../activesupport/lib"
if File.directory?(activesupport_path)
$:.unshift activesupport_path
require 'active_support'
diff --git a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
index 75e481fc54..74ce85a1c2 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/array/extract_options'
+
# Extends the class object with class and instance accessors for class attributes,
# just like the native attr* accessors for instance attributes.
#
diff --git a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
index b0784d8416..fd029544c3 100644
--- a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
+++ b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
@@ -1,4 +1,4 @@
-require 'active_support/core_ext/blank'
+require 'active_support/core_ext/object/blank'
class Class
def superclass_delegating_reader(*names)
--
cgit v1.2.3
From 5c4ba6e3fc66a779c28a70b8d7bde14b49e7c36c Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 22 Apr 2009 17:17:31 -0700
Subject: new_callbacks core extensions
---
activesupport/lib/active_support/new_callbacks.rb | 3 +++
activesupport/test/new_callbacks_test.rb | 10 +++++-----
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb
index 356d70b650..7a48dbac04 100644
--- a/activesupport/lib/active_support/new_callbacks.rb
+++ b/activesupport/lib/active_support/new_callbacks.rb
@@ -1,3 +1,6 @@
+require 'active_support/core_ext/array/wrap'
+require 'active_support/core_ext/class/inheritable_attributes'
+
module ActiveSupport
# Callbacks are hooks into the lifecycle of an object that allow you to trigger logic
# before or after an alteration of the object state.
diff --git a/activesupport/test/new_callbacks_test.rb b/activesupport/test/new_callbacks_test.rb
index 5cde078b65..abe7790ebf 100644
--- a/activesupport/test/new_callbacks_test.rb
+++ b/activesupport/test/new_callbacks_test.rb
@@ -19,11 +19,11 @@ module NewCallbacksTest
class << self
def callback_symbol(callback_method)
- returning(:"#{callback_method}_method") do |method_name|
- define_method(method_name) do
- history << [callback_method, :symbol]
- end
+ method_name = :"#{callback_method}_method"
+ define_method(method_name) do
+ history << [callback_method, :symbol]
end
+ method_name
end
def callback_string(callback_method)
@@ -381,4 +381,4 @@ module NewCallbacksTest
assert_equal ["first", "second", "third", "second", "first"], terminator.history
end
end
-end
\ No newline at end of file
+end
--
cgit v1.2.3
From 0a132c2fe13fb2b8d5dade9cf6abd70601376287 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 22 Apr 2009 17:16:28 -0700
Subject: Refactor ActionView::Path
* Decouple from ActionController and ActionMailer
* Bring back localization support.
* Prepare to decouple templates from the filesystem.
* Prepare to decouple localization from ActionView
* Fix ActionMailer to take advantage of ActionView::Path
---
actionmailer/lib/action_mailer/base.rb | 49 +++----
.../action_mailer/vendor/tmail-1.2.3/tmail/mail.rb | 1 +
.../fixtures/auto_layout_mailer/multipart.html.erb | 1 +
.../fixtures/auto_layout_mailer/multipart.text.erb | 1 +
.../auto_layout_mailer/multipart.text.html.erb | 1 -
.../auto_layout_mailer/multipart.text.plain.erb | 1 -
.../fixtures/test_mailer/_subtemplate.text.erb | 1 +
.../test_mailer/_subtemplate.text.plain.erb | 1 -
.../custom_templating_extension.html.haml | 6 +
.../custom_templating_extension.text.haml | 6 +
.../custom_templating_extension.text.html.haml | 6 -
.../custom_templating_extension.text.plain.haml | 6 -
.../implicitly_multipart_example.html.erb | 10 ++
.../implicitly_multipart_example.html.erb~ | 10 ++
.../implicitly_multipart_example.text.erb | 2 +
.../implicitly_multipart_example.text.html.erb | 10 --
.../implicitly_multipart_example.text.html.erb~ | 10 --
.../implicitly_multipart_example.text.plain.erb | 2 -
.../implicitly_multipart_example.text.yaml.erb | 1 -
.../implicitly_multipart_example.yaml.erb | 1 +
.../test_mailer/included_subtemplate.text.erb | 1 +
.../included_subtemplate.text.plain.erb | 1 -
.../fixtures/test_mailer/rxml_template.builder | 2 -
actionmailer/test/mail_service_test.rb | 14 +-
.../lib/action_controller/abstract/layouts.rb | 4 +-
.../lib/action_controller/abstract/renderer.rb | 2 +-
actionpack/lib/action_controller/base/layout.rb | 2 +-
actionpack/lib/action_controller/base/render.rb | 7 +-
actionpack/lib/action_view/paths.rb | 6 +-
actionpack/lib/action_view/render/partials.rb | 7 +-
actionpack/lib/action_view/render/rendering.rb | 4 +-
actionpack/lib/action_view/template/handlers.rb | 4 +
actionpack/lib/action_view/template/path.rb | 151 +++++++++++++--------
actionpack/lib/action_view/template/template.rb | 2 +-
.../abstract_controller_test.rb | 4 +-
actionpack/test/template/render_test.rb | 20 ++-
36 files changed, 204 insertions(+), 153 deletions(-)
create mode 100644 actionmailer/test/fixtures/auto_layout_mailer/multipart.html.erb
create mode 100644 actionmailer/test/fixtures/auto_layout_mailer/multipart.text.erb
delete mode 100644 actionmailer/test/fixtures/auto_layout_mailer/multipart.text.html.erb
delete mode 100644 actionmailer/test/fixtures/auto_layout_mailer/multipart.text.plain.erb
create mode 100644 actionmailer/test/fixtures/test_mailer/_subtemplate.text.erb
delete mode 100644 actionmailer/test/fixtures/test_mailer/_subtemplate.text.plain.erb
create mode 100644 actionmailer/test/fixtures/test_mailer/custom_templating_extension.html.haml
create mode 100644 actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.haml
delete mode 100644 actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.html.haml
delete mode 100644 actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.plain.haml
create mode 100644 actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb
create mode 100644 actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb~
create mode 100644 actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.erb
delete mode 100644 actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.html.erb
delete mode 100644 actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.html.erb~
delete mode 100644 actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.plain.erb
delete mode 100644 actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.erb
create mode 100644 actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.yaml.erb
create mode 100644 actionmailer/test/fixtures/test_mailer/included_subtemplate.text.erb
delete mode 100644 actionmailer/test/fixtures/test_mailer/included_subtemplate.text.plain.erb
delete mode 100644 actionmailer/test/fixtures/test_mailer/rxml_template.builder
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 9eee5783a0..69e77871b0 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -465,48 +465,48 @@ module ActionMailer #:nodoc:
def create!(method_name, *parameters) #:nodoc:
initialize_defaults(method_name)
__send__(method_name, *parameters)
-
+
# If an explicit, textual body has not been set, we check assumptions.
unless String === @body
# First, we look to see if there are any likely templates that match,
# which include the content-type in their file name (i.e.,
# "the_template_file.text.html.erb", etc.). Only do this if parts
# have not already been specified manually.
- if @parts.empty?
- Dir.glob("#{template_path}/#{@template}.*").each do |path|
- template = template_root.find_by_parts("#{mailer_name}/#{File.basename(path)}")
-
- # Skip unless template has a multipart format
- next unless template && template.multipart?
-
+ # if @parts.empty?
+ template_root.find_all_by_parts(@template, {}, template_path).each do |template|
@parts << Part.new(
- :content_type => template.content_type,
+ :content_type => Mime::Type.lookup_by_extension(template.content_type || "text").to_s,
:disposition => "inline",
:charset => charset,
:body => render_template(template, @body)
)
end
- unless @parts.empty?
+
+ if @parts.size > 1
@content_type = "multipart/alternative" if @content_type !~ /^multipart/
@parts = sort_parts(@parts, @implicit_parts_order)
end
- end
-
+ # end
+
# Then, if there were such templates, we check to see if we ought to
# also render a "normal" template (without the content type). If a
# normal template exists (or if there were no implicit parts) we render
# it.
- template_exists = @parts.empty?
- template_exists ||= template_root.find_by_parts("#{mailer_name}/#{@template}")
- @body = render_message(@template, @body) if template_exists
+ # ====
+ # TODO: Revisit this
+ # template_exists = @parts.empty?
+ # template_exists ||= template_root.find_by_parts("#{mailer_name}/#{@template}")
+ # @body = render_message(@template, @body) if template_exists
# Finally, if there are other message parts and a textual body exists,
# we shift it onto the front of the parts and set the body to nil (so
# that create_mail doesn't try to render it in addition to the parts).
- if !@parts.empty? && String === @body
- @parts.unshift Part.new(:charset => charset, :body => @body)
- @body = nil
- end
+ # ====
+ # TODO: Revisit this
+ # if !@parts.empty? && String === @body
+ # @parts.unshift Part.new(:charset => charset, :body => @body)
+ # @body = nil
+ # end
end
# If this is a multipart e-mail add the mime_version if it is not
@@ -580,7 +580,7 @@ module ActionMailer #:nodoc:
if file
prefix = mailer_name unless file =~ /\//
- template = view_paths.find_by_parts(file, formats, prefix)
+ template = view_paths.find_by_parts(file, {:formats => formats}, prefix)
end
layout = _pick_layout(layout,
@@ -611,7 +611,7 @@ module ActionMailer #:nodoc:
end
def template_path
- "#{template_root}/#{mailer_name}"
+ "#{mailer_name}"
end
def initialize_template_class(assigns)
@@ -622,7 +622,7 @@ module ActionMailer #:nodoc:
def sort_parts(parts, order = [])
order = order.collect { |s| s.downcase }
-
+
parts = parts.sort do |a, b|
a_ct = a.content_type.downcase
b_ct = b.content_type.downcase
@@ -663,10 +663,13 @@ module ActionMailer #:nodoc:
headers.each { |k, v| m[k] = v }
real_content_type, ctype_attrs = parse_content_type
-
+
if @parts.empty?
m.set_content_type(real_content_type, nil, ctype_attrs)
m.body = normalize_new_lines(body)
+ elsif @parts.size == 1 && @parts.first.parts.empty?
+ m.set_content_type(real_content_type, nil, ctype_attrs)
+ m.body = normalize_new_lines(@parts.first.body)
else
if String === body
part = TMail::Mail.new
diff --git a/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb b/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb
index c3a8803dc4..23a3f75de3 100644
--- a/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb
+++ b/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb
@@ -518,6 +518,7 @@ module TMail
def parse_body( f = nil )
return if @body_parsed
+
if f
parse_body_0 f
else
diff --git a/actionmailer/test/fixtures/auto_layout_mailer/multipart.html.erb b/actionmailer/test/fixtures/auto_layout_mailer/multipart.html.erb
new file mode 100644
index 0000000000..6d73f199c4
--- /dev/null
+++ b/actionmailer/test/fixtures/auto_layout_mailer/multipart.html.erb
@@ -0,0 +1 @@
+text/html multipart
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/auto_layout_mailer/multipart.text.erb b/actionmailer/test/fixtures/auto_layout_mailer/multipart.text.erb
new file mode 100644
index 0000000000..f4b91e4031
--- /dev/null
+++ b/actionmailer/test/fixtures/auto_layout_mailer/multipart.text.erb
@@ -0,0 +1 @@
+text/plain multipart
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/auto_layout_mailer/multipart.text.html.erb b/actionmailer/test/fixtures/auto_layout_mailer/multipart.text.html.erb
deleted file mode 100644
index 6d73f199c4..0000000000
--- a/actionmailer/test/fixtures/auto_layout_mailer/multipart.text.html.erb
+++ /dev/null
@@ -1 +0,0 @@
-text/html multipart
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/auto_layout_mailer/multipart.text.plain.erb b/actionmailer/test/fixtures/auto_layout_mailer/multipart.text.plain.erb
deleted file mode 100644
index f4b91e4031..0000000000
--- a/actionmailer/test/fixtures/auto_layout_mailer/multipart.text.plain.erb
+++ /dev/null
@@ -1 +0,0 @@
-text/plain multipart
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/_subtemplate.text.erb b/actionmailer/test/fixtures/test_mailer/_subtemplate.text.erb
new file mode 100644
index 0000000000..3b4ba35f20
--- /dev/null
+++ b/actionmailer/test/fixtures/test_mailer/_subtemplate.text.erb
@@ -0,0 +1 @@
+let's go!
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/_subtemplate.text.plain.erb b/actionmailer/test/fixtures/test_mailer/_subtemplate.text.plain.erb
deleted file mode 100644
index 3b4ba35f20..0000000000
--- a/actionmailer/test/fixtures/test_mailer/_subtemplate.text.plain.erb
+++ /dev/null
@@ -1 +0,0 @@
-let's go!
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/custom_templating_extension.html.haml b/actionmailer/test/fixtures/test_mailer/custom_templating_extension.html.haml
new file mode 100644
index 0000000000..847d065c37
--- /dev/null
+++ b/actionmailer/test/fixtures/test_mailer/custom_templating_extension.html.haml
@@ -0,0 +1,6 @@
+%p Hello there,
+
+%p
+ Mr.
+ = @recipient
+ from haml
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.haml b/actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.haml
new file mode 100644
index 0000000000..847d065c37
--- /dev/null
+++ b/actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.haml
@@ -0,0 +1,6 @@
+%p Hello there,
+
+%p
+ Mr.
+ = @recipient
+ from haml
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.html.haml b/actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.html.haml
deleted file mode 100644
index 847d065c37..0000000000
--- a/actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-%p Hello there,
-
-%p
- Mr.
- = @recipient
- from haml
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.plain.haml b/actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.plain.haml
deleted file mode 100644
index 847d065c37..0000000000
--- a/actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.plain.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-%p Hello there,
-
-%p
- Mr.
- = @recipient
- from haml
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb
new file mode 100644
index 0000000000..946d99ede5
--- /dev/null
+++ b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb
@@ -0,0 +1,10 @@
+
+
+ HTML formatted message to <%= @recipient %> .
+
+
+
+
+ HTML formatted message to <%= @recipient %> .
+
+
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb~ b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb~
new file mode 100644
index 0000000000..946d99ede5
--- /dev/null
+++ b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb~
@@ -0,0 +1,10 @@
+
+
+ HTML formatted message to <%= @recipient %> .
+
+
+
+
+ HTML formatted message to <%= @recipient %> .
+
+
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.erb b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.erb
new file mode 100644
index 0000000000..a6c8d54cf9
--- /dev/null
+++ b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.erb
@@ -0,0 +1,2 @@
+Plain text to <%= @recipient %>.
+Plain text to <%= @recipient %>.
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.html.erb b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.html.erb
deleted file mode 100644
index 946d99ede5..0000000000
--- a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.html.erb
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
- HTML formatted message to <%= @recipient %> .
-
-
-
-
- HTML formatted message to <%= @recipient %> .
-
-
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.html.erb~ b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.html.erb~
deleted file mode 100644
index 946d99ede5..0000000000
--- a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.html.erb~
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
- HTML formatted message to <%= @recipient %> .
-
-
-
-
- HTML formatted message to <%= @recipient %> .
-
-
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.plain.erb b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.plain.erb
deleted file mode 100644
index a6c8d54cf9..0000000000
--- a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.plain.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-Plain text to <%= @recipient %>.
-Plain text to <%= @recipient %>.
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.erb b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.erb
deleted file mode 100644
index c14348c770..0000000000
--- a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.erb
+++ /dev/null
@@ -1 +0,0 @@
-yaml to: <%= @recipient %>
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.yaml.erb b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.yaml.erb
new file mode 100644
index 0000000000..c14348c770
--- /dev/null
+++ b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.yaml.erb
@@ -0,0 +1 @@
+yaml to: <%= @recipient %>
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/included_subtemplate.text.erb b/actionmailer/test/fixtures/test_mailer/included_subtemplate.text.erb
new file mode 100644
index 0000000000..a93c30ea1a
--- /dev/null
+++ b/actionmailer/test/fixtures/test_mailer/included_subtemplate.text.erb
@@ -0,0 +1 @@
+Hey Ho, <%= render :partial => "subtemplate" %>
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/included_subtemplate.text.plain.erb b/actionmailer/test/fixtures/test_mailer/included_subtemplate.text.plain.erb
deleted file mode 100644
index a93c30ea1a..0000000000
--- a/actionmailer/test/fixtures/test_mailer/included_subtemplate.text.plain.erb
+++ /dev/null
@@ -1 +0,0 @@
-Hey Ho, <%= render :partial => "subtemplate" %>
\ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/rxml_template.builder b/actionmailer/test/fixtures/test_mailer/rxml_template.builder
deleted file mode 100644
index d566bd8d7c..0000000000
--- a/actionmailer/test/fixtures/test_mailer/rxml_template.builder
+++ /dev/null
@@ -1,2 +0,0 @@
-xml.instruct!
-xml.test
\ No newline at end of file
diff --git a/actionmailer/test/mail_service_test.rb b/actionmailer/test/mail_service_test.rb
index b7d5fd5dd3..b27bda49be 100644
--- a/actionmailer/test/mail_service_test.rb
+++ b/actionmailer/test/mail_service_test.rb
@@ -338,6 +338,7 @@ class ActionMailerTest < Test::Unit::TestCase
def test_nested_parts_with_body
created = nil
+ TestMailer.create_nested_multipart_with_body(@recipient)
assert_nothing_raised { created = TestMailer.create_nested_multipart_with_body(@recipient)}
assert_equal 1,created.parts.size
assert_equal 2,created.parts.first.parts.size
@@ -351,8 +352,8 @@ class ActionMailerTest < Test::Unit::TestCase
def test_attachment_with_custom_header
created = nil
- assert_nothing_raised { created = TestMailer.create_attachment_with_custom_header(@recipient)}
- assert_equal "", created.parts[1].header['content-id'].to_s
+ assert_nothing_raised { created = TestMailer.create_attachment_with_custom_header(@recipient) }
+ assert created.parts.any? { |p| p.header['content-id'].to_s == "" }
end
def test_signed_up
@@ -824,7 +825,7 @@ EOF
assert_equal 3, mail.parts.length
assert_equal "1.0", mail.mime_version
assert_equal "multipart/alternative", mail.content_type
- assert_equal "text/yaml", mail.parts[0].content_type
+ assert_equal "application/x-yaml", mail.parts[0].content_type
assert_equal "utf-8", mail.parts[0].sub_header("content-type", "charset")
assert_equal "text/plain", mail.parts[1].content_type
assert_equal "utf-8", mail.parts[1].sub_header("content-type", "charset")
@@ -835,11 +836,11 @@ EOF
def test_implicitly_multipart_messages_with_custom_order
assert ActionView::Template.template_handler_extensions.include?("bak"), "bak extension was not registered"
- mail = TestMailer.create_implicitly_multipart_example(@recipient, nil, ["text/yaml", "text/plain"])
+ mail = TestMailer.create_implicitly_multipart_example(@recipient, nil, ["application/x-yaml", "text/plain"])
assert_equal 3, mail.parts.length
assert_equal "text/html", mail.parts[0].content_type
assert_equal "text/plain", mail.parts[1].content_type
- assert_equal "text/yaml", mail.parts[2].content_type
+ assert_equal "application/x-yaml", mail.parts[2].content_type
end
def test_implicitly_multipart_messages_with_charset
@@ -938,8 +939,7 @@ EOF
def test_multipart_with_template_path_with_dots
mail = FunkyPathMailer.create_multipart_with_template_path_with_dots(@recipient)
assert_equal 2, mail.parts.length
- assert_equal 'text/plain', mail.parts[0].content_type
- assert_equal 'utf-8', mail.parts[0].charset
+ assert mail.parts.any? {|part| part.content_type == "text/plain" && part.charset == "utf-8"}
end
def test_custom_content_type_attributes
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 478b301a26..0039e67c5a 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -38,7 +38,7 @@ module AbstractController
else
self.class_eval %{
def _layout
- if view_paths.find_by_parts?("#{_implied_layout_name}", formats, "layouts")
+ if view_paths.find_by_parts?("#{_implied_layout_name}", {:formats => formats}, "layouts")
"#{_implied_layout_name}"
else
super
@@ -62,7 +62,7 @@ module AbstractController
raise ArgumentError, "String, false, or nil expected; you passed #{name.inspect}"
end
- name && view_paths.find_by_parts(name, formats, "layouts")
+ name && view_paths.find_by_parts(name, {:formats => formats}, "layouts")
end
def _default_layout(require_layout = false)
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index a86eef889e..e31accbbfc 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -29,7 +29,7 @@ module AbstractController
def render_to_body(options = {})
name = options[:_template_name] || action_name
- template = options[:_template] || view_paths.find_by_parts(name.to_s, formats, options[:_prefix])
+ template = options[:_template] || view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix])
_render_template(template, options)
end
diff --git a/actionpack/lib/action_controller/base/layout.rb b/actionpack/lib/action_controller/base/layout.rb
index 4fcef6c5d9..1ad5191c73 100644
--- a/actionpack/lib/action_controller/base/layout.rb
+++ b/actionpack/lib/action_controller/base/layout.rb
@@ -182,7 +182,7 @@ module ActionController #:nodoc:
def memoized_find_layout(layout, formats) #:nodoc:
return layout if layout.nil? || layout.respond_to?(:render)
prefix = layout.to_s =~ /layouts\// ? nil : "layouts"
- view_paths.find_by_parts(layout.to_s, formats, prefix)
+ view_paths.find_by_parts(layout.to_s, {:formats => formats}, prefix)
end
def find_layout(*args)
diff --git a/actionpack/lib/action_controller/base/render.rb b/actionpack/lib/action_controller/base/render.rb
index 606df58518..52934076e6 100644
--- a/actionpack/lib/action_controller/base/render.rb
+++ b/actionpack/lib/action_controller/base/render.rb
@@ -374,8 +374,13 @@ module ActionController
render_for_file(name.sub(/^\//, ''), [layout, true], options)
end
end
-
+
+ # ==== Arguments
+ # parts::
+ # Example: ["show", [:html, :xml], "users", false]
def render_for_parts(parts, layout, 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?
diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb
index 1d0279889c..e48088f344 100644
--- a/actionpack/lib/action_view/paths.rb
+++ b/actionpack/lib/action_view/paths.rb
@@ -33,18 +33,18 @@ module ActionView #:nodoc:
super(*objs.map { |obj| self.class.type_cast(obj) })
end
- def find_by_parts(path, extension = nil, prefix = nil, partial = false)
+ def find_by_parts(path, details = {}, prefix = nil, partial = false)
template_path = path.sub(/^\//, '')
each do |load_path|
- if template = load_path.find_by_parts(template_path, extension, prefix, partial)
+ if template = load_path.find_by_parts(template_path, details, prefix, partial)
return template
end
end
Template.new(path, self)
rescue ActionView::MissingTemplate => e
- extension ||= []
+ extension = details[:formats] || []
raise ActionView::MissingTemplate.new(self, "#{prefix}/#{path}.{#{extension.join(",")}}")
end
diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb
index e337dcb63b..43f8a1edf8 100644
--- a/actionpack/lib/action_view/render/partials.rb
+++ b/actionpack/lib/action_view/render/partials.rb
@@ -187,6 +187,7 @@ module ActionView
path = ActionController::RecordIdentifier.partial_path(object, controller_path)
end
_, _, prefix, object = parts = partial_parts(path, options)
+ parts[1] = {:formats => parts[1]}
template = find_by_parts(*parts)
_render_partial_object(template, options, (object unless object == true))
end
@@ -225,7 +226,7 @@ module ActionView
def _render_partial_with_layout(layout, options)
if layout
prefix = controller && !layout.include?("/") ? controller.controller_path : nil
- layout = find_by_parts(layout, formats, prefix, true)
+ layout = find_by_parts(layout, {:formats => formats}, prefix, true)
end
content = _render_partial(options)
return _render_content_with_layout(content, layout, options[:locals])
@@ -253,7 +254,7 @@ module ActionView
def _render_partial_with_layout(layout, options)
if layout
prefix = controller && !layout.include?("/") ? controller.controller_path : nil
- layout = find_by_parts(layout, formats, prefix, true)
+ layout = find_by_parts(layout, {:formats => formats}, prefix, true)
end
content = _render_partial(options)
return _render_content_with_layout(content, layout, options[:locals])
@@ -321,7 +322,7 @@ module ActionView
def _pick_partial_template(partial_path) #:nodoc:
prefix = controller_path unless partial_path.include?('/')
- find_by_parts(partial_path, formats, prefix, true)
+ find_by_parts(partial_path, {:formats => formats}, prefix, true)
end
memoize :_pick_partial_template
end
diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb
index a9b2acecd5..4213b09e48 100644
--- a/actionpack/lib/action_view/render/rendering.rb
+++ b/actionpack/lib/action_view/render/rendering.rb
@@ -23,10 +23,10 @@ module ActionView
return _render_partial_with_layout(layout, options) if options.key?(:partial)
return _render_partial_with_block(layout, block, options) if block_given?
- layout = find_by_parts(layout, formats) if layout
+ layout = find_by_parts(layout, {:formats => formats}) if layout
if file = options[:file]
- template = find_by_parts(file, formats)
+ template = find_by_parts(file, {:formats => formats})
_render_template_with_layout(template, layout, :locals => options[:locals])
elsif inline = options[:inline]
_render_inline(inline, layout, options)
diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb
index fb85f28851..448ab6731b 100644
--- a/actionpack/lib/action_view/template/handlers.rb
+++ b/actionpack/lib/action_view/template/handlers.rb
@@ -16,6 +16,10 @@ module ActionView #:nodoc:
@@template_handlers = {}
@@default_template_handlers = nil
+
+ def self.extensions
+ @@template_handlers.keys
+ end
# Register a class that knows how to handle template files with the given
# extension. This can be used to implement new template types.
diff --git a/actionpack/lib/action_view/template/path.rb b/actionpack/lib/action_view/template/path.rb
index 9709549b70..660a7e91a2 100644
--- a/actionpack/lib/action_view/template/path.rb
+++ b/actionpack/lib/action_view/template/path.rb
@@ -1,13 +1,81 @@
module ActionView
class Template
+ # Abstract super class
class Path
- attr_reader :path, :paths
- delegate :hash, :inspect, :to => :path
-
def initialize(options)
- @cache = options[:cache]
+ @cache = options[:cache]
+ @cached = {}
end
-
+
+ # Normalizes the arguments and passes it on to find_template
+ def find_by_parts(*args)
+ find_all_by_parts(*args).first
+ end
+
+ def find_all_by_parts(name, details = {}, prefix = nil, partial = nil)
+ details[:locales] = [I18n.locale]
+ name = name.to_s.gsub(handler_matcher, '').split("/")
+ find_templates(name.pop, details, [prefix, *name].compact.join("/"), partial)
+ end
+
+ private
+
+ # This is what child classes implement. No defaults are needed
+ # because Path guarentees that the arguments are present and
+ # normalized.
+ 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
+ end
+
+ def handler_matcher
+ @handler_matcher ||= begin
+ e = valid_handlers.join('|')
+ /\.(?:#{e})$/
+ end
+ end
+
+ def handler_glob
+ e = TemplateHandlers.extensions.join(',')
+ ".{#{e}}"
+ end
+
+ def formats_glob
+ @formats_glob ||= begin
+ formats = Mime::SET.map { |m| m.symbol }
+ '{' + formats.map { |l| ".#{l}," }.join + '}'
+ end
+ end
+
+ def cached(key)
+ return yield unless @cache
+ return @cached[key] if @cached.key?(key)
+ @cached[key] = yield
+ end
+ end
+
+ class FileSystemPath < Path
+
+ def initialize(path, options = {})
+ raise ArgumentError, "path already is a Path class" if path.is_a?(Path)
+ super(options)
+ @path = 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))}\//, '')
@@ -27,61 +95,36 @@ module ActionView
def eql?(path)
to_str == path.to_str
end
-
- def find_by_parts(name, extensions = nil, prefix = nil, partial = nil)
- path = prefix ? "#{prefix}/" : ""
+ # ====
- name = name.to_s.split("/")
- name[-1] = "_#{name[-1]}" if partial
-
- path << name.join("/")
-
- template = nil
-
- Array(extensions).each do |extension|
- extensioned_path = extension ? "#{path}.#{extension}" : path
- break if (template = find_template(extensioned_path))
+ def find_templates(name, details, prefix, partial)
+ if glob = parts_to_glob(name, details, prefix, partial)
+ cached(glob) do
+ Dir[glob].map do |path|
+ initialize_template(path) unless File.directory?(path)
+ end.compact
+ end
end
- template || find_template(path)
end
-
- private
- def create_template(file)
- Template.new(file.split("#{self}/").last, self)
- end
- end
-
- class FileSystemPath < Path
- def initialize(path, options = {})
- raise ArgumentError, "path already is a Path class" if path.is_a?(Path)
-
- super(options)
- @path, @paths = path, {}
-
- # **/*/** is a hax for symlinked directories
- load_templates("#{@path}/{**/*,**}/**") if @cache
- end
-
- private
-
- def load_template(template)
- template.load!
- template.accessible_paths.each do |path|
- @paths[path] = template
- end
- end
-
- def find_template(path)
- load_templates("#{@path}/#{path}{,.*}") unless @cache
- @paths[path]
- end
- def load_templates(glob)
- Dir[glob].each do |file|
- load_template(create_template(file)) unless File.directory?(file)
+ private
+
+ def parts_to_glob(name, details, prefix, partial)
+ path = ""
+ path << "#{prefix}/" unless prefix.empty?
+ path << (partial ? "_#{name}" : name)
+
+ extensions = ""
+ [:locales, :formats].each do |k|
+ extensions << if exts = details[k]
+ '{' + exts.map {|e| ".#{e},"}.join + '}'
+ else
+ k == :formats ? formats_glob : ''
+ end
end
+
+ "#{@path}/#{path}#{extensions}#{handler_glob}"
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 b6967a2013..e541336613 100644
--- a/actionpack/lib/action_view/template/template.rb
+++ b/actionpack/lib/action_view/template/template.rb
@@ -101,7 +101,7 @@ module ActionView #:nodoc:
end
def content_type
- format.gsub('.', '/')
+ format && format.gsub('.', '/')
end
private
diff --git a/actionpack/test/abstract_controller/abstract_controller_test.rb b/actionpack/test/abstract_controller/abstract_controller_test.rb
index 918062c7db..f1dcb39ef1 100644
--- a/actionpack/test/abstract_controller/abstract_controller_test.rb
+++ b/actionpack/test/abstract_controller/abstract_controller_test.rb
@@ -139,10 +139,10 @@ module AbstractController
private
def self.layout(formats)
begin
- view_paths.find_by_parts(name.underscore, formats, "layouts")
+ view_paths.find_by_parts(name.underscore, {:formats => formats}t, "layouts")
rescue ActionView::MissingTemplate
begin
- view_paths.find_by_parts("application", formats, "layouts")
+ view_paths.find_by_parts("application", {:formats => formats}, "layouts")
rescue ActionView::MissingTemplate
end
end
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index 8843f6fdd7..7191df0dfd 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -29,23 +29,19 @@ module RenderTestCases
end
def test_render_file_with_localization
- pending do
- begin
- old_locale = I18n.locale
- I18n.locale = :da
- assert_equal "Hey verden", @view.render(:file => "test/hello_world")
- ensure
- I18n.locale = old_locale
- end
+ begin
+ old_locale = I18n.locale
+ I18n.locale = :da
+ assert_equal "Hey verden", @view.render(:file => "test/hello_world")
+ ensure
+ I18n.locale = old_locale
end
end
def test_render_file_with_dashed_locale
old_locale = I18n.locale
- pending do
- I18n.locale = :"pt-BR"
- assert_equal "Ola mundo", @view.render(:file => "test/hello_world")
- end
+ I18n.locale = :"pt-BR"
+ assert_equal "Ola mundo", @view.render(:file => "test/hello_world")
ensure
I18n.locale = old_locale
end
--
cgit v1.2.3
From f28bd9557c669cd63c31704202a46dd83f0a4102 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 22 Apr 2009 17:41:28 -0700
Subject: Fix dependencies revealed by testing in isolation
---
activesupport/Rakefile | 6 ++++++
activesupport/lib/active_support/cache.rb | 1 +
.../lib/active_support/cache/strategy/local_cache.rb | 2 ++
activesupport/lib/active_support/callbacks.rb | 2 ++
.../lib/active_support/core_ext/array/conversions.rb | 6 +++++-
.../core_ext/class/inheritable_attributes.rb | 4 +++-
activesupport/lib/active_support/core_ext/class/removal.rb | 3 +++
.../lib/active_support/core_ext/date/calculations.rb | 2 ++
.../lib/active_support/core_ext/date/conversions.rb | 2 ++
activesupport/lib/active_support/core_ext/date_time.rb | 3 +--
.../lib/active_support/core_ext/hash/conversions.rb | 2 ++
activesupport/lib/active_support/core_ext/logger.rb | 5 +++--
.../lib/active_support/core_ext/module/attr_internal.rb | 8 ++++----
.../lib/active_support/core_ext/module/introspection.rb | 6 ++++--
.../lib/active_support/core_ext/module/model_naming.rb | 8 +++++---
.../lib/active_support/core_ext/module/synchronization.rb | 2 ++
activesupport/lib/active_support/core_ext/numeric/time.rb | 2 ++
activesupport/lib/active_support/core_ext/object.rb | 1 +
.../lib/active_support/core_ext/range/blockless_step.rb | 2 ++
.../lib/active_support/core_ext/string/conversions.rb | 1 +
.../lib/active_support/core_ext/string/multibyte.rb | 1 +
activesupport/lib/active_support/dependencies.rb | 8 +++++---
.../lib/active_support/deprecation/method_wrappers.rb | 1 +
.../lib/active_support/deprecation/proxy_wrappers.rb | 4 +++-
activesupport/lib/active_support/duration.rb | 1 +
activesupport/lib/active_support/inflector.rb | 3 ++-
activesupport/lib/active_support/json/encoders/time.rb | 2 ++
activesupport/lib/active_support/memoizable.rb | 2 ++
activesupport/lib/active_support/multibyte.rb | 2 ++
activesupport/lib/active_support/testing/assertions.rb | 2 ++
activesupport/lib/active_support/time_with_zone.rb | 2 +-
activesupport/lib/active_support/xml_mini.rb | 2 ++
activesupport/lib/active_support/xml_mini/rexml.rb | 2 ++
activesupport/test/buffered_logger_test.rb | 14 ++++++++------
activesupport/test/core_ext/array_ext_test.rb | 3 +++
activesupport/test/core_ext/blank_test.rb | 1 +
.../test/core_ext/class/attribute_accessor_test.rb | 1 +
.../core_ext/class/class_inheritable_attributes_test.rb | 1 +
activesupport/test/core_ext/date_time_ext_test.rb | 1 +
activesupport/test/core_ext/duplicable_test.rb | 2 ++
activesupport/test/core_ext/duration_test.rb | 1 +
activesupport/test/core_ext/exception_test.rb | 1 +
activesupport/test/core_ext/hash_ext_test.rb | 2 ++
.../core_ext/module/attr_accessor_with_default_test.rb | 1 +
activesupport/test/core_ext/module/attr_internal_test.rb | 7 ++++---
.../test/core_ext/module/attribute_accessor_test.rb | 1 +
activesupport/test/core_ext/module/model_naming_test.rb | 1 +
activesupport/test/core_ext/name_error_test.rb | 1 +
activesupport/test/core_ext/numeric_ext_test.rb | 5 +++--
activesupport/test/core_ext/object_and_class_ext_test.rb | 2 ++
activesupport/test/core_ext/proc_test.rb | 1 +
activesupport/test/core_ext/range_ext_test.rb | 1 +
activesupport/test/core_ext/string_ext_test.rb | 1 +
activesupport/test/core_ext/time_ext_test.rb | 1 +
activesupport/test/core_ext/time_with_zone_test.rb | 1 +
activesupport/test/dependencies_test.rb | 2 ++
activesupport/test/i18n_test.rb | 2 ++
activesupport/test/inflector_test.rb | 2 ++
activesupport/test/test_test.rb | 1 +
activesupport/test/time_zone_test.rb | 1 +
activesupport/test/xml_mini/nokogiri_engine_test.rb | 1 +
61 files changed, 127 insertions(+), 32 deletions(-)
diff --git a/activesupport/Rakefile b/activesupport/Rakefile
index f7fd52c7d8..a4e8200a43 100644
--- a/activesupport/Rakefile
+++ b/activesupport/Rakefile
@@ -21,6 +21,12 @@ Rake::TestTask.new { |t|
t.verbose = true
t.warning = true
}
+task :isolated_test do
+ Dir['test/**/*_test.rb'].all? do |file|
+ ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
+ system(ruby, '-Ilib:test', file)
+ end or raise "Failures"
+end
# Create compressed packages
dist_dirs = [ "lib", "test"]
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index 4b2eebb007..feb6b1f2cf 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -2,6 +2,7 @@ require 'benchmark'
require 'active_support/core_ext/benchmark'
require 'active_support/core_ext/exception'
require 'active_support/core_ext/class/attribute_accessors'
+require 'active_support/core_ext' # FIXME: pulling in all to_param extensions
module ActiveSupport
# See ActiveSupport::Cache::Store for documentation.
diff --git a/activesupport/lib/active_support/cache/strategy/local_cache.rb b/activesupport/lib/active_support/cache/strategy/local_cache.rb
index 84d9a0e6d8..4bbcd8e4c4 100644
--- a/activesupport/lib/active_support/cache/strategy/local_cache.rb
+++ b/activesupport/lib/active_support/cache/strategy/local_cache.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/object/duplicable'
+
module ActiveSupport
module Cache
module Strategy
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 4bac8292e2..f049189b9a 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/array/extract_options'
+
module ActiveSupport
# Callbacks are hooks into the lifecycle of an object that allow you to trigger logic
# before or after an alteration of the object state.
diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb
index 81e466779e..5f1ce4142f 100644
--- a/activesupport/lib/active_support/core_ext/array/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/array/conversions.rb
@@ -1,3 +1,7 @@
+require 'active_support/core_ext/hash/keys'
+require 'active_support/core_ext/hash/reverse_merge'
+require 'active_support/inflector'
+
class Array
# Converts the array to a comma-separated sentence where the last element is joined by the connector word. Options:
# * :words_connector - The sign or word used to join the elements in arrays with two or more elements (default: ", ")
@@ -155,7 +159,7 @@ class Array
raise "Not all elements respond to to_xml" unless all? { |e| e.respond_to? :to_xml }
require 'builder' unless defined?(Builder)
- options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? first.class.to_s.underscore.pluralize : "records"
+ options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? ActiveSupport::Inflector.pluralize(ActiveSupport::Inflector.underscore(first.class.name)) : "records"
options[:children] ||= options[:root].singularize
options[:indent] ||= 2
options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
diff --git a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
index 2f18666ab9..cca93a0b9f 100644
--- a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
+++ b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/object/duplicable'
+
# Retain for backward compatibility. Methods are now included in Class.
module ClassInheritableAttributes # :nodoc:
end
@@ -216,4 +218,4 @@ class Class
extlib_inheritable_reader(*syms)
extlib_inheritable_writer(*syms)
end
-end
\ No newline at end of file
+end
diff --git a/activesupport/lib/active_support/core_ext/class/removal.rb b/activesupport/lib/active_support/core_ext/class/removal.rb
index 10660edb2c..2dea3c24d5 100644
--- a/activesupport/lib/active_support/core_ext/class/removal.rb
+++ b/activesupport/lib/active_support/core_ext/class/removal.rb
@@ -1,3 +1,6 @@
+require 'active_support/core_ext/object/extending'
+require 'active_support/core_ext/module/introspection'
+
class Class #:nodoc:
# Unassociates the class with its subclasses and removes the subclasses
diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb
index 59efdbd1b6..04a32edefd 100644
--- a/activesupport/lib/active_support/core_ext/date/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -1,3 +1,5 @@
+require 'active_support/duration'
+
class Date
class << self
# Returns a new Date representing the date 1 day ago (i.e. yesterday's date).
diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb
index f6c870035b..54facf4430 100644
--- a/activesupport/lib/active_support/core_ext/date/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date/conversions.rb
@@ -1,4 +1,6 @@
require 'active_support/inflector'
+require 'active_support/core_ext/time/conversions'
+require 'active_support/core_ext/date_time/conversions'
class Date
DATE_FORMATS = {
diff --git a/activesupport/lib/active_support/core_ext/date_time.rb b/activesupport/lib/active_support/core_ext/date_time.rb
index 83a11da1c7..004fd0ad29 100644
--- a/activesupport/lib/active_support/core_ext/date_time.rb
+++ b/activesupport/lib/active_support/core_ext/date_time.rb
@@ -1,5 +1,4 @@
-require 'date'
-
+require 'active_support/core_ext/time'
require 'active_support/core_ext/date_time/acts_like'
require 'active_support/core_ext/date_time/calculations'
require 'active_support/core_ext/date_time/conversions'
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index fa171720f9..f9dddec687 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -1,6 +1,8 @@
require 'date'
require 'active_support/core_ext/object/conversions'
require 'active_support/core_ext/array/conversions'
+require 'active_support/core_ext/hash/reverse_merge'
+require 'active_support/core/time'
class Hash
# This module exists to decorate files deserialized using Hash.from_xml with
diff --git a/activesupport/lib/active_support/core_ext/logger.rb b/activesupport/lib/active_support/core_ext/logger.rb
index 858da7aa07..22749229a3 100644
--- a/activesupport/lib/active_support/core_ext/logger.rb
+++ b/activesupport/lib/active_support/core_ext/logger.rb
@@ -1,6 +1,7 @@
-# Adds the 'around_level' method to Logger.
+require 'active_support/core_ext/class/attribute_accessors'
-class Logger
+# Adds the 'around_level' method to Logger.
+class Logger #:nodoc:
def self.define_around_helper(level)
module_eval <<-end_eval
def around_#{level}(before_message, after_message, &block) # def around_debug(before_message, after_message, &block)
diff --git a/activesupport/lib/active_support/core_ext/module/attr_internal.rb b/activesupport/lib/active_support/core_ext/module/attr_internal.rb
index b66c0d7500..d052bfed2d 100644
--- a/activesupport/lib/active_support/core_ext/module/attr_internal.rb
+++ b/activesupport/lib/active_support/core_ext/module/attr_internal.rb
@@ -22,11 +22,11 @@ class Module
alias_method :attr_internal, :attr_internal_accessor
- private
- mattr_accessor :attr_internal_naming_format
- self.attr_internal_naming_format = '@_%s'
+ class << self; attr_accessor :attr_internal_naming_format end
+ self.attr_internal_naming_format = '@_%s'
+ private
def attr_internal_ivar_name(attr)
- attr_internal_naming_format % attr
+ Module.attr_internal_naming_format % attr
end
end
diff --git a/activesupport/lib/active_support/core_ext/module/introspection.rb b/activesupport/lib/active_support/core_ext/module/introspection.rb
index 7708d573fa..23a1063901 100644
--- a/activesupport/lib/active_support/core_ext/module/introspection.rb
+++ b/activesupport/lib/active_support/core_ext/module/introspection.rb
@@ -1,3 +1,5 @@
+require 'active_support/inflector'
+
class Module
# Returns the name of the module containing this one.
#
@@ -26,7 +28,7 @@ class Module
# p Module.new.parent # => Object
#
def parent
- parent_name ? parent_name.constantize : Object
+ parent_name ? ActiveSupport::Inflector.constantize(parent_name) : Object
end
# Returns all the parents of this module according to its name, ordered from
@@ -47,7 +49,7 @@ class Module
if parent_name
parts = parent_name.split('::')
until parts.empty?
- parents << (parts * '::').constantize
+ parents << ActiveSupport::Inflector.constantize(parts * '::')
parts.pop
end
end
diff --git a/activesupport/lib/active_support/core_ext/module/model_naming.rb b/activesupport/lib/active_support/core_ext/module/model_naming.rb
index 004b96a3c1..36fde87b23 100644
--- a/activesupport/lib/active_support/core_ext/module/model_naming.rb
+++ b/activesupport/lib/active_support/core_ext/module/model_naming.rb
@@ -1,13 +1,15 @@
+require 'active_support/inflector'
+
module ActiveSupport
class ModelName < String
attr_reader :singular, :plural, :cache_key, :partial_path
def initialize(name)
super
- @singular = underscore.tr('/', '_').freeze
- @plural = @singular.pluralize.freeze
+ @singular = ActiveSupport::Inflector.underscore(self).tr('/', '_').freeze
+ @plural = ActiveSupport::Inflector.pluralize(@singular).freeze
@cache_key = tableize.freeze
- @partial_path = "#{@cache_key}/#{demodulize.underscore}".freeze
+ @partial_path = "#{@cache_key}/#{ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self))}".freeze
end
end
end
diff --git a/activesupport/lib/active_support/core_ext/module/synchronization.rb b/activesupport/lib/active_support/core_ext/module/synchronization.rb
index 069db3fed0..f72d512340 100644
--- a/activesupport/lib/active_support/core_ext/module/synchronization.rb
+++ b/activesupport/lib/active_support/core_ext/module/synchronization.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/module/aliasing'
+
class Module
# Synchronize access around a method, delegating synchronization to a
# particular mutex. A mutex (either a Mutex, or any object that responds to
diff --git a/activesupport/lib/active_support/core_ext/numeric/time.rb b/activesupport/lib/active_support/core_ext/numeric/time.rb
index 2955e8ff1d..d1062805c5 100644
--- a/activesupport/lib/active_support/core_ext/numeric/time.rb
+++ b/activesupport/lib/active_support/core_ext/numeric/time.rb
@@ -1,3 +1,5 @@
+require 'active_support/duration'
+
class Numeric
# Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years.
#
diff --git a/activesupport/lib/active_support/core_ext/object.rb b/activesupport/lib/active_support/core_ext/object.rb
index 96385d2b87..04e8f06b3d 100644
--- a/activesupport/lib/active_support/core_ext/object.rb
+++ b/activesupport/lib/active_support/core_ext/object.rb
@@ -1,3 +1,4 @@
+require 'active_support/core_ext/object/acts_like'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/object/duplicable'
require 'active_support/core_ext/object/try'
diff --git a/activesupport/lib/active_support/core_ext/range/blockless_step.rb b/activesupport/lib/active_support/core_ext/range/blockless_step.rb
index f4792d03b7..db42ef5c47 100644
--- a/activesupport/lib/active_support/core_ext/range/blockless_step.rb
+++ b/activesupport/lib/active_support/core_ext/range/blockless_step.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/module/aliasing'
+
class Range
begin
(1..2).step
diff --git a/activesupport/lib/active_support/core_ext/string/conversions.rb b/activesupport/lib/active_support/core_ext/string/conversions.rb
index 39c2b1b8ed..3f05db62c3 100644
--- a/activesupport/lib/active_support/core_ext/string/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/string/conversions.rb
@@ -1,4 +1,5 @@
require 'date'
+require 'active_support/core_ext/time/calculations'
class String
# 'a'.ord == 'a'[0] for Ruby 1.9 forward compatibility.
diff --git a/activesupport/lib/active_support/core_ext/string/multibyte.rb b/activesupport/lib/active_support/core_ext/string/multibyte.rb
index 0f0dfb2443..13208c6ee2 100644
--- a/activesupport/lib/active_support/core_ext/string/multibyte.rb
+++ b/activesupport/lib/active_support/core_ext/string/multibyte.rb
@@ -1,4 +1,5 @@
# encoding: utf-8
+require 'active_support/multibyte'
class String
unless '1.9'.respond_to?(:force_encoding)
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 1804c14618..855b720ef1 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -1,11 +1,13 @@
require 'set'
require 'thread'
-require 'active_support/inflector'
-require 'active_support/core_ext/name_error'
-require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/module/aliasing'
require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/core_ext/module/introspection'
+require 'active_support/core_ext/object/blank'
+require 'active_support/core_ext/load_error'
+require 'active_support/core_ext/name_error'
+require 'active_support/core_ext/string/starts_ends_with'
+require 'active_support/inflector'
module ActiveSupport #:nodoc:
module Dependencies #:nodoc:
diff --git a/activesupport/lib/active_support/deprecation/method_wrappers.rb b/activesupport/lib/active_support/deprecation/method_wrappers.rb
index b35d4daf9a..b9eb539aa7 100644
--- a/activesupport/lib/active_support/deprecation/method_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/method_wrappers.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/module/deprecation'
+require 'active_support/core_ext/module/aliasing'
module ActiveSupport
class << Deprecation
diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
index 1c268d0d9c..ec54efe08e 100644
--- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
@@ -1,3 +1,5 @@
+require 'active_support/inflector'
+
module ActiveSupport
module Deprecation
class DeprecationProxy #:nodoc:
@@ -61,7 +63,7 @@ module ActiveSupport
private
def target
- @new_const.to_s.constantize
+ ActiveSupport::Inflector.constantize(@new_const.to_s)
end
def warn(callstack, called, args)
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb
index f64661c5b1..a33586f77f 100644
--- a/activesupport/lib/active_support/duration.rb
+++ b/activesupport/lib/active_support/duration.rb
@@ -1,4 +1,5 @@
require 'active_support/basic_object'
+require 'active_support/core_ext/array/conversions'
module ActiveSupport
# Provides accurate date and time measurements using Date#advance and
diff --git a/activesupport/lib/active_support/inflector.rb b/activesupport/lib/active_support/inflector.rb
index 614afa1bd6..ff70d6d76e 100644
--- a/activesupport/lib/active_support/inflector.rb
+++ b/activesupport/lib/active_support/inflector.rb
@@ -1,6 +1,7 @@
# encoding: utf-8
require 'iconv'
-
+require 'active_support/core_ext/object/blank'
+require 'active_support/core_ext/string/access'
require 'active_support/core_ext/string/multibyte'
module ActiveSupport
diff --git a/activesupport/lib/active_support/json/encoders/time.rb b/activesupport/lib/active_support/json/encoders/time.rb
index f45a0059e8..7d97c38d77 100644
--- a/activesupport/lib/active_support/json/encoders/time.rb
+++ b/activesupport/lib/active_support/json/encoders/time.rb
@@ -1,3 +1,5 @@
+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.
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb
index 2b85fd7be4..edf626802a 100644
--- a/activesupport/lib/active_support/memoizable.rb
+++ b/activesupport/lib/active_support/memoizable.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/object/metaclass'
+
module ActiveSupport
module SafelyMemoizable
def safely_memoize(*symbols)
diff --git a/activesupport/lib/active_support/multibyte.rb b/activesupport/lib/active_support/multibyte.rb
index 65a96af49a..d8d58f3bce 100644
--- a/activesupport/lib/active_support/multibyte.rb
+++ b/activesupport/lib/active_support/multibyte.rb
@@ -4,6 +4,8 @@ require 'active_support/multibyte/chars'
require 'active_support/multibyte/exceptions'
require 'active_support/multibyte/unicode_database'
+require 'active_support/core_ext/module/attribute_accessors'
+
module ActiveSupport #:nodoc:
module Multibyte
# A list of all available normalization forms. See http://www.unicode.org/reports/tr15/tr15-29.html for more
diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb
index ca51adba1e..c529b92240 100644
--- a/activesupport/lib/active_support/testing/assertions.rb
+++ b/activesupport/lib/active_support/testing/assertions.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/array/wrap'
+
module ActiveSupport
module Testing
module Assertions
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index aa448debda..0d4c75d272 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -131,7 +131,7 @@ module ActiveSupport
# Time.utc(2005,2,1,15,15,10).in_time_zone.to_json
# # => "2005/02/01 15:15:10 +0000"
def to_json(options = nil)
- if ActiveSupport.use_standard_json_time_format
+ 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)}")
diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb
index ccd1349491..f22fbcc0e1 100644
--- a/activesupport/lib/active_support/xml_mini.rb
+++ b/activesupport/lib/active_support/xml_mini.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/module/delegation'
+
module ActiveSupport
# = XmlMini
#
diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb
index 771109514c..5033210aae 100644
--- a/activesupport/lib/active_support/xml_mini/rexml.rb
+++ b/activesupport/lib/active_support/xml_mini/rexml.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/object/blank'
+
# = XmlMini ReXML implementation
module ActiveSupport
module XmlMini_REXML #:nodoc:
diff --git a/activesupport/test/buffered_logger_test.rb b/activesupport/test/buffered_logger_test.rb
index d48c7fcc54..7a0ec2e910 100644
--- a/activesupport/test/buffered_logger_test.rb
+++ b/activesupport/test/buffered_logger_test.rb
@@ -4,11 +4,13 @@ require 'fileutils'
require 'active_support/buffered_logger'
class BufferedLoggerTest < Test::Unit::TestCase
+ Logger = ActiveSupport::BufferedLogger
+
def setup
@message = "A debug message"
@integer_message = 12345
@output = StringIO.new
- @logger = ActiveSupport::BufferedLogger.new(@output)
+ @logger = Logger.new(@output)
end
def test_should_log_debugging_message_when_debugging
@@ -76,9 +78,9 @@ class BufferedLoggerTest < Test::Unit::TestCase
define_method "test_disabling_auto_flush_with_#{disable.inspect}_should_flush_at_max_buffer_size_as_failsafe" do
@logger.auto_flushing = disable
- assert_equal ActiveSupport::BufferedLogger::MAX_BUFFER_SIZE, @logger.auto_flushing
+ assert_equal Logger::MAX_BUFFER_SIZE, @logger.auto_flushing
- (ActiveSupport::BufferedLogger::MAX_BUFFER_SIZE - 1).times do
+ (Logger::MAX_BUFFER_SIZE - 1).times do
@logger.info 'wait for it..'
assert @output.string.empty?, @output.string
end
@@ -89,8 +91,8 @@ class BufferedLoggerTest < Test::Unit::TestCase
end
def test_should_know_if_its_loglevel_is_below_a_given_level
- ActiveSupport::BufferedLogger::Severity.constants.each do |level|
- @logger.level = ActiveSupport::BufferedLogger::Severity.const_get(level) - 1
+ Logger::Severity.constants.each do |level|
+ @logger.level = Logger::Severity.const_get(level) - 1
assert @logger.send("#{level.downcase}?"), "didn't know if it was #{level.downcase}? or below"
end
end
@@ -111,7 +113,7 @@ class BufferedLoggerTest < Test::Unit::TestCase
tmp_directory = File.join(File.dirname(__FILE__), "tmp")
log_file = File.join(tmp_directory, "development.log")
assert !File.exist?(tmp_directory)
- @logger = ActiveSupport::BufferedLogger.new(log_file)
+ @logger = Logger.new(log_file)
assert File.exist?(tmp_directory)
ensure
FileUtils.rm_rf(tmp_directory)
diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb
index 112cb998b1..24d33896ce 100644
--- a/activesupport/test/core_ext/array_ext_test.rb
+++ b/activesupport/test/core_ext/array_ext_test.rb
@@ -1,6 +1,9 @@
require 'abstract_unit'
require 'active_support/core_ext/array'
require 'active_support/core_ext/big_decimal'
+require 'active_support/core_ext/object/conversions'
+
+require 'active_support/core_ext' # FIXME: pulling in all to_xml extensions
class ArrayExtAccessTests < Test::Unit::TestCase
def test_from
diff --git a/activesupport/test/core_ext/blank_test.rb b/activesupport/test/core_ext/blank_test.rb
index 00fea74639..1dbbf3ff30 100644
--- a/activesupport/test/core_ext/blank_test.rb
+++ b/activesupport/test/core_ext/blank_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/object/blank'
class EmptyTrue
def empty?() true; end
diff --git a/activesupport/test/core_ext/class/attribute_accessor_test.rb b/activesupport/test/core_ext/class/attribute_accessor_test.rb
index 85d0dd89e2..2214ba9894 100644
--- a/activesupport/test/core_ext/class/attribute_accessor_test.rb
+++ b/activesupport/test/core_ext/class/attribute_accessor_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/class/attribute_accessors'
class ClassAttributeAccessorTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/test/core_ext/class/class_inheritable_attributes_test.rb b/activesupport/test/core_ext/class/class_inheritable_attributes_test.rb
index 7f859772e7..eeda468d9c 100644
--- a/activesupport/test/core_ext/class/class_inheritable_attributes_test.rb
+++ b/activesupport/test/core_ext/class/class_inheritable_attributes_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/class/inheritable_attributes'
class ClassInheritableAttributesTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb
index 45eb52c720..a7b179b2be 100644
--- a/activesupport/test/core_ext/date_time_ext_test.rb
+++ b/activesupport/test/core_ext/date_time_ext_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/date_time'
class DateTimeExtCalculationsTest < Test::Unit::TestCase
def test_to_s
diff --git a/activesupport/test/core_ext/duplicable_test.rb b/activesupport/test/core_ext/duplicable_test.rb
index 8b6127f31e..6e1f876959 100644
--- a/activesupport/test/core_ext/duplicable_test.rb
+++ b/activesupport/test/core_ext/duplicable_test.rb
@@ -1,4 +1,6 @@
require 'abstract_unit'
+require 'bigdecimal'
+require 'active_support/core_ext/object/duplicable'
class DuplicableTest < Test::Unit::TestCase
NO = [nil, false, true, :symbol, 1, 2.3, BigDecimal.new('4.56'), Class.new]
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index d4a4627e3e..ea6979bc6b 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core/time'
class DurationTest < ActiveSupport::TestCase
def test_inspect
diff --git a/activesupport/test/core_ext/exception_test.rb b/activesupport/test/core_ext/exception_test.rb
index dabd8c7c06..e63842c0bd 100644
--- a/activesupport/test/core_ext/exception_test.rb
+++ b/activesupport/test/core_ext/exception_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/exception'
class ExceptionExtTests < Test::Unit::TestCase
diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb
index bbb1c631f9..d65a5323bf 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -1,5 +1,7 @@
require 'abstract_unit'
require 'active_support/core_ext/hash'
+require 'bigdecimal'
+require 'active_support/core_ext/string/access'
class HashExtTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/test/core_ext/module/attr_accessor_with_default_test.rb b/activesupport/test/core_ext/module/attr_accessor_with_default_test.rb
index 7c59348af9..7c0d0bb242 100644
--- a/activesupport/test/core_ext/module/attr_accessor_with_default_test.rb
+++ b/activesupport/test/core_ext/module/attr_accessor_with_default_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/module/attr_accessor_with_default'
class AttrAccessorWithDefaultTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/test/core_ext/module/attr_internal_test.rb b/activesupport/test/core_ext/module/attr_internal_test.rb
index 52833019e7..93578c9610 100644
--- a/activesupport/test/core_ext/module/attr_internal_test.rb
+++ b/activesupport/test/core_ext/module/attr_internal_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/module/attr_internal'
class AttrInternalTest < Test::Unit::TestCase
def setup
@@ -37,8 +38,8 @@ class AttrInternalTest < Test::Unit::TestCase
end
def test_naming_format
- assert_equal '@_%s', @target.attr_internal_naming_format
- assert_nothing_raised { @target.attr_internal_naming_format = '@abc%sdef' }
+ assert_equal '@_%s', Module.attr_internal_naming_format
+ assert_nothing_raised { Module.attr_internal_naming_format = '@abc%sdef' }
@target.attr_internal :foo
assert !@instance.instance_variable_defined?('@_foo')
@@ -47,6 +48,6 @@ class AttrInternalTest < Test::Unit::TestCase
assert !@instance.instance_variable_defined?('@_foo')
assert @instance.instance_variable_defined?('@abcfoodef')
ensure
- @target.attr_internal_naming_format = '@_%s'
+ Module.attr_internal_naming_format = '@_%s'
end
end
diff --git a/activesupport/test/core_ext/module/attribute_accessor_test.rb b/activesupport/test/core_ext/module/attribute_accessor_test.rb
index 96975085cf..bd9461e62c 100644
--- a/activesupport/test/core_ext/module/attribute_accessor_test.rb
+++ b/activesupport/test/core_ext/module/attribute_accessor_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/module/attribute_accessors'
class ModuleAttributeAccessorTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/test/core_ext/module/model_naming_test.rb b/activesupport/test/core_ext/module/model_naming_test.rb
index d08349dd97..da3b6c4932 100644
--- a/activesupport/test/core_ext/module/model_naming_test.rb
+++ b/activesupport/test/core_ext/module/model_naming_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/module/model_naming'
class ModelNamingTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/test/core_ext/name_error_test.rb b/activesupport/test/core_ext/name_error_test.rb
index bae004809f..10913e2ade 100644
--- a/activesupport/test/core_ext/name_error_test.rb
+++ b/activesupport/test/core_ext/name_error_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/name_error'
class NameErrorTest < Test::Unit::TestCase
def test_name_error_should_set_missing_name
diff --git a/activesupport/test/core_ext/numeric_ext_test.rb b/activesupport/test/core_ext/numeric_ext_test.rb
index 9cca4d3aaf..74b086fa9c 100644
--- a/activesupport/test/core_ext/numeric_ext_test.rb
+++ b/activesupport/test/core_ext/numeric_ext_test.rb
@@ -1,6 +1,7 @@
require 'abstract_unit'
-
-require 'active_support/core_ext/numeric/bytes'
+require 'active_support/core_ext/numeric'
+require 'active_support/core_ext/integer'
+require 'active_support/core/time'
class NumericExtTimeAndDateTimeTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/test/core_ext/object_and_class_ext_test.rb b/activesupport/test/core_ext/object_and_class_ext_test.rb
index c919698c0f..8869b053e6 100644
--- a/activesupport/test/core_ext/object_and_class_ext_test.rb
+++ b/activesupport/test/core_ext/object_and_class_ext_test.rb
@@ -1,5 +1,7 @@
require 'abstract_unit'
require 'active_support/core_ext/object'
+require 'active_support/core_ext/class/removal'
+require 'active_support/core/time'
class ClassA; end
class ClassB < ClassA; end
diff --git a/activesupport/test/core_ext/proc_test.rb b/activesupport/test/core_ext/proc_test.rb
index 29f85371de..dc7b2c957d 100644
--- a/activesupport/test/core_ext/proc_test.rb
+++ b/activesupport/test/core_ext/proc_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/proc'
class ProcTests < Test::Unit::TestCase
def test_bind_returns_method_with_changed_self
diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb
index 76e05e9954..2565c56b8a 100644
--- a/activesupport/test/core_ext/range_ext_test.rb
+++ b/activesupport/test/core_ext/range_ext_test.rb
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'active_support/core_ext/range'
+require 'active_support/core_ext/date/conversions'
class RangeTest < Test::Unit::TestCase
def test_to_s_from_dates
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index a357ba5852..237a843f9a 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -4,6 +4,7 @@ require 'abstract_unit'
require 'inflector_test_cases'
require 'active_support/core_ext/string'
+require 'active_support/core_ext/time'
class StringInflectionsTest < Test::Unit::TestCase
include InflectorTestCases
diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb
index 8ee4904036..3bf7b789ce 100644
--- a/activesupport/test/core_ext/time_ext_test.rb
+++ b/activesupport/test/core_ext/time_ext_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core/time'
class TimeExtCalculationsTest < Test::Unit::TestCase
def test_seconds_since_midnight
diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb
index 3dec4c95f4..612a50c225 100644
--- a/activesupport/test/core_ext/time_with_zone_test.rb
+++ b/activesupport/test/core_ext/time_with_zone_test.rb
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'active_support/time_with_zone'
+require 'active_support/json'
class TimeWithZoneTest < Test::Unit::TestCase
diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb
index 01c1d67f4c..99c53924c2 100644
--- a/activesupport/test/dependencies_test.rb
+++ b/activesupport/test/dependencies_test.rb
@@ -1,6 +1,8 @@
require 'abstract_unit'
require 'pp'
require 'active_support/dependencies'
+require 'active_support/core_ext/module/loading'
+require 'active_support/core_ext/kernel/reporting'
module ModuleWithMissing
mattr_accessor :missing_count
diff --git a/activesupport/test/i18n_test.rb b/activesupport/test/i18n_test.rb
index 7535f4ad7a..2a08abfb3e 100644
--- a/activesupport/test/i18n_test.rb
+++ b/activesupport/test/i18n_test.rb
@@ -1,4 +1,6 @@
require 'abstract_unit'
+require 'active_support/core/time'
+require 'active_support/core_ext/array/conversions'
class I18nTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb
index 6b9fbd3156..8c4d831a39 100644
--- a/activesupport/test/inflector_test.rb
+++ b/activesupport/test/inflector_test.rb
@@ -1,4 +1,6 @@
require 'abstract_unit'
+require 'active_support/inflector'
+
require 'inflector_test_cases'
module Ace
diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb
index d250b10822..40d3d612e7 100644
--- a/activesupport/test/test_test.rb
+++ b/activesupport/test/test_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/kernel/reporting'
class AssertDifferenceTest < ActiveSupport::TestCase
def setup
diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb
index 7e8047566e..87d6ccc30d 100644
--- a/activesupport/test/time_zone_test.rb
+++ b/activesupport/test/time_zone_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core/time'
class TimeZoneTest < Test::Unit::TestCase
def test_utc_to_local
diff --git a/activesupport/test/xml_mini/nokogiri_engine_test.rb b/activesupport/test/xml_mini/nokogiri_engine_test.rb
index e5174a0b57..886a9d1aba 100644
--- a/activesupport/test/xml_mini/nokogiri_engine_test.rb
+++ b/activesupport/test/xml_mini/nokogiri_engine_test.rb
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'active_support/xml_mini'
+require 'active_support/core_ext/hash/conversions'
begin
gem 'nokogiri', '>= 1.1.1'
--
cgit v1.2.3
From d23ab4fbb6fadd484d44d2f568eb81302a0a5670 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 22 Apr 2009 19:35:58 -0700
Subject: Remove Symbol#to_proc dependency
---
railties/test/plugin_locator_test.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/railties/test/plugin_locator_test.rb b/railties/test/plugin_locator_test.rb
index 471d9fc7c3..f028bd3a61 100644
--- a/railties/test/plugin_locator_test.rb
+++ b/railties/test/plugin_locator_test.rb
@@ -42,12 +42,12 @@ class PluginFileSystemLocatorTest < Test::Unit::TestCase
end
def test_should_return_all_plugins_found_under_the_set_plugin_paths
- assert_equal ["a", "acts_as_chunky_bacon", "engine", "gemlike", "plugin_with_no_lib_dir", "stubby"].sort, @locator.plugins.map(&:name).sort
+ assert_equal ["a", "acts_as_chunky_bacon", "engine", "gemlike", "plugin_with_no_lib_dir", "stubby"].sort, @locator.plugins.map { |p| p.name }.sort
end
def test_should_find_plugins_only_under_the_plugin_paths_set_in_configuration
@configuration.plugin_paths = [File.join(plugin_fixture_root_path, "default")]
- assert_equal ["acts_as_chunky_bacon", "gemlike", "plugin_with_no_lib_dir", "stubby"].sort, @locator.plugins.map(&:name).sort
+ assert_equal ["acts_as_chunky_bacon", "gemlike", "plugin_with_no_lib_dir", "stubby"].sort, @locator.plugins.map { |p| p.name }.sort
@configuration.plugin_paths = [File.join(plugin_fixture_root_path, "alternate")]
assert_equal ["a"], @locator.plugins.map(&:name)
--
cgit v1.2.3
From 236169e85ec46644795520b826543187cf93b984 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 22 Apr 2009 19:50:24 -0700
Subject: Missed one
---
railties/test/plugin_locator_test.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/railties/test/plugin_locator_test.rb b/railties/test/plugin_locator_test.rb
index f028bd3a61..855ac7d82f 100644
--- a/railties/test/plugin_locator_test.rb
+++ b/railties/test/plugin_locator_test.rb
@@ -50,7 +50,7 @@ class PluginFileSystemLocatorTest < Test::Unit::TestCase
assert_equal ["acts_as_chunky_bacon", "gemlike", "plugin_with_no_lib_dir", "stubby"].sort, @locator.plugins.map { |p| p.name }.sort
@configuration.plugin_paths = [File.join(plugin_fixture_root_path, "alternate")]
- assert_equal ["a"], @locator.plugins.map(&:name)
+ assert_equal ["a"], @locator.plugins.map { |p| p.name }
end
def test_should_not_raise_any_error_and_return_no_plugins_if_the_plugin_path_value_does_not_exist
--
cgit v1.2.3
From bab2bfa69220ca1b6c7b56dccc79cf8e41245306 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 22 Apr 2009 19:52:28 -0700
Subject: Removed rest of Symbol#to_proc from railties tests
---
railties/test/gem_dependency_test.rb | 2 +-
railties/test/plugin_test_helper.rb | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/railties/test/gem_dependency_test.rb b/railties/test/gem_dependency_test.rb
index 189ad02b76..d9cd5148a3 100644
--- a/railties/test/gem_dependency_test.rb
+++ b/railties/test/gem_dependency_test.rb
@@ -18,7 +18,7 @@ class GemDependencyTest < Test::Unit::TestCase
def test_configuration_adds_gem_dependency
config = Rails::Configuration.new
config.gem "xaws-s3x", :lib => "aws/s3", :version => "0.4.0"
- assert_equal [["install", "xaws-s3x", "--version", '"= 0.4.0"']], config.gems.collect(&:install_command)
+ assert_equal [["install", "xaws-s3x", "--version", '"= 0.4.0"']], config.gems.collect { |g| g.install_command }
end
def test_gem_creates_install_command
diff --git a/railties/test/plugin_test_helper.rb b/railties/test/plugin_test_helper.rb
index f8c094d19f..93d50dc07f 100644
--- a/railties/test/plugin_test_helper.rb
+++ b/railties/test/plugin_test_helper.rb
@@ -24,6 +24,6 @@ class Test::Unit::TestCase
end
def assert_plugins(list_of_names, array_of_plugins, message=nil)
- assert_equal list_of_names.map(&:to_s), array_of_plugins.map(&:name), message
+ assert_equal list_of_names.map { |n| n.to_s }, array_of_plugins.map { |p| p.name }, message
end
-end
\ No newline at end of file
+end
--
cgit v1.2.3
From 3c4c6bd0df598f865f49a983b4c65c415af4bcfc Mon Sep 17 00:00:00 2001
From: rick
Date: Thu, 23 Apr 2009 00:08:40 -0700
Subject: * Add pluggable JSON backends with support for the JSON gem. [rick]
Example: ActiveSupport::JSON.backend = "JSONGem"
All internal Rails JSON encoding is now handled by ActiveSupport::JSON.encode(). Use of #to_json is not recommended, as it may clash with other libraries that overwrite it. However, you can recover Rails specific functionality
if you really want to use #to_json.
gem 'json'
ActiveSupport::JSON.backend = "JSONGem"
class ActiveRecord::Base
alias to_json rails_to_json
end
---
actionpack/lib/action_controller/base/render.rb | 2 +-
.../lib/action_view/helpers/prototype_helper.rb | 16 +--
.../action_view/helpers/scriptaculous_helper.rb | 10 +-
actionpack/test/controller/render_test.rb | 18 ++--
actionpack/test/template/prototype_helper_test.rb | 16 +--
.../active_record/serializers/json_serializer.rb | 10 +-
activerecord/test/cases/json_serialization_test.rb | 112 ++++++++++-----------
activeresource/lib/active_resource/base.rb | 5 +-
activesupport/CHANGELOG | 15 +++
activesupport/lib/active_support/json.rb | 34 ++++++-
.../lib/active_support/json/backends/jsongem.rb | 36 +++++++
.../lib/active_support/json/backends/yaml.rb | 83 +++++++++++++++
activesupport/lib/active_support/json/decoding.rb | 82 ---------------
.../lib/active_support/json/encoders/date.rb | 4 +-
.../lib/active_support/json/encoders/date_time.rb | 4 +-
.../lib/active_support/json/encoders/enumerable.rb | 6 +-
.../active_support/json/encoders/false_class.rb | 4 +-
.../lib/active_support/json/encoders/hash.rb | 8 +-
.../lib/active_support/json/encoders/nil_class.rb | 4 +-
.../lib/active_support/json/encoders/numeric.rb | 4 +-
.../lib/active_support/json/encoders/object.rb | 4 +-
.../lib/active_support/json/encoders/regexp.rb | 4 +-
.../lib/active_support/json/encoders/string.rb | 4 +-
.../lib/active_support/json/encoders/symbol.rb | 4 +-
.../lib/active_support/json/encoders/time.rb | 4 +-
.../lib/active_support/json/encoders/true_class.rb | 4 +-
activesupport/lib/active_support/json/encoding.rb | 2 +-
activesupport/lib/active_support/json/variable.rb | 2 +-
activesupport/lib/active_support/time_with_zone.rb | 4 +-
activesupport/test/core_ext/time_with_zone_test.rb | 4 +-
activesupport/test/json/decoding_test.rb | 76 +++++++++-----
activesupport/test/json/encoding_test.rb | 38 +++----
32 files changed, 384 insertions(+), 239 deletions(-)
create mode 100644 activesupport/lib/active_support/json/backends/jsongem.rb
create mode 100644 activesupport/lib/active_support/json/backends/yaml.rb
delete mode 100644 activesupport/lib/active_support/json/decoding.rb
diff --git a/actionpack/lib/action_controller/base/render.rb b/actionpack/lib/action_controller/base/render.rb
index 52934076e6..33695cd78e 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 = json.to_json unless json.is_a?(String)
+ json = ActiveSupport::JSON.encode(json) unless json.is_a?(String)
json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
response.content_type ||= Mime::JSON
render_for_text(json)
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index 6bad11e354..fb8122af35 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}(#{ids.first.to_json})")
+ "#{method}(#{ActiveSupport::JSON.encode(ids.first)})")
end
def page
@@ -997,7 +997,7 @@ module ActionView
end
def javascript_object_for(object)
- object.respond_to?(:to_json) ? object.to_json : object.inspect
+ 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, "$(#{id.to_json})")
+ super(generator, "$(#{ActiveSupport::JSON.encode(id)})")
end
# Allows access of element attributes through +attribute+. Examples:
@@ -1184,10 +1184,12 @@ module ActionView
true
end
- def to_json(options = nil)
+ def rails_to_json(options = nil)
@variable
end
+ alias to_json rails_to_json
+
private
def append_to_function_chain!(call)
@generator << @variable if @empty
@@ -1211,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(#{number.to_json});")
+ append_enumerable_function!("eachSlice(#{ActiveSupport::JSON.encode(number)});")
end
end
@@ -1232,7 +1234,7 @@ module ActionView
def pluck(variable, property)
add_variable_assignment!(variable)
- append_enumerable_function!("pluck(#{property.to_json});")
+ append_enumerable_function!("pluck(#{ActiveSupport::JSON.encode(property)});")
end
def zip(variable, *arguments, &block)
@@ -1296,7 +1298,7 @@ module ActionView
class JavaScriptElementCollectionProxy < JavaScriptCollectionProxy #:nodoc:\
def initialize(generator, pattern)
- super(generator, "$$(#{pattern.to_json})")
+ super(generator, "$$(#{ActiveSupport::JSON.encode(pattern)})")
end
end
end
diff --git a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
index e16935ea87..04af2781d7 100644
--- a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
+++ b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
@@ -43,7 +43,7 @@ module ActionView
# You can change the behaviour with various options, see
# http://script.aculo.us for more documentation.
def visual_effect(name, element_id = false, js_options = {})
- element = element_id ? element_id.to_json : "element"
+ element = element_id ? ActiveSupport::JSON.encode(element_id) : "element"
js_options[:queue] = if js_options[:queue].is_a?(Hash)
'{' + js_options[:queue].map {|k, v| k == :limit ? "#{k}:#{v}" : "#{k}:'#{v}'" }.join(',') + '}'
@@ -138,7 +138,7 @@ module ActionView
end
def sortable_element_js(element_id, options = {}) #:nodoc:
- options[:with] ||= "Sortable.serialize(#{element_id.to_json})"
+ options[:with] ||= "Sortable.serialize(#{ActiveSupport::JSON.encode(element_id)})"
options[:onUpdate] ||= "function(){" + remote_function(options) + "}"
options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) }
@@ -149,7 +149,7 @@ module ActionView
options[:containment] = array_or_string_for_javascript(options[:containment]) if options[:containment]
options[:only] = array_or_string_for_javascript(options[:only]) if options[:only]
- %(Sortable.create(#{element_id.to_json}, #{options_for_javascript(options)});)
+ %(Sortable.create(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});)
end
# Makes the element with the DOM ID specified by +element_id+ draggable.
@@ -164,7 +164,7 @@ module ActionView
end
def draggable_element_js(element_id, options = {}) #:nodoc:
- %(new Draggable(#{element_id.to_json}, #{options_for_javascript(options)});)
+ %(new Draggable(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});)
end
# Makes the element with the DOM ID specified by +element_id+ receive
@@ -219,7 +219,7 @@ module ActionView
# Confirmation happens during the onDrop callback, so it can be removed from the options
options.delete(:confirm) if options[:confirm]
- %(Droppables.add(#{element_id.to_json}, #{options_for_javascript(options)});)
+ %(Droppables.add(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});)
end
end
end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 9a34bcebe6..bf72730bea 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -194,19 +194,19 @@ class TestController < ActionController::Base
end
def render_json_hello_world
- render :json => {:hello => 'world'}.to_json
+ render :json => ActiveSupport::JSON.encode(:hello => 'world')
end
def render_json_hello_world_with_callback
- render :json => {:hello => 'world'}.to_json, :callback => 'alert'
+ render :json => ActiveSupport::JSON.encode(:hello => 'world'), :callback => 'alert'
end
def render_json_with_custom_content_type
- render :json => {:hello => 'world'}.to_json, :content_type => 'text/javascript'
+ render :json => ActiveSupport::JSON.encode(:hello => 'world'), :content_type => 'text/javascript'
end
def render_symbol_json
- render :json => {:hello => 'world'}.to_json
+ render :json => ActiveSupport::JSON.encode(:hello => 'world')
end
def render_json_with_render_to_string
@@ -875,31 +875,31 @@ class RenderTest < ActionController::TestCase
def test_render_json
get :render_json_hello_world
- assert_equal '{"hello": "world"}', @response.body
+ assert_equal '{"hello":"world"}', @response.body
assert_equal 'application/json', @response.content_type
end
def test_render_json_with_callback
get :render_json_hello_world_with_callback
- assert_equal 'alert({"hello": "world"})', @response.body
+ assert_equal 'alert({"hello":"world"})', @response.body
assert_equal 'application/json', @response.content_type
end
def test_render_json_with_custom_content_type
get :render_json_with_custom_content_type
- assert_equal '{"hello": "world"}', @response.body
+ assert_equal '{"hello":"world"}', @response.body
assert_equal 'text/javascript', @response.content_type
end
def test_render_symbol_json
get :render_symbol_json
- assert_equal '{"hello": "world"}', @response.body
+ assert_equal '{"hello":"world"}', @response.body
assert_equal 'application/json', @response.content_type
end
def test_render_json_with_render_to_string
get :render_json_with_render_to_string
- assert_equal '{"hello": "partial html"}', @response.body
+ assert_equal '{"hello":"partial html"}', @response.body
assert_equal 'application/json', @response.content_type
end
diff --git a/actionpack/test/template/prototype_helper_test.rb b/actionpack/test/template/prototype_helper_test.rb
index cd6ee6ea11..28851f113f 100644
--- a/actionpack/test/template/prototype_helper_test.rb
+++ b/actionpack/test/template/prototype_helper_test.rb
@@ -328,28 +328,28 @@ class JavaScriptGeneratorTest < PrototypeHelperBaseTest
def test_remove
assert_equal 'Element.remove("foo");',
@generator.remove('foo')
- assert_equal '["foo", "bar", "baz"].each(Element.remove);',
+ assert_equal '["foo","bar","baz"].each(Element.remove);',
@generator.remove('foo', 'bar', 'baz')
end
def test_show
assert_equal 'Element.show("foo");',
@generator.show('foo')
- assert_equal '["foo", "bar", "baz"].each(Element.show);',
+ assert_equal '["foo","bar","baz"].each(Element.show);',
@generator.show('foo', 'bar', 'baz')
end
def test_hide
assert_equal 'Element.hide("foo");',
@generator.hide('foo')
- assert_equal '["foo", "bar", "baz"].each(Element.hide);',
+ assert_equal '["foo","bar","baz"].each(Element.hide);',
@generator.hide('foo', 'bar', 'baz')
end
def test_toggle
assert_equal 'Element.toggle("foo");',
@generator.toggle('foo')
- assert_equal '["foo", "bar", "baz"].each(Element.toggle);',
+ assert_equal '["foo","bar","baz"].each(Element.toggle);',
@generator.toggle('foo', 'bar', 'baz')
end
@@ -386,7 +386,7 @@ class JavaScriptGeneratorTest < PrototypeHelperBaseTest
assert_equal <<-EOS.chomp, @generator.to_s
Element.insert("element", { top: "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E" });
Element.insert("element", { bottom: "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E" });
-["foo", "bar"].each(Element.remove);
+["foo","bar"].each(Element.remove);
Element.update("baz", "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");
EOS
end
@@ -555,8 +555,8 @@ return (value.className == "welcome");
end
assert_equal <<-EOS.strip, @generator.to_s
-var a = [1, 2, 3].zip([4, 5, 6], [7, 8, 9]);
-var b = [1, 2, 3].zip([4, 5, 6], [7, 8, 9], function(array) {
+var a = [1, 2, 3].zip([4,5,6], [7,8,9]);
+var b = [1, 2, 3].zip([4,5,6], [7,8,9], function(array) {
return array.reverse();
});
EOS
@@ -607,7 +607,7 @@ return value.reverse();
def test_literal
literal = @generator.literal("function() {}")
- assert_equal "function() {}", literal.to_json
+ assert_equal "function() {}", ActiveSupport::JSON.encode(literal)
assert_equal "", @generator.to_s
end
diff --git a/activerecord/lib/active_record/serializers/json_serializer.rb b/activerecord/lib/active_record/serializers/json_serializer.rb
index c709c3f1eb..e9cb8bfca9 100644
--- a/activerecord/lib/active_record/serializers/json_serializer.rb
+++ b/activerecord/lib/active_record/serializers/json_serializer.rb
@@ -74,13 +74,17 @@ module ActiveRecord #:nodoc:
# {"comments": [{"body": "Don't think too hard"}],
# "title": "So I was thinking"}]}
def to_json(options = {})
+ json = JsonSerializer.new(self, options).to_s
if include_root_in_json
- "{#{self.class.json_class_name}: #{JsonSerializer.new(self, options).to_s}}"
+ "{#{self.class.json_class_name}:#{json}}"
else
- JsonSerializer.new(self, options).to_s
+ json
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
@@ -88,7 +92,7 @@ module ActiveRecord #:nodoc:
class JsonSerializer < ActiveRecord::Serialization::Serializer #:nodoc:
def serialize
- serializable_record.to_json
+ ActiveSupport::JSON.encode(serializable_record)
end
end
diff --git a/activerecord/test/cases/json_serialization_test.rb b/activerecord/test/cases/json_serialization_test.rb
index 975acde096..0ffbc9bf3b 100644
--- a/activerecord/test/cases/json_serialization_test.rb
+++ b/activerecord/test/cases/json_serialization_test.rb
@@ -26,19 +26,19 @@ class JsonSerializationTest < ActiveRecord::TestCase
NamespacedContact.include_root_in_json = true
@contact = NamespacedContact.new :name => 'whatever'
json = @contact.to_json
- assert_match %r{^\{"namespaced_contact": \{}, json
+ assert_match %r{^\{"namespaced_contact":\{}, json
end
def test_should_include_root_in_json
Contact.include_root_in_json = true
json = @contact.to_json
- assert_match %r{^\{"contact": \{}, json
- assert_match %r{"name": "Konata Izumi"}, json
- assert_match %r{"age": 16}, json
- assert json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
- assert_match %r{"awesome": true}, json
- assert_match %r{"preferences": \{"shows": "anime"\}}, json
+ assert_match %r{^\{"contact":\{}, json
+ assert_match %r{"name":"Konata Izumi"}, json
+ assert_match %r{"age":16}, json
+ assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_match %r{"awesome":true}, json
+ assert_match %r{"preferences":\{"shows":"anime"\}}, json
ensure
Contact.include_root_in_json = false
end
@@ -46,31 +46,31 @@ class JsonSerializationTest < ActiveRecord::TestCase
def test_should_encode_all_encodable_attributes
json = @contact.to_json
- assert_match %r{"name": "Konata Izumi"}, json
- assert_match %r{"age": 16}, json
- assert json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
- assert_match %r{"awesome": true}, json
- assert_match %r{"preferences": \{"shows": "anime"\}}, json
+ assert_match %r{"name":"Konata Izumi"}, json
+ assert_match %r{"age":16}, json
+ assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_match %r{"awesome":true}, json
+ assert_match %r{"preferences":\{"shows":"anime"\}}, json
end
def test_should_allow_attribute_filtering_with_only
json = @contact.to_json(:only => [:name, :age])
- assert_match %r{"name": "Konata Izumi"}, json
- assert_match %r{"age": 16}, json
- assert_no_match %r{"awesome": true}, json
- assert !json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
- assert_no_match %r{"preferences": \{"shows": "anime"\}}, json
+ assert_match %r{"name":"Konata Izumi"}, json
+ assert_match %r{"age":16}, json
+ assert_no_match %r{"awesome":true}, json
+ assert !json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_no_match %r{"preferences":\{"shows":"anime"\}}, json
end
def test_should_allow_attribute_filtering_with_except
json = @contact.to_json(:except => [:name, :age])
- assert_no_match %r{"name": "Konata Izumi"}, json
- assert_no_match %r{"age": 16}, json
- assert_match %r{"awesome": true}, json
- assert json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
- assert_match %r{"preferences": \{"shows": "anime"\}}, json
+ assert_no_match %r{"name":"Konata Izumi"}, json
+ assert_no_match %r{"age":16}, json
+ assert_match %r{"awesome":true}, json
+ assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_match %r{"preferences":\{"shows":"anime"\}}, json
end
def test_methods_are_called_on_object
@@ -79,12 +79,12 @@ class JsonSerializationTest < ActiveRecord::TestCase
def @contact.favorite_quote; "Constraints are liberating"; end
# Single method.
- assert_match %r{"label": "Has cheezburger"}, @contact.to_json(:only => :name, :methods => :label)
+ assert_match %r{"label":"Has cheezburger"}, @contact.to_json(:only => :name, :methods => :label)
# Both methods.
methods_json = @contact.to_json(:only => :name, :methods => [:label, :favorite_quote])
- assert_match %r{"label": "Has cheezburger"}, methods_json
- assert_match %r{"favorite_quote": "Constraints are liberating"}, methods_json
+ assert_match %r{"label":"Has cheezburger"}, methods_json
+ assert_match %r{"favorite_quote":"Constraints are liberating"}, methods_json
end
end
@@ -99,42 +99,42 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
def test_includes_uses_association_name
json = @david.to_json(:include => :posts)
- assert_match %r{"posts": \[}, json
+ assert_match %r{"posts":\[}, json
- assert_match %r{"id": 1}, json
- assert_match %r{"name": "David"}, json
+ assert_match %r{"id":1}, json
+ assert_match %r{"name":"David"}, json
- assert_match %r{"author_id": 1}, json
- assert_match %r{"title": "Welcome to the weblog"}, json
- assert_match %r{"body": "Such a lovely day"}, json
+ assert_match %r{"author_id":1}, json
+ assert_match %r{"title":"Welcome to the weblog"}, json
+ assert_match %r{"body":"Such a lovely day"}, json
- assert_match %r{"title": "So I was thinking"}, json
- assert_match %r{"body": "Like I hopefully always am"}, json
+ assert_match %r{"title":"So I was thinking"}, json
+ assert_match %r{"body":"Like I hopefully always am"}, json
end
def test_includes_uses_association_name_and_applies_attribute_filters
json = @david.to_json(:include => { :posts => { :only => :title } })
- assert_match %r{"name": "David"}, json
- assert_match %r{"posts": \[}, json
+ assert_match %r{"name":"David"}, json
+ assert_match %r{"posts":\[}, json
- assert_match %r{"title": "Welcome to the weblog"}, json
- assert_no_match %r{"body": "Such a lovely day"}, json
+ assert_match %r{"title":"Welcome to the weblog"}, json
+ assert_no_match %r{"body":"Such a lovely day"}, json
- assert_match %r{"title": "So I was thinking"}, json
- assert_no_match %r{"body": "Like I hopefully always am"}, json
+ assert_match %r{"title":"So I was thinking"}, json
+ assert_no_match %r{"body":"Like I hopefully always am"}, json
end
def test_includes_fetches_second_level_associations
json = @david.to_json(:include => { :posts => { :include => { :comments => { :only => :body } } } })
- assert_match %r{"name": "David"}, json
- assert_match %r{"posts": \[}, json
+ assert_match %r{"name":"David"}, json
+ assert_match %r{"posts":\[}, json
- assert_match %r{"comments": \[}, json
- assert_match %r{\{"body": "Thank you again for the welcome"\}}, json
- assert_match %r{\{"body": "Don't think too hard"\}}, json
- assert_no_match %r{"post_id": }, json
+ assert_match %r{"comments":\[}, json
+ assert_match %r{\{"body":"Thank you again for the welcome"\}}, json
+ assert_match %r{\{"body":"Don't think too hard"\}}, json
+ assert_no_match %r{"post_id":}, json
end
def test_includes_fetches_nth_level_associations
@@ -151,11 +151,11 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
}
})
- assert_match %r{"name": "David"}, json
- assert_match %r{"posts": \[}, json
+ assert_match %r{"name":"David"}, json
+ assert_match %r{"posts":\[}, json
- assert_match %r{"taggings": \[}, json
- assert_match %r{"tag": \{"name": "General"\}}, json
+ assert_match %r{"taggings":\[}, json
+ assert_match %r{"tag":\{"name":"General"\}}, json
end
def test_should_not_call_methods_on_associations_that_dont_respond
@@ -163,20 +163,20 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
json = @david.to_json(:include => :posts, :methods => :favorite_quote)
assert !@david.posts.first.respond_to?(:favorite_quote)
- assert_match %r{"favorite_quote": "Constraints are liberating"}, json
- assert_equal %r{"favorite_quote": }.match(json).size, 1
+ assert_match %r{"favorite_quote":"Constraints are liberating"}, json
+ assert_equal %r{"favorite_quote":}.match(json).size, 1
end
def test_should_allow_only_option_for_list_of_authors
authors = [@david, @mary]
- assert_equal %([{"name": "David"}, {"name": "Mary"}]), authors.to_json(:only => :name)
+ assert_equal %([{"name":"David"},{"name":"Mary"}]), authors.to_json(:only => :name)
end
def test_should_allow_except_option_for_list_of_authors
authors = [@david, @mary]
- assert_equal %([{"id": 1}, {"id": 2}]), authors.to_json(:except => [:name, :author_address_id, :author_address_extra_id])
+ assert_equal %([{"id":1},{"id":2}]), authors.to_json(:except => [:name, :author_address_id, :author_address_extra_id])
end
def test_should_allow_includes_for_list_of_authors
@@ -188,8 +188,8 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
}
)
- ['"name": "David"', '"posts": [', '{"id": 1}', '{"id": 2}', '{"id": 4}',
- '{"id": 5}', '{"id": 6}', '"name": "Mary"', '"posts": [{"id": 7}]'].each do |fragment|
+ ['"name":"David"', '"posts":[', '{"id":1}', '{"id":2}', '{"id":4}',
+ '{"id":5}', '{"id":6}', '"name":"Mary"', '"posts":[{"id":7}]'].each do |fragment|
assert json.include?(fragment), json
end
end
@@ -200,6 +200,6 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
2 => @mary
}
- assert_equal %({"1": {"name": "David"}}), authors_hash.to_json(:only => [1, :name])
+ assert_equal %({"1":{"name":"David"}}), authors_hash.to_json(:only => [1, :name])
end
end
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index 6cb5beb789..2e742267ba 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -887,9 +887,12 @@ module ActiveResource
# person.to_json(:except => ["first_name"])
# # => {"last_name": "Smith"}
def to_json(options={})
- attributes.to_json(options)
+ 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.
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index cd7b47d780..ca5ab13a46 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,20 @@
*Edge*
+* Add ActiveSupport.parse_json_times to disable time parsing in JSON backends that don't support it or don't need it. [rick]
+
+* Add pluggable JSON backends with support for the JSON gem. [rick]
+ Example: ActiveSupport::JSON.backend = "JSONGem"
+
+ All internal Rails JSON encoding is now handled by ActiveSupport::JSON.encode(). Use of #to_json is not recommended, as it may clash with other libraries that overwrite it. However, you can recover Rails specific functionality
+ if you really want to use #to_json.
+
+ gem 'json'
+ ActiveSupport::JSON.backend = "JSONGem"
+
+ class ActiveRecord::Base
+ alias to_json rails_to_json
+ end
+
* require 'active_support' no longer orders the whole menu of core extensions. Ask for just what you need: e.g. require 'active_support/core/time' to use timezones, durations, and stdlib date/time extensions. [Jeremy Kemper]
* Removed rarely-used DRb cache store. [Jeremy Kemper]
diff --git a/activesupport/lib/active_support/json.rb b/activesupport/lib/active_support/json.rb
index 91f19f8a70..fc433de582 100644
--- a/activesupport/lib/active_support/json.rb
+++ b/activesupport/lib/active_support/json.rb
@@ -1,8 +1,37 @@
+require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/module/attribute_accessors'
module ActiveSupport
# If true, use ISO 8601 format for dates and times. Otherwise, fall back to the Active Support legacy format.
mattr_accessor :use_standard_json_time_format
+ # Look for and parse json strings that look like ISO 8601 times.
+ mattr_accessor :parse_json_times
+
+ module JSON
+ # 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})?))$/
+
+ class << self
+ attr_reader :backend
+ delegate :decode, :to => :backend
+
+ def backend=(name)
+ if name.is_a?(Module)
+ @backend = name
+ else
+ require "active_support/json/backends/#{name.to_s.downcase}.rb"
+ @backend = ActiveSupport::JSON::Backends::const_get(name)
+ end
+ end
+
+ def with_backend(name)
+ old_backend, self.backend = backend, name
+ yield
+ ensure
+ self.backend = old_backend
+ end
+ end
+ end
class << self
def escape_html_entities_in_json
@@ -19,7 +48,8 @@ module ActiveSupport
@escape_html_entities_in_json = value
end
end
+
+ JSON.backend = 'Yaml'
end
-require 'active_support/json/encoding'
-require 'active_support/json/decoding'
+require 'active_support/json/encoding'
\ No newline at end of file
diff --git a/activesupport/lib/active_support/json/backends/jsongem.rb b/activesupport/lib/active_support/json/backends/jsongem.rb
new file mode 100644
index 0000000000..de847e30a3
--- /dev/null
+++ b/activesupport/lib/active_support/json/backends/jsongem.rb
@@ -0,0 +1,36 @@
+module ActiveSupport
+ module JSON
+ ParseError = ::JSON::ParserError
+
+ module Backends
+ module JSONGem
+ extend self
+
+ # Converts a JSON string into a Ruby object.
+ def decode(json)
+ data = ::JSON.parse(json)
+ if ActiveSupport.parse_json_times
+ convert_dates_from(data)
+ else
+ data
+ end
+ end
+
+ private
+ def convert_dates_from(data)
+ case data
+ when DATE_REGEX
+ DateTime.parse(data)
+ when Array
+ data.map! { |d| convert_dates_from(d) }
+ when Hash
+ data.each do |key, value|
+ data[key] = convert_dates_from(value)
+ end
+ else data
+ end
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/activesupport/lib/active_support/json/backends/yaml.rb b/activesupport/lib/active_support/json/backends/yaml.rb
new file mode 100644
index 0000000000..c7db508c23
--- /dev/null
+++ b/activesupport/lib/active_support/json/backends/yaml.rb
@@ -0,0 +1,83 @@
+require 'active_support/core_ext/string/starts_ends_with'
+
+module ActiveSupport
+ module JSON
+ class ParseError < StandardError
+ end
+
+ module Backends
+ module Yaml
+ extend self
+
+ # Converts a JSON string into a Ruby object.
+ def decode(json)
+ YAML.load(convert_json_to_yaml(json))
+ rescue ArgumentError => e
+ raise ParseError, "Invalid JSON string"
+ end
+
+ protected
+ # Ensure that ":" and "," are always followed by a space
+ def convert_json_to_yaml(json) #:nodoc:
+ require 'strscan' unless defined? ::StringScanner
+ scanner, quoting, marks, pos, times = ::StringScanner.new(json), false, [], nil, []
+ while scanner.scan_until(/(\\['"]|['":,\\]|\\.)/)
+ case char = scanner[1]
+ when '"', "'"
+ if !quoting
+ quoting = char
+ pos = scanner.pos
+ elsif quoting == char
+ if json[pos..scanner.pos-2] =~ DATE_REGEX
+ # found a date, track the exact positions of the quotes so we can remove them later.
+ # oh, and increment them for each current mark, each one is an extra padded space that bumps
+ # the position in the final YAML output
+ total_marks = marks.size
+ times << pos+total_marks << scanner.pos+total_marks
+ end
+ quoting = false
+ end
+ when ":",","
+ marks << scanner.pos - 1 unless quoting
+ end
+ end
+
+ if marks.empty?
+ json.gsub(/\\([\\\/]|u[[:xdigit:]]{4})/) do
+ ustr = $1
+ if ustr.start_with?('u')
+ [ustr[1..-1].to_i(16)].pack("U")
+ elsif ustr == '\\'
+ '\\\\'
+ else
+ ustr
+ end
+ end
+ else
+ left_pos = [-1].push(*marks)
+ right_pos = marks << scanner.pos + scanner.rest_size
+ output = []
+ left_pos.each_with_index do |left, i|
+ scanner.pos = left.succ
+ output << scanner.peek(right_pos[i] - scanner.pos + 1).gsub(/\\([\\\/]|u[[:xdigit:]]{4})/) do
+ ustr = $1
+ if ustr.start_with?('u')
+ [ustr[1..-1].to_i(16)].pack("U")
+ elsif ustr == '\\'
+ '\\\\'
+ else
+ ustr
+ end
+ end
+ end
+ output = output * " "
+
+ times.each { |i| output[i-1] = ' ' }
+ output.gsub!(/\\\//, '/')
+ output
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb
deleted file mode 100644
index 70e9f40fc7..0000000000
--- a/activesupport/lib/active_support/json/decoding.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-require 'active_support/core_ext/string/starts_ends_with'
-
-module ActiveSupport
- module JSON
- class ParseError < StandardError
- end
-
- class << self
- # Converts a JSON string into a Ruby object.
- def decode(json)
- YAML.load(convert_json_to_yaml(json))
- rescue ArgumentError => e
- raise ParseError, "Invalid JSON string"
- end
-
- protected
- # 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})?)?)$/
-
- # Ensure that ":" and "," are always followed by a space
- def convert_json_to_yaml(json) #:nodoc:
- require 'strscan' unless defined? ::StringScanner
- scanner, quoting, marks, pos, times = ::StringScanner.new(json), false, [], nil, []
- while scanner.scan_until(/(\\['"]|['":,\\]|\\.)/)
- case char = scanner[1]
- when '"', "'"
- if !quoting
- quoting = char
- pos = scanner.pos
- elsif quoting == char
- if json[pos..scanner.pos-2] =~ DATE_REGEX
- # found a date, track the exact positions of the quotes so we can remove them later.
- # oh, and increment them for each current mark, each one is an extra padded space that bumps
- # the position in the final YAML output
- total_marks = marks.size
- times << pos+total_marks << scanner.pos+total_marks
- end
- quoting = false
- end
- when ":",","
- marks << scanner.pos - 1 unless quoting
- end
- end
-
- if marks.empty?
- json.gsub(/\\([\\\/]|u[[:xdigit:]]{4})/) do
- ustr = $1
- if ustr.start_with?('u')
- [ustr[1..-1].to_i(16)].pack("U")
- elsif ustr == '\\'
- '\\\\'
- else
- ustr
- end
- end
- else
- left_pos = [-1].push(*marks)
- right_pos = marks << scanner.pos + scanner.rest_size
- output = []
- left_pos.each_with_index do |left, i|
- scanner.pos = left.succ
- output << scanner.peek(right_pos[i] - scanner.pos + 1).gsub(/\\([\\\/]|u[[:xdigit:]]{4})/) do
- ustr = $1
- if ustr.start_with?('u')
- [ustr[1..-1].to_i(16)].pack("U")
- elsif ustr == '\\'
- '\\\\'
- else
- ustr
- end
- end
- end
- output = output * " "
-
- times.each { |i| output[i-1] = ' ' }
- output.gsub!(/\\\//, '/')
- output
- end
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/date.rb b/activesupport/lib/active_support/json/encoders/date.rb
index cc84de1388..79c3957362 100644
--- a/activesupport/lib/active_support/json/encoders/date.rb
+++ b/activesupport/lib/active_support/json/encoders/date.rb
@@ -11,11 +11,13 @@ class Date
# # With ActiveSupport.use_standard_json_time_format = false
# Date.new(2005,2,1).to_json
# # => "2005/02/01"
- def to_json(options = nil)
+ def rails_to_json(options = nil)
if ActiveSupport.use_standard_json_time_format
%("#{strftime("%Y-%m-%d")}")
else
%("#{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 6c85824105..cdfc39b9f3 100644
--- a/activesupport/lib/active_support/json/encoders/date_time.rb
+++ b/activesupport/lib/active_support/json/encoders/date_time.rb
@@ -11,11 +11,13 @@ 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 to_json(options = nil)
+ 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
+
+ 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 881b1d62c1..e1c3ec249d 100644
--- a/activesupport/lib/active_support/json/encoders/enumerable.rb
+++ b/activesupport/lib/active_support/json/encoders/enumerable.rb
@@ -6,7 +6,9 @@ module Enumerable
# # => users.to_json(:only => :name)
#
# will pass the :only => :name option to each user.
- def to_json(options = {}) #:nodoc:
- "[#{map { |value| ActiveSupport::JSON.encode(value, options) } * ', '}]"
+ def rails_to_json(options = {}) #: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 bf0844334b..a7657cca37 100644
--- a/activesupport/lib/active_support/json/encoders/false_class.rb
+++ b/activesupport/lib/active_support/json/encoders/false_class.rb
@@ -1,5 +1,7 @@
class FalseClass
- def to_json(options = nil) #:nodoc:
+ 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 d87b880743..19b97d7b8c 100644
--- a/activesupport/lib/active_support/json/encoders/hash.rb
+++ b/activesupport/lib/active_support/json/encoders/hash.rb
@@ -30,7 +30,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 to_json(options = {}) #:nodoc:
+ def rails_to_json(options = {}) #:nodoc:
hash_keys = self.keys
if except = options[:except]
@@ -41,8 +41,10 @@ class Hash
result = '{'
result << hash_keys.map do |key|
- "#{ActiveSupport::JSON.encode(key.to_s)}: #{ActiveSupport::JSON.encode(self[key], options)}"
- end * ', '
+ "#{ActiveSupport::JSON.encode(key.to_s)}:#{ActiveSupport::JSON.encode(self[key], options)}"
+ 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 4763471ac4..b31e1dd249 100644
--- a/activesupport/lib/active_support/json/encoders/nil_class.rb
+++ b/activesupport/lib/active_support/json/encoders/nil_class.rb
@@ -1,5 +1,7 @@
class NilClass
- def to_json(options = nil) #:nodoc:
+ 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 38713fb369..491b330c39 100644
--- a/activesupport/lib/active_support/json/encoders/numeric.rb
+++ b/activesupport/lib/active_support/json/encoders/numeric.rb
@@ -1,5 +1,7 @@
class Numeric
- def to_json(options = nil) #:nodoc:
+ 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 0475967aee..d68f50562e 100644
--- a/activesupport/lib/active_support/json/encoders/object.rb
+++ b/activesupport/lib/active_support/json/encoders/object.rb
@@ -2,7 +2,9 @@ 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 = {})
+ def rails_to_json(options = {})
ActiveSupport::JSON.encode(instance_values, options)
end
+
+ alias to_json rails_to_json
end
diff --git a/activesupport/lib/active_support/json/encoders/regexp.rb b/activesupport/lib/active_support/json/encoders/regexp.rb
index b6116b70b5..63ccd7c490 100644
--- a/activesupport/lib/active_support/json/encoders/regexp.rb
+++ b/activesupport/lib/active_support/json/encoders/regexp.rb
@@ -1,5 +1,7 @@
class Regexp
- def to_json(options = nil) #:nodoc:
+ 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 5ef797955a..27bef3b9cc 100644
--- a/activesupport/lib/active_support/json/encoders/string.rb
+++ b/activesupport/lib/active_support/json/encoders/string.rb
@@ -22,7 +22,7 @@ end
ActiveSupport.escape_html_entities_in_json = true
class String
- def to_json(options = nil) #:nodoc:
+ def rails_to_json(options = nil) #:nodoc:
json = '"' + gsub(ActiveSupport::JSON::Encoding.escape_regex) { |s|
ActiveSupport::JSON::Encoding::ESCAPED_CHARS[s]
}
@@ -33,4 +33,6 @@ 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 485112f97c..6487bf8cb7 100644
--- a/activesupport/lib/active_support/json/encoders/symbol.rb
+++ b/activesupport/lib/active_support/json/encoders/symbol.rb
@@ -1,5 +1,7 @@
class Symbol
- def to_json(options = {}) #:nodoc:
+ def rails_to_json(options = {}) #: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 7d97c38d77..2699672949 100644
--- a/activesupport/lib/active_support/json/encoders/time.rb
+++ b/activesupport/lib/active_support/json/encoders/time.rb
@@ -13,11 +13,13 @@ 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 to_json(options = nil)
+ 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
+
+ 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 037d812b3f..ac7c7d1e87 100644
--- a/activesupport/lib/active_support/json/encoders/true_class.rb
+++ b/activesupport/lib/active_support/json/encoders/true_class.rb
@@ -1,5 +1,7 @@
class TrueClass
- def to_json(options = nil) #:nodoc:
+ 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 aaaa3cdfd2..42a217cedc 100644
--- a/activesupport/lib/active_support/json/encoding.rb
+++ b/activesupport/lib/active_support/json/encoding.rb
@@ -8,7 +8,7 @@ module ActiveSupport
seen = (options[:seen] ||= [])
raise CircularReferenceError, 'object references itself' if seen.include?(value)
seen << value
- value.send(:to_json, options)
+ value.send(:rails_to_json, options)
ensure
seen.pop
end
diff --git a/activesupport/lib/active_support/json/variable.rb b/activesupport/lib/active_support/json/variable.rb
index 7fd23b0a9e..3ee152ee3c 100644
--- a/activesupport/lib/active_support/json/variable.rb
+++ b/activesupport/lib/active_support/json/variable.rb
@@ -2,7 +2,7 @@ module ActiveSupport
module JSON
# A string that returns itself as its JSON-encoded form.
class Variable < String
- def to_json(options=nil)
+ def rails_to_json(options=nil)
self
end
end
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index 0d4c75d272..1949ce0ad3 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -130,7 +130,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 to_json(options = nil)
+ def rails_to_json(options = nil)
if !ActiveSupport.respond_to?(:use_standard_json_time_format) || ActiveSupport.use_standard_json_time_format
xmlschema.inspect
else
@@ -138,6 +138,8 @@ module ActiveSupport
end
end
+ alias to_json rails_to_json
+
def to_yaml(options = {})
if options.kind_of?(YAML::Emitter)
utc.to_yaml(options)
diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb
index 612a50c225..0380c28c17 100644
--- a/activesupport/test/core_ext/time_with_zone_test.rb
+++ b/activesupport/test/core_ext/time_with_zone_test.rb
@@ -57,12 +57,12 @@ class TimeWithZoneTest < Test::Unit::TestCase
end
def test_to_json
- assert_equal "\"1999/12/31 19:00:00 -0500\"", @twz.to_json
+ assert_equal "\"1999/12/31 19:00:00 -0500\"", ActiveSupport::JSON.encode(@twz)
end
def test_to_json_with_use_standard_json_time_format_config_set_to_true
old, ActiveSupport.use_standard_json_time_format = ActiveSupport.use_standard_json_time_format, true
- assert_equal "\"1999-12-31T19:00:00-05:00\"", @twz.to_json
+ assert_equal "\"1999-12-31T19:00:00-05:00\"", ActiveSupport::JSON.encode(@twz)
ensure
ActiveSupport.use_standard_json_time_format = old
end
diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb
index 9b4b207c88..7e1bfcca84 100644
--- a/activesupport/test/json/decoding_test.rb
+++ b/activesupport/test/json/decoding_test.rb
@@ -1,49 +1,75 @@
# encoding: UTF-8
require 'abstract_unit'
require 'active_support/json'
+require 'active_support/core_ext/kernel/reporting'
class TestJSONDecoding < ActiveSupport::TestCase
TESTS = {
%q({"returnTo":{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
- %q({returnTo:{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
%q({"return\\"To\\":":{"\/categories":"\/"}}) => {"return\"To\":" => {"/categories" => "/"}},
%q({"returnTo":{"\/categories":1}}) => {"returnTo" => {"/categories" => 1}},
%({"returnTo":[1,"a"]}) => {"returnTo" => [1, "a"]},
%({"returnTo":[1,"\\"a\\",", "b"]}) => {"returnTo" => [1, "\"a\",", "b"]},
- %({a: "'", "b": "5,000"}) => {"a" => "'", "b" => "5,000"},
- %({a: "a's, b's and c's", "b": "5,000"}) => {"a" => "a's, b's and c's", "b" => "5,000"},
+ %({"a": "'", "b": "5,000"}) => {"a" => "'", "b" => "5,000"},
+ %({"a": "a's, b's and c's", "b": "5,000"}) => {"a" => "a's, b's and c's", "b" => "5,000"},
# multibyte
%({"matzue": "松江", "asakusa": "浅草"}) => {"matzue" => "松江", "asakusa" => "浅草"},
- %({a: "2007-01-01"}) => {'a' => Date.new(2007, 1, 1)},
- %({a: "2007-01-01 01:12:34 Z"}) => {'a' => Time.utc(2007, 1, 1, 1, 12, 34)},
+ %({"a": "2007-01-01"}) => {'a' => Date.new(2007, 1, 1)},
+ %({"a": "2007-01-01 01:12:34 Z"}) => {'a' => Time.utc(2007, 1, 1, 1, 12, 34)},
# no time zone
- %({a: "2007-01-01 01:12:34"}) => {'a' => "2007-01-01 01:12:34"},
+ %({"a": "2007-01-01 01:12:34"}) => {'a' => "2007-01-01 01:12:34"},
# needs to be *exact*
- %({a: " 2007-01-01 01:12:34 Z "}) => {'a' => " 2007-01-01 01:12:34 Z "},
- %({a: "2007-01-01 : it's your birthday"}) => {'a' => "2007-01-01 : it's your birthday"},
+ %({"a": " 2007-01-01 01:12:34 Z "}) => {'a' => " 2007-01-01 01:12:34 Z "},
+ %({"a": "2007-01-01 : it's your birthday"}) => {'a' => "2007-01-01 : it's your birthday"},
%([]) => [],
%({}) => {},
- %(1) => 1,
- %("") => "",
- %("\\"") => "\"",
- %(null) => nil,
- %(true) => true,
- %(false) => false,
- %q("http:\/\/test.host\/posts\/1") => "http://test.host/posts/1",
- %q("\u003cunicode\u0020escape\u003e") => "",
- %q("\\\\u0020skip double backslashes") => "\\u0020skip double backslashes",
- %q({a: "\u003cbr /\u003e"}) => {'a' => " "},
- %q({b:["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => {'b' => ["","",""]}
+ %({"a":1}) => {"a" => 1},
+ %({"a": ""}) => {"a" => ""},
+ %({"a":"\\""}) => {"a" => "\""},
+ %({"a": null}) => {"a" => nil},
+ %({"a": true}) => {"a" => true},
+ %({"a": false}) => {"a" => false},
+ %q({"a": "http:\/\/test.host\/posts\/1"}) => {"a" => "http://test.host/posts/1"},
+ %q({"a": "\u003cunicode\u0020escape\u003e"}) => {"a" => ""},
+ %q({"a": "\\\\u0020skip double backslashes"}) => {"a" => "\\u0020skip double backslashes"},
+ %q({"a": "\u003cbr /\u003e"}) => {'a' => " "},
+ %q({"b":["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => {'b' => ["","",""]}
}
-
- TESTS.each do |json, expected|
- test "json decodes #{json}" do
- assert_nothing_raised do
- assert_equal expected, ActiveSupport::JSON.decode(json)
+
+ backends = %w(Yaml)
+ begin
+ gem 'json', '>= 1.1'
+ require 'json'
+ backends << "JSONGem"
+ rescue Gem::LoadError
+ # Skip JSON gem tests
+ end
+
+ backends.each do |backend|
+ TESTS.each do |json, expected|
+ test "json decodes #{json} with the #{backend} backend" do
+ ActiveSupport.parse_json_times = true
+ silence_warnings do
+ ActiveSupport::JSON.with_backend backend do
+ assert_nothing_raised do
+ assert_equal expected, ActiveSupport::JSON.decode(json)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ if backends.include?("JSONGem")
+ test "json decodes time json with time parsing disabled" do
+ ActiveSupport.parse_json_times = false
+ expected = {"a" => "2007-01-01 01:12:34 Z"}
+ ActiveSupport::JSON.with_backend "JSONGem" do
+ assert_equal expected, ActiveSupport::JSON.decode(%({"a": "2007-01-01 01:12:34 Z"}))
end
end
end
-
+
def test_failed_json_decoding
assert_raise(ActiveSupport::JSON::ParseError) { ActiveSupport::JSON.decode(%({: 1})) }
end
diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb
index 9e6b4fa501..db24b3d96a 100644
--- a/activesupport/test/json/encoding_test.rb
+++ b/activesupport/test/json/encoding_test.rb
@@ -19,14 +19,14 @@ class TestJSONEncoding < Test::Unit::TestCase
[ 'a "string" with quotes & an ampersand', %("a \\"string\\" with quotes \\u0026 an ampersand") ],
[ 'http://test.host/posts/1', %("http://test.host/posts/1")]]
- ArrayTests = [[ ['a', 'b', 'c'], %([\"a\", \"b\", \"c\"]) ],
- [ [1, 'a', :b, nil, false], %([1, \"a\", \"b\", null, false]) ]]
+ ArrayTests = [[ ['a', 'b', 'c'], %([\"a\",\"b\",\"c\"]) ],
+ [ [1, 'a', :b, nil, false], %([1,\"a\",\"b\",null,false]) ]]
SymbolTests = [[ :a, %("a") ],
[ :this, %("this") ],
[ :"a b", %("a b") ]]
- ObjectTests = [[ Foo.new(1, 2), %({\"a\": 1, \"b\": 2}) ]]
+ ObjectTests = [[ Foo.new(1, 2), %({\"a\":1,\"b\":2}) ]]
VariableTests = [[ ActiveSupport::JSON::Variable.new('foo'), 'foo'],
[ ActiveSupport::JSON::Variable.new('alert("foo")'), 'alert("foo")']]
@@ -47,7 +47,7 @@ class TestJSONEncoding < Test::Unit::TestCase
ActiveSupport.escape_html_entities_in_json = class_tests !~ /^Standard/
ActiveSupport.use_standard_json_time_format = class_tests =~ /^Standard/
self.class.const_get(class_tests).each do |pair|
- assert_equal pair.last, pair.first.to_json
+ assert_equal pair.last, ActiveSupport::JSON.encode(pair.first)
end
ensure
ActiveSupport.escape_html_entities_in_json = false
@@ -57,45 +57,45 @@ class TestJSONEncoding < Test::Unit::TestCase
end
def test_hash_encoding
- assert_equal %({\"a\": \"b\"}), { :a => :b }.to_json
- assert_equal %({\"a\": 1}), { 'a' => 1 }.to_json
- assert_equal %({\"a\": [1, 2]}), { 'a' => [1,2] }.to_json
- assert_equal %({"1": 2}), { 1 => 2 }.to_json
+ assert_equal %({\"a\":\"b\"}), ActiveSupport::JSON.encode(:a => :b)
+ assert_equal %({\"a\":1}), ActiveSupport::JSON.encode('a' => 1)
+ assert_equal %({\"a\":[1,2]}), ActiveSupport::JSON.encode('a' => [1,2])
+ assert_equal %({"1":2}), ActiveSupport::JSON.encode(1 => 2)
- sorted_json = '{' + {:a => :b, :c => :d}.to_json[1..-2].split(', ').sort.join(', ') + '}'
- assert_equal %({\"a\": \"b\", \"c\": \"d\"}), sorted_json
+ sorted_json = '{' + ActiveSupport::JSON.encode(:a => :b, :c => :d)[1..-2].split(',').sort.join(',') + '}'
+ assert_equal %({\"a\":\"b\",\"c\":\"d\"}), sorted_json
end
def test_utf8_string_encoded_properly_when_kcode_is_utf8
with_kcode 'UTF8' do
- assert_equal '"\\u20ac2.99"', '€2.99'.to_json
- assert_equal '"\\u270e\\u263a"', '✎☺'.to_json
+ assert_equal '"\\u20ac2.99"', ActiveSupport::JSON.encode('€2.99')
+ assert_equal '"\\u270e\\u263a"', ActiveSupport::JSON.encode('✎☺')
end
end
def test_exception_raised_when_encoding_circular_reference
a = [1]
a << a
- assert_raise(ActiveSupport::JSON::CircularReferenceError) { a.to_json }
+ assert_raise(ActiveSupport::JSON::CircularReferenceError) { ActiveSupport::JSON.encode(a) }
end
def test_hash_key_identifiers_are_always_quoted
values = {0 => 0, 1 => 1, :_ => :_, "$" => "$", "a" => "a", :A => :A, :A0 => :A0, "A0B" => "A0B"}
- assert_equal %w( "$" "A" "A0" "A0B" "_" "a" "0" "1" ).sort, object_keys(values.to_json)
+ assert_equal %w( "$" "A" "A0" "A0B" "_" "a" "0" "1" ).sort, object_keys(ActiveSupport::JSON.encode(values))
end
def test_hash_should_allow_key_filtering_with_only
- assert_equal %({"a": 1}), { 'a' => 1, :b => 2, :c => 3 }.to_json(:only => 'a')
+ assert_equal %({"a":1}), ActiveSupport::JSON.encode({'a' => 1, :b => 2, :c => 3}, :only => 'a')
end
def test_hash_should_allow_key_filtering_with_except
- assert_equal %({"b": 2}), { 'foo' => 'bar', :b => 2, :c => 3 }.to_json(:except => ['foo', :c])
+ assert_equal %({"b":2}), ActiveSupport::JSON.encode({'foo' => 'bar', :b => 2, :c => 3}, :except => ['foo', :c])
end
def test_time_to_json_includes_local_offset
ActiveSupport.use_standard_json_time_format = true
with_env_tz 'US/Eastern' do
- assert_equal %("2005-02-01T15:15:10-05:00"), Time.local(2005,2,1,15,15,10).to_json
+ assert_equal %("2005-02-01T15:15:10-05:00"), ActiveSupport::JSON.encode(Time.local(2005,2,1,15,15,10))
end
ensure
ActiveSupport.use_standard_json_time_format = false
@@ -109,7 +109,7 @@ class TestJSONEncoding < Test::Unit::TestCase
:latitude => 123.234
}
}
- result = hash.to_json
+ result = ActiveSupport::JSON.encode(hash)
end
end
@@ -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'].to_json(json_options)
+ [1, 2, 'foo'].rails_to_json(json_options)
end
end
--
cgit v1.2.3
From a841cd2503e26d4af908b2ff49592973eabcac46 Mon Sep 17 00:00:00 2001
From: Emilio Tagua
Date: Thu, 23 Apr 2009 10:26:52 -0300
Subject: Fix models load order to be able to run unit tests.
[#2550 state:committed]
Signed-off-by: Jeremy Kemper
---
.../test/cases/associations/eager_load_nested_include_test.rb | 10 +++++-----
activerecord/test/cases/base_test.rb | 6 +++---
activerecord/test/cases/finder_test.rb | 8 ++++----
activerecord/test/cases/method_scoping_test.rb | 2 +-
4 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/activerecord/test/cases/associations/eager_load_nested_include_test.rb b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
index 1b2e0fc11e..677226ec89 100644
--- a/activerecord/test/cases/associations/eager_load_nested_include_test.rb
+++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
@@ -1,6 +1,6 @@
require 'cases/helper'
-require 'models/author'
require 'models/post'
+require 'models/author'
require 'models/comment'
require 'models/category'
require 'models/categorization'
@@ -66,13 +66,13 @@ class EagerLoadPolyAssocsTest < ActiveRecord::TestCase
def setup
generate_test_object_graphs
end
-
+
def teardown
- [Circle, Square, Triangle, PaintColor, PaintTexture,
+ [Circle, Square, Triangle, PaintColor, PaintTexture,
ShapeExpression, NonPolyOne, NonPolyTwo].each do |c|
c.delete_all
end
-
+
end
@@ -127,4 +127,4 @@ class EagerLoadNestedIncludeWithMissingDataTest < ActiveRecord::TestCase
Author.all :include => includes, :conditions => {:authors => {:name => @davey_mcdave.name}}, :order => 'categories.name'
end
end
-end
\ No newline at end of file
+end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index d97cd17d75..7ca2807f7e 100755
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -1,4 +1,5 @@
require "cases/helper"
+require 'models/post'
require 'models/author'
require 'models/topic'
require 'models/reply'
@@ -12,7 +13,6 @@ require 'models/auto_id'
require 'models/column_name'
require 'models/subscriber'
require 'models/keyboard'
-require 'models/post'
require 'models/comment'
require 'models/minimalistic'
require 'models/warehouse_thing'
@@ -1115,7 +1115,7 @@ class BasicsTest < ActiveRecord::TestCase
Time.zone = nil
Topic.skip_time_zone_conversion_for_attributes = []
end
-
+
def test_multiparameter_attributes_on_time_only_column_with_time_zone_aware_attributes_does_not_do_time_zone_conversion
ActiveRecord::Base.time_zone_aware_attributes = true
ActiveRecord::Base.default_timezone = :utc
@@ -1439,7 +1439,7 @@ class BasicsTest < ActiveRecord::TestCase
topic = Topic.create("content" => myobj).reload
assert_equal(myobj, topic.content)
end
-
+
def test_serialized_string_attribute
myobj = "Yes"
topic = Topic.create("content" => myobj).reload
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index d8778957c0..28eb311618 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -1,4 +1,5 @@
require "cases/helper"
+require 'models/post'
require 'models/author'
require 'models/categorization'
require 'models/comment'
@@ -7,7 +8,6 @@ require 'models/topic'
require 'models/reply'
require 'models/entrant'
require 'models/developer'
-require 'models/post'
require 'models/customer'
require 'models/job'
require 'models/categorization'
@@ -94,16 +94,16 @@ class FinderTest < ActiveRecord::TestCase
assert_raise(NoMethodError) { Topic.exists?([1,2]) }
end
-
+
def test_exists_returns_true_with_one_record_and_no_args
assert Topic.exists?
end
-
+
def test_does_not_exist_with_empty_table_and_no_args_given
Topic.delete_all
assert !Topic.exists?
end
-
+
def test_exists_with_aggregate_having_three_mappings
existing_address = customers(:david).address
assert Customer.exists?(:address => existing_address)
diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb
index 3c34cdeade..2165d2f7e8 100644
--- a/activerecord/test/cases/method_scoping_test.rb
+++ b/activerecord/test/cases/method_scoping_test.rb
@@ -1,9 +1,9 @@
require "cases/helper"
+require 'models/post'
require 'models/author'
require 'models/developer'
require 'models/project'
require 'models/comment'
-require 'models/post'
require 'models/category'
class MethodScopingTest < ActiveRecord::TestCase
--
cgit v1.2.3
From cbcc0ca57b0ea713d7d32364b599d88f2bef6d92 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Fri, 24 Apr 2009 10:41:45 -0700
Subject: Use Symbol#to_proc in rails plugin internals
---
railties/lib/rails/plugin.rb | 1 +
1 file changed, 1 insertion(+)
diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb
index dd840ef058..63864058ee 100644
--- a/railties/lib/rails/plugin.rb
+++ b/railties/lib/rails/plugin.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/kernel/reporting'
+require 'active_support/core_ext/symbol'
require 'active_support/dependencies'
module Rails
--
cgit v1.2.3
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 autoload ed 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
-
-
-
- Name
- Size
- Type
- Last Modified
-
-%s
-
-
-
- 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| %>
- <%=h line %>
- <% } %>
-
- <% end %>
-
-
- <%=h frame.context_line %>...
-
- <% if frame.post_context %>
-
- <% frame.post_context.each { |line| %>
- <%=h line %>
- <% } %>
-
- <% end %>
-
- <% end %>
-
-<% } %>
-
-
-
-
-
Request information
-
-
GET
- <% unless req.GET.empty? %>
-
-
-
- Variable
- Value
-
-
-
- <% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %>
-
- <%=h key %>
- <%=h val.inspect %>
-
- <% } %>
-
-
- <% else %>
-
No GET data.
- <% end %>
-
-
POST
- <% unless req.POST.empty? %>
-
-
-
- Variable
- Value
-
-
-
- <% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %>
-
- <%=h key %>
- <%=h val.inspect %>
-
- <% } %>
-
-
- <% else %>
-
No POST data.
- <% end %>
-
-
-
COOKIES
- <% unless req.cookies.empty? %>
-
-
-
- Variable
- Value
-
-
-
- <% req.cookies.each { |key, val| %>
-
- <%=h key %>
- <%=h val.inspect %>
-
- <% } %>
-
-
- <% else %>
-
No cookie data.
- <% end %>
-
-
Rack ENV
-
-
-
- Variable
- Value
-
-
-
- <% env.sort_by { |k, v| k.to_s }.each { |key, val| %>
-
- <%=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 %>)
-
-
-
-
-
-
- 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 38bd60eae4b6d0ec6a29036c6a8d45b79b788af9 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Mon, 27 Apr 2009 18:16:55 -0700
Subject: Makes new callbacks support keys with special characters
---
activesupport/lib/active_support/new_callbacks.rb | 1 +
activesupport/test/new_callbacks_test.rb | 28 +++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb
index 7a48dbac04..8a91e1c674 100644
--- a/activesupport/lib/active_support/new_callbacks.rb
+++ b/activesupport/lib/active_support/new_callbacks.rb
@@ -356,6 +356,7 @@ module ActiveSupport
str = <<-RUBY_EVAL
def _run_#{symbol}_callbacks(key = nil)
if key
+ key = key.hash.to_s.gsub(/-/, '_')
name = "_run__\#{self.class.name.split("::").last}__#{symbol}__\#{key}__callbacks"
if respond_to?(name)
diff --git a/activesupport/test/new_callbacks_test.rb b/activesupport/test/new_callbacks_test.rb
index abe7790ebf..8c887e1bf1 100644
--- a/activesupport/test/new_callbacks_test.rb
+++ b/activesupport/test/new_callbacks_test.rb
@@ -255,6 +255,26 @@ module NewCallbacksTest
end
end
+ class HyphenatedCallbacks
+ include ActiveSupport::NewCallbacks
+ define_callbacks :save
+ attr_reader :stuff
+
+ save_callback :before, :omg, :per_key => {:if => :yes}
+
+ def yes() true end
+
+ def omg
+ @stuff = "OMG"
+ end
+
+ def save
+ _run_save_callbacks("hyphen-ated") do
+ @stuff
+ end
+ end
+ end
+
class AroundCallbacksTest < Test::Unit::TestCase
def test_save_around
around = AroundPerson.new
@@ -381,4 +401,12 @@ module NewCallbacksTest
assert_equal ["first", "second", "third", "second", "first"], terminator.history
end
end
+
+ class HyphenatedKeyTest < Test::Unit::TestCase
+ def test_save
+ obj = HyphenatedCallbacks.new
+ obj.save
+ assert_equal obj.stuff, "OMG"
+ end
+ end
end
--
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
From 091965c0fc7384c17cce9e71a80f515b1139d460 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 29 Apr 2009 23:12:34 -0700
Subject: Prefer behavior check to RUBY_VERSION to catch 1.8 backports
---
activesupport/lib/active_support/core_ext/integer/even_odd.rb | 4 ++--
activesupport/lib/active_support/core_ext/string/conversions.rb | 2 +-
activesupport/lib/active_support/core_ext/time/conversions.rb | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/activesupport/lib/active_support/core_ext/integer/even_odd.rb b/activesupport/lib/active_support/core_ext/integer/even_odd.rb
index 6d005268a3..8f9a97b44c 100644
--- a/activesupport/lib/active_support/core_ext/integer/even_odd.rb
+++ b/activesupport/lib/active_support/core_ext/integer/even_odd.rb
@@ -7,10 +7,10 @@ class Integer
# Is the integer a multiple of 2?
def even?
multiple_of? 2
- end if RUBY_VERSION < '1.9'
+ end unless method_defined?(:even?)
# Is the integer not a multiple of 2?
def odd?
!even?
- end if RUBY_VERSION < '1.9'
+ end unless method_defined?(:odd?)
end
diff --git a/activesupport/lib/active_support/core_ext/string/conversions.rb b/activesupport/lib/active_support/core_ext/string/conversions.rb
index 3f05db62c3..2b9f8c70f6 100644
--- a/activesupport/lib/active_support/core_ext/string/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/string/conversions.rb
@@ -5,7 +5,7 @@ class String
# 'a'.ord == 'a'[0] for Ruby 1.9 forward compatibility.
def ord
self[0]
- end if RUBY_VERSION < '1.9'
+ end unless method_defined?(:ord)
# Form can be either :utc (default) or :local.
def to_time(form = :utc)
diff --git a/activesupport/lib/active_support/core_ext/time/conversions.rb b/activesupport/lib/active_support/core_ext/time/conversions.rb
index 18261e139f..94e01597a9 100644
--- a/activesupport/lib/active_support/core_ext/time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/time/conversions.rb
@@ -63,7 +63,7 @@ class Time
# your_time.to_date # => Tue, 13 Jan 2009
def to_date
::Date.new(year, month, day)
- end
+ end unless method_defined?(:to_date)
# A method to keep Time, Date and DateTime instances interchangeable on conversions.
# In this case, it simply returns +self+.
@@ -80,5 +80,5 @@ class Time
# your_time.to_datetime # => Tue, 13 Jan 2009 13:13:03 -0500
def to_datetime
::DateTime.civil(year, month, day, hour, min, sec, Rational(utc_offset, 86400))
- end
+ end unless method_defined?(:to_datetime)
end
--
cgit v1.2.3
From 7eef11eb657e6efb54dfe782ca2531df93654f83 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 29 Apr 2009 23:29:11 -0700
Subject: Convert params keys to strings
---
actionpack/lib/action_dispatch/test/mock.rb | 1 +
1 file changed, 1 insertion(+)
diff --git a/actionpack/lib/action_dispatch/test/mock.rb b/actionpack/lib/action_dispatch/test/mock.rb
index 4042f9fbc8..68e5b108b4 100644
--- a/actionpack/lib/action_dispatch/test/mock.rb
+++ b/actionpack/lib/action_dispatch/test/mock.rb
@@ -42,6 +42,7 @@ module ActionDispatch
opts[:input] = params
end
else
+ params.stringify_keys!
params.update(::Rack::Utils.parse_query(uri.query))
uri.query = requestify(params)
end
--
cgit v1.2.3
From 79420e71e0e75d6f81e5284184bac4e7d0b02c30 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 30 Apr 2009 01:33:07 -0700
Subject: Work around Float faux precision
---
activesupport/test/core_ext/duration_test.rb | 20 ++++++++++----------
activesupport/test/core_ext/time_ext_test.rb | 8 ++++----
activesupport/test/core_ext/time_with_zone_test.rb | 2 +-
3 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index ea6979bc6b..30d4152729 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -42,23 +42,23 @@ class DurationTest < ActiveSupport::TestCase
end
def test_since_and_ago_with_fractional_days
- Time.stubs(:now).returns Time.local(2000)
+ t = Time.local(2000)
# since
- assert_equal 36.hours.since, 1.5.days.since
- assert_equal((24 * 1.7).hours.since, 1.7.days.since)
+ assert_equal 36.hours.since(t), 1.5.days.since(t)
+ assert_in_delta((24 * 1.7).hours.since(t), 1.7.days.since(t), 1)
# ago
- assert_equal 36.hours.ago, 1.5.days.ago
- assert_equal((24 * 1.7).hours.ago, 1.7.days.ago)
+ assert_equal 36.hours.ago(t), 1.5.days.ago(t)
+ assert_in_delta((24 * 1.7).hours.ago(t), 1.7.days.ago(t), 1)
end
def test_since_and_ago_with_fractional_weeks
- Time.stubs(:now).returns Time.local(2000)
+ t = Time.local(2000)
# since
- assert_equal((7 * 36).hours.since, 1.5.weeks.since)
- assert_equal((7 * 24 * 1.7).hours.since, 1.7.weeks.since)
+ assert_equal((7 * 36).hours.since(t), 1.5.weeks.since(t))
+ assert_in_delta((7 * 24 * 1.7).hours.since(t), 1.7.weeks.since(t), 1)
# ago
- assert_equal((7 * 36).hours.ago, 1.5.weeks.ago)
- assert_equal((7 * 24 * 1.7).hours.ago, 1.7.weeks.ago)
+ assert_equal((7 * 36).hours.ago(t), 1.5.weeks.ago(t))
+ assert_in_delta((7 * 24 * 1.7).hours.ago(t), 1.7.weeks.ago(t), 1)
end
def test_since_and_ago_anchored_to_time_now_when_time_zone_default_not_set
diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb
index 3bf7b789ce..e265423f06 100644
--- a/activesupport/test/core_ext/time_ext_test.rb
+++ b/activesupport/test/core_ext/time_ext_test.rb
@@ -424,10 +424,10 @@ class TimeExtCalculationsTest < Test::Unit::TestCase
assert_equal Time.local(2005,6,28,15,15,10), Time.local(2005,2,28,15,15,10).advance(:months => 4)
assert_equal Time.local(2005,3,21,15,15,10), Time.local(2005,2,28,15,15,10).advance(:weeks => 3)
assert_equal Time.local(2005,3,25,3,15,10), Time.local(2005,2,28,15,15,10).advance(:weeks => 3.5)
- assert_equal Time.local(2005,3,26,12,51,10), Time.local(2005,2,28,15,15,10).advance(:weeks => 3.7)
+ assert_in_delta Time.local(2005,3,26,12,51,10), Time.local(2005,2,28,15,15,10).advance(:weeks => 3.7), 1
assert_equal Time.local(2005,3,5,15,15,10), Time.local(2005,2,28,15,15,10).advance(:days => 5)
assert_equal Time.local(2005,3,6,3,15,10), Time.local(2005,2,28,15,15,10).advance(:days => 5.5)
- assert_equal Time.local(2005,3,6,8,3,10), Time.local(2005,2,28,15,15,10).advance(:days => 5.7)
+ assert_in_delta Time.local(2005,3,6,8,3,10), Time.local(2005,2,28,15,15,10).advance(:days => 5.7), 1
assert_equal Time.local(2012,9,28,15,15,10), Time.local(2005,2,28,15,15,10).advance(:years => 7, :months => 7)
assert_equal Time.local(2013,10,3,15,15,10), Time.local(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :days => 5)
assert_equal Time.local(2013,10,17,15,15,10), Time.local(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :weeks => 2, :days => 5)
@@ -446,10 +446,10 @@ class TimeExtCalculationsTest < Test::Unit::TestCase
assert_equal Time.utc(2005,6,22,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:months => 4)
assert_equal Time.utc(2005,3,21,15,15,10), Time.utc(2005,2,28,15,15,10).advance(:weeks => 3)
assert_equal Time.utc(2005,3,25,3,15,10), Time.utc(2005,2,28,15,15,10).advance(:weeks => 3.5)
- assert_equal Time.utc(2005,3,26,12,51,10), Time.utc(2005,2,28,15,15,10).advance(:weeks => 3.7)
+ assert_in_delta Time.utc(2005,3,26,12,51,10), Time.utc(2005,2,28,15,15,10).advance(:weeks => 3.7), 1
assert_equal Time.utc(2005,3,5,15,15,10), Time.utc(2005,2,28,15,15,10).advance(:days => 5)
assert_equal Time.utc(2005,3,6,3,15,10), Time.utc(2005,2,28,15,15,10).advance(:days => 5.5)
- assert_equal Time.utc(2005,3,6,8,3,10), Time.utc(2005,2,28,15,15,10).advance(:days => 5.7)
+ assert_in_delta Time.utc(2005,3,6,8,3,10), Time.utc(2005,2,28,15,15,10).advance(:days => 5.7), 1
assert_equal Time.utc(2012,9,22,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:years => 7, :months => 7)
assert_equal Time.utc(2013,10,3,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:years => 7, :months => 19, :days => 11)
assert_equal Time.utc(2013,10,17,15,15,10), Time.utc(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :weeks => 2, :days => 5)
diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb
index 0380c28c17..03ae70d420 100644
--- a/activesupport/test/core_ext/time_with_zone_test.rb
+++ b/activesupport/test/core_ext/time_with_zone_test.rb
@@ -92,7 +92,7 @@ class TimeWithZoneTest < Test::Unit::TestCase
end
def test_xmlschema_with_fractional_seconds
- @twz += 0.123456 # advance the time by a fraction of a second
+ @twz += 0.1234560001 # advance the time by a fraction of a second
assert_equal "1999-12-31T19:00:00.123-05:00", @twz.xmlschema(3)
assert_equal "1999-12-31T19:00:00.123456-05:00", @twz.xmlschema(6)
assert_equal "1999-12-31T19:00:00.123456-05:00", @twz.xmlschema(12)
--
cgit v1.2.3
From 988513ac7a0cbd820c9486088256b8ab4e8acf74 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 11:40:29 -0500
Subject: Framework backtrace cleaning is handled by ActiveSupport now
---
.../action_controller/testing/assertions/dom.rb | 20 ++--
.../action_controller/testing/assertions/model.rb | 4 +-
.../testing/assertions/response.rb | 108 ++++++++++-----------
.../testing/assertions/routing.rb | 42 ++++----
.../action_controller/testing/assertions/tag.rb | 16 ++-
.../lib/action_controller/testing/test_case.rb | 8 --
actionpack/test/controller/test_test.rb | 27 ------
7 files changed, 85 insertions(+), 140 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/assertions/dom.rb b/actionpack/lib/action_controller/testing/assertions/dom.rb
index 5ffe5f1883..c0e6c68fcd 100644
--- a/actionpack/lib/action_controller/testing/assertions/dom.rb
+++ b/actionpack/lib/action_controller/testing/assertions/dom.rb
@@ -9,13 +9,11 @@ module ActionController
# assert_dom_equal 'Apples ', link_to("Apples", "http://www.example.com")
#
def assert_dom_equal(expected, actual, message = "")
- clean_backtrace do
- expected_dom = HTML::Document.new(expected).root
- actual_dom = HTML::Document.new(actual).root
- full_message = build_message(message, "> expected to be == to\n>.", expected_dom.to_s, actual_dom.to_s)
+ expected_dom = HTML::Document.new(expected).root
+ actual_dom = HTML::Document.new(actual).root
+ full_message = build_message(message, "> expected to be == to\n>.", expected_dom.to_s, actual_dom.to_s)
- assert_block(full_message) { expected_dom == actual_dom }
- end
+ assert_block(full_message) { expected_dom == actual_dom }
end
# The negated form of +assert_dom_equivalent+.
@@ -26,13 +24,11 @@ module ActionController
# assert_dom_not_equal 'Apples ', link_to("Oranges", "http://www.example.com")
#
def assert_dom_not_equal(expected, actual, message = "")
- clean_backtrace do
- expected_dom = HTML::Document.new(expected).root
- actual_dom = HTML::Document.new(actual).root
- full_message = build_message(message, "> expected to be != to\n>.", expected_dom.to_s, actual_dom.to_s)
+ expected_dom = HTML::Document.new(expected).root
+ actual_dom = HTML::Document.new(actual).root
+ full_message = build_message(message, "> expected to be != to\n>.", expected_dom.to_s, actual_dom.to_s)
- assert_block(full_message) { expected_dom != actual_dom }
- end
+ assert_block(full_message) { expected_dom != actual_dom }
end
end
end
diff --git a/actionpack/lib/action_controller/testing/assertions/model.rb b/actionpack/lib/action_controller/testing/assertions/model.rb
index 3a7b39b106..93e3bcf456 100644
--- a/actionpack/lib/action_controller/testing/assertions/model.rb
+++ b/actionpack/lib/action_controller/testing/assertions/model.rb
@@ -12,9 +12,7 @@ module ActionController
#
def assert_valid(record)
::ActiveSupport::Deprecation.warn("assert_valid is deprecated. Use assert record.valid? instead", caller)
- clean_backtrace do
- assert record.valid?, record.errors.full_messages.join("\n")
- end
+ assert record.valid?, record.errors.full_messages.join("\n")
end
end
end
diff --git a/actionpack/lib/action_controller/testing/assertions/response.rb b/actionpack/lib/action_controller/testing/assertions/response.rb
index 684fe1ffe0..7b2936e26c 100644
--- a/actionpack/lib/action_controller/testing/assertions/response.rb
+++ b/actionpack/lib/action_controller/testing/assertions/response.rb
@@ -24,21 +24,19 @@ module ActionController
def assert_response(type, message = nil)
validate_request!
- clean_backtrace do
- if [ :success, :missing, :redirect, :error ].include?(type) && @response.send("#{type}?")
- assert_block("") { true } # to count the assertion
- elsif type.is_a?(Fixnum) && @response.response_code == type
- assert_block("") { true } # to count the assertion
- elsif type.is_a?(Symbol) && @response.response_code == ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[type]
- assert_block("") { true } # to count the assertion
+ if [ :success, :missing, :redirect, :error ].include?(type) && @response.send("#{type}?")
+ assert_block("") { true } # to count the assertion
+ elsif type.is_a?(Fixnum) && @response.response_code == type
+ assert_block("") { true } # to count the assertion
+ elsif type.is_a?(Symbol) && @response.response_code == ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[type]
+ assert_block("") { true } # to count the assertion
+ else
+ if @controller && @response.error?
+ 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
- if @controller && @response.error?
- 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
- assert_block(build_message(message, "Expected response to be a >, but was >", type, @response.response_code)) { false }
- end
+ assert_block(build_message(message, "Expected response to be a >, but was >", type, @response.response_code)) { false }
end
end
end
@@ -61,21 +59,19 @@ module ActionController
def assert_redirected_to(options = {}, message=nil)
validate_request!
- clean_backtrace do
- assert_response(:redirect, message)
- return true if options == @response.redirected_to
+ assert_response(:redirect, message)
+ return true if options == @response.redirected_to
- # Support partial arguments for hash redirections
- if options.is_a?(Hash) && @response.redirected_to.is_a?(Hash)
- return true if options.all? {|(key, value)| @response.redirected_to[key] == value}
- end
+ # Support partial arguments for hash redirections
+ if options.is_a?(Hash) && @response.redirected_to.is_a?(Hash)
+ return true if options.all? {|(key, value)| @response.redirected_to[key] == value}
+ end
- redirected_to_after_normalisation = normalize_argument_to_redirection(@response.redirected_to)
- options_after_normalisation = normalize_argument_to_redirection(options)
+ redirected_to_after_normalisation = normalize_argument_to_redirection(@response.redirected_to)
+ options_after_normalisation = normalize_argument_to_redirection(options)
- if redirected_to_after_normalisation != options_after_normalisation
- flunk "Expected response to be a redirect to <#{options_after_normalisation}> but was a redirect to <#{redirected_to_after_normalisation}>"
- end
+ if redirected_to_after_normalisation != options_after_normalisation
+ flunk "Expected response to be a redirect to <#{options_after_normalisation}> but was a redirect to <#{redirected_to_after_normalisation}>"
end
end
@@ -95,40 +91,38 @@ module ActionController
def assert_template(options = {}, message = nil)
validate_request!
- clean_backtrace do
- case options
- when NilClass, String
- 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.template.rendered[:template].blank?
- else
- rendered.any? { |t| t.match(options) }
- end
+ case options
+ when NilClass, String
+ 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.template.rendered[:template].blank?
+ else
+ rendered.any? { |t| t.match(options) }
end
- when Hash
- if expected_partial = options[:partial]
- 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
- msg = build_message(message,
- "expecting ? to be rendered ? time(s) but rendered ? time(s)",
- expected_partial, expected_count, actual_count)
- assert(actual_count == expected_count.to_i, msg)
- else
- msg = build_message(message,
- "expecting partial > but action rendered >",
- options[:partial], partials.keys)
- assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg)
- end
+ end
+ when Hash
+ if expected_partial = options[:partial]
+ 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
+ msg = build_message(message,
+ "expecting ? to be rendered ? time(s) but rendered ? time(s)",
+ expected_partial, expected_count, actual_count)
+ assert(actual_count == expected_count.to_i, msg)
else
- assert @controller.template.rendered[:partials].empty?,
- "Expected no partials to be rendered"
+ msg = build_message(message,
+ "expecting partial > but action rendered >",
+ options[:partial], partials.keys)
+ assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg)
end
+ else
+ assert @controller.template.rendered[:partials].empty?,
+ "Expected no partials to be rendered"
end
end
end
diff --git a/actionpack/lib/action_controller/testing/assertions/routing.rb b/actionpack/lib/action_controller/testing/assertions/routing.rb
index 5101751cea..f3f4f54fe3 100644
--- a/actionpack/lib/action_controller/testing/assertions/routing.rb
+++ b/actionpack/lib/action_controller/testing/assertions/routing.rb
@@ -44,19 +44,17 @@ module ActionController
request_method = nil
end
- clean_backtrace do
- ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
- request = recognized_request_for(path, request_method)
+ ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
+ request = recognized_request_for(path, request_method)
- expected_options = expected_options.clone
- extras.each_key { |key| expected_options.delete key } unless extras.nil?
+ expected_options = expected_options.clone
+ extras.each_key { |key| expected_options.delete key } unless extras.nil?
- expected_options.stringify_keys!
- routing_diff = expected_options.diff(request.path_parameters)
- msg = build_message(message, "The recognized options > did not match >, difference: >",
- request.path_parameters, expected_options, expected_options.diff(request.path_parameters))
- assert_block(msg) { request.path_parameters == expected_options }
- end
+ expected_options.stringify_keys!
+ routing_diff = expected_options.diff(request.path_parameters)
+ msg = build_message(message, "The recognized options > did not match >, difference: >",
+ request.path_parameters, expected_options, expected_options.diff(request.path_parameters))
+ assert_block(msg) { request.path_parameters == expected_options }
end
# Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+.
@@ -78,21 +76,19 @@ module ActionController
# # Asserts that the generated route gives us our custom route
# assert_generates "changesets/12", { :controller => 'scm', :action => 'show_diff', :revision => "12" }
def assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)
- clean_backtrace do
- expected_path = "/#{expected_path}" unless expected_path[0] == ?/
- # Load routes.rb if it hasn't been loaded.
- ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
+ expected_path = "/#{expected_path}" unless expected_path[0] == ?/
+ # Load routes.rb if it hasn't been loaded.
+ ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
- generated_path, extra_keys = ActionController::Routing::Routes.generate_extras(options, defaults)
- found_extras = options.reject {|k, v| ! extra_keys.include? k}
+ generated_path, extra_keys = ActionController::Routing::Routes.generate_extras(options, defaults)
+ found_extras = options.reject {|k, v| ! extra_keys.include? k}
- msg = build_message(message, "found extras >, not >", found_extras, extras)
- assert_block(msg) { found_extras == extras }
+ msg = build_message(message, "found extras >, not >", found_extras, extras)
+ assert_block(msg) { found_extras == extras }
- msg = build_message(message, "The generated path > did not match >", generated_path,
- expected_path)
- assert_block(msg) { expected_path == generated_path }
- end
+ msg = build_message(message, "The generated path > did not match >", generated_path,
+ expected_path)
+ assert_block(msg) { expected_path == generated_path }
end
# Asserts that path and options match both ways; in other words, it verifies that path generates
diff --git a/actionpack/lib/action_controller/testing/assertions/tag.rb b/actionpack/lib/action_controller/testing/assertions/tag.rb
index 80249e0e83..d9197b7855 100644
--- a/actionpack/lib/action_controller/testing/assertions/tag.rb
+++ b/actionpack/lib/action_controller/testing/assertions/tag.rb
@@ -94,11 +94,9 @@ module ActionController
# that allow optional closing tags (p, li, td). You must explicitly
# close all of your tags to use these assertions.
def assert_tag(*opts)
- clean_backtrace do
- opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
- tag = find_tag(opts)
- assert tag, "expected tag, but no tag found matching #{opts.inspect} in:\n#{@response.body.inspect}"
- end
+ opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
+ tag = find_tag(opts)
+ assert tag, "expected tag, but no tag found matching #{opts.inspect} in:\n#{@response.body.inspect}"
end
# Identical to +assert_tag+, but asserts that a matching tag does _not_
@@ -116,11 +114,9 @@ module ActionController
# assert_no_tag :tag => "p",
# :children => { :count => 1..3, :only => { :tag => "img" } }
def assert_no_tag(*opts)
- clean_backtrace do
- opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
- tag = find_tag(opts)
- assert !tag, "expected no tag, but found tag matching #{opts.inspect} in:\n#{@response.body.inspect}"
- end
+ opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
+ tag = find_tag(opts)
+ assert !tag, "expected no tag, but found tag matching #{opts.inspect} in:\n#{@response.body.inspect}"
end
end
end
diff --git a/actionpack/lib/action_controller/testing/test_case.rb b/actionpack/lib/action_controller/testing/test_case.rb
index b020b755a0..a80488e13e 100644
--- a/actionpack/lib/action_controller/testing/test_case.rb
+++ b/actionpack/lib/action_controller/testing/test_case.rb
@@ -109,14 +109,6 @@ module ActionController
%w(response selector tag dom routing model).each do |kind|
include ActionController::Assertions.const_get("#{kind.camelize}Assertions")
end
-
- def clean_backtrace(&block)
- yield
- rescue ActiveSupport::TestCase::Assertion => error
- framework_path = Regexp.new(File.expand_path("#{File.dirname(__FILE__)}/assertions"))
- error.backtrace.reject! { |line| File.expand_path(line) =~ framework_path }
- raise
- end
end
include Assertions
diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb
index f68ffc7a2a..b372980242 100644
--- a/actionpack/test/controller/test_test.rb
+++ b/actionpack/test/controller/test_test.rb
@@ -629,33 +629,6 @@ XML
end
end
-class CleanBacktraceTest < ActionController::TestCase
- def test_should_reraise_the_same_object
- exception = ActiveSupport::TestCase::Assertion.new('message')
- clean_backtrace { raise exception }
- rescue Exception => caught
- assert_equal exception.object_id, caught.object_id
- assert_equal exception.message, caught.message
- end
-
- def test_should_clean_assertion_lines_from_backtrace
- path = File.expand_path("#{File.dirname(__FILE__)}/../../lib/action_controller/testing")
- exception = ActiveSupport::TestCase::Assertion.new('message')
- exception.set_backtrace ["#{path}/abc", "#{path}/assertions/def"]
- clean_backtrace { raise exception }
- rescue Exception => caught
- assert_equal ["#{path}/abc"], caught.backtrace
- end
-
- def test_should_only_clean_assertion_failure_errors
- clean_backtrace do
- raise "can't touch this", [File.expand_path("#{File.dirname(__FILE__)}/../../lib/action_controller/assertions/abc")]
- end
- rescue => caught
- assert !caught.backtrace.empty?
- end
-end
-
class InferringClassNameTest < ActionController::TestCase
def test_determine_controller_class
assert_equal ContentController, determine_class("ContentControllerTest")
--
cgit v1.2.3
From 98dd726687259b96fad15cc073c610fda7fc1023 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 11:41:43 -0500
Subject: Test::Unit work arounds are handled by ActiveSupport
---
.../lib/action_controller/testing/integration.rb | 49 ----------------------
1 file changed, 49 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb
index 037463e489..f960698566 100644
--- a/actionpack/lib/action_controller/testing/integration.rb
+++ b/actionpack/lib/action_controller/testing/integration.rb
@@ -508,54 +508,5 @@ module ActionController
# end
class IntegrationTest < ActiveSupport::TestCase
include Integration::Runner
-
- # Work around a bug in test/unit caused by the default test being named
- # as a symbol (:default_test), which causes regex test filters
- # (like "ruby test.rb -n /foo/") to fail because =~ doesn't work on
- # symbols.
- def initialize(name) #:nodoc:
- super(name.to_s)
- end
-
- # Work around test/unit's requirement that every subclass of TestCase have
- # at least one test method. Note that this implementation extends to all
- # subclasses, as well, so subclasses of IntegrationTest may also exist
- # without any test methods.
- def run(*args) #:nodoc:
- return if @method_name == "default_test"
- super
- end
-
- # Because of how use_instantiated_fixtures and use_transactional_fixtures
- # are defined, we need to treat them as special cases. Otherwise, users
- # would potentially have to set their values for both Test::Unit::TestCase
- # ActionController::IntegrationTest, since by the time the value is set on
- # TestCase, IntegrationTest has already been defined and cannot inherit
- # changes to those variables. So, we make those two attributes
- # copy-on-write.
-
- class << self
- def use_transactional_fixtures=(flag) #:nodoc:
- @_use_transactional_fixtures = true
- @use_transactional_fixtures = flag
- end
-
- def use_instantiated_fixtures=(flag) #:nodoc:
- @_use_instantiated_fixtures = true
- @use_instantiated_fixtures = flag
- end
-
- def use_transactional_fixtures #:nodoc:
- @_use_transactional_fixtures ?
- @use_transactional_fixtures :
- superclass.use_transactional_fixtures
- end
-
- def use_instantiated_fixtures #:nodoc:
- @_use_instantiated_fixtures ?
- @use_instantiated_fixtures :
- superclass.use_instantiated_fixtures
- end
- end
end
end
--
cgit v1.2.3
From 7b3b7cb2ab1ccf96d4c8a1bafd87dbfbd2ac8c84 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 11:55:53 -0500
Subject: Move generic assertions into ActionDispatch
---
.../action_controller/testing/assertions/dom.rb | 35 --
.../action_controller/testing/assertions/model.rb | 19 -
.../testing/assertions/response.rb | 156 -----
.../testing/assertions/routing.rb | 142 -----
.../testing/assertions/selector.rb | 632 ---------------------
.../action_controller/testing/assertions/tag.rb | 123 ----
.../lib/action_controller/testing/integration.rb | 2 +-
.../lib/action_controller/testing/test_case.rb | 7 +-
actionpack/lib/action_dispatch.rb | 2 +
.../lib/action_dispatch/testing/assertions.rb | 8 +
.../lib/action_dispatch/testing/assertions/dom.rb | 35 ++
.../action_dispatch/testing/assertions/model.rb | 19 +
.../action_dispatch/testing/assertions/response.rb | 156 +++++
.../action_dispatch/testing/assertions/routing.rb | 142 +++++
.../action_dispatch/testing/assertions/selector.rb | 632 +++++++++++++++++++++
.../lib/action_dispatch/testing/assertions/tag.rb | 123 ++++
actionpack/lib/action_view/test_case.rb | 2 +-
17 files changed, 1120 insertions(+), 1115 deletions(-)
delete mode 100644 actionpack/lib/action_controller/testing/assertions/dom.rb
delete mode 100644 actionpack/lib/action_controller/testing/assertions/model.rb
delete mode 100644 actionpack/lib/action_controller/testing/assertions/response.rb
delete mode 100644 actionpack/lib/action_controller/testing/assertions/routing.rb
delete mode 100644 actionpack/lib/action_controller/testing/assertions/selector.rb
delete mode 100644 actionpack/lib/action_controller/testing/assertions/tag.rb
create mode 100644 actionpack/lib/action_dispatch/testing/assertions.rb
create mode 100644 actionpack/lib/action_dispatch/testing/assertions/dom.rb
create mode 100644 actionpack/lib/action_dispatch/testing/assertions/model.rb
create mode 100644 actionpack/lib/action_dispatch/testing/assertions/response.rb
create mode 100644 actionpack/lib/action_dispatch/testing/assertions/routing.rb
create mode 100644 actionpack/lib/action_dispatch/testing/assertions/selector.rb
create mode 100644 actionpack/lib/action_dispatch/testing/assertions/tag.rb
diff --git a/actionpack/lib/action_controller/testing/assertions/dom.rb b/actionpack/lib/action_controller/testing/assertions/dom.rb
deleted file mode 100644
index c0e6c68fcd..0000000000
--- a/actionpack/lib/action_controller/testing/assertions/dom.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-module ActionController
- module Assertions
- module DomAssertions
- # Test two HTML strings for equivalency (e.g., identical up to reordering of attributes)
- #
- # ==== Examples
- #
- # # assert that the referenced method generates the appropriate HTML string
- # assert_dom_equal 'Apples ', link_to("Apples", "http://www.example.com")
- #
- def assert_dom_equal(expected, actual, message = "")
- expected_dom = HTML::Document.new(expected).root
- actual_dom = HTML::Document.new(actual).root
- full_message = build_message(message, "> expected to be == to\n>.", expected_dom.to_s, actual_dom.to_s)
-
- assert_block(full_message) { expected_dom == actual_dom }
- end
-
- # The negated form of +assert_dom_equivalent+.
- #
- # ==== Examples
- #
- # # assert that the referenced method does not generate the specified HTML string
- # assert_dom_not_equal 'Apples ', link_to("Oranges", "http://www.example.com")
- #
- def assert_dom_not_equal(expected, actual, message = "")
- expected_dom = HTML::Document.new(expected).root
- actual_dom = HTML::Document.new(actual).root
- full_message = build_message(message, "> expected to be != to\n>.", expected_dom.to_s, actual_dom.to_s)
-
- assert_block(full_message) { expected_dom != actual_dom }
- end
- end
- end
-end
diff --git a/actionpack/lib/action_controller/testing/assertions/model.rb b/actionpack/lib/action_controller/testing/assertions/model.rb
deleted file mode 100644
index 93e3bcf456..0000000000
--- a/actionpack/lib/action_controller/testing/assertions/model.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-module ActionController
- module Assertions
- module ModelAssertions
- # Ensures that the passed record is valid by Active Record standards and
- # returns any error messages if it is not.
- #
- # ==== Examples
- #
- # # assert that a newly created record is valid
- # model = Model.new
- # assert_valid(model)
- #
- def assert_valid(record)
- ::ActiveSupport::Deprecation.warn("assert_valid is deprecated. Use assert record.valid? instead", caller)
- assert record.valid?, record.errors.full_messages.join("\n")
- end
- end
- end
-end
diff --git a/actionpack/lib/action_controller/testing/assertions/response.rb b/actionpack/lib/action_controller/testing/assertions/response.rb
deleted file mode 100644
index 7b2936e26c..0000000000
--- a/actionpack/lib/action_controller/testing/assertions/response.rb
+++ /dev/null
@@ -1,156 +0,0 @@
-module ActionController
- module Assertions
- # A small suite of assertions that test responses from Rails applications.
- module ResponseAssertions
- # Asserts that the response is one of the following types:
- #
- # * :success - Status code was 200
- # * :redirect - Status code was in the 300-399 range
- # * :missing - Status code was 404
- # * :error - Status code was in the 500-599 range
- #
- # You can also pass an explicit status number like assert_response(501)
- # or its symbolic equivalent assert_response(:not_implemented).
- # See ActionDispatch::StatusCodes for a full list.
- #
- # ==== Examples
- #
- # # assert that the response was a redirection
- # assert_response :redirect
- #
- # # assert that the response code was status code 401 (unauthorized)
- # assert_response 401
- #
- def assert_response(type, message = nil)
- validate_request!
-
- if [ :success, :missing, :redirect, :error ].include?(type) && @response.send("#{type}?")
- assert_block("") { true } # to count the assertion
- elsif type.is_a?(Fixnum) && @response.response_code == type
- assert_block("") { true } # to count the assertion
- elsif type.is_a?(Symbol) && @response.response_code == ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[type]
- assert_block("") { true } # to count the assertion
- else
- if @controller && @response.error?
- 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
- assert_block(build_message(message, "Expected response to be a >, but was >", type, @response.response_code)) { false }
- end
- end
- end
-
- # Assert that the redirection options passed in match those of the redirect called in the latest action.
- # This match can be partial, such that assert_redirected_to(:controller => "weblog") will also
- # match the redirection of redirect_to(:controller => "weblog", :action => "show") and so on.
- #
- # ==== Examples
- #
- # # assert that the redirection was to the "index" action on the WeblogController
- # assert_redirected_to :controller => "weblog", :action => "index"
- #
- # # assert that the redirection was to the named route login_url
- # assert_redirected_to login_url
- #
- # # assert that the redirection was to the url for @customer
- # assert_redirected_to @customer
- #
- def assert_redirected_to(options = {}, message=nil)
- validate_request!
-
- assert_response(:redirect, message)
- return true if options == @response.redirected_to
-
- # Support partial arguments for hash redirections
- if options.is_a?(Hash) && @response.redirected_to.is_a?(Hash)
- return true if options.all? {|(key, value)| @response.redirected_to[key] == value}
- end
-
- redirected_to_after_normalisation = normalize_argument_to_redirection(@response.redirected_to)
- options_after_normalisation = normalize_argument_to_redirection(options)
-
- if redirected_to_after_normalisation != options_after_normalisation
- flunk "Expected response to be a redirect to <#{options_after_normalisation}> but was a redirect to <#{redirected_to_after_normalisation}>"
- end
- end
-
- # Asserts that the request was rendered with the appropriate template file or partials
- #
- # ==== Examples
- #
- # # assert that the "new" view template was rendered
- # assert_template "new"
- #
- # # assert that the "_customer" partial was rendered twice
- # assert_template :partial => '_customer', :count => 2
- #
- # # assert that no partials were rendered
- # assert_template :partial => false
- #
- def assert_template(options = {}, message = nil)
- validate_request!
-
- case options
- when NilClass, String
- 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.template.rendered[:template].blank?
- else
- rendered.any? { |t| t.match(options) }
- end
- end
- when Hash
- if expected_partial = options[:partial]
- 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
- msg = build_message(message,
- "expecting ? to be rendered ? time(s) but rendered ? time(s)",
- expected_partial, expected_count, actual_count)
- assert(actual_count == expected_count.to_i, msg)
- else
- msg = build_message(message,
- "expecting partial > but action rendered >",
- options[:partial], partials.keys)
- assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg)
- end
- else
- assert @controller.template.rendered[:partials].empty?,
- "Expected no partials to be rendered"
- end
- end
- end
-
- private
- # Proxy to to_param if the object will respond to it.
- def parameterize(value)
- value.respond_to?(:to_param) ? value.to_param : value
- end
-
- def normalize_argument_to_redirection(fragment)
- after_routing = @controller.url_for(fragment)
- if after_routing =~ %r{^\w+://.*}
- after_routing
- else
- # FIXME - this should probably get removed.
- if after_routing.first != '/'
- after_routing = '/' + after_routing
- end
- @request.protocol + @request.host_with_port + after_routing
- end
- end
-
- def validate_request!
- unless @request.is_a?(ActionDispatch::Request)
- raise ArgumentError, "@request must be an ActionDispatch::Request"
- end
- end
- end
- end
-end
diff --git a/actionpack/lib/action_controller/testing/assertions/routing.rb b/actionpack/lib/action_controller/testing/assertions/routing.rb
deleted file mode 100644
index f3f4f54fe3..0000000000
--- a/actionpack/lib/action_controller/testing/assertions/routing.rb
+++ /dev/null
@@ -1,142 +0,0 @@
-module ActionController
- module Assertions
- # Suite of assertions to test routes generated by Rails and the handling of requests made to them.
- module RoutingAssertions
- # Asserts that the routing of the given +path+ was handled correctly and that the parsed options (given in the +expected_options+ hash)
- # match +path+. Basically, it asserts that Rails recognizes the route given by +expected_options+.
- #
- # Pass a hash in the second argument (+path+) to specify the request method. This is useful for routes
- # requiring a specific HTTP method. The hash should contain a :path with the incoming request path
- # and a :method containing the required HTTP verb.
- #
- # # assert that POSTing to /items will call the create action on ItemsController
- # assert_recognizes {:controller => 'items', :action => 'create'}, {:path => 'items', :method => :post}
- #
- # You can also pass in +extras+ with a hash containing URL parameters that would normally be in the query string. This can be used
- # to assert that values in the query string string will end up in the params hash correctly. To test query strings you must use the
- # extras argument, appending the query string on the path directly will not work. For example:
- #
- # # assert that a path of '/items/list/1?view=print' returns the correct options
- # assert_recognizes {:controller => 'items', :action => 'list', :id => '1', :view => 'print'}, 'items/list/1', { :view => "print" }
- #
- # The +message+ parameter allows you to pass in an error message that is displayed upon failure.
- #
- # ==== Examples
- # # Check the default route (i.e., the index action)
- # assert_recognizes {:controller => 'items', :action => 'index'}, 'items'
- #
- # # Test a specific action
- # assert_recognizes {:controller => 'items', :action => 'list'}, 'items/list'
- #
- # # Test an action with a parameter
- # assert_recognizes {:controller => 'items', :action => 'destroy', :id => '1'}, 'items/destroy/1'
- #
- # # Test a custom route
- # assert_recognizes {:controller => 'items', :action => 'show', :id => '1'}, 'view/item1'
- #
- # # Check a Simply RESTful generated route
- # assert_recognizes list_items_url, 'items/list'
- def assert_recognizes(expected_options, path, extras={}, message=nil)
- if path.is_a? Hash
- request_method = path[:method]
- path = path[:path]
- else
- request_method = nil
- end
-
- ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
- request = recognized_request_for(path, request_method)
-
- expected_options = expected_options.clone
- extras.each_key { |key| expected_options.delete key } unless extras.nil?
-
- expected_options.stringify_keys!
- routing_diff = expected_options.diff(request.path_parameters)
- msg = build_message(message, "The recognized options > did not match >, difference: >",
- request.path_parameters, expected_options, expected_options.diff(request.path_parameters))
- assert_block(msg) { request.path_parameters == expected_options }
- end
-
- # Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+.
- # The +extras+ parameter is used to tell the request the names and values of additional request parameters that would be in
- # a query string. The +message+ parameter allows you to specify a custom error message for assertion failures.
- #
- # The +defaults+ parameter is unused.
- #
- # ==== Examples
- # # Asserts that the default action is generated for a route with no action
- # assert_generates "/items", :controller => "items", :action => "index"
- #
- # # Tests that the list action is properly routed
- # assert_generates "/items/list", :controller => "items", :action => "list"
- #
- # # Tests the generation of a route with a parameter
- # assert_generates "/items/list/1", { :controller => "items", :action => "list", :id => "1" }
- #
- # # Asserts that the generated route gives us our custom route
- # assert_generates "changesets/12", { :controller => 'scm', :action => 'show_diff', :revision => "12" }
- def assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)
- expected_path = "/#{expected_path}" unless expected_path[0] == ?/
- # Load routes.rb if it hasn't been loaded.
- ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
-
- generated_path, extra_keys = ActionController::Routing::Routes.generate_extras(options, defaults)
- found_extras = options.reject {|k, v| ! extra_keys.include? k}
-
- msg = build_message(message, "found extras >, not >", found_extras, extras)
- assert_block(msg) { found_extras == extras }
-
- msg = build_message(message, "The generated path > did not match >", generated_path,
- expected_path)
- assert_block(msg) { expected_path == generated_path }
- end
-
- # Asserts that path and options match both ways; in other words, it verifies that path generates
- # options and then that options generates path . This essentially combines +assert_recognizes+
- # and +assert_generates+ into one step.
- #
- # The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The
- # +message+ parameter allows you to specify a custom error message to display upon failure.
- #
- # ==== Examples
- # # Assert a basic route: a controller with the default action (index)
- # assert_routing '/home', :controller => 'home', :action => 'index'
- #
- # # Test a route generated with a specific controller, action, and parameter (id)
- # assert_routing '/entries/show/23', :controller => 'entries', :action => 'show', id => 23
- #
- # # Assert a basic route (controller + default action), with an error message if it fails
- # assert_routing '/store', { :controller => 'store', :action => 'index' }, {}, {}, 'Route for store index not generated properly'
- #
- # # Tests a route, providing a defaults hash
- # assert_routing 'controller/action/9', {:id => "9", :item => "square"}, {:controller => "controller", :action => "action"}, {}, {:item => "square"}
- #
- # # Tests a route with a HTTP method
- # assert_routing { :method => 'put', :path => '/product/321' }, { :controller => "product", :action => "update", :id => "321" }
- def assert_routing(path, options, defaults={}, extras={}, message=nil)
- assert_recognizes(options, path, extras, message)
-
- controller, default_controller = options[:controller], defaults[:controller]
- if controller && controller.include?(?/) && default_controller && default_controller.include?(?/)
- options[:controller] = "/#{controller}"
- end
-
- assert_generates(path.is_a?(Hash) ? path[:path] : path, options, defaults, extras, message)
- end
-
- private
- # Recognizes the route for a given path.
- def recognized_request_for(path, request_method = nil)
- path = "/#{path}" unless path.first == '/'
-
- # Assume given controller
- request = ActionController::TestRequest.new
- request.env["REQUEST_METHOD"] = request_method.to_s.upcase if request_method
- request.path = path
-
- ActionController::Routing::Routes.recognize(request)
- request
- end
- end
- end
-end
diff --git a/actionpack/lib/action_controller/testing/assertions/selector.rb b/actionpack/lib/action_controller/testing/assertions/selector.rb
deleted file mode 100644
index 0d56ea5ef7..0000000000
--- a/actionpack/lib/action_controller/testing/assertions/selector.rb
+++ /dev/null
@@ -1,632 +0,0 @@
-#--
-# Copyright (c) 2006 Assaf Arkin (http://labnotes.org)
-# Under MIT and/or CC By license.
-#++
-
-module ActionController
- module Assertions
- unless const_defined?(:NO_STRIP)
- NO_STRIP = %w{pre script style textarea}
- end
-
- # Adds the +assert_select+ method for use in Rails functional
- # test cases, which can be used to make assertions on the response HTML of a controller
- # action. You can also call +assert_select+ within another +assert_select+ to
- # make assertions on elements selected by the enclosing assertion.
- #
- # Use +css_select+ to select elements without making an assertions, either
- # from the response HTML or elements selected by the enclosing assertion.
- #
- # In addition to HTML responses, you can make the following assertions:
- # * +assert_select_rjs+ - Assertions on HTML content of RJS update and insertion operations.
- # * +assert_select_encoded+ - Assertions on HTML encoded inside XML, for example for dealing with feed item descriptions.
- # * +assert_select_email+ - Assertions on the HTML body of an e-mail.
- #
- # Also see HTML::Selector to learn how to use selectors.
- module SelectorAssertions
- # :call-seq:
- # css_select(selector) => array
- # css_select(element, selector) => array
- #
- # Select and return all matching elements.
- #
- # If called with a single argument, uses that argument as a selector
- # to match all elements of the current page. Returns an empty array
- # if no match is found.
- #
- # If called with two arguments, uses the first argument as the base
- # element and the second argument as the selector. Attempts to match the
- # base element and any of its children. Returns an empty array if no
- # match is found.
- #
- # The selector may be a CSS selector expression (String), an expression
- # with substitution values (Array) or an HTML::Selector object.
- #
- # ==== Examples
- # # Selects all div tags
- # divs = css_select("div")
- #
- # # Selects all paragraph tags and does something interesting
- # pars = css_select("p")
- # pars.each do |par|
- # # Do something fun with paragraphs here...
- # end
- #
- # # Selects all list items in unordered lists
- # items = css_select("ul>li")
- #
- # # Selects all form tags and then all inputs inside the form
- # forms = css_select("form")
- # forms.each do |form|
- # inputs = css_select(form, "input")
- # ...
- # end
- #
- def css_select(*args)
- # See assert_select to understand what's going on here.
- arg = args.shift
-
- if arg.is_a?(HTML::Node)
- root = arg
- arg = args.shift
- elsif arg == nil
- raise ArgumentError, "First argument is either selector or element to select, but nil found. Perhaps you called assert_select with an element that does not exist?"
- elsif @selected
- matches = []
-
- @selected.each do |selected|
- subset = css_select(selected, HTML::Selector.new(arg.dup, args.dup))
- subset.each do |match|
- matches << match unless matches.any? { |m| m.equal?(match) }
- end
- end
-
- return matches
- else
- root = response_from_page_or_rjs
- end
-
- case arg
- when String
- selector = HTML::Selector.new(arg, args)
- when Array
- selector = HTML::Selector.new(*arg)
- when HTML::Selector
- selector = arg
- else raise ArgumentError, "Expecting a selector as the first argument"
- end
-
- selector.select(root)
- end
-
- # :call-seq:
- # assert_select(selector, equality?, message?)
- # assert_select(element, selector, equality?, message?)
- #
- # An assertion that selects elements and makes one or more equality tests.
- #
- # If the first argument is an element, selects all matching elements
- # starting from (and including) that element and all its children in
- # depth-first order.
- #
- # If no element if specified, calling +assert_select+ selects from the
- # response HTML unless +assert_select+ is called from within an +assert_select+ block.
- #
- # When called with a block +assert_select+ passes an array of selected elements
- # to the block. Calling +assert_select+ from the block, with no element specified,
- # runs the assertion on the complete set of elements selected by the enclosing assertion.
- # Alternatively the array may be iterated through so that +assert_select+ can be called
- # separately for each element.
- #
- #
- # ==== Example
- # If the response contains two ordered lists, each with four list elements then:
- # assert_select "ol" do |elements|
- # elements.each do |element|
- # assert_select element, "li", 4
- # end
- # end
- #
- # will pass, as will:
- # assert_select "ol" do
- # assert_select "li", 8
- # end
- #
- # The selector may be a CSS selector expression (String), an expression
- # with substitution values, or an HTML::Selector object.
- #
- # === Equality Tests
- #
- # The equality test may be one of the following:
- # * true - Assertion is true if at least one element selected.
- # * false - Assertion is true if no element selected.
- # * String/Regexp - Assertion is true if the text value of at least
- # one element matches the string or regular expression.
- # * Integer - Assertion is true if exactly that number of
- # elements are selected.
- # * Range - Assertion is true if the number of selected
- # elements fit the range.
- # If no equality test specified, the assertion is true if at least one
- # element selected.
- #
- # To perform more than one equality tests, use a hash with the following keys:
- # * :text - Narrow the selection to elements that have this text
- # value (string or regexp).
- # * :html - Narrow the selection to elements that have this HTML
- # content (string or regexp).
- # * :count - Assertion is true if the number of selected elements
- # is equal to this value.
- # * :minimum - Assertion is true if the number of selected
- # elements is at least this value.
- # * :maximum - Assertion is true if the number of selected
- # elements is at most this value.
- #
- # If the method is called with a block, once all equality tests are
- # evaluated the block is called with an array of all matched elements.
- #
- # ==== Examples
- #
- # # At least one form element
- # assert_select "form"
- #
- # # Form element includes four input fields
- # assert_select "form input", 4
- #
- # # Page title is "Welcome"
- # assert_select "title", "Welcome"
- #
- # # Page title is "Welcome" and there is only one title element
- # assert_select "title", {:count=>1, :text=>"Welcome"},
- # "Wrong title or more than one title element"
- #
- # # Page contains no forms
- # assert_select "form", false, "This page must contain no forms"
- #
- # # Test the content and style
- # assert_select "body div.header ul.menu"
- #
- # # Use substitution values
- # assert_select "ol>li#?", /item-\d+/
- #
- # # All input fields in the form have a name
- # assert_select "form input" do
- # assert_select "[name=?]", /.+/ # Not empty
- # end
- def assert_select(*args, &block)
- # Start with optional element followed by mandatory selector.
- arg = args.shift
-
- if arg.is_a?(HTML::Node)
- # First argument is a node (tag or text, but also HTML root),
- # so we know what we're selecting from.
- root = arg
- arg = args.shift
- elsif arg == nil
- # This usually happens when passing a node/element that
- # happens to be nil.
- raise ArgumentError, "First argument is either selector or element to select, but nil found. Perhaps you called assert_select with an element that does not exist?"
- elsif @selected
- root = HTML::Node.new(nil)
- root.children.concat @selected
- else
- # Otherwise just operate on the response document.
- root = response_from_page_or_rjs
- end
-
- # First or second argument is the selector: string and we pass
- # all remaining arguments. Array and we pass the argument. Also
- # accepts selector itself.
- case arg
- when String
- selector = HTML::Selector.new(arg, args)
- when Array
- selector = HTML::Selector.new(*arg)
- when HTML::Selector
- selector = arg
- else raise ArgumentError, "Expecting a selector as the first argument"
- end
-
- # Next argument is used for equality tests.
- equals = {}
- case arg = args.shift
- when Hash
- equals = arg
- when String, Regexp
- equals[:text] = arg
- when Integer
- equals[:count] = arg
- when Range
- equals[:minimum] = arg.begin
- equals[:maximum] = arg.end
- when FalseClass
- equals[:count] = 0
- when NilClass, TrueClass
- equals[:minimum] = 1
- else raise ArgumentError, "I don't understand what you're trying to match"
- end
-
- # By default we're looking for at least one match.
- if equals[:count]
- equals[:minimum] = equals[:maximum] = equals[:count]
- else
- equals[:minimum] = 1 unless equals[:minimum]
- end
-
- # Last argument is the message we use if the assertion fails.
- message = args.shift
- #- message = "No match made with selector #{selector.inspect}" unless message
- if args.shift
- raise ArgumentError, "Not expecting that last argument, you either have too many arguments, or they're the wrong type"
- end
-
- matches = selector.select(root)
- # If text/html, narrow down to those elements that match it.
- content_mismatch = nil
- if match_with = equals[:text]
- matches.delete_if do |match|
- text = ""
- text.force_encoding(match_with.encoding) if text.respond_to?(:force_encoding)
- stack = match.children.reverse
- while node = stack.pop
- if node.tag?
- stack.concat node.children.reverse
- else
- content = node.content
- content.force_encoding(match_with.encoding) if content.respond_to?(:force_encoding)
- text << content
- end
- end
- text.strip! unless NO_STRIP.include?(match.name)
- unless match_with.is_a?(Regexp) ? (text =~ match_with) : (text == match_with.to_s)
- content_mismatch ||= build_message(message, "> expected but was\n>.", match_with, text)
- true
- end
- end
- elsif match_with = equals[:html]
- matches.delete_if do |match|
- html = match.children.map(&:to_s).join
- html.strip! unless NO_STRIP.include?(match.name)
- unless match_with.is_a?(Regexp) ? (html =~ match_with) : (html == match_with.to_s)
- content_mismatch ||= build_message(message, "> expected but was\n>.", match_with, html)
- true
- end
- end
- end
- # Expecting foo found bar element only if found zero, not if
- # found one but expecting two.
- message ||= content_mismatch if matches.empty?
- # Test minimum/maximum occurrence.
- min, max = equals[:minimum], equals[:maximum]
- message = message || %(Expected #{count_description(min, max)} matching "#{selector.to_s}", found #{matches.size}.)
- assert matches.size >= min, message if min
- assert matches.size <= max, message if max
-
- # If a block is given call that block. Set @selected to allow
- # nested assert_select, which can be nested several levels deep.
- if block_given? && !matches.empty?
- begin
- in_scope, @selected = @selected, matches
- yield matches
- ensure
- @selected = in_scope
- end
- end
-
- # Returns all matches elements.
- matches
- end
-
- def count_description(min, max) #:nodoc:
- pluralize = lambda {|word, quantity| word << (quantity == 1 ? '' : 's')}
-
- if min && max && (max != min)
- "between #{min} and #{max} elements"
- elsif min && !(min == 1 && max == 1)
- "at least #{min} #{pluralize['element', min]}"
- elsif max
- "at most #{max} #{pluralize['element', max]}"
- end
- end
-
- # :call-seq:
- # assert_select_rjs(id?) { |elements| ... }
- # assert_select_rjs(statement, id?) { |elements| ... }
- # assert_select_rjs(:insert, position, id?) { |elements| ... }
- #
- # Selects content from the RJS response.
- #
- # === Narrowing down
- #
- # With no arguments, asserts that one or more elements are updated or
- # inserted by RJS statements.
- #
- # Use the +id+ argument to narrow down the assertion to only statements
- # that update or insert an element with that identifier.
- #
- # Use the first argument to narrow down assertions to only statements
- # of that type. Possible values are :replace , :replace_html ,
- # :show , :hide , :toggle , :remove and
- # :insert_html .
- #
- # Use the argument :insert followed by an insertion position to narrow
- # down the assertion to only statements that insert elements in that
- # position. Possible values are :top , :bottom , :before
- # and :after .
- #
- # Using the :remove statement, you will be able to pass a block, but it will
- # be ignored as there is no HTML passed for this statement.
- #
- # === Using blocks
- #
- # Without a block, +assert_select_rjs+ merely asserts that the response
- # contains one or more RJS statements that replace or update content.
- #
- # With a block, +assert_select_rjs+ also selects all elements used in
- # these statements and passes them to the block. Nested assertions are
- # supported.
- #
- # Calling +assert_select_rjs+ with no arguments and using nested asserts
- # asserts that the HTML content is returned by one or more RJS statements.
- # Using +assert_select+ directly makes the same assertion on the content,
- # but without distinguishing whether the content is returned in an HTML
- # or JavaScript.
- #
- # ==== Examples
- #
- # # Replacing the element foo.
- # # page.replace 'foo', ...
- # assert_select_rjs :replace, "foo"
- #
- # # Replacing with the chained RJS proxy.
- # # page[:foo].replace ...
- # assert_select_rjs :chained_replace, 'foo'
- #
- # # Inserting into the element bar, top position.
- # assert_select_rjs :insert, :top, "bar"
- #
- # # Remove the element bar
- # assert_select_rjs :remove, "bar"
- #
- # # Changing the element foo, with an image.
- # assert_select_rjs "foo" do
- # assert_select "img[src=/images/logo.gif""
- # end
- #
- # # RJS inserts or updates a list with four items.
- # assert_select_rjs do
- # assert_select "ol>li", 4
- # end
- #
- # # The same, but shorter.
- # assert_select "ol>li", 4
- def assert_select_rjs(*args, &block)
- rjs_type = args.first.is_a?(Symbol) ? args.shift : nil
- id = args.first.is_a?(String) ? args.shift : nil
-
- # If the first argument is a symbol, it's the type of RJS statement we're looking
- # for (update, replace, insertion, etc). Otherwise, we're looking for just about
- # any RJS statement.
- if rjs_type
- if rjs_type == :insert
- position = args.shift
- id = args.shift
- insertion = "insert_#{position}".to_sym
- raise ArgumentError, "Unknown RJS insertion type #{position}" unless RJS_STATEMENTS[insertion]
- statement = "(#{RJS_STATEMENTS[insertion]})"
- else
- raise ArgumentError, "Unknown RJS statement type #{rjs_type}" unless RJS_STATEMENTS[rjs_type]
- statement = "(#{RJS_STATEMENTS[rjs_type]})"
- end
- else
- statement = "#{RJS_STATEMENTS[:any]}"
- end
-
- # Next argument we're looking for is the element identifier. If missing, we pick
- # any element, otherwise we replace it in the statement.
- pattern = Regexp.new(
- id ? statement.gsub(RJS_ANY_ID, "\"#{id}\"") : statement
- )
-
- # Duplicate the body since the next step involves destroying it.
- matches = nil
- case rjs_type
- when :remove, :show, :hide, :toggle
- matches = @response.body.match(pattern)
- else
- @response.body.gsub(pattern) do |match|
- html = unescape_rjs(match)
- matches ||= []
- matches.concat HTML::Document.new(html).root.children.select { |n| n.tag? }
- ""
- end
- end
-
- if matches
- assert_block("") { true } # to count the assertion
- if block_given? && !([:remove, :show, :hide, :toggle].include? rjs_type)
- begin
- in_scope, @selected = @selected, matches
- yield matches
- ensure
- @selected = in_scope
- end
- end
- matches
- else
- # RJS statement not found.
- case rjs_type
- when :remove, :show, :hide, :toggle
- flunk_message = "No RJS statement that #{rjs_type.to_s}s '#{id}' was rendered."
- else
- flunk_message = "No RJS statement that replaces or inserts HTML content."
- end
- flunk args.shift || flunk_message
- end
- end
-
- # :call-seq:
- # assert_select_encoded(element?) { |elements| ... }
- #
- # Extracts the content of an element, treats it as encoded HTML and runs
- # nested assertion on it.
- #
- # You typically call this method within another assertion to operate on
- # all currently selected elements. You can also pass an element or array
- # of elements.
- #
- # The content of each element is un-encoded, and wrapped in the root
- # element +encoded+. It then calls the block with all un-encoded elements.
- #
- # ==== Examples
- # # Selects all bold tags from within the title of an ATOM feed's entries (perhaps to nab a section name prefix)
- # assert_select_feed :atom, 1.0 do
- # # Select each entry item and then the title item
- # assert_select "entry>title" do
- # # Run assertions on the encoded title elements
- # assert_select_encoded do
- # assert_select "b"
- # end
- # end
- # end
- #
- #
- # # Selects all paragraph tags from within the description of an RSS feed
- # assert_select_feed :rss, 2.0 do
- # # Select description element of each feed item.
- # assert_select "channel>item>description" do
- # # Run assertions on the encoded elements.
- # assert_select_encoded do
- # assert_select "p"
- # end
- # end
- # end
- def assert_select_encoded(element = nil, &block)
- case element
- when Array
- elements = element
- when HTML::Node
- elements = [element]
- when nil
- unless elements = @selected
- raise ArgumentError, "First argument is optional, but must be called from a nested assert_select"
- end
- else
- raise ArgumentError, "Argument is optional, and may be node or array of nodes"
- end
-
- fix_content = lambda do |node|
- # Gets around a bug in the Rails 1.1 HTML parser.
- node.content.gsub(/)?/m) { CGI.escapeHTML($1) }
- end
-
- selected = elements.map do |element|
- text = element.children.select{ |c| not c.tag? }.map{ |c| fix_content[c] }.join
- root = HTML::Document.new(CGI.unescapeHTML("#{text} ")).root
- css_select(root, "encoded:root", &block)[0]
- end
-
- begin
- old_selected, @selected = @selected, selected
- assert_select ":root", &block
- ensure
- @selected = old_selected
- end
- end
-
- # :call-seq:
- # assert_select_email { }
- #
- # Extracts the body of an email and runs nested assertions on it.
- #
- # You must enable deliveries for this assertion to work, use:
- # ActionMailer::Base.perform_deliveries = true
- #
- # ==== Examples
- #
- # assert_select_email do
- # assert_select "h1", "Email alert"
- # end
- #
- # assert_select_email do
- # items = assert_select "ol>li"
- # items.each do
- # # Work with items here...
- # end
- # end
- #
- def assert_select_email(&block)
- deliveries = ActionMailer::Base.deliveries
- assert !deliveries.empty?, "No e-mail in delivery list"
-
- for delivery in deliveries
- for part in delivery.parts
- if part["Content-Type"].to_s =~ /^text\/html\W/
- root = HTML::Document.new(part.body).root
- assert_select root, ":root", &block
- end
- end
- end
- end
-
- protected
- unless const_defined?(:RJS_STATEMENTS)
- RJS_PATTERN_HTML = "\"((\\\\\"|[^\"])*)\""
- RJS_ANY_ID = "\"([^\"])*\""
- RJS_STATEMENTS = {
- :chained_replace => "\\$\\(#{RJS_ANY_ID}\\)\\.replace\\(#{RJS_PATTERN_HTML}\\)",
- :chained_replace_html => "\\$\\(#{RJS_ANY_ID}\\)\\.update\\(#{RJS_PATTERN_HTML}\\)",
- :replace_html => "Element\\.update\\(#{RJS_ANY_ID}, #{RJS_PATTERN_HTML}\\)",
- :replace => "Element\\.replace\\(#{RJS_ANY_ID}, #{RJS_PATTERN_HTML}\\)"
- }
- [:remove, :show, :hide, :toggle].each do |action|
- RJS_STATEMENTS[action] = "Element\\.#{action}\\(#{RJS_ANY_ID}\\)"
- end
- RJS_INSERTIONS = ["top", "bottom", "before", "after"]
- RJS_INSERTIONS.each do |insertion|
- RJS_STATEMENTS["insert_#{insertion}".to_sym] = "Element.insert\\(#{RJS_ANY_ID}, \\{ #{insertion}: #{RJS_PATTERN_HTML} \\}\\)"
- end
- RJS_STATEMENTS[:insert_html] = "Element.insert\\(#{RJS_ANY_ID}, \\{ (#{RJS_INSERTIONS.join('|')}): #{RJS_PATTERN_HTML} \\}\\)"
- RJS_STATEMENTS[:any] = Regexp.new("(#{RJS_STATEMENTS.values.join('|')})")
- RJS_PATTERN_UNICODE_ESCAPED_CHAR = /\\u([0-9a-zA-Z]{4})/
- end
-
- # +assert_select+ and +css_select+ call this to obtain the content in the HTML
- # page, or from all the RJS statements, depending on the type of response.
- def response_from_page_or_rjs()
- content_type = @response.content_type
-
- if content_type && Mime::JS =~ content_type
- body = @response.body.dup
- root = HTML::Node.new(nil)
-
- while true
- next if body.sub!(RJS_STATEMENTS[:any]) do |match|
- html = unescape_rjs(match)
- matches = HTML::Document.new(html).root.children.select { |n| n.tag? }
- root.children.concat matches
- ""
- end
- break
- end
-
- root
- else
- html_document.root
- end
- end
-
- # Unescapes a RJS string.
- def unescape_rjs(rjs_string)
- # RJS encodes double quotes and line breaks.
- unescaped= rjs_string.gsub('\"', '"')
- unescaped.gsub!(/\\\//, '/')
- unescaped.gsub!('\n', "\n")
- unescaped.gsub!('\076', '>')
- unescaped.gsub!('\074', '<')
- # RJS encodes non-ascii characters.
- unescaped.gsub!(RJS_PATTERN_UNICODE_ESCAPED_CHAR) {|u| [$1.hex].pack('U*')}
- unescaped
- end
- end
- end
-end
diff --git a/actionpack/lib/action_controller/testing/assertions/tag.rb b/actionpack/lib/action_controller/testing/assertions/tag.rb
deleted file mode 100644
index d9197b7855..0000000000
--- a/actionpack/lib/action_controller/testing/assertions/tag.rb
+++ /dev/null
@@ -1,123 +0,0 @@
-module ActionController
- module Assertions
- # Pair of assertions to testing elements in the HTML output of the response.
- module TagAssertions
- # Asserts that there is a tag/node/element in the body of the response
- # that meets all of the given conditions. The +conditions+ parameter must
- # be a hash of any of the following keys (all are optional):
- #
- # * :tag : the node type must match the corresponding value
- # * :attributes : a hash. The node's attributes must match the
- # corresponding values in the hash.
- # * :parent : a hash. The node's parent must match the
- # corresponding hash.
- # * :child : a hash. At least one of the node's immediate children
- # must meet the criteria described by the hash.
- # * :ancestor : a hash. At least one of the node's ancestors must
- # meet the criteria described by the hash.
- # * :descendant : a hash. At least one of the node's descendants
- # must meet the criteria described by the hash.
- # * :sibling : a hash. At least one of the node's siblings must
- # meet the criteria described by the hash.
- # * :after : a hash. The node must be after any sibling meeting
- # the criteria described by the hash, and at least one sibling must match.
- # * :before : a hash. The node must be before any sibling meeting
- # the criteria described by the hash, and at least one sibling must match.
- # * :children : a hash, for counting children of a node. Accepts
- # the keys:
- # * :count : either a number or a range which must equal (or
- # include) the number of children that match.
- # * :less_than : the number of matching children must be less
- # than this number.
- # * :greater_than : the number of matching children must be
- # greater than this number.
- # * :only : another hash consisting of the keys to use
- # to match on the children, and only matching children will be
- # counted.
- # * :content : the textual content of the node must match the
- # given value. This will not match HTML tags in the body of a
- # tag--only text.
- #
- # Conditions are matched using the following algorithm:
- #
- # * if the condition is a string, it must be a substring of the value.
- # * if the condition is a regexp, it must match the value.
- # * if the condition is a number, the value must match number.to_s.
- # * if the condition is +true+, the value must not be +nil+.
- # * if the condition is +false+ or +nil+, the value must be +nil+.
- #
- # === Examples
- #
- # # Assert that there is a "span" tag
- # assert_tag :tag => "span"
- #
- # # Assert that there is a "span" tag with id="x"
- # assert_tag :tag => "span", :attributes => { :id => "x" }
- #
- # # Assert that there is a "span" tag using the short-hand
- # assert_tag :span
- #
- # # Assert that there is a "span" tag with id="x" using the short-hand
- # assert_tag :span, :attributes => { :id => "x" }
- #
- # # Assert that there is a "span" inside of a "div"
- # assert_tag :tag => "span", :parent => { :tag => "div" }
- #
- # # Assert that there is a "span" somewhere inside a table
- # assert_tag :tag => "span", :ancestor => { :tag => "table" }
- #
- # # Assert that there is a "span" with at least one "em" child
- # assert_tag :tag => "span", :child => { :tag => "em" }
- #
- # # Assert that there is a "span" containing a (possibly nested)
- # # "strong" tag.
- # assert_tag :tag => "span", :descendant => { :tag => "strong" }
- #
- # # Assert that there is a "span" containing between 2 and 4 "em" tags
- # # as immediate children
- # assert_tag :tag => "span",
- # :children => { :count => 2..4, :only => { :tag => "em" } }
- #
- # # Get funky: assert that there is a "div", with an "ul" ancestor
- # # and an "li" parent (with "class" = "enum"), and containing a
- # # "span" descendant that contains text matching /hello world/
- # assert_tag :tag => "div",
- # :ancestor => { :tag => "ul" },
- # :parent => { :tag => "li",
- # :attributes => { :class => "enum" } },
- # :descendant => { :tag => "span",
- # :child => /hello world/ }
- #
- # Please note : +assert_tag+ and +assert_no_tag+ only work
- # with well-formed XHTML. They recognize a few tags as implicitly self-closing
- # (like br and hr and such) but will not work correctly with tags
- # that allow optional closing tags (p, li, td). You must explicitly
- # close all of your tags to use these assertions.
- def assert_tag(*opts)
- opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
- tag = find_tag(opts)
- assert tag, "expected tag, but no tag found matching #{opts.inspect} in:\n#{@response.body.inspect}"
- end
-
- # Identical to +assert_tag+, but asserts that a matching tag does _not_
- # exist. (See +assert_tag+ for a full discussion of the syntax.)
- #
- # === Examples
- # # Assert that there is not a "div" containing a "p"
- # assert_no_tag :tag => "div", :descendant => { :tag => "p" }
- #
- # # Assert that an unordered list is empty
- # assert_no_tag :tag => "ul", :descendant => { :tag => "li" }
- #
- # # Assert that there is not a "p" tag with between 1 to 3 "img" tags
- # # as immediate children
- # assert_no_tag :tag => "p",
- # :children => { :count => 1..3, :only => { :tag => "img" } }
- def assert_no_tag(*opts)
- opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
- tag = find_tag(opts)
- assert !tag, "expected no tag, but found tag matching #{opts.inspect} in:\n#{@response.body.inspect}"
- end
- end
- end
-end
diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb
index f960698566..7fa1fd93bf 100644
--- a/actionpack/lib/action_controller/testing/integration.rb
+++ b/actionpack/lib/action_controller/testing/integration.rb
@@ -14,7 +14,7 @@ module ActionController
# Integration::Session directly.
class Session
include Test::Unit::Assertions
- include ActionController::TestCase::Assertions
+ include ActionDispatch::Assertions
include ActionController::TestProcess
# The integer HTTP status code of the last request.
diff --git a/actionpack/lib/action_controller/testing/test_case.rb b/actionpack/lib/action_controller/testing/test_case.rb
index a80488e13e..7b4eda58e5 100644
--- a/actionpack/lib/action_controller/testing/test_case.rb
+++ b/actionpack/lib/action_controller/testing/test_case.rb
@@ -105,12 +105,7 @@ module ActionController
class TestCase < ActiveSupport::TestCase
include TestProcess
- module Assertions
- %w(response selector tag dom routing model).each do |kind|
- include ActionController::Assertions.const_get("#{kind.camelize}Assertions")
- end
- end
- include Assertions
+ include ActionDispatch::Assertions
# When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline
# (bystepping the regular exception handling from rescue_action). If the request.remote_addr is anything else, the regular
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 4f65dcadee..8b8a1774e4 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -45,6 +45,8 @@ module ActionDispatch
autoload :Reloader, 'action_dispatch/middleware/reloader'
autoload :MiddlewareStack, 'action_dispatch/middleware/stack'
+ autoload :Assertions, 'action_dispatch/testing/assertions'
+
module Http
autoload :Headers, 'action_dispatch/http/headers'
end
diff --git a/actionpack/lib/action_dispatch/testing/assertions.rb b/actionpack/lib/action_dispatch/testing/assertions.rb
new file mode 100644
index 0000000000..96f08f2355
--- /dev/null
+++ b/actionpack/lib/action_dispatch/testing/assertions.rb
@@ -0,0 +1,8 @@
+module ActionDispatch
+ module Assertions
+ %w(response selector tag dom routing model).each do |kind|
+ require "action_dispatch/testing/assertions/#{kind}"
+ include const_get("#{kind.camelize}Assertions")
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/testing/assertions/dom.rb b/actionpack/lib/action_dispatch/testing/assertions/dom.rb
new file mode 100644
index 0000000000..9a917f704a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/testing/assertions/dom.rb
@@ -0,0 +1,35 @@
+module ActionDispatch
+ module Assertions
+ module DomAssertions
+ # Test two HTML strings for equivalency (e.g., identical up to reordering of attributes)
+ #
+ # ==== Examples
+ #
+ # # assert that the referenced method generates the appropriate HTML string
+ # assert_dom_equal 'Apples ', link_to("Apples", "http://www.example.com")
+ #
+ def assert_dom_equal(expected, actual, message = "")
+ expected_dom = HTML::Document.new(expected).root
+ actual_dom = HTML::Document.new(actual).root
+ full_message = build_message(message, "> expected to be == to\n>.", expected_dom.to_s, actual_dom.to_s)
+
+ assert_block(full_message) { expected_dom == actual_dom }
+ end
+
+ # The negated form of +assert_dom_equivalent+.
+ #
+ # ==== Examples
+ #
+ # # assert that the referenced method does not generate the specified HTML string
+ # assert_dom_not_equal 'Apples ', link_to("Oranges", "http://www.example.com")
+ #
+ def assert_dom_not_equal(expected, actual, message = "")
+ expected_dom = HTML::Document.new(expected).root
+ actual_dom = HTML::Document.new(actual).root
+ full_message = build_message(message, "> expected to be != to\n>.", expected_dom.to_s, actual_dom.to_s)
+
+ assert_block(full_message) { expected_dom != actual_dom }
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/testing/assertions/model.rb b/actionpack/lib/action_dispatch/testing/assertions/model.rb
new file mode 100644
index 0000000000..46714418c6
--- /dev/null
+++ b/actionpack/lib/action_dispatch/testing/assertions/model.rb
@@ -0,0 +1,19 @@
+module ActionDispatch
+ module Assertions
+ module ModelAssertions
+ # Ensures that the passed record is valid by Active Record standards and
+ # returns any error messages if it is not.
+ #
+ # ==== Examples
+ #
+ # # assert that a newly created record is valid
+ # model = Model.new
+ # assert_valid(model)
+ #
+ def assert_valid(record)
+ ::ActiveSupport::Deprecation.warn("assert_valid is deprecated. Use assert record.valid? instead", caller)
+ assert record.valid?, record.errors.full_messages.join("\n")
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb
new file mode 100644
index 0000000000..a72ce9084f
--- /dev/null
+++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb
@@ -0,0 +1,156 @@
+module ActionDispatch
+ module Assertions
+ # A small suite of assertions that test responses from Rails applications.
+ module ResponseAssertions
+ # Asserts that the response is one of the following types:
+ #
+ # * :success - Status code was 200
+ # * :redirect - Status code was in the 300-399 range
+ # * :missing - Status code was 404
+ # * :error - Status code was in the 500-599 range
+ #
+ # You can also pass an explicit status number like assert_response(501)
+ # or its symbolic equivalent assert_response(:not_implemented).
+ # See ActionDispatch::StatusCodes for a full list.
+ #
+ # ==== Examples
+ #
+ # # assert that the response was a redirection
+ # assert_response :redirect
+ #
+ # # assert that the response code was status code 401 (unauthorized)
+ # assert_response 401
+ #
+ def assert_response(type, message = nil)
+ validate_request!
+
+ if [ :success, :missing, :redirect, :error ].include?(type) && @response.send("#{type}?")
+ assert_block("") { true } # to count the assertion
+ elsif type.is_a?(Fixnum) && @response.response_code == type
+ assert_block("") { true } # to count the assertion
+ elsif type.is_a?(Symbol) && @response.response_code == ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[type]
+ assert_block("") { true } # to count the assertion
+ else
+ if @controller && @response.error?
+ 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
+ assert_block(build_message(message, "Expected response to be a >, but was >", type, @response.response_code)) { false }
+ end
+ end
+ end
+
+ # Assert that the redirection options passed in match those of the redirect called in the latest action.
+ # This match can be partial, such that assert_redirected_to(:controller => "weblog") will also
+ # match the redirection of redirect_to(:controller => "weblog", :action => "show") and so on.
+ #
+ # ==== Examples
+ #
+ # # assert that the redirection was to the "index" action on the WeblogController
+ # assert_redirected_to :controller => "weblog", :action => "index"
+ #
+ # # assert that the redirection was to the named route login_url
+ # assert_redirected_to login_url
+ #
+ # # assert that the redirection was to the url for @customer
+ # assert_redirected_to @customer
+ #
+ def assert_redirected_to(options = {}, message=nil)
+ validate_request!
+
+ assert_response(:redirect, message)
+ return true if options == @response.redirected_to
+
+ # Support partial arguments for hash redirections
+ if options.is_a?(Hash) && @response.redirected_to.is_a?(Hash)
+ return true if options.all? {|(key, value)| @response.redirected_to[key] == value}
+ end
+
+ redirected_to_after_normalisation = normalize_argument_to_redirection(@response.redirected_to)
+ options_after_normalisation = normalize_argument_to_redirection(options)
+
+ if redirected_to_after_normalisation != options_after_normalisation
+ flunk "Expected response to be a redirect to <#{options_after_normalisation}> but was a redirect to <#{redirected_to_after_normalisation}>"
+ end
+ end
+
+ # Asserts that the request was rendered with the appropriate template file or partials
+ #
+ # ==== Examples
+ #
+ # # assert that the "new" view template was rendered
+ # assert_template "new"
+ #
+ # # assert that the "_customer" partial was rendered twice
+ # assert_template :partial => '_customer', :count => 2
+ #
+ # # assert that no partials were rendered
+ # assert_template :partial => false
+ #
+ def assert_template(options = {}, message = nil)
+ validate_request!
+
+ case options
+ when NilClass, String
+ 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.template.rendered[:template].blank?
+ else
+ rendered.any? { |t| t.match(options) }
+ end
+ end
+ when Hash
+ if expected_partial = options[:partial]
+ 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
+ msg = build_message(message,
+ "expecting ? to be rendered ? time(s) but rendered ? time(s)",
+ expected_partial, expected_count, actual_count)
+ assert(actual_count == expected_count.to_i, msg)
+ else
+ msg = build_message(message,
+ "expecting partial > but action rendered >",
+ options[:partial], partials.keys)
+ assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg)
+ end
+ else
+ assert @controller.template.rendered[:partials].empty?,
+ "Expected no partials to be rendered"
+ end
+ end
+ end
+
+ private
+ # Proxy to to_param if the object will respond to it.
+ def parameterize(value)
+ value.respond_to?(:to_param) ? value.to_param : value
+ end
+
+ def normalize_argument_to_redirection(fragment)
+ after_routing = @controller.url_for(fragment)
+ if after_routing =~ %r{^\w+://.*}
+ after_routing
+ else
+ # FIXME - this should probably get removed.
+ if after_routing.first != '/'
+ after_routing = '/' + after_routing
+ end
+ @request.protocol + @request.host_with_port + after_routing
+ end
+ end
+
+ def validate_request!
+ unless @request.is_a?(ActionDispatch::Request)
+ raise ArgumentError, "@request must be an ActionDispatch::Request"
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
new file mode 100644
index 0000000000..89d1a49403
--- /dev/null
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -0,0 +1,142 @@
+module ActionDispatch
+ module Assertions
+ # Suite of assertions to test routes generated by Rails and the handling of requests made to them.
+ module RoutingAssertions
+ # Asserts that the routing of the given +path+ was handled correctly and that the parsed options (given in the +expected_options+ hash)
+ # match +path+. Basically, it asserts that Rails recognizes the route given by +expected_options+.
+ #
+ # Pass a hash in the second argument (+path+) to specify the request method. This is useful for routes
+ # requiring a specific HTTP method. The hash should contain a :path with the incoming request path
+ # and a :method containing the required HTTP verb.
+ #
+ # # assert that POSTing to /items will call the create action on ItemsController
+ # assert_recognizes {:controller => 'items', :action => 'create'}, {:path => 'items', :method => :post}
+ #
+ # You can also pass in +extras+ with a hash containing URL parameters that would normally be in the query string. This can be used
+ # to assert that values in the query string string will end up in the params hash correctly. To test query strings you must use the
+ # extras argument, appending the query string on the path directly will not work. For example:
+ #
+ # # assert that a path of '/items/list/1?view=print' returns the correct options
+ # assert_recognizes {:controller => 'items', :action => 'list', :id => '1', :view => 'print'}, 'items/list/1', { :view => "print" }
+ #
+ # The +message+ parameter allows you to pass in an error message that is displayed upon failure.
+ #
+ # ==== Examples
+ # # Check the default route (i.e., the index action)
+ # assert_recognizes {:controller => 'items', :action => 'index'}, 'items'
+ #
+ # # Test a specific action
+ # assert_recognizes {:controller => 'items', :action => 'list'}, 'items/list'
+ #
+ # # Test an action with a parameter
+ # assert_recognizes {:controller => 'items', :action => 'destroy', :id => '1'}, 'items/destroy/1'
+ #
+ # # Test a custom route
+ # assert_recognizes {:controller => 'items', :action => 'show', :id => '1'}, 'view/item1'
+ #
+ # # Check a Simply RESTful generated route
+ # assert_recognizes list_items_url, 'items/list'
+ def assert_recognizes(expected_options, path, extras={}, message=nil)
+ if path.is_a? Hash
+ request_method = path[:method]
+ path = path[:path]
+ else
+ request_method = nil
+ end
+
+ ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
+ request = recognized_request_for(path, request_method)
+
+ expected_options = expected_options.clone
+ extras.each_key { |key| expected_options.delete key } unless extras.nil?
+
+ expected_options.stringify_keys!
+ routing_diff = expected_options.diff(request.path_parameters)
+ msg = build_message(message, "The recognized options > did not match >, difference: >",
+ request.path_parameters, expected_options, expected_options.diff(request.path_parameters))
+ assert_block(msg) { request.path_parameters == expected_options }
+ end
+
+ # Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+.
+ # The +extras+ parameter is used to tell the request the names and values of additional request parameters that would be in
+ # a query string. The +message+ parameter allows you to specify a custom error message for assertion failures.
+ #
+ # The +defaults+ parameter is unused.
+ #
+ # ==== Examples
+ # # Asserts that the default action is generated for a route with no action
+ # assert_generates "/items", :controller => "items", :action => "index"
+ #
+ # # Tests that the list action is properly routed
+ # assert_generates "/items/list", :controller => "items", :action => "list"
+ #
+ # # Tests the generation of a route with a parameter
+ # assert_generates "/items/list/1", { :controller => "items", :action => "list", :id => "1" }
+ #
+ # # Asserts that the generated route gives us our custom route
+ # assert_generates "changesets/12", { :controller => 'scm', :action => 'show_diff', :revision => "12" }
+ def assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)
+ expected_path = "/#{expected_path}" unless expected_path[0] == ?/
+ # Load routes.rb if it hasn't been loaded.
+ ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
+
+ generated_path, extra_keys = ActionController::Routing::Routes.generate_extras(options, defaults)
+ found_extras = options.reject {|k, v| ! extra_keys.include? k}
+
+ msg = build_message(message, "found extras >, not >", found_extras, extras)
+ assert_block(msg) { found_extras == extras }
+
+ msg = build_message(message, "The generated path > did not match >", generated_path,
+ expected_path)
+ assert_block(msg) { expected_path == generated_path }
+ end
+
+ # Asserts that path and options match both ways; in other words, it verifies that path generates
+ # options and then that options generates path . This essentially combines +assert_recognizes+
+ # and +assert_generates+ into one step.
+ #
+ # The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The
+ # +message+ parameter allows you to specify a custom error message to display upon failure.
+ #
+ # ==== Examples
+ # # Assert a basic route: a controller with the default action (index)
+ # assert_routing '/home', :controller => 'home', :action => 'index'
+ #
+ # # Test a route generated with a specific controller, action, and parameter (id)
+ # assert_routing '/entries/show/23', :controller => 'entries', :action => 'show', id => 23
+ #
+ # # Assert a basic route (controller + default action), with an error message if it fails
+ # assert_routing '/store', { :controller => 'store', :action => 'index' }, {}, {}, 'Route for store index not generated properly'
+ #
+ # # Tests a route, providing a defaults hash
+ # assert_routing 'controller/action/9', {:id => "9", :item => "square"}, {:controller => "controller", :action => "action"}, {}, {:item => "square"}
+ #
+ # # Tests a route with a HTTP method
+ # assert_routing { :method => 'put', :path => '/product/321' }, { :controller => "product", :action => "update", :id => "321" }
+ def assert_routing(path, options, defaults={}, extras={}, message=nil)
+ assert_recognizes(options, path, extras, message)
+
+ controller, default_controller = options[:controller], defaults[:controller]
+ if controller && controller.include?(?/) && default_controller && default_controller.include?(?/)
+ options[:controller] = "/#{controller}"
+ end
+
+ assert_generates(path.is_a?(Hash) ? path[:path] : path, options, defaults, extras, message)
+ end
+
+ private
+ # Recognizes the route for a given path.
+ def recognized_request_for(path, request_method = nil)
+ path = "/#{path}" unless path.first == '/'
+
+ # Assume given controller
+ request = ActionController::TestRequest.new
+ request.env["REQUEST_METHOD"] = request_method.to_s.upcase if request_method
+ request.path = path
+
+ ActionController::Routing::Routes.recognize(request)
+ request
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb
new file mode 100644
index 0000000000..dd75cda6b9
--- /dev/null
+++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb
@@ -0,0 +1,632 @@
+#--
+# Copyright (c) 2006 Assaf Arkin (http://labnotes.org)
+# Under MIT and/or CC By license.
+#++
+
+module ActionDispatch
+ module Assertions
+ unless const_defined?(:NO_STRIP)
+ NO_STRIP = %w{pre script style textarea}
+ end
+
+ # Adds the +assert_select+ method for use in Rails functional
+ # test cases, which can be used to make assertions on the response HTML of a controller
+ # action. You can also call +assert_select+ within another +assert_select+ to
+ # make assertions on elements selected by the enclosing assertion.
+ #
+ # Use +css_select+ to select elements without making an assertions, either
+ # from the response HTML or elements selected by the enclosing assertion.
+ #
+ # In addition to HTML responses, you can make the following assertions:
+ # * +assert_select_rjs+ - Assertions on HTML content of RJS update and insertion operations.
+ # * +assert_select_encoded+ - Assertions on HTML encoded inside XML, for example for dealing with feed item descriptions.
+ # * +assert_select_email+ - Assertions on the HTML body of an e-mail.
+ #
+ # Also see HTML::Selector to learn how to use selectors.
+ module SelectorAssertions
+ # :call-seq:
+ # css_select(selector) => array
+ # css_select(element, selector) => array
+ #
+ # Select and return all matching elements.
+ #
+ # If called with a single argument, uses that argument as a selector
+ # to match all elements of the current page. Returns an empty array
+ # if no match is found.
+ #
+ # If called with two arguments, uses the first argument as the base
+ # element and the second argument as the selector. Attempts to match the
+ # base element and any of its children. Returns an empty array if no
+ # match is found.
+ #
+ # The selector may be a CSS selector expression (String), an expression
+ # with substitution values (Array) or an HTML::Selector object.
+ #
+ # ==== Examples
+ # # Selects all div tags
+ # divs = css_select("div")
+ #
+ # # Selects all paragraph tags and does something interesting
+ # pars = css_select("p")
+ # pars.each do |par|
+ # # Do something fun with paragraphs here...
+ # end
+ #
+ # # Selects all list items in unordered lists
+ # items = css_select("ul>li")
+ #
+ # # Selects all form tags and then all inputs inside the form
+ # forms = css_select("form")
+ # forms.each do |form|
+ # inputs = css_select(form, "input")
+ # ...
+ # end
+ #
+ def css_select(*args)
+ # See assert_select to understand what's going on here.
+ arg = args.shift
+
+ if arg.is_a?(HTML::Node)
+ root = arg
+ arg = args.shift
+ elsif arg == nil
+ raise ArgumentError, "First argument is either selector or element to select, but nil found. Perhaps you called assert_select with an element that does not exist?"
+ elsif @selected
+ matches = []
+
+ @selected.each do |selected|
+ subset = css_select(selected, HTML::Selector.new(arg.dup, args.dup))
+ subset.each do |match|
+ matches << match unless matches.any? { |m| m.equal?(match) }
+ end
+ end
+
+ return matches
+ else
+ root = response_from_page_or_rjs
+ end
+
+ case arg
+ when String
+ selector = HTML::Selector.new(arg, args)
+ when Array
+ selector = HTML::Selector.new(*arg)
+ when HTML::Selector
+ selector = arg
+ else raise ArgumentError, "Expecting a selector as the first argument"
+ end
+
+ selector.select(root)
+ end
+
+ # :call-seq:
+ # assert_select(selector, equality?, message?)
+ # assert_select(element, selector, equality?, message?)
+ #
+ # An assertion that selects elements and makes one or more equality tests.
+ #
+ # If the first argument is an element, selects all matching elements
+ # starting from (and including) that element and all its children in
+ # depth-first order.
+ #
+ # If no element if specified, calling +assert_select+ selects from the
+ # response HTML unless +assert_select+ is called from within an +assert_select+ block.
+ #
+ # When called with a block +assert_select+ passes an array of selected elements
+ # to the block. Calling +assert_select+ from the block, with no element specified,
+ # runs the assertion on the complete set of elements selected by the enclosing assertion.
+ # Alternatively the array may be iterated through so that +assert_select+ can be called
+ # separately for each element.
+ #
+ #
+ # ==== Example
+ # If the response contains two ordered lists, each with four list elements then:
+ # assert_select "ol" do |elements|
+ # elements.each do |element|
+ # assert_select element, "li", 4
+ # end
+ # end
+ #
+ # will pass, as will:
+ # assert_select "ol" do
+ # assert_select "li", 8
+ # end
+ #
+ # The selector may be a CSS selector expression (String), an expression
+ # with substitution values, or an HTML::Selector object.
+ #
+ # === Equality Tests
+ #
+ # The equality test may be one of the following:
+ # * true - Assertion is true if at least one element selected.
+ # * false - Assertion is true if no element selected.
+ # * String/Regexp - Assertion is true if the text value of at least
+ # one element matches the string or regular expression.
+ # * Integer - Assertion is true if exactly that number of
+ # elements are selected.
+ # * Range - Assertion is true if the number of selected
+ # elements fit the range.
+ # If no equality test specified, the assertion is true if at least one
+ # element selected.
+ #
+ # To perform more than one equality tests, use a hash with the following keys:
+ # * :text - Narrow the selection to elements that have this text
+ # value (string or regexp).
+ # * :html - Narrow the selection to elements that have this HTML
+ # content (string or regexp).
+ # * :count - Assertion is true if the number of selected elements
+ # is equal to this value.
+ # * :minimum - Assertion is true if the number of selected
+ # elements is at least this value.
+ # * :maximum - Assertion is true if the number of selected
+ # elements is at most this value.
+ #
+ # If the method is called with a block, once all equality tests are
+ # evaluated the block is called with an array of all matched elements.
+ #
+ # ==== Examples
+ #
+ # # At least one form element
+ # assert_select "form"
+ #
+ # # Form element includes four input fields
+ # assert_select "form input", 4
+ #
+ # # Page title is "Welcome"
+ # assert_select "title", "Welcome"
+ #
+ # # Page title is "Welcome" and there is only one title element
+ # assert_select "title", {:count=>1, :text=>"Welcome"},
+ # "Wrong title or more than one title element"
+ #
+ # # Page contains no forms
+ # assert_select "form", false, "This page must contain no forms"
+ #
+ # # Test the content and style
+ # assert_select "body div.header ul.menu"
+ #
+ # # Use substitution values
+ # assert_select "ol>li#?", /item-\d+/
+ #
+ # # All input fields in the form have a name
+ # assert_select "form input" do
+ # assert_select "[name=?]", /.+/ # Not empty
+ # end
+ def assert_select(*args, &block)
+ # Start with optional element followed by mandatory selector.
+ arg = args.shift
+
+ if arg.is_a?(HTML::Node)
+ # First argument is a node (tag or text, but also HTML root),
+ # so we know what we're selecting from.
+ root = arg
+ arg = args.shift
+ elsif arg == nil
+ # This usually happens when passing a node/element that
+ # happens to be nil.
+ raise ArgumentError, "First argument is either selector or element to select, but nil found. Perhaps you called assert_select with an element that does not exist?"
+ elsif @selected
+ root = HTML::Node.new(nil)
+ root.children.concat @selected
+ else
+ # Otherwise just operate on the response document.
+ root = response_from_page_or_rjs
+ end
+
+ # First or second argument is the selector: string and we pass
+ # all remaining arguments. Array and we pass the argument. Also
+ # accepts selector itself.
+ case arg
+ when String
+ selector = HTML::Selector.new(arg, args)
+ when Array
+ selector = HTML::Selector.new(*arg)
+ when HTML::Selector
+ selector = arg
+ else raise ArgumentError, "Expecting a selector as the first argument"
+ end
+
+ # Next argument is used for equality tests.
+ equals = {}
+ case arg = args.shift
+ when Hash
+ equals = arg
+ when String, Regexp
+ equals[:text] = arg
+ when Integer
+ equals[:count] = arg
+ when Range
+ equals[:minimum] = arg.begin
+ equals[:maximum] = arg.end
+ when FalseClass
+ equals[:count] = 0
+ when NilClass, TrueClass
+ equals[:minimum] = 1
+ else raise ArgumentError, "I don't understand what you're trying to match"
+ end
+
+ # By default we're looking for at least one match.
+ if equals[:count]
+ equals[:minimum] = equals[:maximum] = equals[:count]
+ else
+ equals[:minimum] = 1 unless equals[:minimum]
+ end
+
+ # Last argument is the message we use if the assertion fails.
+ message = args.shift
+ #- message = "No match made with selector #{selector.inspect}" unless message
+ if args.shift
+ raise ArgumentError, "Not expecting that last argument, you either have too many arguments, or they're the wrong type"
+ end
+
+ matches = selector.select(root)
+ # If text/html, narrow down to those elements that match it.
+ content_mismatch = nil
+ if match_with = equals[:text]
+ matches.delete_if do |match|
+ text = ""
+ text.force_encoding(match_with.encoding) if text.respond_to?(:force_encoding)
+ stack = match.children.reverse
+ while node = stack.pop
+ if node.tag?
+ stack.concat node.children.reverse
+ else
+ content = node.content
+ content.force_encoding(match_with.encoding) if content.respond_to?(:force_encoding)
+ text << content
+ end
+ end
+ text.strip! unless NO_STRIP.include?(match.name)
+ unless match_with.is_a?(Regexp) ? (text =~ match_with) : (text == match_with.to_s)
+ content_mismatch ||= build_message(message, "> expected but was\n>.", match_with, text)
+ true
+ end
+ end
+ elsif match_with = equals[:html]
+ matches.delete_if do |match|
+ html = match.children.map(&:to_s).join
+ html.strip! unless NO_STRIP.include?(match.name)
+ unless match_with.is_a?(Regexp) ? (html =~ match_with) : (html == match_with.to_s)
+ content_mismatch ||= build_message(message, "> expected but was\n>.", match_with, html)
+ true
+ end
+ end
+ end
+ # Expecting foo found bar element only if found zero, not if
+ # found one but expecting two.
+ message ||= content_mismatch if matches.empty?
+ # Test minimum/maximum occurrence.
+ min, max = equals[:minimum], equals[:maximum]
+ message = message || %(Expected #{count_description(min, max)} matching "#{selector.to_s}", found #{matches.size}.)
+ assert matches.size >= min, message if min
+ assert matches.size <= max, message if max
+
+ # If a block is given call that block. Set @selected to allow
+ # nested assert_select, which can be nested several levels deep.
+ if block_given? && !matches.empty?
+ begin
+ in_scope, @selected = @selected, matches
+ yield matches
+ ensure
+ @selected = in_scope
+ end
+ end
+
+ # Returns all matches elements.
+ matches
+ end
+
+ def count_description(min, max) #:nodoc:
+ pluralize = lambda {|word, quantity| word << (quantity == 1 ? '' : 's')}
+
+ if min && max && (max != min)
+ "between #{min} and #{max} elements"
+ elsif min && !(min == 1 && max == 1)
+ "at least #{min} #{pluralize['element', min]}"
+ elsif max
+ "at most #{max} #{pluralize['element', max]}"
+ end
+ end
+
+ # :call-seq:
+ # assert_select_rjs(id?) { |elements| ... }
+ # assert_select_rjs(statement, id?) { |elements| ... }
+ # assert_select_rjs(:insert, position, id?) { |elements| ... }
+ #
+ # Selects content from the RJS response.
+ #
+ # === Narrowing down
+ #
+ # With no arguments, asserts that one or more elements are updated or
+ # inserted by RJS statements.
+ #
+ # Use the +id+ argument to narrow down the assertion to only statements
+ # that update or insert an element with that identifier.
+ #
+ # Use the first argument to narrow down assertions to only statements
+ # of that type. Possible values are :replace , :replace_html ,
+ # :show , :hide , :toggle , :remove and
+ # :insert_html .
+ #
+ # Use the argument :insert followed by an insertion position to narrow
+ # down the assertion to only statements that insert elements in that
+ # position. Possible values are :top , :bottom , :before
+ # and :after .
+ #
+ # Using the :remove statement, you will be able to pass a block, but it will
+ # be ignored as there is no HTML passed for this statement.
+ #
+ # === Using blocks
+ #
+ # Without a block, +assert_select_rjs+ merely asserts that the response
+ # contains one or more RJS statements that replace or update content.
+ #
+ # With a block, +assert_select_rjs+ also selects all elements used in
+ # these statements and passes them to the block. Nested assertions are
+ # supported.
+ #
+ # Calling +assert_select_rjs+ with no arguments and using nested asserts
+ # asserts that the HTML content is returned by one or more RJS statements.
+ # Using +assert_select+ directly makes the same assertion on the content,
+ # but without distinguishing whether the content is returned in an HTML
+ # or JavaScript.
+ #
+ # ==== Examples
+ #
+ # # Replacing the element foo.
+ # # page.replace 'foo', ...
+ # assert_select_rjs :replace, "foo"
+ #
+ # # Replacing with the chained RJS proxy.
+ # # page[:foo].replace ...
+ # assert_select_rjs :chained_replace, 'foo'
+ #
+ # # Inserting into the element bar, top position.
+ # assert_select_rjs :insert, :top, "bar"
+ #
+ # # Remove the element bar
+ # assert_select_rjs :remove, "bar"
+ #
+ # # Changing the element foo, with an image.
+ # assert_select_rjs "foo" do
+ # assert_select "img[src=/images/logo.gif""
+ # end
+ #
+ # # RJS inserts or updates a list with four items.
+ # assert_select_rjs do
+ # assert_select "ol>li", 4
+ # end
+ #
+ # # The same, but shorter.
+ # assert_select "ol>li", 4
+ def assert_select_rjs(*args, &block)
+ rjs_type = args.first.is_a?(Symbol) ? args.shift : nil
+ id = args.first.is_a?(String) ? args.shift : nil
+
+ # If the first argument is a symbol, it's the type of RJS statement we're looking
+ # for (update, replace, insertion, etc). Otherwise, we're looking for just about
+ # any RJS statement.
+ if rjs_type
+ if rjs_type == :insert
+ position = args.shift
+ id = args.shift
+ insertion = "insert_#{position}".to_sym
+ raise ArgumentError, "Unknown RJS insertion type #{position}" unless RJS_STATEMENTS[insertion]
+ statement = "(#{RJS_STATEMENTS[insertion]})"
+ else
+ raise ArgumentError, "Unknown RJS statement type #{rjs_type}" unless RJS_STATEMENTS[rjs_type]
+ statement = "(#{RJS_STATEMENTS[rjs_type]})"
+ end
+ else
+ statement = "#{RJS_STATEMENTS[:any]}"
+ end
+
+ # Next argument we're looking for is the element identifier. If missing, we pick
+ # any element, otherwise we replace it in the statement.
+ pattern = Regexp.new(
+ id ? statement.gsub(RJS_ANY_ID, "\"#{id}\"") : statement
+ )
+
+ # Duplicate the body since the next step involves destroying it.
+ matches = nil
+ case rjs_type
+ when :remove, :show, :hide, :toggle
+ matches = @response.body.match(pattern)
+ else
+ @response.body.gsub(pattern) do |match|
+ html = unescape_rjs(match)
+ matches ||= []
+ matches.concat HTML::Document.new(html).root.children.select { |n| n.tag? }
+ ""
+ end
+ end
+
+ if matches
+ assert_block("") { true } # to count the assertion
+ if block_given? && !([:remove, :show, :hide, :toggle].include? rjs_type)
+ begin
+ in_scope, @selected = @selected, matches
+ yield matches
+ ensure
+ @selected = in_scope
+ end
+ end
+ matches
+ else
+ # RJS statement not found.
+ case rjs_type
+ when :remove, :show, :hide, :toggle
+ flunk_message = "No RJS statement that #{rjs_type.to_s}s '#{id}' was rendered."
+ else
+ flunk_message = "No RJS statement that replaces or inserts HTML content."
+ end
+ flunk args.shift || flunk_message
+ end
+ end
+
+ # :call-seq:
+ # assert_select_encoded(element?) { |elements| ... }
+ #
+ # Extracts the content of an element, treats it as encoded HTML and runs
+ # nested assertion on it.
+ #
+ # You typically call this method within another assertion to operate on
+ # all currently selected elements. You can also pass an element or array
+ # of elements.
+ #
+ # The content of each element is un-encoded, and wrapped in the root
+ # element +encoded+. It then calls the block with all un-encoded elements.
+ #
+ # ==== Examples
+ # # Selects all bold tags from within the title of an ATOM feed's entries (perhaps to nab a section name prefix)
+ # assert_select_feed :atom, 1.0 do
+ # # Select each entry item and then the title item
+ # assert_select "entry>title" do
+ # # Run assertions on the encoded title elements
+ # assert_select_encoded do
+ # assert_select "b"
+ # end
+ # end
+ # end
+ #
+ #
+ # # Selects all paragraph tags from within the description of an RSS feed
+ # assert_select_feed :rss, 2.0 do
+ # # Select description element of each feed item.
+ # assert_select "channel>item>description" do
+ # # Run assertions on the encoded elements.
+ # assert_select_encoded do
+ # assert_select "p"
+ # end
+ # end
+ # end
+ def assert_select_encoded(element = nil, &block)
+ case element
+ when Array
+ elements = element
+ when HTML::Node
+ elements = [element]
+ when nil
+ unless elements = @selected
+ raise ArgumentError, "First argument is optional, but must be called from a nested assert_select"
+ end
+ else
+ raise ArgumentError, "Argument is optional, and may be node or array of nodes"
+ end
+
+ fix_content = lambda do |node|
+ # Gets around a bug in the Rails 1.1 HTML parser.
+ node.content.gsub(/)?/m) { CGI.escapeHTML($1) }
+ end
+
+ selected = elements.map do |element|
+ text = element.children.select{ |c| not c.tag? }.map{ |c| fix_content[c] }.join
+ root = HTML::Document.new(CGI.unescapeHTML("#{text} ")).root
+ css_select(root, "encoded:root", &block)[0]
+ end
+
+ begin
+ old_selected, @selected = @selected, selected
+ assert_select ":root", &block
+ ensure
+ @selected = old_selected
+ end
+ end
+
+ # :call-seq:
+ # assert_select_email { }
+ #
+ # Extracts the body of an email and runs nested assertions on it.
+ #
+ # You must enable deliveries for this assertion to work, use:
+ # ActionMailer::Base.perform_deliveries = true
+ #
+ # ==== Examples
+ #
+ # assert_select_email do
+ # assert_select "h1", "Email alert"
+ # end
+ #
+ # assert_select_email do
+ # items = assert_select "ol>li"
+ # items.each do
+ # # Work with items here...
+ # end
+ # end
+ #
+ def assert_select_email(&block)
+ deliveries = ActionMailer::Base.deliveries
+ assert !deliveries.empty?, "No e-mail in delivery list"
+
+ for delivery in deliveries
+ for part in delivery.parts
+ if part["Content-Type"].to_s =~ /^text\/html\W/
+ root = HTML::Document.new(part.body).root
+ assert_select root, ":root", &block
+ end
+ end
+ end
+ end
+
+ protected
+ unless const_defined?(:RJS_STATEMENTS)
+ RJS_PATTERN_HTML = "\"((\\\\\"|[^\"])*)\""
+ RJS_ANY_ID = "\"([^\"])*\""
+ RJS_STATEMENTS = {
+ :chained_replace => "\\$\\(#{RJS_ANY_ID}\\)\\.replace\\(#{RJS_PATTERN_HTML}\\)",
+ :chained_replace_html => "\\$\\(#{RJS_ANY_ID}\\)\\.update\\(#{RJS_PATTERN_HTML}\\)",
+ :replace_html => "Element\\.update\\(#{RJS_ANY_ID}, #{RJS_PATTERN_HTML}\\)",
+ :replace => "Element\\.replace\\(#{RJS_ANY_ID}, #{RJS_PATTERN_HTML}\\)"
+ }
+ [:remove, :show, :hide, :toggle].each do |action|
+ RJS_STATEMENTS[action] = "Element\\.#{action}\\(#{RJS_ANY_ID}\\)"
+ end
+ RJS_INSERTIONS = ["top", "bottom", "before", "after"]
+ RJS_INSERTIONS.each do |insertion|
+ RJS_STATEMENTS["insert_#{insertion}".to_sym] = "Element.insert\\(#{RJS_ANY_ID}, \\{ #{insertion}: #{RJS_PATTERN_HTML} \\}\\)"
+ end
+ RJS_STATEMENTS[:insert_html] = "Element.insert\\(#{RJS_ANY_ID}, \\{ (#{RJS_INSERTIONS.join('|')}): #{RJS_PATTERN_HTML} \\}\\)"
+ RJS_STATEMENTS[:any] = Regexp.new("(#{RJS_STATEMENTS.values.join('|')})")
+ RJS_PATTERN_UNICODE_ESCAPED_CHAR = /\\u([0-9a-zA-Z]{4})/
+ end
+
+ # +assert_select+ and +css_select+ call this to obtain the content in the HTML
+ # page, or from all the RJS statements, depending on the type of response.
+ def response_from_page_or_rjs()
+ content_type = @response.content_type
+
+ if content_type && Mime::JS =~ content_type
+ body = @response.body.dup
+ root = HTML::Node.new(nil)
+
+ while true
+ next if body.sub!(RJS_STATEMENTS[:any]) do |match|
+ html = unescape_rjs(match)
+ matches = HTML::Document.new(html).root.children.select { |n| n.tag? }
+ root.children.concat matches
+ ""
+ end
+ break
+ end
+
+ root
+ else
+ html_document.root
+ end
+ end
+
+ # Unescapes a RJS string.
+ def unescape_rjs(rjs_string)
+ # RJS encodes double quotes and line breaks.
+ unescaped= rjs_string.gsub('\"', '"')
+ unescaped.gsub!(/\\\//, '/')
+ unescaped.gsub!('\n', "\n")
+ unescaped.gsub!('\076', '>')
+ unescaped.gsub!('\074', '<')
+ # RJS encodes non-ascii characters.
+ unescaped.gsub!(RJS_PATTERN_UNICODE_ESCAPED_CHAR) {|u| [$1.hex].pack('U*')}
+ unescaped
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/testing/assertions/tag.rb b/actionpack/lib/action_dispatch/testing/assertions/tag.rb
new file mode 100644
index 0000000000..ef6867576e
--- /dev/null
+++ b/actionpack/lib/action_dispatch/testing/assertions/tag.rb
@@ -0,0 +1,123 @@
+module ActionDispatch
+ module Assertions
+ # Pair of assertions to testing elements in the HTML output of the response.
+ module TagAssertions
+ # Asserts that there is a tag/node/element in the body of the response
+ # that meets all of the given conditions. The +conditions+ parameter must
+ # be a hash of any of the following keys (all are optional):
+ #
+ # * :tag : the node type must match the corresponding value
+ # * :attributes : a hash. The node's attributes must match the
+ # corresponding values in the hash.
+ # * :parent : a hash. The node's parent must match the
+ # corresponding hash.
+ # * :child : a hash. At least one of the node's immediate children
+ # must meet the criteria described by the hash.
+ # * :ancestor : a hash. At least one of the node's ancestors must
+ # meet the criteria described by the hash.
+ # * :descendant : a hash. At least one of the node's descendants
+ # must meet the criteria described by the hash.
+ # * :sibling : a hash. At least one of the node's siblings must
+ # meet the criteria described by the hash.
+ # * :after : a hash. The node must be after any sibling meeting
+ # the criteria described by the hash, and at least one sibling must match.
+ # * :before : a hash. The node must be before any sibling meeting
+ # the criteria described by the hash, and at least one sibling must match.
+ # * :children : a hash, for counting children of a node. Accepts
+ # the keys:
+ # * :count : either a number or a range which must equal (or
+ # include) the number of children that match.
+ # * :less_than : the number of matching children must be less
+ # than this number.
+ # * :greater_than : the number of matching children must be
+ # greater than this number.
+ # * :only : another hash consisting of the keys to use
+ # to match on the children, and only matching children will be
+ # counted.
+ # * :content : the textual content of the node must match the
+ # given value. This will not match HTML tags in the body of a
+ # tag--only text.
+ #
+ # Conditions are matched using the following algorithm:
+ #
+ # * if the condition is a string, it must be a substring of the value.
+ # * if the condition is a regexp, it must match the value.
+ # * if the condition is a number, the value must match number.to_s.
+ # * if the condition is +true+, the value must not be +nil+.
+ # * if the condition is +false+ or +nil+, the value must be +nil+.
+ #
+ # === Examples
+ #
+ # # Assert that there is a "span" tag
+ # assert_tag :tag => "span"
+ #
+ # # Assert that there is a "span" tag with id="x"
+ # assert_tag :tag => "span", :attributes => { :id => "x" }
+ #
+ # # Assert that there is a "span" tag using the short-hand
+ # assert_tag :span
+ #
+ # # Assert that there is a "span" tag with id="x" using the short-hand
+ # assert_tag :span, :attributes => { :id => "x" }
+ #
+ # # Assert that there is a "span" inside of a "div"
+ # assert_tag :tag => "span", :parent => { :tag => "div" }
+ #
+ # # Assert that there is a "span" somewhere inside a table
+ # assert_tag :tag => "span", :ancestor => { :tag => "table" }
+ #
+ # # Assert that there is a "span" with at least one "em" child
+ # assert_tag :tag => "span", :child => { :tag => "em" }
+ #
+ # # Assert that there is a "span" containing a (possibly nested)
+ # # "strong" tag.
+ # assert_tag :tag => "span", :descendant => { :tag => "strong" }
+ #
+ # # Assert that there is a "span" containing between 2 and 4 "em" tags
+ # # as immediate children
+ # assert_tag :tag => "span",
+ # :children => { :count => 2..4, :only => { :tag => "em" } }
+ #
+ # # Get funky: assert that there is a "div", with an "ul" ancestor
+ # # and an "li" parent (with "class" = "enum"), and containing a
+ # # "span" descendant that contains text matching /hello world/
+ # assert_tag :tag => "div",
+ # :ancestor => { :tag => "ul" },
+ # :parent => { :tag => "li",
+ # :attributes => { :class => "enum" } },
+ # :descendant => { :tag => "span",
+ # :child => /hello world/ }
+ #
+ # Please note : +assert_tag+ and +assert_no_tag+ only work
+ # with well-formed XHTML. They recognize a few tags as implicitly self-closing
+ # (like br and hr and such) but will not work correctly with tags
+ # that allow optional closing tags (p, li, td). You must explicitly
+ # close all of your tags to use these assertions.
+ def assert_tag(*opts)
+ opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
+ tag = find_tag(opts)
+ assert tag, "expected tag, but no tag found matching #{opts.inspect} in:\n#{@response.body.inspect}"
+ end
+
+ # Identical to +assert_tag+, but asserts that a matching tag does _not_
+ # exist. (See +assert_tag+ for a full discussion of the syntax.)
+ #
+ # === Examples
+ # # Assert that there is not a "div" containing a "p"
+ # assert_no_tag :tag => "div", :descendant => { :tag => "p" }
+ #
+ # # Assert that an unordered list is empty
+ # assert_no_tag :tag => "ul", :descendant => { :tag => "li" }
+ #
+ # # Assert that there is not a "p" tag with between 1 to 3 "img" tags
+ # # as immediate children
+ # assert_no_tag :tag => "p",
+ # :children => { :count => 1..3, :only => { :tag => "img" } }
+ def assert_no_tag(*opts)
+ opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
+ tag = find_tag(opts)
+ assert !tag, "expected no tag, but found tag matching #{opts.inspect} in:\n#{@response.body.inspect}"
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index 50bed67f7d..22adf97304 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -21,7 +21,7 @@ module ActionView
end
class TestCase < ActiveSupport::TestCase
- include ActionController::TestCase::Assertions
+ include ActionDispatch::Assertions
include ActionController::TestProcess
class_inheritable_accessor :helper_class
--
cgit v1.2.3
From ba9887c9c02a3671c3d1d893cbee9f360ea2df2d Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 13:45:12 -0500
Subject: Switch to action_dispatch rack namespace
---
actionpack/lib/action_controller/testing/process.rb | 2 +-
actionpack/lib/action_dispatch/http/request.rb | 4 ++--
actionpack/lib/action_dispatch/middleware/params_parser.rb | 2 +-
actionpack/test/dispatch/request_test.rb | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 16a8f66bc4..a2bb9afaa5 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -109,7 +109,7 @@ module ActionController #:nodoc:
end
def recycle!
- @env["action_controller.request.request_parameters"] = {}
+ @env["action_dispatch.request.request_parameters"] = {}
self.query_parameters = {}
self.path_parameters = {}
@headers, @request_method, @accepts, @content_type = nil, nil, nil, nil
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 2602b344ca..9f0361a874 100755
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -437,13 +437,13 @@ EOM
# Override Rack's GET method to support indifferent access
def GET
- @env["action_controller.request.query_parameters"] ||= normalize_parameters(super)
+ @env["action_dispatch.request.query_parameters"] ||= normalize_parameters(super)
end
alias_method :query_parameters, :GET
# Override Rack's POST method to support indifferent access
def POST
- @env["action_controller.request.request_parameters"] ||= normalize_parameters(super)
+ @env["action_dispatch.request.request_parameters"] ||= normalize_parameters(super)
end
alias_method :request_parameters, :POST
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index abaee2829e..58d527a6e7 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -11,7 +11,7 @@ module ActionDispatch
def call(env)
if params = parse_formatted_parameters(env)
- env["action_controller.request.request_parameters"] = params
+ env["action_dispatch.request.request_parameters"] = params
end
@app.call(env)
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index d57a2a611f..3a85db8aa5 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -307,7 +307,7 @@ class RequestTest < ActiveSupport::TestCase
test "restrict method hacking" do
[:get, :put, :delete].each do |method|
request = stub_request 'REQUEST_METHOD' => method.to_s.upcase,
- 'action_controller.request.request_parameters' => { :_method => 'put' }
+ 'action_dispatch.request.request_parameters' => { :_method => 'put' }
assert_equal method, request.method
end
end
--
cgit v1.2.3
From 9bac470c7ac7bc15830a66f416358d8efc74a39d Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 14:28:42 -0500
Subject: Group integration test helpers and delegate other helpers to request
and response objects
---
.../lib/action_controller/testing/integration.rb | 273 ++++++++++-----------
actionpack/lib/action_dispatch/http/response.rb | 9 +
actionpack/test/controller/integration_test.rb | 12 +-
3 files changed, 136 insertions(+), 158 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb
index 7fa1fd93bf..f088e91de4 100644
--- a/actionpack/lib/action_controller/testing/integration.rb
+++ b/actionpack/lib/action_controller/testing/integration.rb
@@ -4,6 +4,114 @@ require 'active_support/test_case'
module ActionController
module Integration #:nodoc:
+ module RequestHelpers
+ # Performs a GET request with the given parameters.
+ #
+ # - +path+: The URI (as a String) on which you want to perform a GET
+ # request.
+ # - +parameters+: The HTTP parameters that you want to pass. This may
+ # be +nil+,
+ # a Hash, or a String that is appropriately encoded
+ # (application/x-www-form-urlencoded or
+ # multipart/form-data ).
+ # - +headers+: Additional HTTP headers to pass, as a Hash. The keys will
+ # automatically be upcased, with the prefix 'HTTP_' added if needed.
+ #
+ # This method returns an Response object, which one can use to
+ # inspect the details of the response. Furthermore, if this method was
+ # called from an ActionController::IntegrationTest object, then that
+ # object's @response instance variable will point to the same
+ # response object.
+ #
+ # You can also perform POST, PUT, DELETE, and HEAD requests with +post+,
+ # +put+, +delete+, and +head+.
+ def get(path, parameters = nil, headers = nil)
+ process :get, path, parameters, headers
+ end
+
+ # Performs a POST request with the given parameters. See get() for more
+ # details.
+ def post(path, parameters = nil, headers = nil)
+ process :post, path, parameters, headers
+ end
+
+ # Performs a PUT request with the given parameters. See get() for more
+ # details.
+ def put(path, parameters = nil, headers = nil)
+ process :put, path, parameters, headers
+ end
+
+ # Performs a DELETE request with the given parameters. See get() for
+ # more details.
+ def delete(path, parameters = nil, headers = nil)
+ process :delete, path, parameters, headers
+ end
+
+ # Performs a HEAD request with the given parameters. See get() for more
+ # details.
+ def head(path, parameters = nil, headers = nil)
+ process :head, path, parameters, headers
+ end
+
+ # Performs an XMLHttpRequest request with the given parameters, mirroring
+ # a request from the Prototype library.
+ #
+ # The request_method is :get, :post, :put, :delete or :head; the
+ # parameters are +nil+, a hash, or a url-encoded or multipart string;
+ # the headers are a hash. Keys are automatically upcased and prefixed
+ # with 'HTTP_' if not already.
+ def xml_http_request(request_method, path, parameters = nil, headers = nil)
+ headers ||= {}
+ headers['X-Requested-With'] = 'XMLHttpRequest'
+ headers['Accept'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
+ process(request_method, path, parameters, headers)
+ end
+ alias xhr :xml_http_request
+
+ # Follow a single redirect response. If the last response was not a
+ # redirect, an exception will be raised. Otherwise, the redirect is
+ # performed on the location header.
+ def follow_redirect!
+ raise "not a redirect! #{status} #{status_message}" unless redirect?
+ get(response.location)
+ status
+ end
+
+ # Performs a request using the specified method, following any subsequent
+ # redirect. Note that the redirects are followed until the response is
+ # not a redirect--this means you may run into an infinite loop if your
+ # redirect loops back to itself.
+ def request_via_redirect(http_method, path, parameters = nil, headers = nil)
+ process(http_method, path, parameters, headers)
+ follow_redirect! while redirect?
+ status
+ end
+
+ # Performs a GET request, following any subsequent redirect.
+ # See +request_via_redirect+ for more information.
+ def get_via_redirect(path, parameters = nil, headers = nil)
+ request_via_redirect(:get, path, parameters, headers)
+ end
+
+ # Performs a POST request, following any subsequent redirect.
+ # See +request_via_redirect+ for more information.
+ def post_via_redirect(path, parameters = nil, headers = nil)
+ request_via_redirect(:post, path, parameters, headers)
+ end
+
+ # Performs a PUT request, following any subsequent redirect.
+ # See +request_via_redirect+ for more information.
+ def put_via_redirect(path, parameters = nil, headers = nil)
+ request_via_redirect(:put, path, parameters, headers)
+ end
+
+ # Performs a DELETE request, following any subsequent redirect.
+ # See +request_via_redirect+ for more information.
+ def delete_via_redirect(path, parameters = nil, headers = nil)
+ request_via_redirect(:delete, path, parameters, headers)
+ end
+ end
+
# An integration Session instance represents a set of requests and responses
# performed sequentially by some virtual user. Because you can instantiate
# multiple sessions and run them side-by-side, you can also mimic (to some
@@ -16,18 +124,15 @@ module ActionController
include Test::Unit::Assertions
include ActionDispatch::Assertions
include ActionController::TestProcess
+ include RequestHelpers
- # The integer HTTP status code of the last request.
- attr_reader :status
-
- # The status message that accompanied the status code of the last request.
- attr_reader :status_message
-
- # The body of the last request.
- attr_reader :body
+ %w( status status_message headers body redirect? ).each do |method|
+ delegate method, :to => :response, :allow_nil => true
+ end
- # The URI of the last request.
- attr_reader :path
+ %w( path ).each do |method|
+ delegate method, :to => :request, :allow_nil => true
+ end
# The hostname used in the last request.
attr_accessor :host
@@ -42,9 +147,6 @@ module ActionController
# sent with the next request.
attr_reader :cookies
- # A map of the headers returned by the last response.
- attr_reader :headers
-
# A reference to the controller instance used by the last request.
attr_reader :controller
@@ -69,8 +171,6 @@ module ActionController
#
# session.reset!
def reset!
- @status = @path = @headers = nil
- @result = @status_message = nil
@https = false
@cookies = {}
@controller = @request = @response = nil
@@ -118,117 +218,6 @@ module ActionController
@host = name
end
- # Follow a single redirect response. If the last response was not a
- # redirect, an exception will be raised. Otherwise, the redirect is
- # performed on the location header.
- def follow_redirect!
- raise "not a redirect! #{@status} #{@status_message}" unless redirect?
- get(interpret_uri(headers['location']))
- status
- end
-
- # Performs a request using the specified method, following any subsequent
- # redirect. Note that the redirects are followed until the response is
- # not a redirect--this means you may run into an infinite loop if your
- # redirect loops back to itself.
- def request_via_redirect(http_method, path, parameters = nil, headers = nil)
- send(http_method, path, parameters, headers)
- follow_redirect! while redirect?
- status
- end
-
- # Performs a GET request, following any subsequent redirect.
- # See +request_via_redirect+ for more information.
- def get_via_redirect(path, parameters = nil, headers = nil)
- request_via_redirect(:get, path, parameters, headers)
- end
-
- # Performs a POST request, following any subsequent redirect.
- # See +request_via_redirect+ for more information.
- def post_via_redirect(path, parameters = nil, headers = nil)
- request_via_redirect(:post, path, parameters, headers)
- end
-
- # Performs a PUT request, following any subsequent redirect.
- # See +request_via_redirect+ for more information.
- def put_via_redirect(path, parameters = nil, headers = nil)
- request_via_redirect(:put, path, parameters, headers)
- end
-
- # Performs a DELETE request, following any subsequent redirect.
- # See +request_via_redirect+ for more information.
- def delete_via_redirect(path, parameters = nil, headers = nil)
- request_via_redirect(:delete, path, parameters, headers)
- end
-
- # Returns +true+ if the last response was a redirect.
- def redirect?
- status/100 == 3
- end
-
- # Performs a GET request with the given parameters.
- #
- # - +path+: The URI (as a String) on which you want to perform a GET
- # request.
- # - +parameters+: The HTTP parameters that you want to pass. This may
- # be +nil+,
- # a Hash, or a String that is appropriately encoded
- # (application/x-www-form-urlencoded or
- # multipart/form-data ).
- # - +headers+: Additional HTTP headers to pass, as a Hash. The keys will
- # automatically be upcased, with the prefix 'HTTP_' added if needed.
- #
- # This method returns an Response object, which one can use to
- # inspect the details of the response. Furthermore, if this method was
- # called from an ActionController::IntegrationTest object, then that
- # object's @response instance variable will point to the same
- # response object.
- #
- # You can also perform POST, PUT, DELETE, and HEAD requests with +post+,
- # +put+, +delete+, and +head+.
- def get(path, parameters = nil, headers = nil)
- process :get, path, parameters, headers
- end
-
- # Performs a POST request with the given parameters. See get() for more
- # details.
- def post(path, parameters = nil, headers = nil)
- process :post, path, parameters, headers
- end
-
- # Performs a PUT request with the given parameters. See get() for more
- # details.
- def put(path, parameters = nil, headers = nil)
- process :put, path, parameters, headers
- end
-
- # Performs a DELETE request with the given parameters. See get() for
- # more details.
- def delete(path, parameters = nil, headers = nil)
- process :delete, path, parameters, headers
- end
-
- # Performs a HEAD request with the given parameters. See get() for more
- # details.
- def head(path, parameters = nil, headers = nil)
- process :head, path, parameters, headers
- end
-
- # Performs an XMLHttpRequest request with the given parameters, mirroring
- # a request from the Prototype library.
- #
- # The request_method is :get, :post, :put, :delete or :head; the
- # parameters are +nil+, a hash, or a url-encoded or multipart string;
- # the headers are a hash. Keys are automatically upcased and prefixed
- # with 'HTTP_' if not already.
- def xml_http_request(request_method, path, parameters = nil, headers = nil)
- headers ||= {}
- headers['X-Requested-With'] = 'XMLHttpRequest'
- headers['Accept'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
- process(request_method, path, parameters, headers)
- end
- alias xhr :xml_http_request
-
# Returns the URL for the given options, according to the rules specified
# in the application's routes.
def url_for(options)
@@ -238,19 +227,14 @@ module ActionController
end
private
- # Tailors the session based on the given URI, setting the HTTPS value
- # and the hostname.
- def interpret_uri(path)
- location = URI.parse(path)
- https! URI::HTTPS === location if location.scheme
- host! location.host if location.host
- location.query ? "#{location.path}?#{location.query}" : location.path
- end
-
# Performs the actual request.
def process(method, path, parameters = nil, headers = nil)
- path = interpret_uri(path) if path =~ %r{://}
- @path = path
+ if path =~ %r{://}
+ location = URI.parse(path)
+ https! URI::HTTPS === location if location.scheme
+ host! location.host if location.host
+ path = location.query ? "#{location.path}?#{location.query}" : location.path
+ end
[ControllerCapture, ActionController::ProcessWithTest].each do |mod|
unless ActionController::Base < mod
@@ -279,7 +263,7 @@ module ActionController
string << "#{name}=#{value}; "
}
}
- env = ActionDispatch::Test::MockRequest.env_for(@path, opts)
+ env = ActionDispatch::Test::MockRequest.env_for(path, opts)
(headers || {}).each do |key, value|
key = key.to_s.upcase.gsub(/-/, "_")
@@ -289,17 +273,12 @@ module ActionController
app = Rack::Lint.new(@app)
status, headers, body = app.call(env)
- response = ::Rack::MockResponse.new(status, headers, body)
+ mock_response = ::Rack::MockResponse.new(status, headers, body)
@request_count += 1
- @request = Request.new(env)
-
- @response = Response.new
- @response.status = @status = response.status
- @response.headers = @headers = response.headers
- @response.body = @body = response.body
+ @request = Request.new(env)
+ @response = Response.from_response(mock_response)
- @status_message = ActionDispatch::StatusCodes::STATUS_CODES[@status]
@cookies.merge!(@response.cookies)
@html_document = nil
@@ -312,7 +291,7 @@ module ActionController
@controller.send(:set_test_assigns)
end
- return @status
+ return response.status
end
# Get a temporary URL writer object
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index d104dcb8a0..1b12308cc9 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -31,6 +31,14 @@ module ActionDispatch # :nodoc:
# end
# end
class Response < Rack::Response
+ def self.from_response(response)
+ new.tap do |resp|
+ resp.status = response.status
+ resp.headers = response.headers
+ resp.body = response.body
+ end
+ end
+
DEFAULT_HEADERS = { "Cache-Control" => "no-cache" }
attr_accessor :request
@@ -80,6 +88,7 @@ module ActionDispatch # :nodoc:
def message
status.to_s.split(' ',2)[1] || StatusCodes::STATUS_CODES[response_code]
end
+ alias_method :status_message, :message
# Was the response successful?
def success?
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index 70fa41aded..c616107324 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -30,7 +30,7 @@ class SessionTest < Test::Unit::TestCase
def test_request_via_redirect_uses_given_method
path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue"}
- @session.expects(:put).with(path, args, headers)
+ @session.expects(:process).with(:put, path, args, headers)
@session.stubs(:redirect?).returns(false)
@session.request_via_redirect(:put, path, args, headers)
end
@@ -90,16 +90,6 @@ class SessionTest < Test::Unit::TestCase
assert_equal '/show', @session.url_for(options)
end
- def test_redirect_bool_with_status_in_300s
- @session.stubs(:status).returns 301
- assert @session.redirect?
- end
-
- def test_redirect_bool_with_status_in_200s
- @session.stubs(:status).returns 200
- assert !@session.redirect?
- end
-
def test_get
path = "/index"; params = "blah"; headers = {:location => 'blah'}
@session.expects(:process).with(:get,path,params,headers)
--
cgit v1.2.3
From 64e66cf161ee8db0bdbccb1be18fb760f5a9d24e Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 14:40:46 -0500
Subject: Vendor new Rack::Mock changes
---
.../lib/action_controller/testing/integration.rb | 2 +-
.../lib/action_controller/testing/process.rb | 2 +-
actionpack/lib/action_dispatch.rb | 6 +-
actionpack/lib/action_dispatch/extensions/rack.rb | 5 +
.../lib/action_dispatch/extensions/rack/mock.rb | 65 +++++
.../lib/action_dispatch/extensions/rack/utils.rb | 262 +++++++++++++++++++++
actionpack/lib/action_dispatch/test/mock.rb | 115 ---------
.../lib/action_dispatch/test/uploaded_file.rb | 33 ---
8 files changed, 335 insertions(+), 155 deletions(-)
create mode 100644 actionpack/lib/action_dispatch/extensions/rack.rb
create mode 100644 actionpack/lib/action_dispatch/extensions/rack/mock.rb
create mode 100644 actionpack/lib/action_dispatch/extensions/rack/utils.rb
delete mode 100644 actionpack/lib/action_dispatch/test/mock.rb
delete 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 f088e91de4..ce161ef846 100644
--- a/actionpack/lib/action_controller/testing/integration.rb
+++ b/actionpack/lib/action_controller/testing/integration.rb
@@ -263,7 +263,7 @@ module ActionController
string << "#{name}=#{value}; "
}
}
- env = ActionDispatch::Test::MockRequest.env_for(path, opts)
+ env = Rack::MockRequest.env_for(path, opts)
(headers || {}).each do |key, value|
key = key.to_s.upcase.gsub(/-/, "_")
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index a2bb9afaa5..3a7445f890 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -250,7 +250,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)
- TestUploadedFile = ActionDispatch::Test::UploadedFile
+ TestUploadedFile = Rack::Utils::Multipart::UploadedFile
module TestProcess
def self.included(base)
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 8b8a1774e4..078e631be4 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -34,6 +34,7 @@ require 'active_support/core/all'
gem 'rack', '~> 1.0.0'
require 'rack'
+require 'action_dispatch/extensions/rack'
module ActionDispatch
autoload :Request, 'action_dispatch/http/request'
@@ -56,11 +57,6 @@ 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/extensions/rack.rb b/actionpack/lib/action_dispatch/extensions/rack.rb
new file mode 100644
index 0000000000..8a543e2110
--- /dev/null
+++ b/actionpack/lib/action_dispatch/extensions/rack.rb
@@ -0,0 +1,5 @@
+# Monkey patch in new test helper methods
+unless Rack::Utils.respond_to?(:build_nested_query)
+ require 'action_dispatch/extensions/rack/mock'
+ require 'action_dispatch/extensions/rack/utils'
+end
diff --git a/actionpack/lib/action_dispatch/extensions/rack/mock.rb b/actionpack/lib/action_dispatch/extensions/rack/mock.rb
new file mode 100644
index 0000000000..d773a74244
--- /dev/null
+++ b/actionpack/lib/action_dispatch/extensions/rack/mock.rb
@@ -0,0 +1,65 @@
+require 'rack/mock'
+
+module Rack
+ class MockRequest
+ # Return the Rack environment used for a request to +uri+.
+ def self.env_for(uri="", opts={})
+ uri = URI(uri)
+ uri.path = "/#{uri.path}" unless uri.path[0] == ?/
+
+ env = DEFAULT_ENV.dup
+
+ env["REQUEST_METHOD"] = opts[:method] ? opts[:method].to_s.upcase : "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["HTTPS"] = env["rack.url_scheme"] == "https" ? "on" : "off"
+
+ env["SCRIPT_NAME"] = opts[:script_name] || ""
+
+ if opts[:fatal]
+ env["rack.errors"] = FatalWarner.new
+ else
+ env["rack.errors"] = StringIO.new
+ end
+
+ if params = opts[:params]
+ if env["REQUEST_METHOD"] == "GET"
+ params = Utils.parse_nested_query(params) if params.is_a?(String)
+ params.update(Utils.parse_nested_query(env["QUERY_STRING"]))
+ env["QUERY_STRING"] = Utils.build_nested_query(params)
+ elsif !opts.has_key?(:input)
+ opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
+ if params.is_a?(Hash)
+ if data = Utils::Multipart.build_multipart(params)
+ opts[:input] = data
+ opts["CONTENT_LENGTH"] ||= data.length.to_s
+ opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{Utils::Multipart::MULTIPART_BOUNDARY}"
+ else
+ opts[:input] = Utils.build_nested_query(params)
+ end
+ else
+ opts[:input] = params
+ end
+ end
+ 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
+end
diff --git a/actionpack/lib/action_dispatch/extensions/rack/utils.rb b/actionpack/lib/action_dispatch/extensions/rack/utils.rb
new file mode 100644
index 0000000000..1a46f8a4db
--- /dev/null
+++ b/actionpack/lib/action_dispatch/extensions/rack/utils.rb
@@ -0,0 +1,262 @@
+# -*- encoding: binary -*-
+
+require 'rack/utils'
+
+module Rack
+ module Utils
+ def normalize_params(params, name, v = nil)
+ name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
+ k = $1 || ''
+ after = $' || ''
+
+ return if k.empty?
+
+ if after == ""
+ params[k] = v
+ elsif after == "[]"
+ params[k] ||= []
+ raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
+ params[k] << v
+ elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
+ child_key = $1
+ params[k] ||= []
+ raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" 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] ||= {}
+ raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash)
+ params[k] = normalize_params(params[k], after, v)
+ end
+
+ return params
+ end
+ module_function :normalize_params
+
+ def build_nested_query(value, prefix = nil)
+ case value
+ when Array
+ value.map { |v|
+ build_nested_query(v, "#{prefix}[]")
+ }.join("&")
+ when Hash
+ value.map { |k, v|
+ build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
+ }.join("&")
+ when String
+ raise ArgumentError, "value must be a Hash" if prefix.nil?
+ "#{prefix}=#{escape(value)}"
+ else
+ prefix
+ end
+ end
+ module_function :build_nested_query
+
+ module Multipart
+ 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
+
+ EOL = "\r\n"
+ MULTIPART_BOUNDARY = "AaB03x"
+
+ def self.parse_multipart(env)
+ unless env['CONTENT_TYPE'] =~
+ %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
+ nil
+ else
+ boundary = "--#{$1}"
+
+ params = {}
+ buf = ""
+ content_length = env['CONTENT_LENGTH'].to_i
+ input = env['rack.input']
+ input.rewind
+
+ boundary_size = Utils.bytesize(boundary) + EOL.size
+ bufsize = 16384
+
+ content_length -= boundary_size
+
+ read_buffer = ''
+
+ status = input.read(boundary_size, read_buffer)
+ 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(EOL+EOL)
+ 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: (.*)#{EOL}/ni, 1]
+ name = head[/Content-Disposition:.*\s+name="?([^\";]*)"?/ni, 1] || head[/Content-ID:\s*([^#{EOL}]*)/ni, 1]
+
+ if content_type || 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, read_buffer)
+ 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}
+ elsif !filename && content_type
+ body.rewind
+
+ # Generic multipart cases, not coming from a form
+ data = {: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
+ }
+
+ input.rewind
+
+ params
+ end
+ end
+
+ def self.build_multipart(params, first = true)
+ if first
+ unless params.is_a?(Hash)
+ raise ArgumentError, "value must be a Hash"
+ end
+
+ multipart = false
+ query = lambda { |value|
+ case value
+ when Array
+ value.each(&query)
+ when Hash
+ value.values.each(&query)
+ when UploadedFile
+ multipart = true
+ end
+ }
+ params.values.each(&query)
+ return nil unless multipart
+ end
+
+ flattened_params = Hash.new
+
+ params.each do |key, value|
+ k = first ? key.to_s : "[#{key}]"
+
+ case value
+ when Array
+ value.map { |v|
+ build_multipart(v, false).each { |subkey, subvalue|
+ flattened_params["#{k}[]#{subkey}"] = subvalue
+ }
+ }
+ when Hash
+ build_multipart(value, false).each { |subkey, subvalue|
+ flattened_params[k + subkey] = subvalue
+ }
+ else
+ flattened_params[k] = value
+ end
+ end
+
+ if first
+ flattened_params.map { |name, file|
+ if file.respond_to?(:original_filename)
+ ::File.open(file.path, "rb") do |f|
+ f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
+<<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{name}"; filename="#{Utils.escape(file.original_filename)}"\r
+Content-Type: #{file.content_type}\r
+Content-Length: #{::File.stat(file.path).size}\r
+\r
+#{f.read}\r
+EOF
+ end
+ else
+<<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{name}"\r
+\r
+#{file}\r
+EOF
+ end
+ }.join + "--#{MULTIPART_BOUNDARY}--\r"
+ else
+ flattened_params
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/test/mock.rb b/actionpack/lib/action_dispatch/test/mock.rb
deleted file mode 100644
index 68e5b108b4..0000000000
--- a/actionpack/lib/action_dispatch/test/mock.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-module ActionDispatch
- module Test
- class MockRequest < Rack::MockRequest
- MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
-
- class << self
- def env_for(path, opts)
- 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].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
- 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.stringify_keys!
- params.update(::Rack::Utils.parse_query(uri.query))
- uri.query = requestify(params)
- end
-
- ::Rack::MockRequest.env_for(uri.to_s, opts)
- 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
deleted file mode 100644
index 0ac7db4863..0000000000
--- a/actionpack/lib/action_dispatch/test/uploaded_file.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-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
--
cgit v1.2.3
From 00d1a57e9f99a1b2439281cb741fd82ef47a5c55 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 17:26:03 -0500
Subject: Start moving TestRequest and TestResponse into ActionDispatch
---
actionpack/lib/action_controller/base/base.rb | 3 +-
.../lib/action_controller/testing/integration.rb | 11 +-
.../lib/action_controller/testing/process.rb | 170 ++-------------------
actionpack/lib/action_dispatch.rb | 2 +
.../lib/action_dispatch/extensions/rack/utils.rb | 1 -
actionpack/lib/action_dispatch/http/request.rb | 36 +++--
actionpack/lib/action_dispatch/http/response.rb | 56 -------
.../lib/action_dispatch/testing/test_request.rb | 56 +++++++
.../lib/action_dispatch/testing/test_response.rb | 131 ++++++++++++++++
.../test/controller/action_pack_assertions_test.rb | 22 ++-
actionpack/test/controller/caching_test.rb | 2 +-
actionpack/test/controller/routing_test.rb | 8 +-
actionpack/test/controller/test_test.rb | 4 +-
actionpack/test/dispatch/test_request_test.rb | 30 ++++
14 files changed, 279 insertions(+), 253 deletions(-)
create mode 100644 actionpack/lib/action_dispatch/testing/test_request.rb
create mode 100644 actionpack/lib/action_dispatch/testing/test_response.rb
create mode 100644 actionpack/test/dispatch/test_request_test.rb
diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb
index 14c4339c94..99b5963891 100644
--- a/actionpack/lib/action_controller/base/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -817,7 +817,8 @@ module ActionController #:nodoc:
end
def initialize_template_class(response)
- @template = response.template = ActionView::Base.new(self.class.view_paths, {}, self, formats)
+ @template = ActionView::Base.new(self.class.view_paths, {}, self, formats)
+ response.template = @template if response.respond_to?(:template=)
@template.helpers.send :include, self.class.master_helper_module
response.redirected_to = nil
@performed_render = @performed_redirect = false
diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb
index ce161ef846..4f39ee6a01 100644
--- a/actionpack/lib/action_controller/testing/integration.rb
+++ b/actionpack/lib/action_controller/testing/integration.rb
@@ -245,7 +245,7 @@ module ActionController
ActionController::Base.clear_last_instantiation!
opts = {
- :method => method.to_s.upcase,
+ :method => method,
:params => parameters,
"SERVER_NAME" => host,
@@ -276,17 +276,12 @@ module ActionController
mock_response = ::Rack::MockResponse.new(status, headers, body)
@request_count += 1
- @request = Request.new(env)
- @response = Response.from_response(mock_response)
+ @request = ActionDispatch::Request.new(env)
+ @response = ActionDispatch::TestResponse.from_response(mock_response)
@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
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 3a7445f890..e0f8f026fd 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -1,24 +1,19 @@
require 'rack/session/abstract/id'
module ActionController #:nodoc:
- class TestRequest < ActionDispatch::Request #:nodoc:
+ class TestRequest < ActionDispatch::TestRequest #:nodoc:
attr_accessor :cookies
- attr_accessor :query_parameters, :path
- attr_accessor :host
-
- def self.new(env = {})
- super
- end
+ attr_accessor :query_parameters
def initialize(env = {})
- super(Rack::MockRequest.env_for("/").merge(env))
+ super
- @query_parameters = {}
+ @query_parameters = {}
self.session = TestSession.new
self.session_options = TestSession::DEFAULT_OPTIONS.merge(:id => ActiveSupport::SecureRandom.hex(16))
- initialize_default_values
- initialize_containers
+ @request_uri = "/"
+ @cookies = {}
end
# Wraps raw_post in a StringIO.
@@ -36,55 +31,8 @@ module ActionController #:nodoc:
end
end
- def port=(number)
- @env["SERVER_PORT"] = number.to_i
- end
-
def action=(action_name)
- @query_parameters.update({ "action" => action_name })
- @parameters = nil
- end
-
- # Used to check AbstractRequest's request_uri functionality.
- # Disables the use of @path and @request_uri so superclass can handle those.
- def set_REQUEST_URI(value)
- @env["REQUEST_URI"] = value
- @request_uri = nil
- @path = nil
- end
-
- def request_uri=(uri)
- @request_uri = uri
- @path = uri.split("?").first
- end
-
- def request_method=(method)
- @request_method = method
- end
-
- def accept=(mime_types)
- @env["HTTP_ACCEPT"] = Array(mime_types).collect { |mime_types| mime_types.to_s }.join(",")
- @accepts = nil
- end
-
- def if_modified_since=(last_modified)
- @env["HTTP_IF_MODIFIED_SINCE"] = last_modified
- end
-
- def if_none_match=(etag)
- @env["HTTP_IF_NONE_MATCH"] = etag
- end
-
- def remote_addr=(addr)
- @env['REMOTE_ADDR'] = addr
- end
-
- def request_uri(*args)
- @request_uri || super()
- end
-
- def path(*args)
- @path || super()
+ query_parameters.update({ "action" => action_name })
end
def assign_parameters(controller_path, action, parameters)
@@ -105,34 +53,15 @@ module ActionController #:nodoc:
end
end
raw_post # populate env['RAW_POST_DATA']
- @parameters = nil # reset TestRequest#parameters to use the new path_parameters
end
def recycle!
- @env["action_dispatch.request.request_parameters"] = {}
- self.query_parameters = {}
- self.path_parameters = {}
- @headers, @request_method, @accepts, @content_type = nil, nil, nil, nil
- end
-
- def user_agent=(user_agent)
- @env['HTTP_USER_AGENT'] = user_agent
+ @env.delete_if { |k, v| k =~ /^action_dispatch\.request/ }
+ self.query_parameters = {}
+ @headers = nil
end
private
- def initialize_containers
- @cookies = {}
- end
-
- def initialize_default_values
- @host = "test.host"
- @request_uri = "/"
- @env['HTTP_USER_AGENT'] = "Rails Testing"
- @env['REMOTE_ADDR'] = "0.0.0.0"
- @env["SERVER_PORT"] = 80
- @env['REQUEST_METHOD'] = "GET"
- end
-
def url_encoded_request_parameters
params = self.request_parameters.dup
@@ -145,84 +74,13 @@ module ActionController #:nodoc:
end
end
- # A refactoring of TestResponse to allow the same behavior to be applied
- # 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
- return false if p.nil?
- p.match(redirect_url) != nil
- end
-
- # Returns the template of the file which was used to
- # render this response (or nil)
- def 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.
- def flash
- request.session['flash'] || {}
- end
-
- # Do we have a flash?
- def has_flash?
- !flash.empty?
- end
-
- # Do we have a flash that has contents?
- def has_flash_with_contents?
- !flash.empty?
- end
-
- # Does the specified flash object exist?
- def has_flash_object?(name=nil)
- !flash[name].nil?
- end
-
- # Does the specified object exist in the session?
- def has_session_object?(name=nil)
- !session[name].nil?
- end
-
- # A shortcut to the template.assigns
- def template_objects
- 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
-
- # 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)
- require 'stringio'
-
- sio = StringIO.new
- body_parts.call(self, sio)
-
- sio.rewind
- sio.read
- end
- end
-
# Integration test methods such as ActionController::Integration::Session#get
# and ActionController::Integration::Session#post return objects of class
# TestResponse, which represent the HTTP response results of the requested
# controller actions.
#
# See Response for more information on controller response objects.
- class TestResponse < ActionDispatch::Response
- include TestResponseBehavior
-
+ class TestResponse < ActionDispatch::TestResponse
def recycle!
body_parts.clear
headers.delete('ETag')
@@ -293,7 +151,7 @@ module ActionController #:nodoc:
@response.recycle!
@html_document = nil
- @request.env['REQUEST_METHOD'] = http_method
+ @request.request_method = http_method
@request.action = action.to_s
@@ -331,7 +189,7 @@ module ActionController #:nodoc:
end
def flash
- @response.flash
+ @request.flash
end
def cookies
@@ -348,7 +206,7 @@ module ActionController #:nodoc:
options.update(:only_path => true, :action => action)
url = ActionController::UrlRewriter.new(@request, parameters)
- @request.set_REQUEST_URI(url.rewrite(options))
+ @request.request_uri = url.rewrite(options)
end
end
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 078e631be4..53368b3d1d 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -47,6 +47,8 @@ module ActionDispatch
autoload :MiddlewareStack, 'action_dispatch/middleware/stack'
autoload :Assertions, 'action_dispatch/testing/assertions'
+ autoload :TestRequest, 'action_dispatch/testing/test_request'
+ autoload :TestResponse, 'action_dispatch/testing/test_response'
module Http
autoload :Headers, 'action_dispatch/http/headers'
diff --git a/actionpack/lib/action_dispatch/extensions/rack/utils.rb b/actionpack/lib/action_dispatch/extensions/rack/utils.rb
index 1a46f8a4db..8e4b94eda0 100644
--- a/actionpack/lib/action_dispatch/extensions/rack/utils.rb
+++ b/actionpack/lib/action_dispatch/extensions/rack/utils.rb
@@ -83,7 +83,6 @@ module Rack
end
end
- EOL = "\r\n"
MULTIPART_BOUNDARY = "AaB03x"
def self.parse_multipart(env)
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 9f0361a874..c28f59dbd6 100755
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -31,7 +31,7 @@ module ActionDispatch
# :get . If the request \method is not listed in the HTTP_METHODS
# constant above, an UnknownHttpMethod exception is raised.
def request_method
- @request_method ||= HTTP_METHOD_LOOKUP[super] || raise(ActionController::UnknownHttpMethod, "#{super}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
+ HTTP_METHOD_LOOKUP[super] || raise(ActionController::UnknownHttpMethod, "#{super}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
end
# Returns the HTTP request \method used for action processing as a
@@ -85,7 +85,7 @@ module ActionDispatch
# For backward compatibility, the post \format is extracted from the
# X-Post-Data-Format HTTP header if present.
def content_type
- @content_type ||= begin
+ @env["action_dispatch.request.content_type"] ||= begin
if @env['CONTENT_TYPE'] =~ /^([^,\;]*)/
Mime::Type.lookup($1.strip.downcase)
else
@@ -100,7 +100,7 @@ module ActionDispatch
# Returns the accepted MIME type for the request.
def accepts
- @accepts ||= begin
+ @env["action_dispatch.request.accepts"] ||= begin
header = @env['HTTP_ACCEPT'].to_s.strip
fallback = xhr? ? Mime::JS : Mime::HTML
@@ -160,7 +160,7 @@ module ActionDispatch
# GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of ActionController::Base.use_accept_header
def format(view_path = [])
- @format ||=
+ @env["action_dispatch.request.format"] ||=
if parameters[:format]
Mime[parameters[:format]]
elsif ActionController::Base.use_accept_header && !(accepts == ONLY_ALL)
@@ -171,12 +171,11 @@ module ActionDispatch
end
def formats
- @formats =
- if ActionController::Base.use_accept_header
- Array(Mime[parameters[:format]] || accepts)
- else
- [format]
- end
+ if ActionController::Base.use_accept_header
+ Array(Mime[parameters[:format]] || accepts)
+ else
+ [format]
+ end
end
# Sets the \format by string extension, which can be used to force custom formats
@@ -192,7 +191,7 @@ module ActionDispatch
# end
def format=(extension)
parameters[:format] = extension.to_s
- @format = Mime::Type.lookup_by_extension(parameters[:format])
+ @env["action_dispatch.request.format"] = Mime::Type.lookup_by_extension(parameters[:format])
end
# Returns a symbolized version of the :format parameter of the request.
@@ -328,6 +327,10 @@ EOM
port == standard_port ? '' : ":#{port}"
end
+ def server_port
+ @env['SERVER_PORT'].to_i
+ end
+
# Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify
# a different tld_length , such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
def domain(tld_length = 1)
@@ -396,18 +399,19 @@ EOM
# Returns both GET and POST \parameters in a single hash.
def parameters
- @parameters ||= request_parameters.merge(query_parameters).update(path_parameters).with_indifferent_access
+ @env["action_dispatch.request.parameters"] ||= request_parameters.merge(query_parameters).update(path_parameters).with_indifferent_access
end
alias_method :params, :parameters
def path_parameters=(parameters) #:nodoc:
+ @env.delete("action_dispatch.request.symbolized_path_parameters")
+ @env.delete("action_dispatch.request.parameters")
@env["action_dispatch.request.path_parameters"] = parameters
- @symbolized_path_parameters = @parameters = nil
end
# The same as path_parameters with explicitly symbolized keys.
def symbolized_path_parameters
- @symbolized_path_parameters ||= path_parameters.symbolize_keys
+ @env["action_dispatch.request.symbolized_path_parameters"] ||= path_parameters.symbolize_keys
end
# Returns a hash with the \parameters used to form the \path of the request.
@@ -464,8 +468,8 @@ EOM
@env['rack.session.options'] = options
end
- def server_port
- @env['SERVER_PORT'].to_i
+ def flash
+ session['flash'] || {}
end
private
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 1b12308cc9..2b969323ca 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -31,14 +31,6 @@ module ActionDispatch # :nodoc:
# end
# end
class Response < Rack::Response
- def self.from_response(response)
- new.tap do |resp|
- resp.status = response.status
- resp.headers = response.headers
- resp.body = response.body
- end
- end
-
DEFAULT_HEADERS = { "Cache-Control" => "no-cache" }
attr_accessor :request
@@ -47,27 +39,6 @@ module ActionDispatch # :nodoc:
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
- end
-
- def assigns
- ActiveSupport::Deprecation.warn("response.assigns has been deprecated. Use controller.assigns instead", caller)
- @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'
def initialize
@@ -90,33 +61,6 @@ module ActionDispatch # :nodoc:
end
alias_method :status_message, :message
- # 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 }
diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb
new file mode 100644
index 0000000000..3d20b466d3
--- /dev/null
+++ b/actionpack/lib/action_dispatch/testing/test_request.rb
@@ -0,0 +1,56 @@
+module ActionDispatch
+ class TestRequest < Request
+ def self.new(env = {})
+ super
+ end
+
+ def initialize(env = {})
+ super(Rack::MockRequest.env_for('/').merge(env))
+
+ self.host = 'test.host'
+ self.remote_addr = '0.0.0.0'
+ self.user_agent = 'Rails Testing'
+ end
+
+ def request_method=(method)
+ @env['REQUEST_METHOD'] = method.to_s.upcase
+ end
+
+ def host=(host)
+ @env['HTTP_HOST'] = host
+ end
+
+ def port=(number)
+ @env['SERVER_PORT'] = number.to_i
+ end
+
+ def request_uri=(uri)
+ @env['REQUEST_URI'] = uri
+ end
+
+ def path=(path)
+ @env['PATH_INFO'] = path
+ end
+
+ def if_modified_since=(last_modified)
+ @env['HTTP_IF_MODIFIED_SINCE'] = last_modified
+ end
+
+ def if_none_match=(etag)
+ @env['HTTP_IF_NONE_MATCH'] = etag
+ end
+
+ def remote_addr=(addr)
+ @env['REMOTE_ADDR'] = addr
+ end
+
+ def user_agent=(user_agent)
+ @env['HTTP_USER_AGENT'] = user_agent
+ end
+
+ def accept=(mime_types)
+ @env.delete("action_dispatch.request.accepts")
+ @env["HTTP_ACCEPT"] = Array(mime_types).collect { |mime_types| mime_types.to_s }.join(",")
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/testing/test_response.rb b/actionpack/lib/action_dispatch/testing/test_response.rb
new file mode 100644
index 0000000000..50c6d85828
--- /dev/null
+++ b/actionpack/lib/action_dispatch/testing/test_response.rb
@@ -0,0 +1,131 @@
+module ActionDispatch
+ class TestResponse < Response
+ def self.from_response(response)
+ new.tap do |resp|
+ resp.status = response.status
+ resp.headers = response.headers
+ resp.body = response.body
+ end
+ end
+
+ module DeprecatedHelpers
+ 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
+ end
+
+ def assigns
+ ActiveSupport::Deprecation.warn("response.assigns has been deprecated. Use controller.assigns instead", caller)
+ @template.controller.assigns
+ end
+
+ def layout
+ ActiveSupport::Deprecation.warn("response.layout has been deprecated. Use template.layout instead", caller)
+ @template.layout
+ end
+
+ 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
+ return false if p.nil?
+ p.match(redirect_url) != nil
+ end
+
+ # Returns the template of the file which was used to
+ # render this response (or nil)
+ def 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.
+ def flash
+ ActiveSupport::Deprecation.warn("response.flash has been deprecated. Use request.flash instead", caller)
+ request.session['flash'] || {}
+ end
+
+ # Do we have a flash?
+ def has_flash?
+ ActiveSupport::Deprecation.warn("response.has_flash? has been deprecated. Use flash.any? instead", caller)
+ !flash.empty?
+ end
+
+ # Do we have a flash that has contents?
+ def has_flash_with_contents?
+ ActiveSupport::Deprecation.warn("response.has_flash_with_contents? has been deprecated. Use flash.any? instead", caller)
+ !flash.empty?
+ end
+
+ # Does the specified flash object exist?
+ def has_flash_object?(name=nil)
+ ActiveSupport::Deprecation.warn("response.has_flash_object? has been deprecated. Use flash[name] instead", caller)
+ !flash[name].nil?
+ end
+
+ # Does the specified object exist in the session?
+ def has_session_object?(name=nil)
+ ActiveSupport::Deprecation.warn("response.has_session_object? has been deprecated. Use session[name] instead", caller)
+ !session[name].nil?
+ end
+
+ # A shortcut to the template.assigns
+ def template_objects
+ 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
+ end
+ include DeprecatedHelpers
+
+ # 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 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)
+ require 'stringio'
+
+ sio = StringIO.new
+ body_parts.call(self, sio)
+
+ sio.rewind
+ sio.read
+ end
+ end
+end
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index dd59999a0c..711640f9a9 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -305,24 +305,30 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
# check the empty flashing
def test_flash_me_naked
process :flash_me_naked
- assert !@response.has_flash?
- assert !@response.has_flash_with_contents?
+ assert_deprecated do
+ assert !@response.has_flash?
+ assert !@response.has_flash_with_contents?
+ end
end
# check if we have flash objects
def test_flash_haves
process :flash_me
- assert @response.has_flash?
- assert @response.has_flash_with_contents?
- assert @response.has_flash_object?('hello')
+ assert_deprecated do
+ assert @response.has_flash?
+ assert @response.has_flash_with_contents?
+ assert @response.has_flash_object?('hello')
+ end
end
# ensure we don't have flash objects
def test_flash_have_nots
process :nothing
- assert !@response.has_flash?
- assert !@response.has_flash_with_contents?
- assert_nil @response.flash['hello']
+ assert_deprecated do
+ assert !@response.has_flash?
+ assert !@response.has_flash_with_contents?
+ assert_nil @response.flash['hello']
+ end
end
# check if we were rendered by a file-based template?
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index b61a58dd09..df1a1b7683 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -345,7 +345,7 @@ class ActionCacheTest < ActionController::TestCase
cached_time = content_to_cache
reset!
- @request.set_REQUEST_URI "/action_caching_test/expire.xml"
+ @request.request_uri = "/action_caching_test/expire.xml"
get :expire, :format => :xml
reset!
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index ef56119751..77abb68f32 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -1923,7 +1923,7 @@ class RouteSetTest < Test::Unit::TestCase
end
end
- request.path = "/people"
+ request.request_uri = "/people"
request.env["REQUEST_METHOD"] = "GET"
assert_nothing_raised { set.recognize(request) }
assert_equal("index", request.path_parameters[:action])
@@ -1945,7 +1945,7 @@ class RouteSetTest < Test::Unit::TestCase
}
request.recycle!
- request.path = "/people/5"
+ request.request_uri = "/people/5"
request.env["REQUEST_METHOD"] = "GET"
assert_nothing_raised { set.recognize(request) }
assert_equal("show", request.path_parameters[:action])
@@ -2047,7 +2047,7 @@ class RouteSetTest < Test::Unit::TestCase
end
end
- request.path = "/people/5"
+ request.request_uri = "/people/5"
request.env["REQUEST_METHOD"] = "GET"
assert_nothing_raised { set.recognize(request) }
assert_equal("show", request.path_parameters[:action])
@@ -2059,7 +2059,7 @@ class RouteSetTest < Test::Unit::TestCase
assert_equal("update", request.path_parameters[:action])
request.recycle!
- request.path = "/people/5.png"
+ request.request_uri = "/people/5.png"
request.env["REQUEST_METHOD"] = "GET"
assert_nothing_raised { set.recognize(request) }
assert_equal("show", request.path_parameters[:action])
diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb
index b372980242..919f9815ec 100644
--- a/actionpack/test/controller/test_test.rb
+++ b/actionpack/test/controller/test_test.rb
@@ -201,7 +201,7 @@ XML
end
def test_process_with_request_uri_with_params_with_explicit_uri
- @request.set_REQUEST_URI "/explicit/uri"
+ @request.request_uri = "/explicit/uri"
process :test_uri, :id => 7
assert_equal "/explicit/uri", @response.body
end
@@ -212,7 +212,7 @@ XML
end
def test_process_with_query_string_with_explicit_uri
- @request.set_REQUEST_URI "/explicit/uri?q=test?extra=question"
+ @request.request_uri = "/explicit/uri?q=test?extra=question"
process :test_query_string
assert_equal "q=test?extra=question", @response.body
end
diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb
new file mode 100644
index 0000000000..40a7f04079
--- /dev/null
+++ b/actionpack/test/dispatch/test_request_test.rb
@@ -0,0 +1,30 @@
+require 'abstract_unit'
+
+class TestRequestTest < ActiveSupport::TestCase
+ test "sane defaults" do
+ env = ActionDispatch::TestRequest.new.env
+
+ assert_equal "GET", env.delete("REQUEST_METHOD")
+ assert_equal "off", env.delete("HTTPS")
+ assert_equal "http", env.delete("rack.url_scheme")
+ assert_equal "example.org", env.delete("SERVER_NAME")
+ assert_equal "80", env.delete("SERVER_PORT")
+ assert_equal "/", env.delete("PATH_INFO")
+ assert_equal "", env.delete("SCRIPT_NAME")
+ assert_equal "", env.delete("QUERY_STRING")
+ assert_equal "0", env.delete("CONTENT_LENGTH")
+
+ assert_equal "test.host", env.delete("HTTP_HOST")
+ assert_equal "0.0.0.0", env.delete("REMOTE_ADDR")
+ assert_equal "Rails Testing", env.delete("HTTP_USER_AGENT")
+
+ assert_equal [0, 1], env.delete("rack.version")
+ assert_equal "", env.delete("rack.input").string
+ assert_kind_of StringIO, env.delete("rack.errors")
+ assert_equal true, env.delete("rack.multithread")
+ assert_equal true, env.delete("rack.multiprocess")
+ assert_equal false, env.delete("rack.run_once")
+
+ assert env.empty?, env.inspect
+ end
+end
--
cgit v1.2.3
From f0b9e2861943d32ca73a53ab5fb6f86d10c89b04 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 30 Apr 2009 16:34:00 -0700
Subject: Fix render :json => nil [#2589 state:resolved]
---
actionpack/lib/action_controller/base/render.rb | 3 ++-
actionpack/test/controller/render_test.rb | 10 ++++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/actionpack/lib/action_controller/base/render.rb b/actionpack/lib/action_controller/base/render.rb
index 4286577ec5..cc0d878e01 100644
--- a/actionpack/lib/action_controller/base/render.rb
+++ b/actionpack/lib/action_controller/base/render.rb
@@ -253,7 +253,8 @@ module ActionController
response.content_type ||= Mime::JS
render_for_text(js)
- elsif json = options[:json]
+ elsif options.include?(:json)
+ json = options[:json]
json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str)
json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
response.content_type ||= Mime::JSON
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index da063710a9..023bf0eeaa 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -194,6 +194,10 @@ class TestController < ActionController::Base
render :inline => "<%= controller_name %>"
end
+ def render_json_nil
+ render :json => nil
+ end
+
def render_json_hello_world
render :json => ActiveSupport::JSON.encode(:hello => 'world')
end
@@ -874,6 +878,12 @@ class RenderTest < ActionController::TestCase
assert_equal "The secret is in the sauce\n", @response.body
end
+ def test_render_json_nil
+ get :render_json_nil
+ assert_equal 'null', @response.body
+ assert_equal 'application/json', @response.content_type
+ end
+
def test_render_json
get :render_json_hello_world
assert_equal '{"hello":"world"}', @response.body
--
cgit v1.2.3
From e59835bd0934a7458b71b13bf65786c8484905bd Mon Sep 17 00:00:00 2001
From: "John F. Douthat"
Date: Tue, 21 Apr 2009 13:35:54 -0500
Subject: Fix action-cached exception responses.
Methods raising ActiveRecord::RecordNotFound were returning 404 on first request and 200 OK with blank body on subsequent requests.
[#2533 state:committed]
Signed-off-by: Jeremy Kemper
---
.../lib/action_controller/caching/actions.rb | 10 ++++++-
actionpack/test/controller/caching_test.rb | 35 ++++++++++++++++++++++
2 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb
index d95a346862..2b822b52c8 100644
--- a/actionpack/lib/action_controller/caching/actions.rb
+++ b/actionpack/lib/action_controller/caching/actions.rb
@@ -61,7 +61,9 @@ module ActionController #:nodoc:
filter_options = { :only => actions, :if => options.delete(:if), :unless => options.delete(:unless) }
cache_filter = ActionCacheFilter.new(:layout => options.delete(:layout), :cache_path => options.delete(:cache_path), :store_options => options)
- around_filter(cache_filter, filter_options)
+ around_filter(filter_options) do |controller, action|
+ cache_filter.filter(controller, action)
+ end
end
end
@@ -83,6 +85,12 @@ module ActionController #:nodoc:
@options = options
end
+ def filter(controller, action)
+ should_continue = before(controller)
+ action.call if should_continue
+ after(controller)
+ end
+
def before(controller)
cache_path = ActionCachePath.new(controller, path_options_for(controller, @options.slice(:cache_path)))
if cache = controller.read_fragment(cache_path.path, @options[:store_options])
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index df1a1b7683..10b904481d 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -1,5 +1,6 @@
require 'fileutils'
require 'abstract_unit'
+require 'active_record_unit'
CACHE_DIR = 'test_cache'
# Don't change '/../temp/' cavalierly or you might hose something you don't want hosed
@@ -153,6 +154,7 @@ class ActionCachingTestController < ActionController::Base
caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]};edit" : "http://test.host/edit" }
caches_action :with_layout
caches_action :layout_false, :layout => false
+ caches_action :record_not_found, :four_oh_four, :simple_runtime_error
layout 'talk_from_action.erb'
@@ -175,6 +177,18 @@ class ActionCachingTestController < ActionController::Base
render :text => @cache_this, :layout => true
end
+ def record_not_found
+ raise ActiveRecord::RecordNotFound, "oops!"
+ end
+
+ def four_oh_four
+ render :text => "404'd!", :status => 404
+ end
+
+ def simple_runtime_error
+ raise "oops!"
+ end
+
alias_method :show, :index
alias_method :edit, :index
alias_method :destroy, :index
@@ -458,6 +472,27 @@ class ActionCacheTest < ActionController::TestCase
assert_response :success
end
+ def test_record_not_found_returns_404_for_multiple_requests
+ get :record_not_found
+ assert_response 404
+ get :record_not_found
+ assert_response 404
+ end
+
+ def test_four_oh_four_returns_404_for_multiple_requests
+ get :four_oh_four
+ assert_response 404
+ get :four_oh_four
+ assert_response 404
+ end
+
+ def test_simple_runtime_error_returns_500_for_multiple_requests
+ get :simple_runtime_error
+ assert_response 500
+ get :simple_runtime_error
+ assert_response 500
+ end
+
private
def content_to_cache
assigns(:cache_this)
--
cgit v1.2.3
From d54604c352ca444c49e54f4dbbfcaff58f8c7d06 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 19:09:47 -0500
Subject: Depend on unreleased rack 1.1
---
actionpack/lib/action_dispatch.rb | 3 +-
actionpack/lib/action_dispatch/extensions/rack.rb | 5 -
.../lib/action_dispatch/extensions/rack/mock.rb | 65 -----
.../lib/action_dispatch/extensions/rack/utils.rb | 261 ---------------------
actionpack/test/dispatch/test_request_test.rb | 2 +-
5 files changed, 2 insertions(+), 334 deletions(-)
delete mode 100644 actionpack/lib/action_dispatch/extensions/rack.rb
delete mode 100644 actionpack/lib/action_dispatch/extensions/rack/mock.rb
delete mode 100644 actionpack/lib/action_dispatch/extensions/rack/utils.rb
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 53368b3d1d..01e894cde6 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -32,9 +32,8 @@ rescue LoadError
end
require 'active_support/core/all'
-gem 'rack', '~> 1.0.0'
+gem 'rack', '~> 1.1.0'
require 'rack'
-require 'action_dispatch/extensions/rack'
module ActionDispatch
autoload :Request, 'action_dispatch/http/request'
diff --git a/actionpack/lib/action_dispatch/extensions/rack.rb b/actionpack/lib/action_dispatch/extensions/rack.rb
deleted file mode 100644
index 8a543e2110..0000000000
--- a/actionpack/lib/action_dispatch/extensions/rack.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# Monkey patch in new test helper methods
-unless Rack::Utils.respond_to?(:build_nested_query)
- require 'action_dispatch/extensions/rack/mock'
- require 'action_dispatch/extensions/rack/utils'
-end
diff --git a/actionpack/lib/action_dispatch/extensions/rack/mock.rb b/actionpack/lib/action_dispatch/extensions/rack/mock.rb
deleted file mode 100644
index d773a74244..0000000000
--- a/actionpack/lib/action_dispatch/extensions/rack/mock.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-require 'rack/mock'
-
-module Rack
- class MockRequest
- # Return the Rack environment used for a request to +uri+.
- def self.env_for(uri="", opts={})
- uri = URI(uri)
- uri.path = "/#{uri.path}" unless uri.path[0] == ?/
-
- env = DEFAULT_ENV.dup
-
- env["REQUEST_METHOD"] = opts[:method] ? opts[:method].to_s.upcase : "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["HTTPS"] = env["rack.url_scheme"] == "https" ? "on" : "off"
-
- env["SCRIPT_NAME"] = opts[:script_name] || ""
-
- if opts[:fatal]
- env["rack.errors"] = FatalWarner.new
- else
- env["rack.errors"] = StringIO.new
- end
-
- if params = opts[:params]
- if env["REQUEST_METHOD"] == "GET"
- params = Utils.parse_nested_query(params) if params.is_a?(String)
- params.update(Utils.parse_nested_query(env["QUERY_STRING"]))
- env["QUERY_STRING"] = Utils.build_nested_query(params)
- elsif !opts.has_key?(:input)
- opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
- if params.is_a?(Hash)
- if data = Utils::Multipart.build_multipart(params)
- opts[:input] = data
- opts["CONTENT_LENGTH"] ||= data.length.to_s
- opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{Utils::Multipart::MULTIPART_BOUNDARY}"
- else
- opts[:input] = Utils.build_nested_query(params)
- end
- else
- opts[:input] = params
- end
- end
- 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
-end
diff --git a/actionpack/lib/action_dispatch/extensions/rack/utils.rb b/actionpack/lib/action_dispatch/extensions/rack/utils.rb
deleted file mode 100644
index 8e4b94eda0..0000000000
--- a/actionpack/lib/action_dispatch/extensions/rack/utils.rb
+++ /dev/null
@@ -1,261 +0,0 @@
-# -*- encoding: binary -*-
-
-require 'rack/utils'
-
-module Rack
- module Utils
- def normalize_params(params, name, v = nil)
- name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
- k = $1 || ''
- after = $' || ''
-
- return if k.empty?
-
- if after == ""
- params[k] = v
- elsif after == "[]"
- params[k] ||= []
- raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
- params[k] << v
- elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
- child_key = $1
- params[k] ||= []
- raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" 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] ||= {}
- raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash)
- params[k] = normalize_params(params[k], after, v)
- end
-
- return params
- end
- module_function :normalize_params
-
- def build_nested_query(value, prefix = nil)
- case value
- when Array
- value.map { |v|
- build_nested_query(v, "#{prefix}[]")
- }.join("&")
- when Hash
- value.map { |k, v|
- build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
- }.join("&")
- when String
- raise ArgumentError, "value must be a Hash" if prefix.nil?
- "#{prefix}=#{escape(value)}"
- else
- prefix
- end
- end
- module_function :build_nested_query
-
- module Multipart
- 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
-
- MULTIPART_BOUNDARY = "AaB03x"
-
- def self.parse_multipart(env)
- unless env['CONTENT_TYPE'] =~
- %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
- nil
- else
- boundary = "--#{$1}"
-
- params = {}
- buf = ""
- content_length = env['CONTENT_LENGTH'].to_i
- input = env['rack.input']
- input.rewind
-
- boundary_size = Utils.bytesize(boundary) + EOL.size
- bufsize = 16384
-
- content_length -= boundary_size
-
- read_buffer = ''
-
- status = input.read(boundary_size, read_buffer)
- 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(EOL+EOL)
- 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: (.*)#{EOL}/ni, 1]
- name = head[/Content-Disposition:.*\s+name="?([^\";]*)"?/ni, 1] || head[/Content-ID:\s*([^#{EOL}]*)/ni, 1]
-
- if content_type || 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, read_buffer)
- 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}
- elsif !filename && content_type
- body.rewind
-
- # Generic multipart cases, not coming from a form
- data = {: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
- }
-
- input.rewind
-
- params
- end
- end
-
- def self.build_multipart(params, first = true)
- if first
- unless params.is_a?(Hash)
- raise ArgumentError, "value must be a Hash"
- end
-
- multipart = false
- query = lambda { |value|
- case value
- when Array
- value.each(&query)
- when Hash
- value.values.each(&query)
- when UploadedFile
- multipart = true
- end
- }
- params.values.each(&query)
- return nil unless multipart
- end
-
- flattened_params = Hash.new
-
- params.each do |key, value|
- k = first ? key.to_s : "[#{key}]"
-
- case value
- when Array
- value.map { |v|
- build_multipart(v, false).each { |subkey, subvalue|
- flattened_params["#{k}[]#{subkey}"] = subvalue
- }
- }
- when Hash
- build_multipart(value, false).each { |subkey, subvalue|
- flattened_params[k + subkey] = subvalue
- }
- else
- flattened_params[k] = value
- end
- end
-
- if first
- flattened_params.map { |name, file|
- if file.respond_to?(:original_filename)
- ::File.open(file.path, "rb") do |f|
- f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
-<<-EOF
---#{MULTIPART_BOUNDARY}\r
-Content-Disposition: form-data; name="#{name}"; filename="#{Utils.escape(file.original_filename)}"\r
-Content-Type: #{file.content_type}\r
-Content-Length: #{::File.stat(file.path).size}\r
-\r
-#{f.read}\r
-EOF
- end
- else
-<<-EOF
---#{MULTIPART_BOUNDARY}\r
-Content-Disposition: form-data; name="#{name}"\r
-\r
-#{file}\r
-EOF
- end
- }.join + "--#{MULTIPART_BOUNDARY}--\r"
- else
- flattened_params
- end
- end
- end
- end
-end
diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb
index 40a7f04079..f13f67f0ae 100644
--- a/actionpack/test/dispatch/test_request_test.rb
+++ b/actionpack/test/dispatch/test_request_test.rb
@@ -18,7 +18,7 @@ class TestRequestTest < ActiveSupport::TestCase
assert_equal "0.0.0.0", env.delete("REMOTE_ADDR")
assert_equal "Rails Testing", env.delete("HTTP_USER_AGENT")
- assert_equal [0, 1], env.delete("rack.version")
+ assert_equal [1, 0], env.delete("rack.version")
assert_equal "", env.delete("rack.input").string
assert_kind_of StringIO, env.delete("rack.errors")
assert_equal true, env.delete("rack.multithread")
--
cgit v1.2.3
From a6fff94baf0ca5d436cbc5c0fa81f690c8024ff5 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 19:23:50 -0500
Subject: Move TestRequest cookies accessor into AD TestRequest
---
.../lib/action_controller/testing/process.rb | 2 --
.../lib/action_dispatch/testing/test_request.rb | 24 +++++++++++++++++++---
actionpack/test/dispatch/test_request_test.rb | 15 ++++++++++++++
3 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index e0f8f026fd..2fbd89ae1c 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -2,7 +2,6 @@ require 'rack/session/abstract/id'
module ActionController #:nodoc:
class TestRequest < ActionDispatch::TestRequest #:nodoc:
- attr_accessor :cookies
attr_accessor :query_parameters
def initialize(env = {})
@@ -13,7 +12,6 @@ module ActionController #:nodoc:
self.session_options = TestSession::DEFAULT_OPTIONS.merge(:id => ActiveSupport::SecureRandom.hex(16))
@request_uri = "/"
- @cookies = {}
end
# Wraps raw_post in a StringIO.
diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb
index 3d20b466d3..bd6c26b69b 100644
--- a/actionpack/lib/action_dispatch/testing/test_request.rb
+++ b/actionpack/lib/action_dispatch/testing/test_request.rb
@@ -1,17 +1,24 @@
module ActionDispatch
class TestRequest < Request
+ DEFAULT_ENV = Rack::MockRequest.env_for('/')
+
def self.new(env = {})
super
end
def initialize(env = {})
- super(Rack::MockRequest.env_for('/').merge(env))
+ super(DEFAULT_ENV.merge(env))
self.host = 'test.host'
self.remote_addr = '0.0.0.0'
self.user_agent = 'Rails Testing'
end
+ def env
+ write_cookies!
+ super
+ end
+
def request_method=(method)
@env['REQUEST_METHOD'] = method.to_s.upcase
end
@@ -49,8 +56,19 @@ module ActionDispatch
end
def accept=(mime_types)
- @env.delete("action_dispatch.request.accepts")
- @env["HTTP_ACCEPT"] = Array(mime_types).collect { |mime_types| mime_types.to_s }.join(",")
+ @env.delete('action_dispatch.request.accepts')
+ @env['HTTP_ACCEPT'] = Array(mime_types).collect { |mime_types| mime_types.to_s }.join(",")
end
+
+ def cookies
+ @cookies ||= super
+ end
+
+ private
+ def write_cookies!
+ unless @cookies.blank?
+ @env['HTTP_COOKIE'] = @cookies.map { |name, value| "#{name}=#{value};" }.join(' ')
+ end
+ end
end
end
diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb
index f13f67f0ae..19b5e2988b 100644
--- a/actionpack/test/dispatch/test_request_test.rb
+++ b/actionpack/test/dispatch/test_request_test.rb
@@ -27,4 +27,19 @@ class TestRequestTest < ActiveSupport::TestCase
assert env.empty?, env.inspect
end
+
+ test "cookie jar" do
+ req = ActionDispatch::TestRequest.new
+
+ assert_equal({}, req.cookies)
+ assert_equal nil, req.env["HTTP_COOKIE"]
+
+ req.cookies["user_name"] = "david"
+ assert_equal({"user_name" => "david"}, req.cookies)
+ assert_equal "user_name=david;", req.env["HTTP_COOKIE"]
+
+ req.cookies["login"] = "XJ-122"
+ assert_equal({"user_name" => "david", "login" => "XJ-122"}, req.cookies)
+ assert_equal "login=XJ-122; user_name=david;", req.env["HTTP_COOKIE"]
+ end
end
--
cgit v1.2.3
From 261ec996de6279a58d5b10f6f36ee1cc1fb96fc6 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 19:36:18 -0500
Subject: Missed stray @request_uri
---
actionpack/lib/action_controller/testing/process.rb | 2 --
1 file changed, 2 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 2fbd89ae1c..d059b37f6d 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -10,8 +10,6 @@ module ActionController #:nodoc:
@query_parameters = {}
self.session = TestSession.new
self.session_options = TestSession::DEFAULT_OPTIONS.merge(:id => ActiveSupport::SecureRandom.hex(16))
-
- @request_uri = "/"
end
# Wraps raw_post in a StringIO.
--
cgit v1.2.3
From 0fa1e75d416f529c61ef1cbfce230a91417d436c Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 20:04:55 -0500
Subject: Set rack.input instead of RAW_POST_DATA in TestRequest
---
.../lib/action_controller/testing/process.rb | 39 ++++++----------------
1 file changed, 11 insertions(+), 28 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index d059b37f6d..d397bc0283 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -12,21 +12,6 @@ module ActionController #:nodoc:
self.session_options = TestSession::DEFAULT_OPTIONS.merge(:id => ActiveSupport::SecureRandom.hex(16))
end
- # Wraps raw_post in a StringIO.
- def body_stream #:nodoc:
- StringIO.new(raw_post)
- end
-
- # Either the RAW_POST_DATA environment variable or the URL-encoded request
- # parameters.
- def raw_post
- @env['RAW_POST_DATA'] ||= begin
- data = url_encoded_request_parameters
- data.force_encoding(Encoding::BINARY) if data.respond_to?(:force_encoding)
- data
- end
- end
-
def action=(action_name)
query_parameters.update({ "action" => action_name })
end
@@ -48,7 +33,17 @@ module ActionController #:nodoc:
path_parameters[key.to_s] = value
end
end
- raw_post # populate env['RAW_POST_DATA']
+
+ params = self.request_parameters.dup
+
+ %w(controller action only_path).each do |k|
+ params.delete(k)
+ params.delete(k.to_sym)
+ end
+
+ data = params.to_query
+ @env['CONTENT_LENGTH'] = data.length
+ @env['rack.input'] = StringIO.new(data)
end
def recycle!
@@ -56,18 +51,6 @@ module ActionController #:nodoc:
self.query_parameters = {}
@headers = nil
end
-
- private
- def url_encoded_request_parameters
- params = self.request_parameters.dup
-
- %w(controller action only_path).each do |k|
- params.delete(k)
- params.delete(k.to_sym)
- end
-
- params.to_query
- end
end
# Integration test methods such as ActionController::Integration::Session#get
--
cgit v1.2.3
From 9b852af49783096124aa34c4638b99768f701a78 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 30 Apr 2009 20:33:50 -0700
Subject: Explicitly require builder for to_xml
---
activerecord/lib/active_record/validations.rb | 2 ++
1 file changed, 2 insertions(+)
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index d2d12b80c9..e6b61e0b35 100644
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -1,3 +1,5 @@
+require 'builder'
+
module ActiveRecord
# Raised by save! and create! when the record is invalid. Use the
# +record+ method to retrieve the record which did not validate.
--
cgit v1.2.3
From dc9f53b05b650614520086ae780ca5e58efe65b1 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 30 Apr 2009 21:02:11 -0700
Subject: Selectively require rake sshpublisher so full gem isn't required
---
activerecord/Rakefile | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/activerecord/Rakefile b/activerecord/Rakefile
index b50008c971..5905c67e29 100644
--- a/activerecord/Rakefile
+++ b/activerecord/Rakefile
@@ -4,7 +4,6 @@ require 'rake/testtask'
require 'rake/rdoctask'
require 'rake/packagetask'
require 'rake/gempackagetask'
-require 'rake/contrib/sshpublisher'
require File.join(File.dirname(__FILE__), 'lib', 'active_record', 'version')
require File.expand_path(File.dirname(__FILE__)) + "/test/config"
@@ -231,12 +230,14 @@ end
desc "Publish the beta gem"
task :pgem => [:package] do
+ require 'rake/contrib/sshpublisher'
Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
`ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'`
end
desc "Publish the API documentation"
task :pdoc => [:rdoc] do
+ require 'rake/contrib/sshpublisher'
Rake::SshDirPublisher.new("wrath.rubyonrails.org", "public_html/ar", "doc").upload
end
--
cgit v1.2.3
From 1fcc7dbcc8dcf7f1d42ca8486ad313f0c805033a Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 23:31:20 -0500
Subject: Move TestRequest#query_parameters into AD TestRequest
---
actionpack/lib/action_controller/testing/process.rb | 14 ++------------
actionpack/lib/action_dispatch/http/request.rb | 2 +-
actionpack/lib/action_dispatch/testing/test_request.rb | 4 ++++
3 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index d397bc0283..786dc67e2e 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -2,20 +2,13 @@ require 'rack/session/abstract/id'
module ActionController #:nodoc:
class TestRequest < ActionDispatch::TestRequest #:nodoc:
- attr_accessor :query_parameters
-
def initialize(env = {})
super
- @query_parameters = {}
self.session = TestSession.new
self.session_options = TestSession::DEFAULT_OPTIONS.merge(:id => ActiveSupport::SecureRandom.hex(16))
end
- def action=(action_name)
- query_parameters.update({ "action" => action_name })
- end
-
def assign_parameters(controller_path, action, parameters)
parameters = parameters.symbolize_keys.merge(:controller => controller_path, :action => action)
extra_keys = ActionController::Routing::Routes.extra_keys(parameters)
@@ -47,9 +40,8 @@ module ActionController #:nodoc:
end
def recycle!
- @env.delete_if { |k, v| k =~ /^action_dispatch\.request/ }
- self.query_parameters = {}
- @headers = nil
+ @env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
+ @env['action_dispatch.request.query_parameters'] = {}
end
end
@@ -132,8 +124,6 @@ module ActionController #:nodoc:
@html_document = nil
@request.request_method = http_method
- @request.action = action.to_s
-
parameters ||= {}
@request.assign_parameters(@controller.class.controller_path, action.to_s, parameters)
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index c28f59dbd6..e4f3a8f125 100755
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -351,7 +351,7 @@ EOM
# Returns the query string, accounting for server idiosyncrasies.
def query_string
- @env['QUERY_STRING'].present? ? @env['QUERY_STRING'] : (@env['REQUEST_URI'].split('?', 2)[1] || '')
+ @env['QUERY_STRING'].present? ? @env['QUERY_STRING'] : (@env['REQUEST_URI'].to_s.split('?', 2)[1] || '')
end
# Returns the request URI, accounting for server idiosyncrasies.
diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb
index bd6c26b69b..5d8cd7e619 100644
--- a/actionpack/lib/action_dispatch/testing/test_request.rb
+++ b/actionpack/lib/action_dispatch/testing/test_request.rb
@@ -39,6 +39,10 @@ module ActionDispatch
@env['PATH_INFO'] = path
end
+ def action=(action_name)
+ path_parameters["action"] = action_name.to_s
+ end
+
def if_modified_since=(last_modified)
@env['HTTP_IF_MODIFIED_SINCE'] = last_modified
end
--
cgit v1.2.3
From 05bd863c022601bb0bbd17c51adbcb420f349323 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 23:36:47 -0500
Subject: alias method chain process with test
---
actionpack/lib/action_controller/testing/process.rb | 9 ++++++---
actionpack/test/controller/filters_test.rb | 4 ++--
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 786dc67e2e..8315a160ad 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -132,7 +132,7 @@ module ActionController #:nodoc:
build_request_uri(action, parameters)
Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
- @controller.process_with_test(@request, @response)
+ @controller.process(@request, @response)
end
def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil)
@@ -248,11 +248,14 @@ module ActionController #:nodoc:
module ProcessWithTest #:nodoc:
def self.included(base)
- base.class_eval { attr_reader :assigns }
+ base.class_eval {
+ attr_reader :assigns
+ alias_method_chain :process, :test
+ }
end
def process_with_test(*args)
- process(*args).tap { set_test_assigns }
+ process_without_test(*args).tap { set_test_assigns }
end
private
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index aca7a821c8..bdec5d2d4c 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -674,7 +674,7 @@ class FilterTest < Test::Unit::TestCase
request.action = action
controller = controller.new if controller.is_a?(Class)
@controller = controller
- @controller.process_with_test(request, ActionController::TestResponse.new)
+ @controller.process(request, ActionController::TestResponse.new)
end
end
@@ -917,6 +917,6 @@ class YieldingAroundFiltersTest < Test::Unit::TestCase
request.action = action
controller = controller.new if controller.is_a?(Class)
@controller = controller
- @controller.process_with_test(request, ActionController::TestResponse.new)
+ @controller.process(request, ActionController::TestResponse.new)
end
end
--
cgit v1.2.3
From 664ae187a927ba54c8c7ec6eaf9ad89be291fc95 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 30 Apr 2009 23:43:35 -0500
Subject: Update some old tests to use AC TestProcess
---
actionpack/test/controller/filters_test.rb | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index bdec5d2d4c..9e74538310 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -2,6 +2,8 @@ require 'abstract_unit'
# FIXME: crashes Ruby 1.9
class FilterTest < Test::Unit::TestCase
+ include ActionController::TestProcess
+
class TestController < ActionController::Base
before_filter :ensure_login
after_filter :clean_up
@@ -669,12 +671,11 @@ class FilterTest < Test::Unit::TestCase
private
def test_process(controller, action = "show")
- ActionController::Base.class_eval { include ActionController::ProcessWithTest } unless ActionController::Base < ActionController::ProcessWithTest
- request = ActionController::TestRequest.new
- request.action = action
- controller = controller.new if controller.is_a?(Class)
- @controller = controller
- @controller.process(request, ActionController::TestResponse.new)
+ @controller = controller.is_a?(Class) ? controller.new : controller
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+
+ process(action)
end
end
@@ -810,6 +811,7 @@ end
class YieldingAroundFiltersTest < Test::Unit::TestCase
include PostsController::AroundExceptions
+ include ActionController::TestProcess
def test_filters_registering
assert_equal 1, ControllerWithFilterMethod.filter_chain.size
@@ -912,11 +914,10 @@ class YieldingAroundFiltersTest < Test::Unit::TestCase
protected
def test_process(controller, action = "show")
- ActionController::Base.class_eval { include ActionController::ProcessWithTest } unless ActionController::Base < ActionController::ProcessWithTest
- request = ActionController::TestRequest.new
- request.action = action
- controller = controller.new if controller.is_a?(Class)
- @controller = controller
- @controller.process(request, ActionController::TestResponse.new)
+ @controller = controller.is_a?(Class) ? controller.new : controller
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+
+ process(action)
end
end
--
cgit v1.2.3
From b193f233908823cccd2f1d5fcb4146787ed8c4ed Mon Sep 17 00:00:00 2001
From: Ken Collins
Date: Mon, 9 Feb 2009 15:24:59 -0500
Subject: Use table_exists? in #initialize_schema_migrations_table [#1923
state:resolved]
Signed-off-by: Pratik Naik
---
.../active_record/connection_adapters/abstract/schema_statements.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index c29c1562b4..ff63ea3a2e 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -316,7 +316,7 @@ module ActiveRecord
def initialize_schema_migrations_table
sm_table = ActiveRecord::Migrator.schema_migrations_table_name
- unless tables.detect { |t| t == sm_table }
+ unless table_exists?(sm_table)
create_table(sm_table, :id => false) do |schema_migrations_table|
schema_migrations_table.column :version, :string, :null => false
end
@@ -327,7 +327,7 @@ module ActiveRecord
# migrated up to that point:
si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix
- if tables.detect { |t| t == si_table }
+ if table_exists?(si_table)
old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i
assume_migrated_upto_version(old_version)
--
cgit v1.2.3
From 5501b99a19a2a67a9a920fd3c7bff071a2ecf058 Mon Sep 17 00:00:00 2001
From: steve
Date: Fri, 1 May 2009 14:58:10 +0100
Subject: Ensure ActiveRecord::Base.connection_pool.with_connection creates a
new connection only when needed [#1752 state:resolved]
Signed-off-by: Pratik Naik
---
.../abstract/connection_pool.rb | 11 ++++----
activerecord/test/cases/pooled_connections_test.rb | 29 ++++++++++++++++++++++
2 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index aac84cc5f4..e8e736bf38 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -107,13 +107,14 @@ module ActiveRecord
checkin conn if conn
end
- # Reserve a connection, and yield it to a block. Ensure the connection is
- # checked back in when finished.
+ # If a connection already exists yield it to the block. If no connection
+ # exists checkout a connection, yield it to the block, and checkin the
+ # connection when finished.
def with_connection
- conn = checkout
- yield conn
+ fresh_connection = true unless @reserved_connections[current_connection_id]
+ yield connection
ensure
- checkin conn
+ release_connection if fresh_connection
end
# Returns true if a connection has already been opened.
diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb
index 2649a9358a..bbd943fc6e 100644
--- a/activerecord/test/cases/pooled_connections_test.rb
+++ b/activerecord/test/cases/pooled_connections_test.rb
@@ -1,4 +1,6 @@
require "cases/helper"
+require "models/project"
+require "timeout"
class PooledConnectionsTest < ActiveRecord::TestCase
def setup
@@ -89,6 +91,33 @@ class PooledConnectionsTest < ActiveRecord::TestCase
ensure
ActiveRecord::Base.connection_handler = old_handler
end
+
+ def test_with_connection_nesting_safety
+ ActiveRecord::Base.establish_connection(@connection.merge({:pool => 1, :wait_timeout => 0.1}))
+
+ before_count = Project.count
+
+ add_record('one')
+
+ ActiveRecord::Base.connection.transaction do
+ add_record('two')
+ # Have another thread try to screw up the transaction
+ Thread.new do
+ raise ActiveRecord::Rollback
+ ActiveRecord::Base.connection_pool.release_connection
+ end.join rescue nil
+ add_record('three')
+ end
+
+ after_count = Project.count
+ assert_equal 3, after_count - before_count
+ end
+
+ private
+
+ def add_record(name)
+ ActiveRecord::Base.connection_pool.with_connection { Project.create! :name => name }
+ end
end unless %w(FrontBase).include? ActiveRecord::Base.connection.adapter_name
class AllowConcurrencyDeprecatedTest < ActiveRecord::TestCase
--
cgit v1.2.3
From 60a6284a461afda5911ecadf3a147d4da6ed5d22 Mon Sep 17 00:00:00 2001
From: steve
Date: Fri, 1 May 2009 16:00:09 +0100
Subject: Tests should use
ActiveRecord::Base.connection.rollback_db_transaction to rollback a
transaction
Signed-off-by: Pratik Naik
---
activerecord/test/cases/pooled_connections_test.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb
index bbd943fc6e..bb9013c2a1 100644
--- a/activerecord/test/cases/pooled_connections_test.rb
+++ b/activerecord/test/cases/pooled_connections_test.rb
@@ -103,7 +103,7 @@ class PooledConnectionsTest < ActiveRecord::TestCase
add_record('two')
# Have another thread try to screw up the transaction
Thread.new do
- raise ActiveRecord::Rollback
+ ActiveRecord::Base.connection.rollback_db_transaction
ActiveRecord::Base.connection_pool.release_connection
end.join rescue nil
add_record('three')
--
cgit v1.2.3
From 432e631d5c9cc59db3e5c515c348352a4268eb7f Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Fri, 1 May 2009 20:12:49 +0100
Subject: Vendor Rack edge ( commit : 815342a8e15db564b766f209ffb1e340233f064f
)
---
actionpack/lib/action_dispatch.rb | 7 +-
actionpack/lib/action_dispatch/vendor/rack/rack.rb | 90 ++++
.../vendor/rack/rack/adapter/camping.rb | 22 +
.../vendor/rack/rack/auth/abstract/handler.rb | 37 ++
.../vendor/rack/rack/auth/abstract/request.rb | 37 ++
.../action_dispatch/vendor/rack/rack/auth/basic.rb | 58 +++
.../vendor/rack/rack/auth/digest/md5.rb | 124 +++++
.../vendor/rack/rack/auth/digest/nonce.rb | 51 ++
.../vendor/rack/rack/auth/digest/params.rb | 55 +++
.../vendor/rack/rack/auth/digest/request.rb | 40 ++
.../vendor/rack/rack/auth/openid.rb | 480 ++++++++++++++++++
.../action_dispatch/vendor/rack/rack/builder.rb | 63 +++
.../action_dispatch/vendor/rack/rack/cascade.rb | 36 ++
.../action_dispatch/vendor/rack/rack/chunked.rb | 49 ++
.../vendor/rack/rack/commonlogger.rb | 61 +++
.../vendor/rack/rack/conditionalget.rb | 47 ++
.../vendor/rack/rack/content_length.rb | 29 ++
.../vendor/rack/rack/content_type.rb | 23 +
.../action_dispatch/vendor/rack/rack/deflater.rb | 96 ++++
.../action_dispatch/vendor/rack/rack/directory.rb | 153 ++++++
.../lib/action_dispatch/vendor/rack/rack/file.rb | 88 ++++
.../action_dispatch/vendor/rack/rack/handler.rb | 69 +++
.../vendor/rack/rack/handler/cgi.rb | 61 +++
.../vendor/rack/rack/handler/evented_mongrel.rb | 8 +
.../vendor/rack/rack/handler/fastcgi.rb | 88 ++++
.../vendor/rack/rack/handler/lsws.rb | 55 +++
.../vendor/rack/rack/handler/mongrel.rb | 84 ++++
.../vendor/rack/rack/handler/scgi.rb | 59 +++
.../rack/rack/handler/swiftiplied_mongrel.rb | 8 +
.../vendor/rack/rack/handler/thin.rb | 18 +
.../vendor/rack/rack/handler/webrick.rb | 67 +++
.../lib/action_dispatch/vendor/rack/rack/head.rb | 19 +
.../lib/action_dispatch/vendor/rack/rack/lint.rb | 537 +++++++++++++++++++++
.../action_dispatch/vendor/rack/rack/lobster.rb | 65 +++
.../lib/action_dispatch/vendor/rack/rack/lock.rb | 16 +
.../vendor/rack/rack/methodoverride.rb | 27 ++
.../lib/action_dispatch/vendor/rack/rack/mime.rb | 204 ++++++++
.../lib/action_dispatch/vendor/rack/rack/mock.rb | 184 +++++++
.../action_dispatch/vendor/rack/rack/recursive.rb | 57 +++
.../action_dispatch/vendor/rack/rack/reloader.rb | 106 ++++
.../action_dispatch/vendor/rack/rack/request.rb | 254 ++++++++++
.../action_dispatch/vendor/rack/rack/response.rb | 183 +++++++
.../vendor/rack/rack/rewindable_input.rb | 98 ++++
.../vendor/rack/rack/session/abstract/id.rb | 142 ++++++
.../vendor/rack/rack/session/cookie.rb | 91 ++++
.../vendor/rack/rack/session/memcache.rb | 109 +++++
.../vendor/rack/rack/session/pool.rb | 100 ++++
.../vendor/rack/rack/showexceptions.rb | 349 +++++++++++++
.../action_dispatch/vendor/rack/rack/showstatus.rb | 106 ++++
.../lib/action_dispatch/vendor/rack/rack/static.rb | 38 ++
.../lib/action_dispatch/vendor/rack/rack/urlmap.rb | 55 +++
.../lib/action_dispatch/vendor/rack/rack/utils.rb | 516 ++++++++++++++++++++
52 files changed, 5418 insertions(+), 1 deletion(-)
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/adapter/camping.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/abstract/handler.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/abstract/request.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/basic.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/md5.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/nonce.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/params.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/request.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/openid.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/builder.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/cascade.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/chunked.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/commonlogger.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/conditionalget.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/content_length.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/content_type.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/deflater.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/directory.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/file.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/cgi.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/evented_mongrel.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/fastcgi.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/lsws.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/mongrel.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/scgi.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/swiftiplied_mongrel.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/thin.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/webrick.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/head.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/lint.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/lobster.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/lock.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/methodoverride.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/mime.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/mock.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/recursive.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/reloader.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/request.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/response.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/rewindable_input.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/session/abstract/id.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/session/cookie.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/session/memcache.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/session/pool.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/showexceptions.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/showstatus.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/static.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/urlmap.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/utils.rb
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 01e894cde6..a57fc5abdd 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -32,7 +32,12 @@ rescue LoadError
end
require 'active_support/core/all'
-gem 'rack', '~> 1.1.0'
+begin
+ gem 'rack', '~> 1.1.0'
+rescue Gem::LoadError
+ $:.unshift "#{File.dirname(__FILE__)}/action_dispatch/vendor/rack"
+end
+
require 'rack'
module ActionDispatch
diff --git a/actionpack/lib/action_dispatch/vendor/rack/rack.rb b/actionpack/lib/action_dispatch/vendor/rack/rack.rb
new file mode 100644
index 0000000000..371d015690
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack.rb
@@ -0,0 +1,90 @@
+# 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.
+
+path = File.expand_path(File.dirname(__FILE__))
+$:.unshift(path) unless $:.include?(path)
+
+
+# The Rack main module, serving as a namespace for all core Rack
+# modules and classes.
+#
+# All modules meant for use in your application are autoload ed here,
+# so it should be enough just to require rack.rb in your code.
+
+module Rack
+ # The Rack protocol version number implemented.
+ VERSION = [1,0]
+
+ # 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"
+ 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/rack/adapter/camping.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/adapter/camping.rb
new file mode 100644
index 0000000000..63bc787f54
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/adapter/camping.rb
@@ -0,0 +1,22 @@
+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/rack/auth/abstract/handler.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/abstract/handler.rb
new file mode 100644
index 0000000000..214df6299e
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/abstract/handler.rb
@@ -0,0 +1,37 @@
+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/rack/auth/abstract/request.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/abstract/request.rb
new file mode 100644
index 0000000000..1d9ccec685
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/abstract/request.rb
@@ -0,0 +1,37 @@
+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/rack/auth/basic.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/basic.rb
new file mode 100644
index 0000000000..9557224648
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/basic.rb
@@ -0,0 +1,58 @@
+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/rack/auth/digest/md5.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/md5.rb
new file mode 100644
index 0000000000..e579dc9632
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/md5.rb
@@ -0,0 +1,124 @@
+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/rack/auth/digest/nonce.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/nonce.rb
new file mode 100644
index 0000000000..dbe109f29a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/nonce.rb
@@ -0,0 +1,51 @@
+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/rack/auth/digest/params.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/params.rb
new file mode 100644
index 0000000000..730e2efdc8
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/params.rb
@@ -0,0 +1,55 @@
+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/rack/auth/digest/request.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/request.rb
new file mode 100644
index 0000000000..a8aa3bf996
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/request.rb
@@ -0,0 +1,40 @@
+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/rack/auth/openid.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/openid.rb
new file mode 100644
index 0000000000..c5f6a5143e
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/openid.rb
@@ -0,0 +1,480 @@
+# 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/rack/builder.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/builder.rb
new file mode 100644
index 0000000000..295235e56a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/builder.rb
@@ -0,0 +1,63 @@
+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/rack/cascade.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/cascade.rb
new file mode 100644
index 0000000000..a038aa1105
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/cascade.rb
@@ -0,0 +1,36 @@
+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/rack/chunked.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/chunked.rb
new file mode 100644
index 0000000000..280d89dd65
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/chunked.rb
@@ -0,0 +1,49 @@
+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/rack/commonlogger.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/commonlogger.rb
new file mode 100644
index 0000000000..5e68ac626d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/commonlogger.rb
@@ -0,0 +1,61 @@
+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/rack/conditionalget.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/conditionalget.rb
new file mode 100644
index 0000000000..046ebdb00a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/conditionalget.rb
@@ -0,0 +1,47 @@
+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
+ headers.delete('Content-Type')
+ headers.delete('Content-Length')
+ 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/rack/content_length.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/content_length.rb
new file mode 100644
index 0000000000..1e56d43853
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/content_length.rb
@@ -0,0 +1,29 @@
+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/rack/content_type.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/content_type.rb
new file mode 100644
index 0000000000..0c1e1ca3e1
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/content_type.rb
@@ -0,0 +1,23 @@
+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/rack/deflater.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/deflater.rb
new file mode 100644
index 0000000000..14137a944d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/deflater.rb
@@ -0,0 +1,96 @@
+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"
+ headers['Content-Encoding'] = "gzip"
+ headers.delete('Content-Length')
+ mtime = headers.key?("Last-Modified") ?
+ Time.httpdate(headers["Last-Modified"]) : Time.now
+ [status, headers, GzipStream.new(body, mtime)]
+ when "deflate"
+ headers['Content-Encoding'] = "deflate"
+ headers.delete('Content-Length')
+ [status, headers, DeflateStream.new(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
+
+ class GzipStream
+ def initialize(body, mtime)
+ @body = body
+ @mtime = mtime
+ end
+
+ def each(&block)
+ @writer = block
+ gzip =::Zlib::GzipWriter.new(self)
+ gzip.mtime = @mtime
+ @body.each { |part| gzip << part }
+ @body.close if @body.respond_to?(:close)
+ gzip.close
+ @writer = nil
+ end
+
+ def write(data)
+ @writer.call(data)
+ end
+ end
+
+ class DeflateStream
+ 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
+ ]
+
+ def initialize(body)
+ @body = body
+ end
+
+ def each
+ deflater = ::Zlib::Deflate.new(*DEFLATE_ARGS)
+ @body.each { |part| yield deflater.deflate(part) }
+ @body.close if @body.respond_to?(:close)
+ yield deflater.finish
+ nil
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack/rack/directory.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/directory.rb
new file mode 100644
index 0000000000..acdd3029d3
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/directory.rb
@@ -0,0 +1,153 @@
+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
+
+
+
+ Name
+ Size
+ Type
+ Last Modified
+
+%s
+
+
+
+ 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/rack/file.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/file.rb
new file mode 100644
index 0000000000..fe62bd6b86
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/file.rb
@@ -0,0 +1,88 @@
+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/rack/handler.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler.rb
new file mode 100644
index 0000000000..5624a1e79d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/handler.rb
@@ -0,0 +1,69 @@
+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
+ server = server.to_s
+
+ if klass = @handlers[server]
+ obj = Object
+ klass.split("::").each { |x| obj = obj.const_get(x) }
+ obj
+ else
+ try_require('rack/handler', server)
+ const_get(server)
+ end
+ end
+
+ # Transforms server-name constants to their canonical form as filenames,
+ # then tries to require them but silences the LoadError if not found
+ #
+ # Naming convention:
+ #
+ # Foo # => 'foo'
+ # FooBar # => 'foo_bar.rb'
+ # FooBAR # => 'foobar.rb'
+ # FOObar # => 'foobar.rb'
+ # FOOBAR # => 'foobar.rb'
+ # FooBarBaz # => 'foo_bar_baz.rb'
+ def self.try_require(prefix, const_name)
+ file = const_name.gsub(/^[A-Z]+/) { |pre| pre.downcase }.
+ gsub(/[A-Z]+[^A-Z]/, '_\&').downcase
+
+ require(::File.join(prefix, file))
+ rescue LoadError
+ 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/rack/handler/cgi.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/cgi.rb
new file mode 100644
index 0000000000..f45f3d735a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/cgi.rb
@@ -0,0 +1,61 @@
+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" => [1,0],
+ "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/rack/handler/evented_mongrel.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/evented_mongrel.rb
new file mode 100644
index 0000000000..0f5cbf7293
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/evented_mongrel.rb
@@ -0,0 +1,8 @@
+require 'swiftcore/evented_mongrel'
+
+module Rack
+ module Handler
+ class EventedMongrel < Handler::Mongrel
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack/rack/handler/fastcgi.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/fastcgi.rb
new file mode 100644
index 0000000000..11e1fcaa74
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/fastcgi.rb
@@ -0,0 +1,88 @@
+require 'fcgi'
+require 'socket'
+require 'rack/content_length'
+require 'rack/rewindable_input'
+
+class FCGI::Stream
+ alias _rack_read_without_buffer read
+
+ def read(n, buffer=nil)
+ buf = _rack_read_without_buffer n
+ buffer.replace(buf.to_s) if buffer
+ buf
+ end
+end
+
+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
+
+ def self.serve(request, app)
+ app = Rack::ContentLength.new(app)
+
+ env = request.env
+ env.delete "HTTP_CONTENT_LENGTH"
+
+ env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
+
+ rack_input = RewindableInput.new(request.in)
+
+ env.update({"rack.version" => [1,0],
+ "rack.input" => rack_input,
+ "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"] == ""
+
+ begin
+ 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
+ end
+ ensure
+ rack_input.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/rack/handler/lsws.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/lsws.rb
new file mode 100644
index 0000000000..7231336d7b
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/lsws.rb
@@ -0,0 +1,55 @@
+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" => [1,0],
+ "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/rack/handler/mongrel.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/mongrel.rb
new file mode 100644
index 0000000000..3a5ef32d4b
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/mongrel.rb
@@ -0,0 +1,84 @@
+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" => [1,0],
+ "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/rack/handler/scgi.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/scgi.rb
new file mode 100644
index 0000000000..6c4932df95
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/scgi.rb
@@ -0,0 +1,59 @@
+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" => [1,0],
+ "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/rack/handler/swiftiplied_mongrel.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/swiftiplied_mongrel.rb
new file mode 100644
index 0000000000..4bafd0b953
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/swiftiplied_mongrel.rb
@@ -0,0 +1,8 @@
+require 'swiftcore/swiftiplied_mongrel'
+
+module Rack
+ module Handler
+ class SwiftipliedMongrel < Handler::Mongrel
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack/rack/handler/thin.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/thin.rb
new file mode 100644
index 0000000000..3d4fedff75
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/thin.rb
@@ -0,0 +1,18 @@
+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/rack/handler/webrick.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/webrick.rb
new file mode 100644
index 0000000000..2bdc83a9ff
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/webrick.rb
@@ -0,0 +1,67 @@
+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" => [1,0],
+ "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/rack/head.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/head.rb
new file mode 100644
index 0000000000..deab822a99
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/head.rb
@@ -0,0 +1,19 @@
+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/rack/lint.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/lint.rb
new file mode 100644
index 0000000000..bf2e9787a1
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/lint.rb
@@ -0,0 +1,537 @@
+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 value may be
+ ## percent-encoded when I originating 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 [1,0], 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).
+ ##
+
+ ## Additional environment specifications have approved to
+ ## standardized middleware APIs. None of these are required to
+ ## be implemented by the server.
+
+ ## rack.session :: A hash like interface for storing request session data.
+ ## The store must implement:
+ if session = env['rack.session']
+ ## store(key, value) (aliased as []=);
+ assert("session #{session.inspect} must respond to store and []=") {
+ session.respond_to?(:store) && session.respond_to?(:[]=)
+ }
+
+ ## fetch(key, default = nil) (aliased as []);
+ assert("session #{session.inspect} must respond to fetch and []") {
+ session.respond_to?(:fetch) && session.respond_to?(:[])
+ }
+
+ ## delete(key);
+ assert("session #{session.inspect} must respond to delete") {
+ session.respond_to?(:delete)
+ }
+
+ ## clear;
+ assert("session #{session.inspect} must respond to clear") {
+ session.respond_to?(:clear)
+ }
+ end
+
+ ## 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 other
+ ## accepted specifications 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
+ ##
+ ## The input stream is an IO-like object which contains the raw HTTP
+ ## POST data. If it is a file then it must be opened in binary mode.
+ def check_input(input)
+ ## The input stream must respond to +gets+, +each+, +read+ and +rewind+.
+ [:gets, :each, :read, :rewind].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
+
+ ## * +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+ behaves like IO#read. Its signature is read([length, [buffer]]) .
+ ## If given, +length+ must be an non-negative Integer (>= 0) or +nil+, and +buffer+ must
+ ## be a String and may not be nil. If +length+ is given and not nil, then this method
+ ## reads at most +length+ bytes from the input stream. If +length+ is not given or nil,
+ ## then this method reads all data until EOF.
+ ## When EOF is reached, this method returns nil if +length+ is given and not nil, or ""
+ ## if +length+ is not given or is nil.
+ ## If +buffer+ is given, then the read data will be placed into +buffer+ instead of a
+ ## newly created String object.
+ def read(*args)
+ assert("rack.input#read called with too many arguments") {
+ args.size <= 2
+ }
+ if args.size >= 1
+ assert("rack.input#read called with non-integer and non-nil length") {
+ args.first.kind_of?(Integer) || args.first.nil?
+ }
+ assert("rack.input#read called with a negative length") {
+ args.first.nil? || args.first >= 0
+ }
+ end
+ if args.size >= 2
+ assert("rack.input#read called with non-String buffer") {
+ args[1].kind_of?(String)
+ }
+ end
+
+ v = @input.read(*args)
+
+ assert("rack.input#read didn't return nil or a String") {
+ v.nil? or v.instance_of? String
+ }
+ if args[0].nil?
+ assert("rack.input#read(nil) returned nil on EOF") {
+ !v.nil?
+ }
+ end
+
+ 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
+
+ ## * +rewind+ must be called without arguments. It rewinds the input
+ ## stream back to the beginning. It must not raise Errno::ESPIPE:
+ ## that is, it may not be a pipe or a socket. Therefore, handler
+ ## developers must buffer the input data into some rewindable object
+ ## if the underlying input stream is not rewindable.
+ def rewind(*args)
+ assert("rack.input#rewind called with arguments") { args.size == 0 }
+ assert("rack.input#rewind raised Errno::ESPIPE") {
+ begin
+ @input.rewind
+ true
+ rescue Errno::ESPIPE
+ false
+ end
+ }
+ 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)
+ ## This is an HTTP status. When parsed as integer (+to_i+), it 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, e.g. multiple
+ ## Set-Cookie 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
+ }
+ ##
+ ## The Body itself should not be an instance of String, as this will
+ ## break in Ruby 1.9.
+ ##
+ ## 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+; this may be used by the
+ ## server as an alternative, possibly more efficient way to
+ ## transport the response.
+
+ 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/rack/lobster.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/lobster.rb
new file mode 100644
index 0000000000..f63f419a49
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/lobster.rb
@@ -0,0 +1,65 @@
+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/rack/lock.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/lock.rb
new file mode 100644
index 0000000000..93238528c4
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/lock.rb
@@ -0,0 +1,16 @@
+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/rack/methodoverride.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/methodoverride.rb
new file mode 100644
index 0000000000..0eed29f471
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/methodoverride.rb
@@ -0,0 +1,27 @@
+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/rack/mime.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/mime.rb
new file mode 100644
index 0000000000..5a6a73a97b
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/mime.rb
@@ -0,0 +1,204 @@
+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/rack/mock.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/mock.rb
new file mode 100644
index 0000000000..fdefb0340a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/mock.rb
@@ -0,0 +1,184 @@
+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" => [1,0],
+ "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)
+ uri.path = "/#{uri.path}" unless uri.path[0] == ?/
+
+ env = DEFAULT_ENV.dup
+
+ env["REQUEST_METHOD"] = opts[:method] ? opts[:method].to_s.upcase : "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["HTTPS"] = env["rack.url_scheme"] == "https" ? "on" : "off"
+
+ env["SCRIPT_NAME"] = opts[:script_name] || ""
+
+ if opts[:fatal]
+ env["rack.errors"] = FatalWarner.new
+ else
+ env["rack.errors"] = StringIO.new
+ end
+
+ if params = opts[:params]
+ if env["REQUEST_METHOD"] == "GET"
+ params = Utils.parse_nested_query(params) if params.is_a?(String)
+ params.update(Utils.parse_nested_query(env["QUERY_STRING"]))
+ env["QUERY_STRING"] = Utils.build_nested_query(params)
+ elsif !opts.has_key?(:input)
+ opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
+ if params.is_a?(Hash)
+ if data = Utils::Multipart.build_multipart(params)
+ opts[:input] = data
+ opts["CONTENT_LENGTH"] ||= data.length.to_s
+ opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{Utils::Multipart::MULTIPART_BOUNDARY}"
+ else
+ opts[:input] = Utils.build_nested_query(params)
+ end
+ else
+ opts[:input] = params
+ end
+ end
+ 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 if errors.respond_to?(: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/rack/recursive.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/recursive.rb
new file mode 100644
index 0000000000..bf8b965925
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/recursive.rb
@@ -0,0 +1,57 @@
+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/rack/reloader.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/reloader.rb
new file mode 100644
index 0000000000..aa2f060be5
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/reloader.rb
@@ -0,0 +1,106 @@
+# Copyright (c) 2009 Michael Fellinger m.fellinger@gmail.com
+# All files in this distribution are subject to the terms of the Ruby license.
+
+require 'pathname'
+
+module Rack
+
+ # High performant source reloader
+ #
+ # This class acts as Rack middleware.
+ #
+ # What makes it especially suited for use in a production environment is that
+ # any file will only be checked once and there will only be made one system
+ # call stat(2).
+ #
+ # Please note that this will not reload files in the background, it does so
+ # only when actively called.
+ #
+ # It is performing a check/reload cycle at the start of every request, but
+ # also respects a cool down time, during which nothing will be done.
+ class Reloader
+ def initialize(app, cooldown = 10, backend = Stat)
+ @app = app
+ @cooldown = cooldown
+ @last = (Time.now - cooldown)
+ @cache = {}
+ @mtimes = {}
+
+ extend backend
+ end
+
+ def call(env)
+ if @cooldown and Time.now > @last + @cooldown
+ if Thread.list.size > 1
+ Thread.exclusive{ reload! }
+ else
+ reload!
+ end
+
+ @last = Time.now
+ end
+
+ @app.call(env)
+ end
+
+ def reload!(stderr = $stderr)
+ rotation do |file, mtime|
+ previous_mtime = @mtimes[file] ||= mtime
+ safe_load(file, mtime, stderr) if mtime > previous_mtime
+ end
+ end
+
+ # A safe Kernel::load, issuing the hooks depending on the results
+ def safe_load(file, mtime, stderr = $stderr)
+ load(file)
+ stderr.puts "#{self.class}: reloaded `#{file}'"
+ file
+ rescue LoadError, SyntaxError => ex
+ stderr.puts ex
+ ensure
+ @mtimes[file] = mtime
+ end
+
+ module Stat
+ def rotation
+ files = [$0, *$LOADED_FEATURES].uniq
+ paths = ['./', *$LOAD_PATH].uniq
+
+ files.map{|file|
+ next if file =~ /\.(so|bundle)$/ # cannot reload compiled files
+
+ found, stat = figure_path(file, paths)
+ next unless found and stat and mtime = stat.mtime
+
+ @cache[file] = found
+
+ yield(found, mtime)
+ }.compact
+ end
+
+ # Takes a relative or absolute +file+ name, a couple possible +paths+ that
+ # the +file+ might reside in. Returns the full path and File::Stat for the
+ # path.
+ def figure_path(file, paths)
+ found = @cache[file]
+ found = file if !found and Pathname.new(file).absolute?
+ found, stat = safe_stat(found)
+ return found, stat if found
+
+ paths.each do |possible_path|
+ path = ::File.join(possible_path, file)
+ found, stat = safe_stat(path)
+ return ::File.expand_path(found), stat if found
+ end
+ end
+
+ def safe_stat(file)
+ return unless file
+ stat = ::File.stat(file)
+ return file, stat if stat.file?
+ rescue Errno::ENOENT, Errno::ENOTDIR
+ @cache.delete(file) and false
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack/rack/request.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/request.rb
new file mode 100644
index 0000000000..0bff7af038
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/request.rb
@@ -0,0 +1,254 @@
+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, *args)
+ 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
+ def session; @env['rack.session'] ||= {} end
+ def session_options; @env['rack.session.options'] ||= {} 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).first.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'
+ ]
+
+ # The set of media-types. Requests that do not indicate
+ # one of the media types presents in this list will not be eligible
+ # for param parsing like soap attachments or generic multiparts
+ PARSEABLE_DATA_MEDIA_TYPES = [
+ 'multipart/related',
+ 'multipart/mixed'
+ ]
+
+ # 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
+
+ # Determine whether the request body contains data by checking
+ # the request media_type against registered parse-data media-types
+ def parseable_data?
+ PARSEABLE_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? || parseable_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)
+
+ @env["rack.input"].rewind
+ 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 path
+ script_name + path_info
+ end
+
+ def fullpath
+ query_string.empty? ? path : "#{path}?#{query_string}"
+ 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/rack/response.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/response.rb
new file mode 100644
index 0000000000..28b4d8302f
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/response.rb
@@ -0,0 +1,183 @@
+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 redirect(target, status=302)
+ self.status = status
+ self["Location"] = target
+ 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 += Rack::Utils.bytesize(s)
+ @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/rack/rewindable_input.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/rewindable_input.rb
new file mode 100644
index 0000000000..9e9b21ff99
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/rewindable_input.rb
@@ -0,0 +1,98 @@
+require 'tempfile'
+
+module Rack
+ # Class which can make any IO object rewindable, including non-rewindable ones. It does
+ # this by buffering the data into a tempfile, which is rewindable.
+ #
+ # rack.input is required to be rewindable, so if your input stream IO is non-rewindable
+ # by nature (e.g. a pipe or a socket) then you can wrap it in an object of this class
+ # to easily make it rewindable.
+ #
+ # Don't forget to call #close when you're done. This frees up temporary resources that
+ # RewindableInput uses, though it does *not* close the original IO object.
+ class RewindableInput
+ def initialize(io)
+ @io = io
+ @rewindable_io = nil
+ @unlinked = false
+ end
+
+ def gets
+ make_rewindable unless @rewindable_io
+ @rewindable_io.gets
+ end
+
+ def read(*args)
+ make_rewindable unless @rewindable_io
+ @rewindable_io.read(*args)
+ end
+
+ def each(&block)
+ make_rewindable unless @rewindable_io
+ @rewindable_io.each(&block)
+ end
+
+ def rewind
+ make_rewindable unless @rewindable_io
+ @rewindable_io.rewind
+ end
+
+ # Closes this RewindableInput object without closing the originally
+ # wrapped IO oject. Cleans up any temporary resources that this RewindableInput
+ # has created.
+ #
+ # This method may be called multiple times. It does nothing on subsequent calls.
+ def close
+ if @rewindable_io
+ if @unlinked
+ @rewindable_io.close
+ else
+ @rewindable_io.close!
+ end
+ @rewindable_io = nil
+ end
+ end
+
+ private
+
+ # Ruby's Tempfile class has a bug. Subclass it and fix it.
+ class Tempfile < ::Tempfile
+ def _close
+ @tmpfile.close if @tmpfile
+ @data[1] = nil if @data
+ @tmpfile = nil
+ end
+ end
+
+ def make_rewindable
+ # Buffer all data into a tempfile. Since this tempfile is private to this
+ # RewindableInput object, we chmod it so that nobody else can read or write
+ # it. On POSIX filesystems we also unlink the file so that it doesn't
+ # even have a file entry on the filesystem anymore, though we can still
+ # access it because we have the file handle open.
+ @rewindable_io = Tempfile.new('RackRewindableInput')
+ @rewindable_io.chmod(0000)
+ if filesystem_has_posix_semantics?
+ @rewindable_io.unlink
+ @unlinked = true
+ end
+
+ buffer = ""
+ while @io.read(1024 * 4, buffer)
+ entire_buffer_written_out = false
+ while !entire_buffer_written_out
+ written = @rewindable_io.write(buffer)
+ entire_buffer_written_out = written == buffer.size
+ if !entire_buffer_written_out
+ buffer.slice!(0 .. written - 1)
+ end
+ end
+ end
+ @rewindable_io.rewind
+ end
+
+ def filesystem_has_posix_semantics?
+ RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack/rack/session/abstract/id.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/session/abstract/id.rb
new file mode 100644
index 0000000000..218144c17f
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/session/abstract/id.rb
@@ -0,0 +1,142 @@
+# 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/rack/session/cookie.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/session/cookie.rb
new file mode 100644
index 0000000000..eace9bd0c6
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/session/cookie.rb
@@ -0,0 +1,91 @@
+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/rack/session/memcache.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/session/memcache.rb
new file mode 100644
index 0000000000..4a65cbf35d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/session/memcache.rb
@@ -0,0 +1,109 @@
+# 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/rack/session/pool.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/session/pool.rb
new file mode 100644
index 0000000000..f6f87408bb
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/session/pool.rb
@@ -0,0 +1,100 @@
+# 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/rack/showexceptions.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/showexceptions.rb
new file mode 100644
index 0000000000..697bc41fdb
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/showexceptions.rb
@@ -0,0 +1,349 @@
+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| %>
+ <%=h line %>
+ <% } %>
+
+ <% end %>
+
+
+ <%=h frame.context_line %>...
+
+ <% if frame.post_context %>
+
+ <% frame.post_context.each { |line| %>
+ <%=h line %>
+ <% } %>
+
+ <% end %>
+
+ <% end %>
+
+<% } %>
+
+
+
+
+
Request information
+
+
GET
+ <% unless req.GET.empty? %>
+
+
+
+ Variable
+ Value
+
+
+
+ <% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %>
+
+ <%=h key %>
+ <%=h val.inspect %>
+
+ <% } %>
+
+
+ <% else %>
+
No GET data.
+ <% end %>
+
+
POST
+ <% unless req.POST.empty? %>
+
+
+
+ Variable
+ Value
+
+
+
+ <% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %>
+
+ <%=h key %>
+ <%=h val.inspect %>
+
+ <% } %>
+
+
+ <% else %>
+
No POST data.
+ <% end %>
+
+
+
COOKIES
+ <% unless req.cookies.empty? %>
+
+
+
+ Variable
+ Value
+
+
+
+ <% req.cookies.each { |key, val| %>
+
+ <%=h key %>
+ <%=h val.inspect %>
+
+ <% } %>
+
+
+ <% else %>
+
No cookie data.
+ <% end %>
+
+
Rack ENV
+
+
+
+ Variable
+ Value
+
+
+
+ <% env.sort_by { |k, v| k.to_s }.each { |key, val| %>
+
+ <%=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/rack/showstatus.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/showstatus.rb
new file mode 100644
index 0000000000..28258c7c89
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/showstatus.rb
@@ -0,0 +1,106 @@
+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 %>)
+
+
+
+
+
+
+ You're seeing this error because you use Rack::ShowStatus
.
+
+
+
+
+HTML
+
+ # :startdoc:
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack/rack/static.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/static.rb
new file mode 100644
index 0000000000..168e8f83b2
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/static.rb
@@ -0,0 +1,38 @@
+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/rack/urlmap.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/urlmap.rb
new file mode 100644
index 0000000000..fcf6616c58
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/urlmap.rb
@@ -0,0 +1,55 @@
+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)| [h ? -h.size : (-1.0 / 0.0), -l.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/rack/utils.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/utils.rb
new file mode 100644
index 0000000000..42e2e698f4
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack/rack/utils.rb
@@ -0,0 +1,516 @@
+# -*- encoding: binary -*-
+
+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(\A[\[\]]*([^\[\]]+)\]*)
+ k = $1 || ''
+ after = $' || ''
+
+ return if k.empty?
+
+ if after == ""
+ params[k] = v
+ elsif after == "[]"
+ params[k] ||= []
+ raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
+ params[k] << v
+ elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
+ child_key = $1
+ params[k] ||= []
+ raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" 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] ||= {}
+ raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash)
+ 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
+
+ def build_nested_query(value, prefix = nil)
+ case value
+ when Array
+ value.map { |v|
+ build_nested_query(v, "#{prefix}[]")
+ }.join("&")
+ when Hash
+ value.map { |k, v|
+ build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
+ }.join("&")
+ when String
+ raise ArgumentError, "value must be a Hash" if prefix.nil?
+ "#{prefix}=#{escape(value)}"
+ else
+ prefix
+ end
+ end
+ module_function :build_nested_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
+ 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
+
+ EOL = "\r\n"
+ MULTIPART_BOUNDARY = "AaB03x"
+
+ def self.parse_multipart(env)
+ unless env['CONTENT_TYPE'] =~
+ %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
+ nil
+ else
+ boundary = "--#{$1}"
+
+ params = {}
+ buf = ""
+ content_length = env['CONTENT_LENGTH'].to_i
+ input = env['rack.input']
+ input.rewind
+
+ boundary_size = Utils.bytesize(boundary) + EOL.size
+ bufsize = 16384
+
+ content_length -= boundary_size
+
+ read_buffer = ''
+
+ status = input.read(boundary_size, read_buffer)
+ 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(EOL+EOL)
+ 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: (.*)#{EOL}/ni, 1]
+ name = head[/Content-Disposition:.*\s+name="?([^\";]*)"?/ni, 1] || head[/Content-ID:\s*([^#{EOL}]*)/ni, 1]
+
+ if content_type || 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, read_buffer)
+ 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}
+ elsif !filename && content_type
+ body.rewind
+
+ # Generic multipart cases, not coming from a form
+ data = {: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
+ }
+
+ input.rewind
+
+ params
+ end
+ end
+
+ def self.build_multipart(params, first = true)
+ if first
+ unless params.is_a?(Hash)
+ raise ArgumentError, "value must be a Hash"
+ end
+
+ multipart = false
+ query = lambda { |value|
+ case value
+ when Array
+ value.each(&query)
+ when Hash
+ value.values.each(&query)
+ when UploadedFile
+ multipart = true
+ end
+ }
+ params.values.each(&query)
+ return nil unless multipart
+ end
+
+ flattened_params = Hash.new
+
+ params.each do |key, value|
+ k = first ? key.to_s : "[#{key}]"
+
+ case value
+ when Array
+ value.map { |v|
+ build_multipart(v, false).each { |subkey, subvalue|
+ flattened_params["#{k}[]#{subkey}"] = subvalue
+ }
+ }
+ when Hash
+ build_multipart(value, false).each { |subkey, subvalue|
+ flattened_params[k + subkey] = subvalue
+ }
+ else
+ flattened_params[k] = value
+ end
+ end
+
+ if first
+ flattened_params.map { |name, file|
+ if file.respond_to?(:original_filename)
+ ::File.open(file.path, "rb") do |f|
+ f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
+<<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{name}"; filename="#{Utils.escape(file.original_filename)}"\r
+Content-Type: #{file.content_type}\r
+Content-Length: #{::File.stat(file.path).size}\r
+\r
+#{f.read}\r
+EOF
+ end
+ else
+<<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{name}"\r
+\r
+#{file}\r
+EOF
+ end
+ }.join + "--#{MULTIPART_BOUNDARY}--\r"
+ else
+ flattened_params
+ end
+ end
+ end
+ end
+end
--
cgit v1.2.3
From 853c229bbdb32c27231df8ad0d446bb35e588586 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Fri, 1 May 2009 20:24:14 +0100
Subject: Rename vendor/rack to vendor/rack-1.1.pre
---
actionpack/lib/action_dispatch.rb | 4 +-
.../action_dispatch/vendor/rack-1.1.pre/rack.rb | 90 ++++
.../vendor/rack-1.1.pre/rack/adapter/camping.rb | 22 +
.../rack-1.1.pre/rack/auth/abstract/handler.rb | 37 ++
.../rack-1.1.pre/rack/auth/abstract/request.rb | 37 ++
.../vendor/rack-1.1.pre/rack/auth/basic.rb | 58 +++
.../vendor/rack-1.1.pre/rack/auth/digest/md5.rb | 124 +++++
.../vendor/rack-1.1.pre/rack/auth/digest/nonce.rb | 51 ++
.../vendor/rack-1.1.pre/rack/auth/digest/params.rb | 55 +++
.../rack-1.1.pre/rack/auth/digest/request.rb | 40 ++
.../vendor/rack-1.1.pre/rack/auth/openid.rb | 480 ++++++++++++++++++
.../vendor/rack-1.1.pre/rack/builder.rb | 63 +++
.../vendor/rack-1.1.pre/rack/cascade.rb | 36 ++
.../vendor/rack-1.1.pre/rack/chunked.rb | 49 ++
.../vendor/rack-1.1.pre/rack/commonlogger.rb | 61 +++
.../vendor/rack-1.1.pre/rack/conditionalget.rb | 47 ++
.../vendor/rack-1.1.pre/rack/content_length.rb | 29 ++
.../vendor/rack-1.1.pre/rack/content_type.rb | 23 +
.../vendor/rack-1.1.pre/rack/deflater.rb | 96 ++++
.../vendor/rack-1.1.pre/rack/directory.rb | 153 ++++++
.../vendor/rack-1.1.pre/rack/file.rb | 88 ++++
.../vendor/rack-1.1.pre/rack/handler.rb | 69 +++
.../vendor/rack-1.1.pre/rack/handler/cgi.rb | 61 +++
.../rack-1.1.pre/rack/handler/evented_mongrel.rb | 8 +
.../vendor/rack-1.1.pre/rack/handler/fastcgi.rb | 88 ++++
.../vendor/rack-1.1.pre/rack/handler/lsws.rb | 55 +++
.../vendor/rack-1.1.pre/rack/handler/mongrel.rb | 84 ++++
.../vendor/rack-1.1.pre/rack/handler/scgi.rb | 59 +++
.../rack/handler/swiftiplied_mongrel.rb | 8 +
.../vendor/rack-1.1.pre/rack/handler/thin.rb | 18 +
.../vendor/rack-1.1.pre/rack/handler/webrick.rb | 67 +++
.../vendor/rack-1.1.pre/rack/head.rb | 19 +
.../vendor/rack-1.1.pre/rack/lint.rb | 537 +++++++++++++++++++++
.../vendor/rack-1.1.pre/rack/lobster.rb | 65 +++
.../vendor/rack-1.1.pre/rack/lock.rb | 16 +
.../vendor/rack-1.1.pre/rack/methodoverride.rb | 27 ++
.../vendor/rack-1.1.pre/rack/mime.rb | 204 ++++++++
.../vendor/rack-1.1.pre/rack/mock.rb | 184 +++++++
.../vendor/rack-1.1.pre/rack/recursive.rb | 57 +++
.../vendor/rack-1.1.pre/rack/reloader.rb | 106 ++++
.../vendor/rack-1.1.pre/rack/request.rb | 254 ++++++++++
.../vendor/rack-1.1.pre/rack/response.rb | 183 +++++++
.../vendor/rack-1.1.pre/rack/rewindable_input.rb | 98 ++++
.../rack-1.1.pre/rack/session/abstract/id.rb | 142 ++++++
.../vendor/rack-1.1.pre/rack/session/cookie.rb | 91 ++++
.../vendor/rack-1.1.pre/rack/session/memcache.rb | 109 +++++
.../vendor/rack-1.1.pre/rack/session/pool.rb | 100 ++++
.../vendor/rack-1.1.pre/rack/showexceptions.rb | 349 +++++++++++++
.../vendor/rack-1.1.pre/rack/showstatus.rb | 106 ++++
.../vendor/rack-1.1.pre/rack/static.rb | 38 ++
.../vendor/rack-1.1.pre/rack/urlmap.rb | 55 +++
.../vendor/rack-1.1.pre/rack/utils.rb | 516 ++++++++++++++++++++
actionpack/lib/action_dispatch/vendor/rack/rack.rb | 90 ----
.../vendor/rack/rack/adapter/camping.rb | 22 -
.../vendor/rack/rack/auth/abstract/handler.rb | 37 --
.../vendor/rack/rack/auth/abstract/request.rb | 37 --
.../action_dispatch/vendor/rack/rack/auth/basic.rb | 58 ---
.../vendor/rack/rack/auth/digest/md5.rb | 124 -----
.../vendor/rack/rack/auth/digest/nonce.rb | 51 --
.../vendor/rack/rack/auth/digest/params.rb | 55 ---
.../vendor/rack/rack/auth/digest/request.rb | 40 --
.../vendor/rack/rack/auth/openid.rb | 480 ------------------
.../action_dispatch/vendor/rack/rack/builder.rb | 63 ---
.../action_dispatch/vendor/rack/rack/cascade.rb | 36 --
.../action_dispatch/vendor/rack/rack/chunked.rb | 49 --
.../vendor/rack/rack/commonlogger.rb | 61 ---
.../vendor/rack/rack/conditionalget.rb | 47 --
.../vendor/rack/rack/content_length.rb | 29 --
.../vendor/rack/rack/content_type.rb | 23 -
.../action_dispatch/vendor/rack/rack/deflater.rb | 96 ----
.../action_dispatch/vendor/rack/rack/directory.rb | 153 ------
.../lib/action_dispatch/vendor/rack/rack/file.rb | 88 ----
.../action_dispatch/vendor/rack/rack/handler.rb | 69 ---
.../vendor/rack/rack/handler/cgi.rb | 61 ---
.../vendor/rack/rack/handler/evented_mongrel.rb | 8 -
.../vendor/rack/rack/handler/fastcgi.rb | 88 ----
.../vendor/rack/rack/handler/lsws.rb | 55 ---
.../vendor/rack/rack/handler/mongrel.rb | 84 ----
.../vendor/rack/rack/handler/scgi.rb | 59 ---
.../rack/rack/handler/swiftiplied_mongrel.rb | 8 -
.../vendor/rack/rack/handler/thin.rb | 18 -
.../vendor/rack/rack/handler/webrick.rb | 67 ---
.../lib/action_dispatch/vendor/rack/rack/head.rb | 19 -
.../lib/action_dispatch/vendor/rack/rack/lint.rb | 537 ---------------------
.../action_dispatch/vendor/rack/rack/lobster.rb | 65 ---
.../lib/action_dispatch/vendor/rack/rack/lock.rb | 16 -
.../vendor/rack/rack/methodoverride.rb | 27 --
.../lib/action_dispatch/vendor/rack/rack/mime.rb | 204 --------
.../lib/action_dispatch/vendor/rack/rack/mock.rb | 184 -------
.../action_dispatch/vendor/rack/rack/recursive.rb | 57 ---
.../action_dispatch/vendor/rack/rack/reloader.rb | 106 ----
.../action_dispatch/vendor/rack/rack/request.rb | 254 ----------
.../action_dispatch/vendor/rack/rack/response.rb | 183 -------
.../vendor/rack/rack/rewindable_input.rb | 98 ----
.../vendor/rack/rack/session/abstract/id.rb | 142 ------
.../vendor/rack/rack/session/cookie.rb | 91 ----
.../vendor/rack/rack/session/memcache.rb | 109 -----
.../vendor/rack/rack/session/pool.rb | 100 ----
.../vendor/rack/rack/showexceptions.rb | 349 -------------
.../action_dispatch/vendor/rack/rack/showstatus.rb | 106 ----
.../lib/action_dispatch/vendor/rack/rack/static.rb | 38 --
.../lib/action_dispatch/vendor/rack/rack/urlmap.rb | 55 ---
.../lib/action_dispatch/vendor/rack/rack/utils.rb | 516 --------------------
103 files changed, 5414 insertions(+), 5414 deletions(-)
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/adapter/camping.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/abstract/handler.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/abstract/request.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/basic.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/digest/md5.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/digest/nonce.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/digest/params.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/digest/request.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/openid.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/builder.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/cascade.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/chunked.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/commonlogger.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/conditionalget.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/content_length.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/content_type.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/deflater.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/directory.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/file.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/cgi.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/evented_mongrel.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/fastcgi.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/lsws.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/mongrel.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/scgi.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/swiftiplied_mongrel.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/thin.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/webrick.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/head.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/lint.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/lobster.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/lock.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/methodoverride.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/mime.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/mock.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/recursive.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/reloader.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/request.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/response.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/rewindable_input.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/abstract/id.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/cookie.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/memcache.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/pool.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/showexceptions.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/showstatus.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/static.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/urlmap.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/utils.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/adapter/camping.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/abstract/handler.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/abstract/request.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/basic.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/md5.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/nonce.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/params.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/request.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/auth/openid.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/builder.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/cascade.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/chunked.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/commonlogger.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/conditionalget.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/content_length.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/content_type.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/deflater.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/directory.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/file.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/cgi.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/evented_mongrel.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/fastcgi.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/lsws.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/mongrel.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/scgi.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/swiftiplied_mongrel.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/thin.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/handler/webrick.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/head.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/lint.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/lobster.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/lock.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/methodoverride.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/mime.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/mock.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/recursive.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/reloader.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/request.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/response.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/rewindable_input.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/session/abstract/id.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/session/cookie.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/session/memcache.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/session/pool.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/showexceptions.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/showstatus.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/static.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/urlmap.rb
delete mode 100644 actionpack/lib/action_dispatch/vendor/rack/rack/utils.rb
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index a57fc5abdd..5f6202d153 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -33,9 +33,9 @@ end
require 'active_support/core/all'
begin
- gem 'rack', '~> 1.1.0'
+ gem 'rack', '~> 1.1.pre'
rescue Gem::LoadError
- $:.unshift "#{File.dirname(__FILE__)}/action_dispatch/vendor/rack"
+ $:.unshift "#{File.dirname(__FILE__)}/action_dispatch/vendor/rack-1.1.pre"
end
require 'rack'
diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack.rb
new file mode 100644
index 0000000000..371d015690
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack.rb
@@ -0,0 +1,90 @@
+# 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.
+
+path = File.expand_path(File.dirname(__FILE__))
+$:.unshift(path) unless $:.include?(path)
+
+
+# The Rack main module, serving as a namespace for all core Rack
+# modules and classes.
+#
+# All modules meant for use in your application are autoload ed here,
+# so it should be enough just to require rack.rb in your code.
+
+module Rack
+ # The Rack protocol version number implemented.
+ VERSION = [1,0]
+
+ # 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"
+ 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.1.pre/rack/adapter/camping.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/adapter/camping.rb
new file mode 100644
index 0000000000..63bc787f54
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/adapter/camping.rb
@@ -0,0 +1,22 @@
+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.1.pre/rack/auth/abstract/handler.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/abstract/handler.rb
new file mode 100644
index 0000000000..214df6299e
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/abstract/handler.rb
@@ -0,0 +1,37 @@
+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.1.pre/rack/auth/abstract/request.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/abstract/request.rb
new file mode 100644
index 0000000000..1d9ccec685
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/abstract/request.rb
@@ -0,0 +1,37 @@
+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.1.pre/rack/auth/basic.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/basic.rb
new file mode 100644
index 0000000000..9557224648
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/basic.rb
@@ -0,0 +1,58 @@
+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.1.pre/rack/auth/digest/md5.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/digest/md5.rb
new file mode 100644
index 0000000000..e579dc9632
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/digest/md5.rb
@@ -0,0 +1,124 @@
+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.1.pre/rack/auth/digest/nonce.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/digest/nonce.rb
new file mode 100644
index 0000000000..dbe109f29a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/digest/nonce.rb
@@ -0,0 +1,51 @@
+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.1.pre/rack/auth/digest/params.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/digest/params.rb
new file mode 100644
index 0000000000..730e2efdc8
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/digest/params.rb
@@ -0,0 +1,55 @@
+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.1.pre/rack/auth/digest/request.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/digest/request.rb
new file mode 100644
index 0000000000..a8aa3bf996
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/digest/request.rb
@@ -0,0 +1,40 @@
+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.1.pre/rack/auth/openid.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/openid.rb
new file mode 100644
index 0000000000..c5f6a5143e
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/auth/openid.rb
@@ -0,0 +1,480 @@
+# 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.1.pre/rack/builder.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/builder.rb
new file mode 100644
index 0000000000..295235e56a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/builder.rb
@@ -0,0 +1,63 @@
+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.1.pre/rack/cascade.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/cascade.rb
new file mode 100644
index 0000000000..a038aa1105
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/cascade.rb
@@ -0,0 +1,36 @@
+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.1.pre/rack/chunked.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/chunked.rb
new file mode 100644
index 0000000000..280d89dd65
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/chunked.rb
@@ -0,0 +1,49 @@
+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.1.pre/rack/commonlogger.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/commonlogger.rb
new file mode 100644
index 0000000000..5e68ac626d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/commonlogger.rb
@@ -0,0 +1,61 @@
+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.1.pre/rack/conditionalget.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/conditionalget.rb
new file mode 100644
index 0000000000..046ebdb00a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/conditionalget.rb
@@ -0,0 +1,47 @@
+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
+ headers.delete('Content-Type')
+ headers.delete('Content-Length')
+ 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.1.pre/rack/content_length.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/content_length.rb
new file mode 100644
index 0000000000..1e56d43853
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/content_length.rb
@@ -0,0 +1,29 @@
+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.1.pre/rack/content_type.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/content_type.rb
new file mode 100644
index 0000000000..0c1e1ca3e1
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/content_type.rb
@@ -0,0 +1,23 @@
+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.1.pre/rack/deflater.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/deflater.rb
new file mode 100644
index 0000000000..14137a944d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/deflater.rb
@@ -0,0 +1,96 @@
+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"
+ headers['Content-Encoding'] = "gzip"
+ headers.delete('Content-Length')
+ mtime = headers.key?("Last-Modified") ?
+ Time.httpdate(headers["Last-Modified"]) : Time.now
+ [status, headers, GzipStream.new(body, mtime)]
+ when "deflate"
+ headers['Content-Encoding'] = "deflate"
+ headers.delete('Content-Length')
+ [status, headers, DeflateStream.new(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
+
+ class GzipStream
+ def initialize(body, mtime)
+ @body = body
+ @mtime = mtime
+ end
+
+ def each(&block)
+ @writer = block
+ gzip =::Zlib::GzipWriter.new(self)
+ gzip.mtime = @mtime
+ @body.each { |part| gzip << part }
+ @body.close if @body.respond_to?(:close)
+ gzip.close
+ @writer = nil
+ end
+
+ def write(data)
+ @writer.call(data)
+ end
+ end
+
+ class DeflateStream
+ 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
+ ]
+
+ def initialize(body)
+ @body = body
+ end
+
+ def each
+ deflater = ::Zlib::Deflate.new(*DEFLATE_ARGS)
+ @body.each { |part| yield deflater.deflate(part) }
+ @body.close if @body.respond_to?(:close)
+ yield deflater.finish
+ nil
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/directory.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/directory.rb
new file mode 100644
index 0000000000..acdd3029d3
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/directory.rb
@@ -0,0 +1,153 @@
+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
+
+
+
+ Name
+ Size
+ Type
+ Last Modified
+
+%s
+
+
+
+ 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.1.pre/rack/file.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/file.rb
new file mode 100644
index 0000000000..fe62bd6b86
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/file.rb
@@ -0,0 +1,88 @@
+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.1.pre/rack/handler.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler.rb
new file mode 100644
index 0000000000..5624a1e79d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler.rb
@@ -0,0 +1,69 @@
+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
+ server = server.to_s
+
+ if klass = @handlers[server]
+ obj = Object
+ klass.split("::").each { |x| obj = obj.const_get(x) }
+ obj
+ else
+ try_require('rack/handler', server)
+ const_get(server)
+ end
+ end
+
+ # Transforms server-name constants to their canonical form as filenames,
+ # then tries to require them but silences the LoadError if not found
+ #
+ # Naming convention:
+ #
+ # Foo # => 'foo'
+ # FooBar # => 'foo_bar.rb'
+ # FooBAR # => 'foobar.rb'
+ # FOObar # => 'foobar.rb'
+ # FOOBAR # => 'foobar.rb'
+ # FooBarBaz # => 'foo_bar_baz.rb'
+ def self.try_require(prefix, const_name)
+ file = const_name.gsub(/^[A-Z]+/) { |pre| pre.downcase }.
+ gsub(/[A-Z]+[^A-Z]/, '_\&').downcase
+
+ require(::File.join(prefix, file))
+ rescue LoadError
+ 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.1.pre/rack/handler/cgi.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/cgi.rb
new file mode 100644
index 0000000000..f45f3d735a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/cgi.rb
@@ -0,0 +1,61 @@
+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" => [1,0],
+ "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.1.pre/rack/handler/evented_mongrel.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/evented_mongrel.rb
new file mode 100644
index 0000000000..0f5cbf7293
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/evented_mongrel.rb
@@ -0,0 +1,8 @@
+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.1.pre/rack/handler/fastcgi.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/fastcgi.rb
new file mode 100644
index 0000000000..11e1fcaa74
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/fastcgi.rb
@@ -0,0 +1,88 @@
+require 'fcgi'
+require 'socket'
+require 'rack/content_length'
+require 'rack/rewindable_input'
+
+class FCGI::Stream
+ alias _rack_read_without_buffer read
+
+ def read(n, buffer=nil)
+ buf = _rack_read_without_buffer n
+ buffer.replace(buf.to_s) if buffer
+ buf
+ end
+end
+
+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
+
+ def self.serve(request, app)
+ app = Rack::ContentLength.new(app)
+
+ env = request.env
+ env.delete "HTTP_CONTENT_LENGTH"
+
+ env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
+
+ rack_input = RewindableInput.new(request.in)
+
+ env.update({"rack.version" => [1,0],
+ "rack.input" => rack_input,
+ "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"] == ""
+
+ begin
+ 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
+ end
+ ensure
+ rack_input.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.1.pre/rack/handler/lsws.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/lsws.rb
new file mode 100644
index 0000000000..7231336d7b
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/lsws.rb
@@ -0,0 +1,55 @@
+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" => [1,0],
+ "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.1.pre/rack/handler/mongrel.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/mongrel.rb
new file mode 100644
index 0000000000..3a5ef32d4b
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/mongrel.rb
@@ -0,0 +1,84 @@
+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" => [1,0],
+ "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.1.pre/rack/handler/scgi.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/scgi.rb
new file mode 100644
index 0000000000..6c4932df95
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/scgi.rb
@@ -0,0 +1,59 @@
+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" => [1,0],
+ "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.1.pre/rack/handler/swiftiplied_mongrel.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/swiftiplied_mongrel.rb
new file mode 100644
index 0000000000..4bafd0b953
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/swiftiplied_mongrel.rb
@@ -0,0 +1,8 @@
+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.1.pre/rack/handler/thin.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/thin.rb
new file mode 100644
index 0000000000..3d4fedff75
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/thin.rb
@@ -0,0 +1,18 @@
+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.1.pre/rack/handler/webrick.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/webrick.rb
new file mode 100644
index 0000000000..2bdc83a9ff
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/handler/webrick.rb
@@ -0,0 +1,67 @@
+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" => [1,0],
+ "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.1.pre/rack/head.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/head.rb
new file mode 100644
index 0000000000..deab822a99
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/head.rb
@@ -0,0 +1,19 @@
+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.1.pre/rack/lint.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/lint.rb
new file mode 100644
index 0000000000..bf2e9787a1
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/lint.rb
@@ -0,0 +1,537 @@
+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 value may be
+ ## percent-encoded when I originating 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 [1,0], 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).
+ ##
+
+ ## Additional environment specifications have approved to
+ ## standardized middleware APIs. None of these are required to
+ ## be implemented by the server.
+
+ ## rack.session :: A hash like interface for storing request session data.
+ ## The store must implement:
+ if session = env['rack.session']
+ ## store(key, value) (aliased as []=);
+ assert("session #{session.inspect} must respond to store and []=") {
+ session.respond_to?(:store) && session.respond_to?(:[]=)
+ }
+
+ ## fetch(key, default = nil) (aliased as []);
+ assert("session #{session.inspect} must respond to fetch and []") {
+ session.respond_to?(:fetch) && session.respond_to?(:[])
+ }
+
+ ## delete(key);
+ assert("session #{session.inspect} must respond to delete") {
+ session.respond_to?(:delete)
+ }
+
+ ## clear;
+ assert("session #{session.inspect} must respond to clear") {
+ session.respond_to?(:clear)
+ }
+ end
+
+ ## 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 other
+ ## accepted specifications 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
+ ##
+ ## The input stream is an IO-like object which contains the raw HTTP
+ ## POST data. If it is a file then it must be opened in binary mode.
+ def check_input(input)
+ ## The input stream must respond to +gets+, +each+, +read+ and +rewind+.
+ [:gets, :each, :read, :rewind].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
+
+ ## * +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+ behaves like IO#read. Its signature is read([length, [buffer]]) .
+ ## If given, +length+ must be an non-negative Integer (>= 0) or +nil+, and +buffer+ must
+ ## be a String and may not be nil. If +length+ is given and not nil, then this method
+ ## reads at most +length+ bytes from the input stream. If +length+ is not given or nil,
+ ## then this method reads all data until EOF.
+ ## When EOF is reached, this method returns nil if +length+ is given and not nil, or ""
+ ## if +length+ is not given or is nil.
+ ## If +buffer+ is given, then the read data will be placed into +buffer+ instead of a
+ ## newly created String object.
+ def read(*args)
+ assert("rack.input#read called with too many arguments") {
+ args.size <= 2
+ }
+ if args.size >= 1
+ assert("rack.input#read called with non-integer and non-nil length") {
+ args.first.kind_of?(Integer) || args.first.nil?
+ }
+ assert("rack.input#read called with a negative length") {
+ args.first.nil? || args.first >= 0
+ }
+ end
+ if args.size >= 2
+ assert("rack.input#read called with non-String buffer") {
+ args[1].kind_of?(String)
+ }
+ end
+
+ v = @input.read(*args)
+
+ assert("rack.input#read didn't return nil or a String") {
+ v.nil? or v.instance_of? String
+ }
+ if args[0].nil?
+ assert("rack.input#read(nil) returned nil on EOF") {
+ !v.nil?
+ }
+ end
+
+ 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
+
+ ## * +rewind+ must be called without arguments. It rewinds the input
+ ## stream back to the beginning. It must not raise Errno::ESPIPE:
+ ## that is, it may not be a pipe or a socket. Therefore, handler
+ ## developers must buffer the input data into some rewindable object
+ ## if the underlying input stream is not rewindable.
+ def rewind(*args)
+ assert("rack.input#rewind called with arguments") { args.size == 0 }
+ assert("rack.input#rewind raised Errno::ESPIPE") {
+ begin
+ @input.rewind
+ true
+ rescue Errno::ESPIPE
+ false
+ end
+ }
+ 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)
+ ## This is an HTTP status. When parsed as integer (+to_i+), it 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, e.g. multiple
+ ## Set-Cookie 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
+ }
+ ##
+ ## The Body itself should not be an instance of String, as this will
+ ## break in Ruby 1.9.
+ ##
+ ## 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+; this may be used by the
+ ## server as an alternative, possibly more efficient way to
+ ## transport the response.
+
+ 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.1.pre/rack/lobster.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/lobster.rb
new file mode 100644
index 0000000000..f63f419a49
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/lobster.rb
@@ -0,0 +1,65 @@
+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.1.pre/rack/lock.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/lock.rb
new file mode 100644
index 0000000000..93238528c4
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/lock.rb
@@ -0,0 +1,16 @@
+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.1.pre/rack/methodoverride.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/methodoverride.rb
new file mode 100644
index 0000000000..0eed29f471
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/methodoverride.rb
@@ -0,0 +1,27 @@
+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.1.pre/rack/mime.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/mime.rb
new file mode 100644
index 0000000000..5a6a73a97b
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/mime.rb
@@ -0,0 +1,204 @@
+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.1.pre/rack/mock.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/mock.rb
new file mode 100644
index 0000000000..fdefb0340a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/mock.rb
@@ -0,0 +1,184 @@
+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" => [1,0],
+ "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)
+ uri.path = "/#{uri.path}" unless uri.path[0] == ?/
+
+ env = DEFAULT_ENV.dup
+
+ env["REQUEST_METHOD"] = opts[:method] ? opts[:method].to_s.upcase : "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["HTTPS"] = env["rack.url_scheme"] == "https" ? "on" : "off"
+
+ env["SCRIPT_NAME"] = opts[:script_name] || ""
+
+ if opts[:fatal]
+ env["rack.errors"] = FatalWarner.new
+ else
+ env["rack.errors"] = StringIO.new
+ end
+
+ if params = opts[:params]
+ if env["REQUEST_METHOD"] == "GET"
+ params = Utils.parse_nested_query(params) if params.is_a?(String)
+ params.update(Utils.parse_nested_query(env["QUERY_STRING"]))
+ env["QUERY_STRING"] = Utils.build_nested_query(params)
+ elsif !opts.has_key?(:input)
+ opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
+ if params.is_a?(Hash)
+ if data = Utils::Multipart.build_multipart(params)
+ opts[:input] = data
+ opts["CONTENT_LENGTH"] ||= data.length.to_s
+ opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{Utils::Multipart::MULTIPART_BOUNDARY}"
+ else
+ opts[:input] = Utils.build_nested_query(params)
+ end
+ else
+ opts[:input] = params
+ end
+ end
+ 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 if errors.respond_to?(: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.1.pre/rack/recursive.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/recursive.rb
new file mode 100644
index 0000000000..bf8b965925
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/recursive.rb
@@ -0,0 +1,57 @@
+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.1.pre/rack/reloader.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/reloader.rb
new file mode 100644
index 0000000000..aa2f060be5
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/reloader.rb
@@ -0,0 +1,106 @@
+# Copyright (c) 2009 Michael Fellinger m.fellinger@gmail.com
+# All files in this distribution are subject to the terms of the Ruby license.
+
+require 'pathname'
+
+module Rack
+
+ # High performant source reloader
+ #
+ # This class acts as Rack middleware.
+ #
+ # What makes it especially suited for use in a production environment is that
+ # any file will only be checked once and there will only be made one system
+ # call stat(2).
+ #
+ # Please note that this will not reload files in the background, it does so
+ # only when actively called.
+ #
+ # It is performing a check/reload cycle at the start of every request, but
+ # also respects a cool down time, during which nothing will be done.
+ class Reloader
+ def initialize(app, cooldown = 10, backend = Stat)
+ @app = app
+ @cooldown = cooldown
+ @last = (Time.now - cooldown)
+ @cache = {}
+ @mtimes = {}
+
+ extend backend
+ end
+
+ def call(env)
+ if @cooldown and Time.now > @last + @cooldown
+ if Thread.list.size > 1
+ Thread.exclusive{ reload! }
+ else
+ reload!
+ end
+
+ @last = Time.now
+ end
+
+ @app.call(env)
+ end
+
+ def reload!(stderr = $stderr)
+ rotation do |file, mtime|
+ previous_mtime = @mtimes[file] ||= mtime
+ safe_load(file, mtime, stderr) if mtime > previous_mtime
+ end
+ end
+
+ # A safe Kernel::load, issuing the hooks depending on the results
+ def safe_load(file, mtime, stderr = $stderr)
+ load(file)
+ stderr.puts "#{self.class}: reloaded `#{file}'"
+ file
+ rescue LoadError, SyntaxError => ex
+ stderr.puts ex
+ ensure
+ @mtimes[file] = mtime
+ end
+
+ module Stat
+ def rotation
+ files = [$0, *$LOADED_FEATURES].uniq
+ paths = ['./', *$LOAD_PATH].uniq
+
+ files.map{|file|
+ next if file =~ /\.(so|bundle)$/ # cannot reload compiled files
+
+ found, stat = figure_path(file, paths)
+ next unless found and stat and mtime = stat.mtime
+
+ @cache[file] = found
+
+ yield(found, mtime)
+ }.compact
+ end
+
+ # Takes a relative or absolute +file+ name, a couple possible +paths+ that
+ # the +file+ might reside in. Returns the full path and File::Stat for the
+ # path.
+ def figure_path(file, paths)
+ found = @cache[file]
+ found = file if !found and Pathname.new(file).absolute?
+ found, stat = safe_stat(found)
+ return found, stat if found
+
+ paths.each do |possible_path|
+ path = ::File.join(possible_path, file)
+ found, stat = safe_stat(path)
+ return ::File.expand_path(found), stat if found
+ end
+ end
+
+ def safe_stat(file)
+ return unless file
+ stat = ::File.stat(file)
+ return file, stat if stat.file?
+ rescue Errno::ENOENT, Errno::ENOTDIR
+ @cache.delete(file) and false
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/request.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/request.rb
new file mode 100644
index 0000000000..0bff7af038
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/request.rb
@@ -0,0 +1,254 @@
+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, *args)
+ 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
+ def session; @env['rack.session'] ||= {} end
+ def session_options; @env['rack.session.options'] ||= {} 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).first.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'
+ ]
+
+ # The set of media-types. Requests that do not indicate
+ # one of the media types presents in this list will not be eligible
+ # for param parsing like soap attachments or generic multiparts
+ PARSEABLE_DATA_MEDIA_TYPES = [
+ 'multipart/related',
+ 'multipart/mixed'
+ ]
+
+ # 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
+
+ # Determine whether the request body contains data by checking
+ # the request media_type against registered parse-data media-types
+ def parseable_data?
+ PARSEABLE_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? || parseable_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)
+
+ @env["rack.input"].rewind
+ 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 path
+ script_name + path_info
+ end
+
+ def fullpath
+ query_string.empty? ? path : "#{path}?#{query_string}"
+ 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.1.pre/rack/response.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/response.rb
new file mode 100644
index 0000000000..28b4d8302f
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/response.rb
@@ -0,0 +1,183 @@
+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 redirect(target, status=302)
+ self.status = status
+ self["Location"] = target
+ 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 += Rack::Utils.bytesize(s)
+ @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.1.pre/rack/rewindable_input.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/rewindable_input.rb
new file mode 100644
index 0000000000..9e9b21ff99
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/rewindable_input.rb
@@ -0,0 +1,98 @@
+require 'tempfile'
+
+module Rack
+ # Class which can make any IO object rewindable, including non-rewindable ones. It does
+ # this by buffering the data into a tempfile, which is rewindable.
+ #
+ # rack.input is required to be rewindable, so if your input stream IO is non-rewindable
+ # by nature (e.g. a pipe or a socket) then you can wrap it in an object of this class
+ # to easily make it rewindable.
+ #
+ # Don't forget to call #close when you're done. This frees up temporary resources that
+ # RewindableInput uses, though it does *not* close the original IO object.
+ class RewindableInput
+ def initialize(io)
+ @io = io
+ @rewindable_io = nil
+ @unlinked = false
+ end
+
+ def gets
+ make_rewindable unless @rewindable_io
+ @rewindable_io.gets
+ end
+
+ def read(*args)
+ make_rewindable unless @rewindable_io
+ @rewindable_io.read(*args)
+ end
+
+ def each(&block)
+ make_rewindable unless @rewindable_io
+ @rewindable_io.each(&block)
+ end
+
+ def rewind
+ make_rewindable unless @rewindable_io
+ @rewindable_io.rewind
+ end
+
+ # Closes this RewindableInput object without closing the originally
+ # wrapped IO oject. Cleans up any temporary resources that this RewindableInput
+ # has created.
+ #
+ # This method may be called multiple times. It does nothing on subsequent calls.
+ def close
+ if @rewindable_io
+ if @unlinked
+ @rewindable_io.close
+ else
+ @rewindable_io.close!
+ end
+ @rewindable_io = nil
+ end
+ end
+
+ private
+
+ # Ruby's Tempfile class has a bug. Subclass it and fix it.
+ class Tempfile < ::Tempfile
+ def _close
+ @tmpfile.close if @tmpfile
+ @data[1] = nil if @data
+ @tmpfile = nil
+ end
+ end
+
+ def make_rewindable
+ # Buffer all data into a tempfile. Since this tempfile is private to this
+ # RewindableInput object, we chmod it so that nobody else can read or write
+ # it. On POSIX filesystems we also unlink the file so that it doesn't
+ # even have a file entry on the filesystem anymore, though we can still
+ # access it because we have the file handle open.
+ @rewindable_io = Tempfile.new('RackRewindableInput')
+ @rewindable_io.chmod(0000)
+ if filesystem_has_posix_semantics?
+ @rewindable_io.unlink
+ @unlinked = true
+ end
+
+ buffer = ""
+ while @io.read(1024 * 4, buffer)
+ entire_buffer_written_out = false
+ while !entire_buffer_written_out
+ written = @rewindable_io.write(buffer)
+ entire_buffer_written_out = written == buffer.size
+ if !entire_buffer_written_out
+ buffer.slice!(0 .. written - 1)
+ end
+ end
+ end
+ @rewindable_io.rewind
+ end
+
+ def filesystem_has_posix_semantics?
+ RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/abstract/id.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/abstract/id.rb
new file mode 100644
index 0000000000..218144c17f
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/abstract/id.rb
@@ -0,0 +1,142 @@
+# 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.1.pre/rack/session/cookie.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/cookie.rb
new file mode 100644
index 0000000000..eace9bd0c6
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/cookie.rb
@@ -0,0 +1,91 @@
+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.1.pre/rack/session/memcache.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/memcache.rb
new file mode 100644
index 0000000000..4a65cbf35d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/memcache.rb
@@ -0,0 +1,109 @@
+# 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.1.pre/rack/session/pool.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/pool.rb
new file mode 100644
index 0000000000..f6f87408bb
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/pool.rb
@@ -0,0 +1,100 @@
+# 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.1.pre/rack/showexceptions.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/showexceptions.rb
new file mode 100644
index 0000000000..697bc41fdb
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/showexceptions.rb
@@ -0,0 +1,349 @@
+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| %>
+ <%=h line %>
+ <% } %>
+
+ <% end %>
+
+
+ <%=h frame.context_line %>...
+
+ <% if frame.post_context %>
+
+ <% frame.post_context.each { |line| %>
+ <%=h line %>
+ <% } %>
+
+ <% end %>
+
+ <% end %>
+
+<% } %>
+
+
+
+
+
Request information
+
+
GET
+ <% unless req.GET.empty? %>
+
+
+
+ Variable
+ Value
+
+
+
+ <% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %>
+
+ <%=h key %>
+ <%=h val.inspect %>
+
+ <% } %>
+
+
+ <% else %>
+
No GET data.
+ <% end %>
+
+
POST
+ <% unless req.POST.empty? %>
+
+
+
+ Variable
+ Value
+
+
+
+ <% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %>
+
+ <%=h key %>
+ <%=h val.inspect %>
+
+ <% } %>
+
+
+ <% else %>
+
No POST data.
+ <% end %>
+
+
+
COOKIES
+ <% unless req.cookies.empty? %>
+
+
+
+ Variable
+ Value
+
+
+
+ <% req.cookies.each { |key, val| %>
+
+ <%=h key %>
+ <%=h val.inspect %>
+
+ <% } %>
+
+
+ <% else %>
+
No cookie data.
+ <% end %>
+
+
Rack ENV
+
+
+
+ Variable
+ Value
+
+
+
+ <% env.sort_by { |k, v| k.to_s }.each { |key, val| %>
+
+ <%=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.1.pre/rack/showstatus.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/showstatus.rb
new file mode 100644
index 0000000000..28258c7c89
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/showstatus.rb
@@ -0,0 +1,106 @@
+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 %>)
+
+
+
+
+
+
+ You're seeing this error because you use Rack::ShowStatus
.
+
+
+
+
+HTML
+
+ # :startdoc:
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/static.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/static.rb
new file mode 100644
index 0000000000..168e8f83b2
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/static.rb
@@ -0,0 +1,38 @@
+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.1.pre/rack/urlmap.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/urlmap.rb
new file mode 100644
index 0000000000..fcf6616c58
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/urlmap.rb
@@ -0,0 +1,55 @@
+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)| [h ? -h.size : (-1.0 / 0.0), -l.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.1.pre/rack/utils.rb b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/utils.rb
new file mode 100644
index 0000000000..42e2e698f4
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/utils.rb
@@ -0,0 +1,516 @@
+# -*- encoding: binary -*-
+
+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(\A[\[\]]*([^\[\]]+)\]*)
+ k = $1 || ''
+ after = $' || ''
+
+ return if k.empty?
+
+ if after == ""
+ params[k] = v
+ elsif after == "[]"
+ params[k] ||= []
+ raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
+ params[k] << v
+ elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
+ child_key = $1
+ params[k] ||= []
+ raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" 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] ||= {}
+ raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash)
+ 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
+
+ def build_nested_query(value, prefix = nil)
+ case value
+ when Array
+ value.map { |v|
+ build_nested_query(v, "#{prefix}[]")
+ }.join("&")
+ when Hash
+ value.map { |k, v|
+ build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
+ }.join("&")
+ when String
+ raise ArgumentError, "value must be a Hash" if prefix.nil?
+ "#{prefix}=#{escape(value)}"
+ else
+ prefix
+ end
+ end
+ module_function :build_nested_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
+ 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
+
+ EOL = "\r\n"
+ MULTIPART_BOUNDARY = "AaB03x"
+
+ def self.parse_multipart(env)
+ unless env['CONTENT_TYPE'] =~
+ %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
+ nil
+ else
+ boundary = "--#{$1}"
+
+ params = {}
+ buf = ""
+ content_length = env['CONTENT_LENGTH'].to_i
+ input = env['rack.input']
+ input.rewind
+
+ boundary_size = Utils.bytesize(boundary) + EOL.size
+ bufsize = 16384
+
+ content_length -= boundary_size
+
+ read_buffer = ''
+
+ status = input.read(boundary_size, read_buffer)
+ 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(EOL+EOL)
+ 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: (.*)#{EOL}/ni, 1]
+ name = head[/Content-Disposition:.*\s+name="?([^\";]*)"?/ni, 1] || head[/Content-ID:\s*([^#{EOL}]*)/ni, 1]
+
+ if content_type || 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, read_buffer)
+ 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}
+ elsif !filename && content_type
+ body.rewind
+
+ # Generic multipart cases, not coming from a form
+ data = {: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
+ }
+
+ input.rewind
+
+ params
+ end
+ end
+
+ def self.build_multipart(params, first = true)
+ if first
+ unless params.is_a?(Hash)
+ raise ArgumentError, "value must be a Hash"
+ end
+
+ multipart = false
+ query = lambda { |value|
+ case value
+ when Array
+ value.each(&query)
+ when Hash
+ value.values.each(&query)
+ when UploadedFile
+ multipart = true
+ end
+ }
+ params.values.each(&query)
+ return nil unless multipart
+ end
+
+ flattened_params = Hash.new
+
+ params.each do |key, value|
+ k = first ? key.to_s : "[#{key}]"
+
+ case value
+ when Array
+ value.map { |v|
+ build_multipart(v, false).each { |subkey, subvalue|
+ flattened_params["#{k}[]#{subkey}"] = subvalue
+ }
+ }
+ when Hash
+ build_multipart(value, false).each { |subkey, subvalue|
+ flattened_params[k + subkey] = subvalue
+ }
+ else
+ flattened_params[k] = value
+ end
+ end
+
+ if first
+ flattened_params.map { |name, file|
+ if file.respond_to?(:original_filename)
+ ::File.open(file.path, "rb") do |f|
+ f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
+<<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{name}"; filename="#{Utils.escape(file.original_filename)}"\r
+Content-Type: #{file.content_type}\r
+Content-Length: #{::File.stat(file.path).size}\r
+\r
+#{f.read}\r
+EOF
+ end
+ else
+<<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{name}"\r
+\r
+#{file}\r
+EOF
+ end
+ }.join + "--#{MULTIPART_BOUNDARY}--\r"
+ else
+ flattened_params
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack/rack.rb b/actionpack/lib/action_dispatch/vendor/rack/rack.rb
deleted file mode 100644
index 371d015690..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/rack.rb
+++ /dev/null
@@ -1,90 +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.
-
-path = File.expand_path(File.dirname(__FILE__))
-$:.unshift(path) unless $:.include?(path)
-
-
-# The Rack main module, serving as a namespace for all core Rack
-# modules and classes.
-#
-# All modules meant for use in your application are autoload ed here,
-# so it should be enough just to require rack.rb in your code.
-
-module Rack
- # The Rack protocol version number implemented.
- VERSION = [1,0]
-
- # 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"
- 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/rack/adapter/camping.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/adapter/camping.rb
deleted file mode 100644
index 63bc787f54..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/auth/abstract/handler.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/abstract/handler.rb
deleted file mode 100644
index 214df6299e..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/auth/abstract/request.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/abstract/request.rb
deleted file mode 100644
index 1d9ccec685..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/auth/basic.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/basic.rb
deleted file mode 100644
index 9557224648..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/auth/digest/md5.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/md5.rb
deleted file mode 100644
index e579dc9632..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/auth/digest/nonce.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/nonce.rb
deleted file mode 100644
index dbe109f29a..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/auth/digest/params.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/params.rb
deleted file mode 100644
index 730e2efdc8..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/auth/digest/request.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/digest/request.rb
deleted file mode 100644
index a8aa3bf996..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/auth/openid.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/auth/openid.rb
deleted file mode 100644
index c5f6a5143e..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/builder.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/builder.rb
deleted file mode 100644
index 295235e56a..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/cascade.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/cascade.rb
deleted file mode 100644
index a038aa1105..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/chunked.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/chunked.rb
deleted file mode 100644
index 280d89dd65..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/commonlogger.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/commonlogger.rb
deleted file mode 100644
index 5e68ac626d..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/conditionalget.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/conditionalget.rb
deleted file mode 100644
index 046ebdb00a..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/rack/conditionalget.rb
+++ /dev/null
@@ -1,47 +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
- headers.delete('Content-Type')
- headers.delete('Content-Length')
- 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/rack/content_length.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/content_length.rb
deleted file mode 100644
index 1e56d43853..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/content_type.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/content_type.rb
deleted file mode 100644
index 0c1e1ca3e1..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/deflater.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/deflater.rb
deleted file mode 100644
index 14137a944d..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/rack/deflater.rb
+++ /dev/null
@@ -1,96 +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"
- headers['Content-Encoding'] = "gzip"
- headers.delete('Content-Length')
- mtime = headers.key?("Last-Modified") ?
- Time.httpdate(headers["Last-Modified"]) : Time.now
- [status, headers, GzipStream.new(body, mtime)]
- when "deflate"
- headers['Content-Encoding'] = "deflate"
- headers.delete('Content-Length')
- [status, headers, DeflateStream.new(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
-
- class GzipStream
- def initialize(body, mtime)
- @body = body
- @mtime = mtime
- end
-
- def each(&block)
- @writer = block
- gzip =::Zlib::GzipWriter.new(self)
- gzip.mtime = @mtime
- @body.each { |part| gzip << part }
- @body.close if @body.respond_to?(:close)
- gzip.close
- @writer = nil
- end
-
- def write(data)
- @writer.call(data)
- end
- end
-
- class DeflateStream
- 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
- ]
-
- def initialize(body)
- @body = body
- end
-
- def each
- deflater = ::Zlib::Deflate.new(*DEFLATE_ARGS)
- @body.each { |part| yield deflater.deflate(part) }
- @body.close if @body.respond_to?(:close)
- yield deflater.finish
- nil
- end
- end
- end
-end
diff --git a/actionpack/lib/action_dispatch/vendor/rack/rack/directory.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/directory.rb
deleted file mode 100644
index acdd3029d3..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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
-
-
-
- Name
- Size
- Type
- Last Modified
-
-%s
-
-
-
- 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/rack/file.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/file.rb
deleted file mode 100644
index fe62bd6b86..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/handler.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler.rb
deleted file mode 100644
index 5624a1e79d..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/rack/handler.rb
+++ /dev/null
@@ -1,69 +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
- server = server.to_s
-
- if klass = @handlers[server]
- obj = Object
- klass.split("::").each { |x| obj = obj.const_get(x) }
- obj
- else
- try_require('rack/handler', server)
- const_get(server)
- end
- end
-
- # Transforms server-name constants to their canonical form as filenames,
- # then tries to require them but silences the LoadError if not found
- #
- # Naming convention:
- #
- # Foo # => 'foo'
- # FooBar # => 'foo_bar.rb'
- # FooBAR # => 'foobar.rb'
- # FOObar # => 'foobar.rb'
- # FOOBAR # => 'foobar.rb'
- # FooBarBaz # => 'foo_bar_baz.rb'
- def self.try_require(prefix, const_name)
- file = const_name.gsub(/^[A-Z]+/) { |pre| pre.downcase }.
- gsub(/[A-Z]+[^A-Z]/, '_\&').downcase
-
- require(::File.join(prefix, file))
- rescue LoadError
- 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/rack/handler/cgi.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/cgi.rb
deleted file mode 100644
index f45f3d735a..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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" => [1,0],
- "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/rack/handler/evented_mongrel.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/evented_mongrel.rb
deleted file mode 100644
index 0f5cbf7293..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/handler/fastcgi.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/fastcgi.rb
deleted file mode 100644
index 11e1fcaa74..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/rack/handler/fastcgi.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-require 'fcgi'
-require 'socket'
-require 'rack/content_length'
-require 'rack/rewindable_input'
-
-class FCGI::Stream
- alias _rack_read_without_buffer read
-
- def read(n, buffer=nil)
- buf = _rack_read_without_buffer n
- buffer.replace(buf.to_s) if buffer
- buf
- end
-end
-
-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
-
- def self.serve(request, app)
- app = Rack::ContentLength.new(app)
-
- env = request.env
- env.delete "HTTP_CONTENT_LENGTH"
-
- env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
-
- rack_input = RewindableInput.new(request.in)
-
- env.update({"rack.version" => [1,0],
- "rack.input" => rack_input,
- "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"] == ""
-
- begin
- 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
- end
- ensure
- rack_input.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/rack/handler/lsws.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/lsws.rb
deleted file mode 100644
index 7231336d7b..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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" => [1,0],
- "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/rack/handler/mongrel.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/mongrel.rb
deleted file mode 100644
index 3a5ef32d4b..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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" => [1,0],
- "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/rack/handler/scgi.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/scgi.rb
deleted file mode 100644
index 6c4932df95..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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" => [1,0],
- "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/rack/handler/swiftiplied_mongrel.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/swiftiplied_mongrel.rb
deleted file mode 100644
index 4bafd0b953..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/handler/thin.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/thin.rb
deleted file mode 100644
index 3d4fedff75..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/handler/webrick.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/handler/webrick.rb
deleted file mode 100644
index 2bdc83a9ff..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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" => [1,0],
- "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/rack/head.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/head.rb
deleted file mode 100644
index deab822a99..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/lint.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/lint.rb
deleted file mode 100644
index bf2e9787a1..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/rack/lint.rb
+++ /dev/null
@@ -1,537 +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 value may be
- ## percent-encoded when I originating 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 [1,0], 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).
- ##
-
- ## Additional environment specifications have approved to
- ## standardized middleware APIs. None of these are required to
- ## be implemented by the server.
-
- ## rack.session :: A hash like interface for storing request session data.
- ## The store must implement:
- if session = env['rack.session']
- ## store(key, value) (aliased as []=);
- assert("session #{session.inspect} must respond to store and []=") {
- session.respond_to?(:store) && session.respond_to?(:[]=)
- }
-
- ## fetch(key, default = nil) (aliased as []);
- assert("session #{session.inspect} must respond to fetch and []") {
- session.respond_to?(:fetch) && session.respond_to?(:[])
- }
-
- ## delete(key);
- assert("session #{session.inspect} must respond to delete") {
- session.respond_to?(:delete)
- }
-
- ## clear;
- assert("session #{session.inspect} must respond to clear") {
- session.respond_to?(:clear)
- }
- end
-
- ## 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 other
- ## accepted specifications 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
- ##
- ## The input stream is an IO-like object which contains the raw HTTP
- ## POST data. If it is a file then it must be opened in binary mode.
- def check_input(input)
- ## The input stream must respond to +gets+, +each+, +read+ and +rewind+.
- [:gets, :each, :read, :rewind].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
-
- ## * +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+ behaves like IO#read. Its signature is read([length, [buffer]]) .
- ## If given, +length+ must be an non-negative Integer (>= 0) or +nil+, and +buffer+ must
- ## be a String and may not be nil. If +length+ is given and not nil, then this method
- ## reads at most +length+ bytes from the input stream. If +length+ is not given or nil,
- ## then this method reads all data until EOF.
- ## When EOF is reached, this method returns nil if +length+ is given and not nil, or ""
- ## if +length+ is not given or is nil.
- ## If +buffer+ is given, then the read data will be placed into +buffer+ instead of a
- ## newly created String object.
- def read(*args)
- assert("rack.input#read called with too many arguments") {
- args.size <= 2
- }
- if args.size >= 1
- assert("rack.input#read called with non-integer and non-nil length") {
- args.first.kind_of?(Integer) || args.first.nil?
- }
- assert("rack.input#read called with a negative length") {
- args.first.nil? || args.first >= 0
- }
- end
- if args.size >= 2
- assert("rack.input#read called with non-String buffer") {
- args[1].kind_of?(String)
- }
- end
-
- v = @input.read(*args)
-
- assert("rack.input#read didn't return nil or a String") {
- v.nil? or v.instance_of? String
- }
- if args[0].nil?
- assert("rack.input#read(nil) returned nil on EOF") {
- !v.nil?
- }
- end
-
- 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
-
- ## * +rewind+ must be called without arguments. It rewinds the input
- ## stream back to the beginning. It must not raise Errno::ESPIPE:
- ## that is, it may not be a pipe or a socket. Therefore, handler
- ## developers must buffer the input data into some rewindable object
- ## if the underlying input stream is not rewindable.
- def rewind(*args)
- assert("rack.input#rewind called with arguments") { args.size == 0 }
- assert("rack.input#rewind raised Errno::ESPIPE") {
- begin
- @input.rewind
- true
- rescue Errno::ESPIPE
- false
- end
- }
- 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)
- ## This is an HTTP status. When parsed as integer (+to_i+), it 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, e.g. multiple
- ## Set-Cookie 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
- }
- ##
- ## The Body itself should not be an instance of String, as this will
- ## break in Ruby 1.9.
- ##
- ## 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+; this may be used by the
- ## server as an alternative, possibly more efficient way to
- ## transport the response.
-
- 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/rack/lobster.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/lobster.rb
deleted file mode 100644
index f63f419a49..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/lock.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/lock.rb
deleted file mode 100644
index 93238528c4..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/methodoverride.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/methodoverride.rb
deleted file mode 100644
index 0eed29f471..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/mime.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/mime.rb
deleted file mode 100644
index 5a6a73a97b..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/mock.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/mock.rb
deleted file mode 100644
index fdefb0340a..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/rack/mock.rb
+++ /dev/null
@@ -1,184 +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" => [1,0],
- "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)
- uri.path = "/#{uri.path}" unless uri.path[0] == ?/
-
- env = DEFAULT_ENV.dup
-
- env["REQUEST_METHOD"] = opts[:method] ? opts[:method].to_s.upcase : "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["HTTPS"] = env["rack.url_scheme"] == "https" ? "on" : "off"
-
- env["SCRIPT_NAME"] = opts[:script_name] || ""
-
- if opts[:fatal]
- env["rack.errors"] = FatalWarner.new
- else
- env["rack.errors"] = StringIO.new
- end
-
- if params = opts[:params]
- if env["REQUEST_METHOD"] == "GET"
- params = Utils.parse_nested_query(params) if params.is_a?(String)
- params.update(Utils.parse_nested_query(env["QUERY_STRING"]))
- env["QUERY_STRING"] = Utils.build_nested_query(params)
- elsif !opts.has_key?(:input)
- opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
- if params.is_a?(Hash)
- if data = Utils::Multipart.build_multipart(params)
- opts[:input] = data
- opts["CONTENT_LENGTH"] ||= data.length.to_s
- opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{Utils::Multipart::MULTIPART_BOUNDARY}"
- else
- opts[:input] = Utils.build_nested_query(params)
- end
- else
- opts[:input] = params
- end
- end
- 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 if errors.respond_to?(: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/rack/recursive.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/recursive.rb
deleted file mode 100644
index bf8b965925..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/reloader.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/reloader.rb
deleted file mode 100644
index aa2f060be5..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/rack/reloader.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-# Copyright (c) 2009 Michael Fellinger m.fellinger@gmail.com
-# All files in this distribution are subject to the terms of the Ruby license.
-
-require 'pathname'
-
-module Rack
-
- # High performant source reloader
- #
- # This class acts as Rack middleware.
- #
- # What makes it especially suited for use in a production environment is that
- # any file will only be checked once and there will only be made one system
- # call stat(2).
- #
- # Please note that this will not reload files in the background, it does so
- # only when actively called.
- #
- # It is performing a check/reload cycle at the start of every request, but
- # also respects a cool down time, during which nothing will be done.
- class Reloader
- def initialize(app, cooldown = 10, backend = Stat)
- @app = app
- @cooldown = cooldown
- @last = (Time.now - cooldown)
- @cache = {}
- @mtimes = {}
-
- extend backend
- end
-
- def call(env)
- if @cooldown and Time.now > @last + @cooldown
- if Thread.list.size > 1
- Thread.exclusive{ reload! }
- else
- reload!
- end
-
- @last = Time.now
- end
-
- @app.call(env)
- end
-
- def reload!(stderr = $stderr)
- rotation do |file, mtime|
- previous_mtime = @mtimes[file] ||= mtime
- safe_load(file, mtime, stderr) if mtime > previous_mtime
- end
- end
-
- # A safe Kernel::load, issuing the hooks depending on the results
- def safe_load(file, mtime, stderr = $stderr)
- load(file)
- stderr.puts "#{self.class}: reloaded `#{file}'"
- file
- rescue LoadError, SyntaxError => ex
- stderr.puts ex
- ensure
- @mtimes[file] = mtime
- end
-
- module Stat
- def rotation
- files = [$0, *$LOADED_FEATURES].uniq
- paths = ['./', *$LOAD_PATH].uniq
-
- files.map{|file|
- next if file =~ /\.(so|bundle)$/ # cannot reload compiled files
-
- found, stat = figure_path(file, paths)
- next unless found and stat and mtime = stat.mtime
-
- @cache[file] = found
-
- yield(found, mtime)
- }.compact
- end
-
- # Takes a relative or absolute +file+ name, a couple possible +paths+ that
- # the +file+ might reside in. Returns the full path and File::Stat for the
- # path.
- def figure_path(file, paths)
- found = @cache[file]
- found = file if !found and Pathname.new(file).absolute?
- found, stat = safe_stat(found)
- return found, stat if found
-
- paths.each do |possible_path|
- path = ::File.join(possible_path, file)
- found, stat = safe_stat(path)
- return ::File.expand_path(found), stat if found
- end
- end
-
- def safe_stat(file)
- return unless file
- stat = ::File.stat(file)
- return file, stat if stat.file?
- rescue Errno::ENOENT, Errno::ENOTDIR
- @cache.delete(file) and false
- end
- end
- end
-end
diff --git a/actionpack/lib/action_dispatch/vendor/rack/rack/request.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/request.rb
deleted file mode 100644
index 0bff7af038..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/rack/request.rb
+++ /dev/null
@@ -1,254 +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, *args)
- 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
- def session; @env['rack.session'] ||= {} end
- def session_options; @env['rack.session.options'] ||= {} 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).first.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'
- ]
-
- # The set of media-types. Requests that do not indicate
- # one of the media types presents in this list will not be eligible
- # for param parsing like soap attachments or generic multiparts
- PARSEABLE_DATA_MEDIA_TYPES = [
- 'multipart/related',
- 'multipart/mixed'
- ]
-
- # 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
-
- # Determine whether the request body contains data by checking
- # the request media_type against registered parse-data media-types
- def parseable_data?
- PARSEABLE_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? || parseable_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)
-
- @env["rack.input"].rewind
- 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 path
- script_name + path_info
- end
-
- def fullpath
- query_string.empty? ? path : "#{path}?#{query_string}"
- 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/rack/response.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/response.rb
deleted file mode 100644
index 28b4d8302f..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/rack/response.rb
+++ /dev/null
@@ -1,183 +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 redirect(target, status=302)
- self.status = status
- self["Location"] = target
- 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 += Rack::Utils.bytesize(s)
- @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/rack/rewindable_input.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/rewindable_input.rb
deleted file mode 100644
index 9e9b21ff99..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/rack/rewindable_input.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-require 'tempfile'
-
-module Rack
- # Class which can make any IO object rewindable, including non-rewindable ones. It does
- # this by buffering the data into a tempfile, which is rewindable.
- #
- # rack.input is required to be rewindable, so if your input stream IO is non-rewindable
- # by nature (e.g. a pipe or a socket) then you can wrap it in an object of this class
- # to easily make it rewindable.
- #
- # Don't forget to call #close when you're done. This frees up temporary resources that
- # RewindableInput uses, though it does *not* close the original IO object.
- class RewindableInput
- def initialize(io)
- @io = io
- @rewindable_io = nil
- @unlinked = false
- end
-
- def gets
- make_rewindable unless @rewindable_io
- @rewindable_io.gets
- end
-
- def read(*args)
- make_rewindable unless @rewindable_io
- @rewindable_io.read(*args)
- end
-
- def each(&block)
- make_rewindable unless @rewindable_io
- @rewindable_io.each(&block)
- end
-
- def rewind
- make_rewindable unless @rewindable_io
- @rewindable_io.rewind
- end
-
- # Closes this RewindableInput object without closing the originally
- # wrapped IO oject. Cleans up any temporary resources that this RewindableInput
- # has created.
- #
- # This method may be called multiple times. It does nothing on subsequent calls.
- def close
- if @rewindable_io
- if @unlinked
- @rewindable_io.close
- else
- @rewindable_io.close!
- end
- @rewindable_io = nil
- end
- end
-
- private
-
- # Ruby's Tempfile class has a bug. Subclass it and fix it.
- class Tempfile < ::Tempfile
- def _close
- @tmpfile.close if @tmpfile
- @data[1] = nil if @data
- @tmpfile = nil
- end
- end
-
- def make_rewindable
- # Buffer all data into a tempfile. Since this tempfile is private to this
- # RewindableInput object, we chmod it so that nobody else can read or write
- # it. On POSIX filesystems we also unlink the file so that it doesn't
- # even have a file entry on the filesystem anymore, though we can still
- # access it because we have the file handle open.
- @rewindable_io = Tempfile.new('RackRewindableInput')
- @rewindable_io.chmod(0000)
- if filesystem_has_posix_semantics?
- @rewindable_io.unlink
- @unlinked = true
- end
-
- buffer = ""
- while @io.read(1024 * 4, buffer)
- entire_buffer_written_out = false
- while !entire_buffer_written_out
- written = @rewindable_io.write(buffer)
- entire_buffer_written_out = written == buffer.size
- if !entire_buffer_written_out
- buffer.slice!(0 .. written - 1)
- end
- end
- end
- @rewindable_io.rewind
- end
-
- def filesystem_has_posix_semantics?
- RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/
- end
- end
-end
diff --git a/actionpack/lib/action_dispatch/vendor/rack/rack/session/abstract/id.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/session/abstract/id.rb
deleted file mode 100644
index 218144c17f..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/session/cookie.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/session/cookie.rb
deleted file mode 100644
index eace9bd0c6..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/session/memcache.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/session/memcache.rb
deleted file mode 100644
index 4a65cbf35d..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/session/pool.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/session/pool.rb
deleted file mode 100644
index f6f87408bb..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/showexceptions.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/showexceptions.rb
deleted file mode 100644
index 697bc41fdb..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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| %>
- <%=h line %>
- <% } %>
-
- <% end %>
-
-
- <%=h frame.context_line %>...
-
- <% if frame.post_context %>
-
- <% frame.post_context.each { |line| %>
- <%=h line %>
- <% } %>
-
- <% end %>
-
- <% end %>
-
-<% } %>
-
-
-
-
-
Request information
-
-
GET
- <% unless req.GET.empty? %>
-
-
-
- Variable
- Value
-
-
-
- <% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %>
-
- <%=h key %>
- <%=h val.inspect %>
-
- <% } %>
-
-
- <% else %>
-
No GET data.
- <% end %>
-
-
POST
- <% unless req.POST.empty? %>
-
-
-
- Variable
- Value
-
-
-
- <% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %>
-
- <%=h key %>
- <%=h val.inspect %>
-
- <% } %>
-
-
- <% else %>
-
No POST data.
- <% end %>
-
-
-
COOKIES
- <% unless req.cookies.empty? %>
-
-
-
- Variable
- Value
-
-
-
- <% req.cookies.each { |key, val| %>
-
- <%=h key %>
- <%=h val.inspect %>
-
- <% } %>
-
-
- <% else %>
-
No cookie data.
- <% end %>
-
-
Rack ENV
-
-
-
- Variable
- Value
-
-
-
- <% env.sort_by { |k, v| k.to_s }.each { |key, val| %>
-
- <%=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/rack/showstatus.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/showstatus.rb
deleted file mode 100644
index 28258c7c89..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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 %>)
-
-
-
-
-
-
- You're seeing this error because you use Rack::ShowStatus
.
-
-
-
-
-HTML
-
- # :startdoc:
- end
-end
diff --git a/actionpack/lib/action_dispatch/vendor/rack/rack/static.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/static.rb
deleted file mode 100644
index 168e8f83b2..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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/rack/urlmap.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/urlmap.rb
deleted file mode 100644
index fcf6616c58..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/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)| [h ? -h.size : (-1.0 / 0.0), -l.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/rack/utils.rb b/actionpack/lib/action_dispatch/vendor/rack/rack/utils.rb
deleted file mode 100644
index 42e2e698f4..0000000000
--- a/actionpack/lib/action_dispatch/vendor/rack/rack/utils.rb
+++ /dev/null
@@ -1,516 +0,0 @@
-# -*- encoding: binary -*-
-
-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(\A[\[\]]*([^\[\]]+)\]*)
- k = $1 || ''
- after = $' || ''
-
- return if k.empty?
-
- if after == ""
- params[k] = v
- elsif after == "[]"
- params[k] ||= []
- raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
- params[k] << v
- elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
- child_key = $1
- params[k] ||= []
- raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" 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] ||= {}
- raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash)
- 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
-
- def build_nested_query(value, prefix = nil)
- case value
- when Array
- value.map { |v|
- build_nested_query(v, "#{prefix}[]")
- }.join("&")
- when Hash
- value.map { |k, v|
- build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
- }.join("&")
- when String
- raise ArgumentError, "value must be a Hash" if prefix.nil?
- "#{prefix}=#{escape(value)}"
- else
- prefix
- end
- end
- module_function :build_nested_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
- 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
-
- EOL = "\r\n"
- MULTIPART_BOUNDARY = "AaB03x"
-
- def self.parse_multipart(env)
- unless env['CONTENT_TYPE'] =~
- %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
- nil
- else
- boundary = "--#{$1}"
-
- params = {}
- buf = ""
- content_length = env['CONTENT_LENGTH'].to_i
- input = env['rack.input']
- input.rewind
-
- boundary_size = Utils.bytesize(boundary) + EOL.size
- bufsize = 16384
-
- content_length -= boundary_size
-
- read_buffer = ''
-
- status = input.read(boundary_size, read_buffer)
- 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(EOL+EOL)
- 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: (.*)#{EOL}/ni, 1]
- name = head[/Content-Disposition:.*\s+name="?([^\";]*)"?/ni, 1] || head[/Content-ID:\s*([^#{EOL}]*)/ni, 1]
-
- if content_type || 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, read_buffer)
- 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}
- elsif !filename && content_type
- body.rewind
-
- # Generic multipart cases, not coming from a form
- data = {: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
- }
-
- input.rewind
-
- params
- end
- end
-
- def self.build_multipart(params, first = true)
- if first
- unless params.is_a?(Hash)
- raise ArgumentError, "value must be a Hash"
- end
-
- multipart = false
- query = lambda { |value|
- case value
- when Array
- value.each(&query)
- when Hash
- value.values.each(&query)
- when UploadedFile
- multipart = true
- end
- }
- params.values.each(&query)
- return nil unless multipart
- end
-
- flattened_params = Hash.new
-
- params.each do |key, value|
- k = first ? key.to_s : "[#{key}]"
-
- case value
- when Array
- value.map { |v|
- build_multipart(v, false).each { |subkey, subvalue|
- flattened_params["#{k}[]#{subkey}"] = subvalue
- }
- }
- when Hash
- build_multipart(value, false).each { |subkey, subvalue|
- flattened_params[k + subkey] = subvalue
- }
- else
- flattened_params[k] = value
- end
- end
-
- if first
- flattened_params.map { |name, file|
- if file.respond_to?(:original_filename)
- ::File.open(file.path, "rb") do |f|
- f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
-<<-EOF
---#{MULTIPART_BOUNDARY}\r
-Content-Disposition: form-data; name="#{name}"; filename="#{Utils.escape(file.original_filename)}"\r
-Content-Type: #{file.content_type}\r
-Content-Length: #{::File.stat(file.path).size}\r
-\r
-#{f.read}\r
-EOF
- end
- else
-<<-EOF
---#{MULTIPART_BOUNDARY}\r
-Content-Disposition: form-data; name="#{name}"\r
-\r
-#{file}\r
-EOF
- end
- }.join + "--#{MULTIPART_BOUNDARY}--\r"
- else
- flattened_params
- end
- end
- end
- end
-end
--
cgit v1.2.3
From db0bfe4ede3cdfc2e4ccdb2a89525a914e6d0913 Mon Sep 17 00:00:00 2001
From: Alexander Podgorbunsky
Date: Thu, 26 Mar 2009 15:00:12 +0300
Subject: Default scope :order should be overridden by named scopes.
[#2346 state:committed]
Signed-off-by: Jeremy Kemper
---
activerecord/lib/active_record/named_scope.rb | 4 ++--
activerecord/test/cases/method_scoping_test.rb | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index 1f3ef300f2..3df7089096 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -114,7 +114,7 @@ module ActiveRecord
end
end
- delegate :scopes, :with_scope, :to => :proxy_scope
+ delegate :scopes, :with_scope, :scoped_methods, :to => :proxy_scope
def initialize(proxy_scope, options, &block)
options ||= {}
@@ -178,7 +178,7 @@ module ActiveRecord
else
with_scope({:find => proxy_options, :create => proxy_options[:conditions].is_a?(Hash) ? proxy_options[:conditions] : {}}, :reverse_merge) do
method = :new if method == :build
- if current_scoped_methods_when_defined
+ if current_scoped_methods_when_defined && !scoped_methods.include?(current_scoped_methods_when_defined)
with_scope current_scoped_methods_when_defined do
proxy_scope.send(method, *args, &block)
end
diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb
index 2165d2f7e8..c479859ee0 100644
--- a/activerecord/test/cases/method_scoping_test.rb
+++ b/activerecord/test/cases/method_scoping_test.rb
@@ -628,9 +628,9 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal expected, received
end
- def test_named_scope
- expected = Developer.find(:all, :order => 'salary DESC, name DESC').collect { |dev| dev.salary }
- received = DeveloperOrderedBySalary.by_name.find(:all).collect { |dev| dev.salary }
+ def test_named_scope_overwrites_default
+ expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.name }
+ received = DeveloperOrderedBySalary.by_name.find(:all).collect { |dev| dev.name }
assert_equal expected, received
end
--
cgit v1.2.3
From 99c103be1165da9c8299bc0977188ecf167e06a5 Mon Sep 17 00:00:00 2001
From: Ruy Asan
Date: Fri, 1 May 2009 13:09:29 -0700
Subject: Fixed bug with polymorphic has_one :as pointing to an STI record
[#2594 state:committed]
Signed-off-by: Jeremy Kemper
---
.../lib/active_record/associations/has_one_association.rb | 2 +-
.../test/cases/associations/has_one_associations_test.rb | 9 ++++++++-
activerecord/test/fixtures/organizations.yml | 4 +++-
activerecord/test/fixtures/sponsors.yml | 4 +++-
activerecord/test/models/organization.rb | 4 ++++
activerecord/test/schema/schema.rb | 3 ++-
6 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb
index b92cbbdeab..1464227bb0 100644
--- a/activerecord/lib/active_record/associations/has_one_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_association.rb
@@ -88,7 +88,7 @@ module ActiveRecord
when @reflection.options[:as]
@finder_sql =
"#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_id = #{owner_quoted_id} AND " +
- "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.base_class.name.to_s)}"
+ "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.name.to_s)}"
else
@finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{owner_quoted_id}"
end
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index 1ddb3f49bf..3984945f9f 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -2,9 +2,11 @@ require "cases/helper"
require 'models/developer'
require 'models/project'
require 'models/company'
+require 'models/sponsor'
+require 'models/organization'
class HasOneAssociationsTest < ActiveRecord::TestCase
- fixtures :accounts, :companies, :developers, :projects, :developers_projects
+ fixtures :accounts, :companies, :developers, :projects, :developers_projects, :organizations, :sponsors
def setup
Account.destroyed_account_ids.clear
@@ -306,4 +308,9 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
Firm.find(@firm.id, :include => :account).save!
end
end
+
+ def test_polymorphic_sti
+ assert_equal organizations(:sponsorable), sponsors(:org_sponsor).sponsorable
+ assert_equal sponsors(:org_sponsor), organizations(:sponsorable).sponsor
+ end
end
diff --git a/activerecord/test/fixtures/organizations.yml b/activerecord/test/fixtures/organizations.yml
index 25295bff87..05d620fbc6 100644
--- a/activerecord/test/fixtures/organizations.yml
+++ b/activerecord/test/fixtures/organizations.yml
@@ -2,4 +2,6 @@ nsa:
name: No Such Agency
discordians:
name: Discordians
-
+sponsorable:
+ name: We Need Money
+ type: SponsorableOrganization
diff --git a/activerecord/test/fixtures/sponsors.yml b/activerecord/test/fixtures/sponsors.yml
index 42df8957d1..97a7784047 100644
--- a/activerecord/test/fixtures/sponsors.yml
+++ b/activerecord/test/fixtures/sponsors.yml
@@ -6,4 +6,6 @@ boring_club_sponsor_for_groucho:
sponsorable: some_other_guy (Member)
crazy_club_sponsor_for_groucho:
sponsor_club: crazy_club
- sponsorable: some_other_guy (Member)
\ No newline at end of file
+ sponsorable: some_other_guy (Member)
+org_sponsor:
+ sponsorable: sponsorable (SponsorableOrganization)
\ No newline at end of file
diff --git a/activerecord/test/models/organization.rb b/activerecord/test/models/organization.rb
index d79d5037c8..5d1308354d 100644
--- a/activerecord/test/models/organization.rb
+++ b/activerecord/test/models/organization.rb
@@ -1,4 +1,8 @@
class Organization < ActiveRecord::Base
has_many :member_details
has_many :members, :through => :member_details
+end
+
+class SponsorableOrganization < Organization
+ has_one :sponsor, :as => :sponsorable
end
\ No newline at end of file
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 98e6d192a5..6918a4fcab 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -283,6 +283,7 @@ ActiveRecord::Schema.define do
create_table :organizations, :force => true do |t|
t.string :name
+ t.string :type
end
create_table :owners, :primary_key => :owner_id ,:force => true do |t|
@@ -388,7 +389,7 @@ ActiveRecord::Schema.define do
create_table :sponsors, :force => true do |t|
t.integer :club_id
t.integer :sponsorable_id
- t.string :sponsorable_type
+ t.string :sponsorable_type
end
create_table :subscribers, :force => true, :id => false do |t|
--
cgit v1.2.3
From 3be3470fab788856b4559742434f195cc6b1009a Mon Sep 17 00:00:00 2001
From: Ruy Asan
Date: Fri, 1 May 2009 13:49:18 -0700
Subject: Added routing test for irregular ID requirements and custom member
action.
[#2595 state:committed]
Signed-off-by: Jeremy Kemper
---
actionpack/test/controller/resources_test.rb | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb
index c807e71cd7..30ab110ef7 100644
--- a/actionpack/test/controller/resources_test.rb
+++ b/actionpack/test/controller/resources_test.rb
@@ -120,6 +120,14 @@ class ResourcesTest < ActionController::TestCase
end
end
+ def test_irregular_id_requirements_should_get_passed_to_member_actions
+ expected_options = {:controller => 'messages', :action => 'custom', :id => '1.1.1'}
+
+ with_restful_routing(:messages, :member => {:custom => :get}, :requirements => {:id => /[0-9]\.[0-9]\.[0-9]/}) do
+ assert_recognizes(expected_options, :path => 'messages/1.1.1/custom', :method => :get)
+ end
+ end
+
def test_with_path_prefix
with_restful_routing :messages, :path_prefix => '/thread/:thread_id' do
assert_simply_restful_for :messages, :path_prefix => 'thread/5/', :options => { :thread_id => '5' }
--
cgit v1.2.3
From 34509777fd375e5bc529f21ca66cf63263c2cf64 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Mon, 27 Apr 2009 18:16:55 -0700
Subject: Makes new callbacks support keys with special characters
---
activesupport/lib/active_support/new_callbacks.rb | 1 +
activesupport/test/new_callbacks_test.rb | 28 +++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb
index 7a48dbac04..8a91e1c674 100644
--- a/activesupport/lib/active_support/new_callbacks.rb
+++ b/activesupport/lib/active_support/new_callbacks.rb
@@ -356,6 +356,7 @@ module ActiveSupport
str = <<-RUBY_EVAL
def _run_#{symbol}_callbacks(key = nil)
if key
+ key = key.hash.to_s.gsub(/-/, '_')
name = "_run__\#{self.class.name.split("::").last}__#{symbol}__\#{key}__callbacks"
if respond_to?(name)
diff --git a/activesupport/test/new_callbacks_test.rb b/activesupport/test/new_callbacks_test.rb
index abe7790ebf..8c887e1bf1 100644
--- a/activesupport/test/new_callbacks_test.rb
+++ b/activesupport/test/new_callbacks_test.rb
@@ -255,6 +255,26 @@ module NewCallbacksTest
end
end
+ class HyphenatedCallbacks
+ include ActiveSupport::NewCallbacks
+ define_callbacks :save
+ attr_reader :stuff
+
+ save_callback :before, :omg, :per_key => {:if => :yes}
+
+ def yes() true end
+
+ def omg
+ @stuff = "OMG"
+ end
+
+ def save
+ _run_save_callbacks("hyphen-ated") do
+ @stuff
+ end
+ end
+ end
+
class AroundCallbacksTest < Test::Unit::TestCase
def test_save_around
around = AroundPerson.new
@@ -381,4 +401,12 @@ module NewCallbacksTest
assert_equal ["first", "second", "third", "second", "first"], terminator.history
end
end
+
+ class HyphenatedKeyTest < Test::Unit::TestCase
+ def test_save
+ obj = HyphenatedCallbacks.new
+ obj.save
+ assert_equal obj.stuff, "OMG"
+ end
+ end
end
--
cgit v1.2.3
From 8a4e77b4200946ba4ed42fe5927a7400a846063a Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Mon, 27 Apr 2009 18:21:26 -0700
Subject: OMG, a lot of work
---
actionpack/Rakefile | 11 +-
.../lib/action_controller/abstract/layouts.rb | 5 +-
.../lib/action_controller/abstract/renderer.rb | 2 +
.../lib/action_controller/dispatch/dispatcher.rb | 2 +-
.../lib/action_controller/dispatch/middlewares.rb | 2 +-
actionpack/lib/action_controller/new_base.rb | 11 +-
actionpack/lib/action_controller/new_base/base.rb | 2 +
.../action_controller/new_base/compatibility.rb | 12 +++
.../abstract_controller_test.rb | 22 ++--
.../test/abstract_controller/layouts_test.rb | 2 +-
actionpack/test/controller/render_test.rb | 3 +
actionpack/test/lib/fixture_template.rb | 115 ++++++++++++++++-----
actionpack/test/new_base/base_test.rb | 8 +-
actionpack/test/new_base/render_action_test.rb | 8 +-
.../test/new_base/render_implicit_action_test.rb | 30 ++++--
actionpack/test/new_base/render_layout_test.rb | 4 +-
actionpack/test/new_base/render_template_test.rb | 39 ++++---
actionpack/test/new_base/render_text_test.rb | 4 +-
actionpack/test/new_base/test_helper.rb | 14 ++-
19 files changed, 210 insertions(+), 86 deletions(-)
create mode 100644 actionpack/lib/action_controller/new_base/compatibility.rb
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 300c2ebf81..18610ed773 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -23,14 +23,14 @@ task :default => [ :test ]
# Run the unit tests
desc "Run all unit tests"
-task :test => [:test_action_pack, :test_active_record_integration]
+task :test => [:test_action_pack, :test_active_record_integration, :test_new_base]
Rake::TestTask.new(:test_action_pack) do |t|
t.libs << "test"
# make sure we include the tests in alphabetical order as on some systems
# this will not happen automatically and the tests (as a whole) will error
- t.test_files = Dir.glob( "test/[cdft]*/**/*_test.rb" ).sort
+ t.test_files = Dir.glob( "test/{controller,dispatch,template}/**/*_test.rb" ).sort
t.verbose = true
#t.warning = true
@@ -43,6 +43,13 @@ Rake::TestTask.new(:test_active_record_integration) do |t|
t.verbose = true
end
+desc 'New Controller Tests'
+Rake::TestTask.new(:test_new_base) do |t|
+ t.libs << "test"
+ t.test_files = Dir.glob("test/{abstract_controller,new_base}/*_test.rb")
+ t.verbose = true
+end
+
# Genereate the RDoc documentation
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 0039e67c5a..315d6151e9 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -50,6 +50,7 @@ module AbstractController
end
def _render_template(template, options)
+ # layout = options[:_layout].is_a?(ActionView::Template) ? options[:_layout] : _layout_for_name(options[:_layout])
_action_view._render_template_with_layout(template, options[:_layout])
end
@@ -67,10 +68,10 @@ module AbstractController
def _default_layout(require_layout = false)
if require_layout && !_layout
- raise ArgumentError,
+ raise ArgumentError,
"There was no default layout for #{self.class} in #{view_paths.inspect}"
end
-
+
begin
layout = _layout_for_name(_layout)
rescue NameError => e
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index e31accbbfc..37da2398ec 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -27,9 +27,11 @@ module AbstractController
#
# :api: plugin
def render_to_body(options = {})
+ options = {:_template_name => options} if options.is_a?(String)
name = options[:_template_name] || action_name
template = options[:_template] || view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix])
+
_render_template(template, options)
end
diff --git a/actionpack/lib/action_controller/dispatch/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb
index bb9d8bd063..af2da8bfe5 100644
--- a/actionpack/lib/action_controller/dispatch/dispatcher.rb
+++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb
@@ -79,7 +79,7 @@ module ActionController
run_callbacks :before_dispatch
Routing::Routes.call(env)
rescue Exception => exception
- if controller ||= (::ApplicationController rescue Base)
+ if !env["rack.test"] && controller ||= (::ApplicationController rescue Base)
controller.call_with_exception(env, exception).to_a
else
raise exception
diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb
index b5adbae746..d87c0f9706 100644
--- a/actionpack/lib/action_controller/dispatch/middlewares.rb
+++ b/actionpack/lib/action_controller/dispatch/middlewares.rb
@@ -9,4 +9,4 @@ use lambda { ActionController::Base.session_store },
use "ActionDispatch::ParamsParser"
use "Rack::MethodOverride"
-use "Rack::Head"
+use "Rack::Head"
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 7c65f1cdc1..51d9c05a1a 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -1,7 +1,8 @@
module ActionController
- autoload :AbstractBase, "action_controller/new_base/base"
- autoload :HideActions, "action_controller/new_base/hide_actions"
- autoload :Layouts, "action_controller/new_base/layouts"
- autoload :Renderer, "action_controller/new_base/renderer"
- autoload :UrlFor, "action_controller/new_base/url_for"
+ autoload :AbstractBase, "action_controller/new_base/base"
+ autoload :HideActions, "action_controller/new_base/hide_actions"
+ autoload :Layouts, "action_controller/new_base/layouts"
+ autoload :Rails2Compatibility, "action_controller/new_base/compatibility"
+ autoload :Renderer, "action_controller/new_base/renderer"
+ autoload :UrlFor, "action_controller/new_base/url_for"
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 08e7a1a0e7..75fe012aed 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -50,6 +50,8 @@ module ActionController
@_request = ActionDispatch::Request.new(env)
@_response = ActionDispatch::Response.new
process(@_request.parameters[:action])
+ @_response.prepare!
+ self
end
# :api: private
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
new file mode 100644
index 0000000000..8682493c8e
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -0,0 +1,12 @@
+module ActionController
+ module Rails2Compatibility
+
+ def render_to_body(options)
+ if options.is_a?(Hash) && options.key?(:template)
+ options[:template].sub!(/^\//, '')
+ end
+ super
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/abstract_controller/abstract_controller_test.rb b/actionpack/test/abstract_controller/abstract_controller_test.rb
index 331797afcf..cf6fb5140d 100644
--- a/actionpack/test/abstract_controller/abstract_controller_test.rb
+++ b/actionpack/test/abstract_controller/abstract_controller_test.rb
@@ -58,11 +58,11 @@ module AbstractController
end
def rendering_to_body
- render_to_body "naked_render.erb"
+ self.response_body = render_to_body :_template_name => "naked_render.erb"
end
def rendering_to_string
- render_to_string "naked_render.erb"
+ self.response_body = render_to_string :_template_name => "naked_render.erb"
end
end
@@ -136,6 +136,11 @@ module AbstractController
class WithLayouts < PrefixedViews
use Layouts
+ def self.inherited(klass)
+ klass._write_layout_method
+ super
+ end
+
private
def self.layout(formats)
begin
@@ -147,13 +152,9 @@ module AbstractController
end
end
end
-
- def _layout
- self.class.layout(formats)
- end
-
+
def render_to_body(options = {})
- options[:_layout] = options[:layout] || _layout
+ options[:_layout] = options[:layout] || _default_layout
super
end
end
@@ -175,11 +176,6 @@ module AbstractController
result = Me4.process(:index)
assert_equal "Me4 Enter : Hello from me4/index.erb : Exit", result.response_obj[:body]
end
-
- test "it can fall back to the application layout" do
- result = Me5.process(:index)
- assert_equal "Application Enter : Hello from me5/index.erb : Exit", result.response_obj[:body]
- end
end
# respond_to_action?(action_name)
diff --git a/actionpack/test/abstract_controller/layouts_test.rb b/actionpack/test/abstract_controller/layouts_test.rb
index 3d4570bfef..078e0037a8 100644
--- a/actionpack/test/abstract_controller/layouts_test.rb
+++ b/actionpack/test/abstract_controller/layouts_test.rb
@@ -8,7 +8,7 @@ module AbstractControllerTests
use AbstractController::Renderer
use AbstractController::Layouts
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/hello.erb" => "With String <%= yield %>",
"layouts/hello_override.erb" => "With Override <%= yield %>",
"layouts/abstract_controller_tests/layouts/with_string_implied_child.erb" =>
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 023bf0eeaa..a97e8ac5c1 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -755,6 +755,7 @@ class RenderTest < ActionController::TestCase
@request.host = "www.nextangle.com"
end
+ # :ported:
def test_simple_show
get :hello_world
assert_response 200
@@ -763,11 +764,13 @@ class RenderTest < ActionController::TestCase
assert_equal "Hello world!", @response.body
end
+ # :ported:
def test_renders_default_template_for_missing_action
get :'hyphen-ated'
assert_template 'test/hyphen-ated'
end
+ # :ported:
def test_render
get :render_hello_world
assert_template "test/hello_world"
diff --git a/actionpack/test/lib/fixture_template.rb b/actionpack/test/lib/fixture_template.rb
index 26f6ec2d0c..e43e329a9e 100644
--- a/actionpack/test/lib/fixture_template.rb
+++ b/actionpack/test/lib/fixture_template.rb
@@ -1,35 +1,104 @@
module ActionView #:nodoc:
- class FixtureTemplate < Template
- class FixturePath < Template::Path
- def initialize(hash = {})
- @hash = {}
-
- hash.each do |k, v|
- @hash[k.sub(/\.\w+$/, '')] = FixtureTemplate.new(v, k.split("/").last, self)
+class Template
+ class FixturePath < Path
+ def initialize(hash = {}, options = {})
+ super(options)
+ @hash = hash
+ end
+
+ def find_templates(name, details, prefix, partial)
+ if regexp = details_to_regexp(name, details, prefix, partial)
+ cached(regexp) do
+ templates = []
+ @hash.select { |k,v| k =~ regexp }.each do |path, source|
+ templates << Template.new(source, path, *path_to_details(path))
+ end
+ templates
end
-
- super("fixtures://root")
- end
-
- def find_template(path)
- @hash[path]
end
end
- def initialize(body, *args)
- @body = body
- super(*args)
+ private
+
+ def formats_regexp
+ @formats_regexp ||= begin
+ formats = Mime::SET.map { |m| m.symbol }
+ '(?:' + formats.map { |l| "\\.#{Regexp.escape(l.to_s)}" }.join('|') + ')?'
+ end
end
- def source
- @body
+ def handler_regexp
+ e = TemplateHandlers.extensions.map{|h| "\\.#{Regexp.escape(h.to_s)}"}.join("|")
+ "(?:#{e})?"
end
- private
-
- def find_full_path(path, load_paths)
- return '/', path
+ def details_to_regexp(name, details, prefix, partial)
+ path = ""
+ path << "#{prefix}/" unless prefix.empty?
+ path << (partial ? "_#{name}" : name)
+
+ extensions = ""
+ [:locales, :formats].each do |k|
+ extensions << if exts = details[k]
+ '(?:' + exts.map {|e| "\\.#{Regexp.escape(e.to_s)}"}.join('|') + ')?'
+ else
+ k == :formats ? formats_regexp : ''
+ end
+ end
+
+ %r'#{Regexp.escape(path)}#{extensions}#{handler_regexp}'
+ 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 FixtureTemplate < Template
+ # class FixturePath < Template::Path
+ # def initialize(hash = {})
+ # @hash = {}
+ #
+ # hash.each do |k, v|
+ # @hash[k.sub(/\.\w+$/, '')] = FixtureTemplate.new(v, k.split("/").last, self)
+ # end
+ #
+ # super("fixtures://root")
+ # end
+ #
+ # def find_template(path)
+ # @hash[path]
+ # end
+ # end
+ #
+ # def initialize(body, *args)
+ # @body = body
+ # super(*args)
+ # end
+ #
+ # def source
+ # @body
+ # end
+ #
+ # private
+ #
+ # def find_full_path(path, load_paths)
+ # return '/', path
+ # end
+ #
+ # end
+end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/base_test.rb b/actionpack/test/new_base/base_test.rb
index 4f46cb6492..b0e87b4f5b 100644
--- a/actionpack/test/new_base/base_test.rb
+++ b/actionpack/test/new_base/base_test.rb
@@ -34,11 +34,11 @@ module HappyPath
end
test "sets the content type" do
- assert_content_type Mime::HTML
+ assert_content_type "text/html; charset=utf-8"
end
test "sets the content length" do
- assert_header "Content-Length", 7
+ assert_header "Content-Length", "7"
end
end
@@ -52,7 +52,7 @@ module HappyPath
end
test "setting the body manually sets the content length" do
- assert_header "Content-Length", 7
+ assert_header "Content-Length", "7"
end
end
@@ -65,7 +65,7 @@ module HappyPath
end
test "updating the response body updates the content length" do
- assert_header "Content-Length", 8
+ assert_header "Content-Length", "8"
end
end
end
diff --git a/actionpack/test/new_base/render_action_test.rb b/actionpack/test/new_base/render_action_test.rb
index 2bfb374a31..37b83fb681 100644
--- a/actionpack/test/new_base/render_action_test.rb
+++ b/actionpack/test/new_base/render_action_test.rb
@@ -5,7 +5,7 @@ module RenderAction
# This has no layout and it works
class BasicController < ActionController::Base2
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = [ActionView::Template::FixturePath.new(
"render_action/basic/hello_world.html.erb" => "Hello world!"
)]
@@ -129,7 +129,7 @@ module RenderActionWithApplicationLayout
class BasicController < ::ApplicationController
# Set the view path to an application view structure with layouts
- self.view_paths = self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = self.view_paths = [ActionView::Template::FixturePath.new(
"render_action_with_application_layout/basic/hello_world.html.erb" => "Hello World!",
"layouts/application.html.erb" => "OHAI <%= yield %> KTHXBAI",
"layouts/greetings.html.erb" => "Greetings <%= yield %> Bai"
@@ -204,7 +204,7 @@ end
module RenderActionWithControllerLayout
class BasicController < ActionController::Base2
- self.view_paths = self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = self.view_paths = [ActionView::Template::FixturePath.new(
"render_action_with_controller_layout/basic/hello_world.html.erb" => "Hello World!",
"layouts/render_action_with_controller_layout/basic.html.erb" => "With Controller Layout! <%= yield %> KTHXBAI"
)]
@@ -267,7 +267,7 @@ end
module RenderActionWithBothLayouts
class BasicController < ActionController::Base2
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new({
+ self.view_paths = [ActionView::Template::FixturePath.new({
"render_action_with_both_layouts/basic/hello_world.html.erb" => "Hello World!",
"layouts/application.html.erb" => "OHAI <%= yield %> KTHXBAI",
"layouts/render_action_with_both_layouts/basic.html.erb" => "With Controller Layout! <%= yield %> KTHXBAI"
diff --git a/actionpack/test/new_base/render_implicit_action_test.rb b/actionpack/test/new_base/render_implicit_action_test.rb
index 798505b539..0a10c070c3 100644
--- a/actionpack/test/new_base/render_implicit_action_test.rb
+++ b/actionpack/test/new_base/render_implicit_action_test.rb
@@ -1,16 +1,28 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
-module HappyPath
-
- class RenderImplicitActionController < ActionController::Base2
- # No actions yet, they are implicit
+module RenderImplicitAction
+ class SimpleController < ::ApplicationController
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "render_implicit_action/simple/hello_world.html.erb" => "Hello world!",
+ "render_implicit_action/simple/hyphen-ated.html.erb" => "Hello hyphen-ated"
+ )]
+
+ def hello_world() end
end
- class TestRendersActionImplicitly < SimpleRouteCase
-
- test "renders action implicitly" do
- assert true
- end
+ class TestImplicitRender < SimpleRouteCase
+ describe "render a simple action with new explicit call to render"
+
+ get "/render_implicit_action/simple/hello_world"
+ assert_body "Hello world!"
+ assert_status 200
+ end
+ class TestImplicitWithSpecialCharactersRender < SimpleRouteCase
+ describe "render an action with a missing method and has special characters"
+
+ get "/render_implicit_action/simple/hyphen-ated"
+ assert_body "Hello hyphen-ated!"
+ assert_status 200
end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_layout_test.rb b/actionpack/test/new_base/render_layout_test.rb
index facf67ea85..07ea2f191e 100644
--- a/actionpack/test/new_base/render_layout_test.rb
+++ b/actionpack/test/new_base/render_layout_test.rb
@@ -3,7 +3,7 @@ require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
module ControllerLayouts
class ImplicitController < ::ApplicationController
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/application.html.erb" => "OMG <%= yield %> KTHXBAI",
"basic.html.erb" => "Hello world!"
)]
@@ -23,7 +23,7 @@ module ControllerLayouts
class ImplicitNameController < ::ApplicationController
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/controller_layouts/implicit_name.html.erb" => "OMGIMPLICIT <%= yield %> KTHXBAI",
"basic.html.erb" => "Hello world!"
)]
diff --git a/actionpack/test/new_base/render_template_test.rb b/actionpack/test/new_base/render_template_test.rb
index c6c0269b40..fd0519159e 100644
--- a/actionpack/test/new_base/render_template_test.rb
+++ b/actionpack/test/new_base/render_template_test.rb
@@ -4,7 +4,7 @@ module HappyPath
class RenderTemplateWithoutLayoutController < ActionController::Base2
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = [ActionView::Template::FixturePath.new(
"test/basic.html.erb" => "Hello from basic.html.erb",
"shared.html.erb" => "Elastica"
)]
@@ -13,10 +13,6 @@ module HappyPath
render :template => "test/basic"
end
- def render_hello_world_with_forward_slash
- render :template => "/test/basic"
- end
-
def render_template_in_top_directory
render :template => 'shared'
end
@@ -34,14 +30,6 @@ module HappyPath
assert_status 200
end
- class TestTemplateRenderWithForwardSlash < SimpleRouteCase
- describe "rendering a normal template with full path starting with a leading slash"
-
- get "/happy_path/render_template_without_layout/render_hello_world_with_forward_slash"
- assert_body "Hello from basic.html.erb"
- assert_status 200
- end
-
class TestTemplateRenderInTopDirectory < SimpleRouteCase
describe "rendering a template not in a subdirectory"
@@ -60,7 +48,7 @@ module HappyPath
class RenderTemplateWithLayoutController < ::ApplicationController
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = [ActionView::Template::FixturePath.new(
"test/basic.html.erb" => "Hello from basic.html.erb",
"shared.html.erb" => "Elastica",
"layouts/application.html.erb" => "<%= yield %>, I'm here!",
@@ -127,7 +115,26 @@ module HappyPath
assert_body "Hello from basic.html.erb, I wish thee well."
assert_status 200
end
-
-
+end
+
+module Compatibility
+ class RenderTemplateWithoutLayoutController < ActionController::CompatibleBase2
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "test/basic.html.erb" => "Hello from basic.html.erb",
+ "shared.html.erb" => "Elastica"
+ )]
+
+ def render_hello_world_with_forward_slash
+ render :template => "/test/basic"
+ end
+ end
+
+ class TestTemplateRenderWithForwardSlash < SimpleRouteCase
+ describe "rendering a normal template with full path starting with a leading slash"
+
+ get "/compatibility/render_template_without_layout/render_hello_world_with_forward_slash"
+ assert_body "Hello from basic.html.erb"
+ assert_status 200
+ end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_text_test.rb b/actionpack/test/new_base/render_text_test.rb
index a20ca5fb8c..3c11524d1d 100644
--- a/actionpack/test/new_base/render_text_test.rb
+++ b/actionpack/test/new_base/render_text_test.rb
@@ -6,7 +6,7 @@ end
module HappyPath
class RenderTextWithoutLayoutsController < ActionController::Base2
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new]
+ self.view_paths = [ActionView::Template::FixturePath.new]
def render_hello_world
render :text => "hello david"
@@ -14,7 +14,7 @@ module HappyPath
end
class RenderTextWithLayoutsController < ::ApplicationController
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/application.html.erb" => "<%= yield %>, I'm here!",
"layouts/greetings.html.erb" => "<%= yield %>, I wish thee well."
)]
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index d29449ddc1..091fb77f9f 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -24,6 +24,14 @@ require 'pp' # require 'pp' early to prevent hidden_methods from not picking up
require 'rubygems'
require 'rack/test'
+module Rails
+ def self.env
+ x = Object.new
+ def x.test?() true end
+ x
+ end
+end
+
module ActionController
class Base2 < AbstractBase
use AbstractController::Callbacks
@@ -54,6 +62,10 @@ module ActionController
CORE_METHODS = self.public_instance_methods
end
+
+ class CompatibleBase2 < Base2
+ use ActionController::Rails2Compatibility
+ end
end
# Temporary base class
@@ -91,7 +103,7 @@ class Rack::TestCase < ActiveSupport::TestCase
end
def assert_body(body)
- assert_equal [body], last_response.body
+ assert_equal body, last_response.body
end
def self.assert_body(body)
--
cgit v1.2.3
From 059afb3a3a48106f430a8478072e34a59b4b72d6 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 29 Apr 2009 11:26:01 -0700
Subject: Removed a stray method_missing in the new callbacks system
---
activesupport/lib/active_support/new_callbacks.rb | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb
index 8a91e1c674..2ae7b006c7 100644
--- a/activesupport/lib/active_support/new_callbacks.rb
+++ b/activesupport/lib/active_support/new_callbacks.rb
@@ -304,15 +304,6 @@ module ActiveSupport
end
end
- # This method_missing is supplied to catch callbacks with keys and create
- # the appropriate callback for future use.
- def method_missing(meth, *args, &blk)
- if meth.to_s =~ /_run__([\w:]+)__(\w+)__(\w+)__callbacks/
- return self.class._create_and_run_keyed_callback($1, $2.to_sym, $3.to_sym, self, &blk)
- end
- super
- end
-
# An Array with a compile method
class CallbackChain < Array
def initialize(symbol)
--
cgit v1.2.3
From b692fceb6aa08791074dd9f4fc3b962094c0b056 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 29 Apr 2009 11:28:12 -0700
Subject: Renamed ActionController::AbstractBase to ActionController::Http
---
actionpack/lib/action_controller/new_base.rb | 2 +-
actionpack/lib/action_controller/new_base/base.rb | 2 +-
.../test/new_base/render_implicit_action_test.rb | 30 +++++++++++-----------
actionpack/test/new_base/test_helper.rb | 2 +-
4 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 51d9c05a1a..bfd8120e10 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -1,6 +1,6 @@
module ActionController
- autoload :AbstractBase, "action_controller/new_base/base"
autoload :HideActions, "action_controller/new_base/hide_actions"
+ autoload :Http, "action_controller/new_base/base"
autoload :Layouts, "action_controller/new_base/layouts"
autoload :Rails2Compatibility, "action_controller/new_base/compatibility"
autoload :Renderer, "action_controller/new_base/renderer"
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 75fe012aed..6711cd932a 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -1,5 +1,5 @@
module ActionController
- class AbstractBase < AbstractController::Base
+ class Http < AbstractController::Base
# :api: public
attr_internal :request, :response, :params
diff --git a/actionpack/test/new_base/render_implicit_action_test.rb b/actionpack/test/new_base/render_implicit_action_test.rb
index 0a10c070c3..3afa444e3e 100644
--- a/actionpack/test/new_base/render_implicit_action_test.rb
+++ b/actionpack/test/new_base/render_implicit_action_test.rb
@@ -10,19 +10,19 @@ module RenderImplicitAction
def hello_world() end
end
- class TestImplicitRender < SimpleRouteCase
- describe "render a simple action with new explicit call to render"
-
- get "/render_implicit_action/simple/hello_world"
- assert_body "Hello world!"
- assert_status 200
- end
-
- class TestImplicitWithSpecialCharactersRender < SimpleRouteCase
- describe "render an action with a missing method and has special characters"
-
- get "/render_implicit_action/simple/hyphen-ated"
- assert_body "Hello hyphen-ated!"
- assert_status 200
- end
+ # class TestImplicitRender < SimpleRouteCase
+ # describe "render a simple action with new explicit call to render"
+ #
+ # get "/render_implicit_action/simple/hello_world"
+ # assert_body "Hello world!"
+ # assert_status 200
+ # end
+ #
+ # class TestImplicitWithSpecialCharactersRender < SimpleRouteCase
+ # describe "render an action with a missing method and has special characters"
+ #
+ # get "/render_implicit_action/simple/hyphen-ated"
+ # assert_body "Hello hyphen-ated!"
+ # assert_status 200
+ # end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index 091fb77f9f..cc79d6faf7 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -33,7 +33,7 @@ module Rails
end
module ActionController
- class Base2 < AbstractBase
+ class Base2 < Http
use AbstractController::Callbacks
use AbstractController::Helpers
use AbstractController::Logger
--
cgit v1.2.3
From 1b459916039259383808625d1758a8bc4a4516d9 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 29 Apr 2009 11:42:27 -0700
Subject: Renamed the new_base tests
---
actionpack/test/controller/render_test.rb | 2 +
actionpack/test/new_base/base_test.rb | 43 +++++++-------
actionpack/test/new_base/render_template_test.rb | 76 ++++++++++++------------
actionpack/test/new_base/render_text_test.rb | 71 ++++++++++++----------
4 files changed, 98 insertions(+), 94 deletions(-)
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index a97e8ac5c1..648e179a15 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -106,6 +106,7 @@ class TestController < ActionController::Base
render :template => '/shared'
end
+ # :ported:
def render_hello_world_from_variable
@person = "david"
render :text => "hello #{@person}"
@@ -123,6 +124,7 @@ class TestController < ActionController::Base
render :action => :hello_world
end
+ # :ported:
def render_text_hello_world
render :text => "hello world"
end
diff --git a/actionpack/test/new_base/base_test.rb b/actionpack/test/new_base/base_test.rb
index b0e87b4f5b..95fdfd6b56 100644
--- a/actionpack/test/new_base/base_test.rb
+++ b/actionpack/test/new_base/base_test.rb
@@ -1,8 +1,8 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
# Tests the controller dispatching happy path
-module HappyPath
- class SimpleDispatchController < ActionController::Base2
+module Dispatching
+ class SimpleController < ActionController::Base2
def index
render :text => "success"
end
@@ -23,7 +23,7 @@ module HappyPath
class TestSimpleDispatch < SimpleRouteCase
- get "/happy_path/simple_dispatch/index"
+ get "/dispatching/simple/index"
test "sets the body" do
assert_body "success"
@@ -45,7 +45,7 @@ module HappyPath
# :api: plugin
class TestDirectResponseMod < SimpleRouteCase
- get "/happy_path/simple_dispatch/modify_response_body"
+ get "/dispatching/simple/modify_response_body"
test "sets the body" do
assert_body "success"
@@ -58,7 +58,7 @@ module HappyPath
# :api: plugin
class TestDirectResponseModTwice < SimpleRouteCase
- get "/happy_path/simple_dispatch/modify_response_body_twice"
+ get "/dispatching/simple/modify_response_body_twice"
test "self.response_body= returns the body being set" do
assert_body "success!"
@@ -68,23 +68,22 @@ module HappyPath
assert_header "Content-Length", "8"
end
end
-end
-
-
-class EmptyController < ActionController::Base2 ; end
-module Submodule
- class ContainedEmptyController < ActionController::Base2 ; end
-end
+
+ class EmptyController < ActionController::Base2 ; end
+ module Submodule
+ class ContainedEmptyController < ActionController::Base2 ; end
+ end
-class ControllerClassTests < Test::Unit::TestCase
- def test_controller_path
- assert_equal 'empty', EmptyController.controller_path
- assert_equal EmptyController.controller_path, EmptyController.new.controller_path
- assert_equal 'submodule/contained_empty', Submodule::ContainedEmptyController.controller_path
- assert_equal Submodule::ContainedEmptyController.controller_path, Submodule::ContainedEmptyController.new.controller_path
+ class ControllerClassTests < Test::Unit::TestCase
+ def test_controller_path
+ assert_equal 'dispatching/empty', EmptyController.controller_path
+ assert_equal EmptyController.controller_path, EmptyController.new.controller_path
+ assert_equal 'dispatching/submodule/contained_empty', Submodule::ContainedEmptyController.controller_path
+ assert_equal Submodule::ContainedEmptyController.controller_path, Submodule::ContainedEmptyController.new.controller_path
+ end
+ def test_controller_name
+ assert_equal 'empty', EmptyController.controller_name
+ assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name
+ end
end
- def test_controller_name
- assert_equal 'empty', EmptyController.controller_name
- assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name
- end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_template_test.rb b/actionpack/test/new_base/render_template_test.rb
index fd0519159e..bc52eb019f 100644
--- a/actionpack/test/new_base/render_template_test.rb
+++ b/actionpack/test/new_base/render_template_test.rb
@@ -1,31 +1,30 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
-module HappyPath
-
- class RenderTemplateWithoutLayoutController < ActionController::Base2
+module RenderTemplate
+ class WithoutLayoutController < ActionController::Base2
self.view_paths = [ActionView::Template::FixturePath.new(
"test/basic.html.erb" => "Hello from basic.html.erb",
"shared.html.erb" => "Elastica"
)]
- def render_hello_world
+ def index
render :template => "test/basic"
end
- def render_template_in_top_directory
+ def in_top_directory
render :template => 'shared'
end
- def render_template_in_top_directory_with_slash
+ def in_top_directory_with_slash
render :template => '/shared'
end
end
- class TestTemplateRenderWithoutLayout < SimpleRouteCase
+ class TestWithoutLayout < SimpleRouteCase
describe "rendering a normal template with full path without layout"
- get "/happy_path/render_template_without_layout/render_hello_world"
+ get "/render_template/without_layout"
assert_body "Hello from basic.html.erb"
assert_status 200
end
@@ -33,7 +32,7 @@ module HappyPath
class TestTemplateRenderInTopDirectory < SimpleRouteCase
describe "rendering a template not in a subdirectory"
- get "/happy_path/render_template_without_layout/render_template_in_top_directory"
+ get "/render_template/without_layout/in_top_directory"
assert_body "Elastica"
assert_status 200
end
@@ -41,12 +40,12 @@ module HappyPath
class TestTemplateRenderInTopDirectoryWithSlash < SimpleRouteCase
describe "rendering a template not in a subdirectory with a leading slash"
- get "/happy_path/render_template_without_layout/render_template_in_top_directory_with_slash"
+ get "/render_template/without_layout/in_top_directory_with_slash"
assert_body "Elastica"
assert_status 200
end
- class RenderTemplateWithLayoutController < ::ApplicationController
+ class WithLayoutController < ::ApplicationController
self.view_paths = [ActionView::Template::FixturePath.new(
"test/basic.html.erb" => "Hello from basic.html.erb",
@@ -55,23 +54,23 @@ module HappyPath
"layouts/greetings.html.erb" => "<%= yield %>, I wish thee well."
)]
- def render_hello_world
+ def index
render :template => "test/basic"
end
- def render_hello_world_with_layout
+ def with_layout
render :template => "test/basic", :layout => true
end
- def render_hello_world_with_layout_false
+ def with_layout_false
render :template => "test/basic", :layout => false
end
- def render_hello_world_with_layout_nil
+ def with_layout_nil
render :template => "test/basic", :layout => nil
end
- def render_hello_world_with_custom_layout
+ def with_custom_layout
render :template => "test/basic", :layout => "greetings"
end
end
@@ -79,7 +78,7 @@ module HappyPath
class TestTemplateRenderWithLayout < SimpleRouteCase
describe "rendering a normal template with full path with layout"
- get "/happy_path/render_template_with_layout/render_hello_world"
+ get "/render_template/with_layout"
assert_body "Hello from basic.html.erb, I'm here!"
assert_status 200
end
@@ -87,7 +86,7 @@ module HappyPath
class TestTemplateRenderWithLayoutTrue < SimpleRouteCase
describe "rendering a normal template with full path with layout => :true"
- get "/happy_path/render_template_with_layout/render_hello_world_with_layout"
+ get "/render_template/with_layout/with_layout"
assert_body "Hello from basic.html.erb, I'm here!"
assert_status 200
end
@@ -95,7 +94,7 @@ module HappyPath
class TestTemplateRenderWithLayoutFalse < SimpleRouteCase
describe "rendering a normal template with full path with layout => :false"
- get "/happy_path/render_template_with_layout/render_hello_world_with_layout_false"
+ get "/render_template/with_layout/with_layout_false"
assert_body "Hello from basic.html.erb"
assert_status 200
end
@@ -103,7 +102,7 @@ module HappyPath
class TestTemplateRenderWithLayoutNil < SimpleRouteCase
describe "rendering a normal template with full path with layout => :nil"
- get "/happy_path/render_template_with_layout/render_hello_world_with_layout_nil"
+ get "/render_template/with_layout/with_layout_nil"
assert_body "Hello from basic.html.erb"
assert_status 200
end
@@ -111,30 +110,29 @@ module HappyPath
class TestTemplateRenderWithCustomLayout < SimpleRouteCase
describe "rendering a normal template with full path with layout => 'greetings'"
- get "/happy_path/render_template_with_layout/render_hello_world_with_custom_layout"
+ get "/render_template/with_layout/with_custom_layout"
assert_body "Hello from basic.html.erb, I wish thee well."
assert_status 200
end
+
+ module Compatibility
+ class WithoutLayoutController < ActionController::CompatibleBase2
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "test/basic.html.erb" => "Hello from basic.html.erb",
+ "shared.html.erb" => "Elastica"
+ )]
-end
+ def with_forward_slash
+ render :template => "/test/basic"
+ end
+ end
-module Compatibility
- class RenderTemplateWithoutLayoutController < ActionController::CompatibleBase2
- self.view_paths = [ActionView::Template::FixturePath.new(
- "test/basic.html.erb" => "Hello from basic.html.erb",
- "shared.html.erb" => "Elastica"
- )]
-
- def render_hello_world_with_forward_slash
- render :template => "/test/basic"
+ class TestTemplateRenderWithForwardSlash < SimpleRouteCase
+ describe "rendering a normal template with full path starting with a leading slash"
+
+ get "/render_template/compatibility/without_layout/with_forward_slash"
+ assert_body "Hello from basic.html.erb"
+ assert_status 200
end
end
-
- class TestTemplateRenderWithForwardSlash < SimpleRouteCase
- describe "rendering a normal template with full path starting with a leading slash"
-
- get "/compatibility/render_template_without_layout/render_hello_world_with_forward_slash"
- assert_body "Hello from basic.html.erb"
- assert_status 200
- end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_text_test.rb b/actionpack/test/new_base/render_text_test.rb
index 3c11524d1d..d97c2ca0a6 100644
--- a/actionpack/test/new_base/render_text_test.rb
+++ b/actionpack/test/new_base/render_text_test.rb
@@ -3,75 +3,80 @@ require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
class ApplicationController < ActionController::Base2
end
-module HappyPath
-
- class RenderTextWithoutLayoutsController < ActionController::Base2
+module RenderText
+ class SimpleController < ActionController::Base2
self.view_paths = [ActionView::Template::FixturePath.new]
- def render_hello_world
+ def index
render :text => "hello david"
end
end
- class RenderTextWithLayoutsController < ::ApplicationController
+ class TestSimpleTextRenderWithNoLayout < SimpleRouteCase
+ describe "Rendering text from a action with default options renders the text with the layout"
+
+ get "/render_text/simple"
+ assert_body "hello david"
+ assert_status 200
+ end
+
+ class WithLayoutController < ::ApplicationController
self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/application.html.erb" => "<%= yield %>, I'm here!",
- "layouts/greetings.html.erb" => "<%= yield %>, I wish thee well."
+ "layouts/greetings.html.erb" => "<%= yield %>, I wish thee well.",
+ "layouts/ivar.html.erb" => "<%= yield %>, <%= @ivar %>"
)]
- def render_hello_world
+ def index
render :text => "hello david"
end
- def render_custom_code
+ def custom_code
render :text => "hello world", :status => 404
end
- def render_with_custom_code_as_string
+ def with_custom_code_as_string
render :text => "hello world", :status => "404 Not Found"
end
- def render_text_with_nil
+ def with_nil
render :text => nil
end
- def render_text_with_nil_and_status
+ def with_nil_and_status
render :text => nil, :status => 403
end
- def render_text_with_false
+ def with_false
render :text => false
end
- def render_text_with_layout
+ def with_layout_true
render :text => "hello world", :layout => true
end
- def render_text_with_layout_false
+ def with_layout_false
render :text => "hello world", :layout => false
end
- def render_text_with_layout_nil
+ def with_layout_nil
render :text => "hello world", :layout => nil
end
- def render_text_with_custom_layout
+ def with_custom_layout
render :text => "hello world", :layout => "greetings"
end
- end
-
- class TestSimpleTextRenderWithNoLayout < SimpleRouteCase
- describe "Rendering text from a action with default options renders the text with the layout"
- get "/happy_path/render_text_without_layouts/render_hello_world"
- assert_body "hello david"
- assert_status 200
+ def with_ivar_in_layout
+ @ivar = "hello world"
+ render :text => "hello world", :layout => "ivar"
+ end
end
-
+
class TestSimpleTextRenderWithLayout < SimpleRouteCase
describe "Rendering text from a action with default options renders the text without the layout"
- get "/happy_path/render_text_with_layouts/render_hello_world"
+ get "/render_text/with_layout"
assert_body "hello david"
assert_status 200
end
@@ -79,7 +84,7 @@ module HappyPath
class TestTextRenderWithStatus < SimpleRouteCase
describe "Rendering text, while also providing a custom status code"
- get "/happy_path/render_text_with_layouts/render_custom_code"
+ get "/render_text/with_layout/custom_code"
assert_body "hello world"
assert_status 404
end
@@ -87,7 +92,7 @@ module HappyPath
class TestTextRenderWithNil < SimpleRouteCase
describe "Rendering text with nil returns a single space character"
- get "/happy_path/render_text_with_layouts/render_text_with_nil"
+ get "/render_text/with_layout/with_nil"
assert_body " "
assert_status 200
end
@@ -95,7 +100,7 @@ module HappyPath
class TestTextRenderWithNilAndStatus < SimpleRouteCase
describe "Rendering text with nil and custom status code returns a single space character with the status"
- get "/happy_path/render_text_with_layouts/render_text_with_nil_and_status"
+ get "/render_text/with_layout/with_nil_and_status"
assert_body " "
assert_status 403
end
@@ -103,7 +108,7 @@ module HappyPath
class TestTextRenderWithFalse < SimpleRouteCase
describe "Rendering text with false returns the string 'false'"
- get "/happy_path/render_text_with_layouts/render_text_with_false"
+ get "/render_text/with_layout/with_false"
assert_body "false"
assert_status 200
end
@@ -111,7 +116,7 @@ module HappyPath
class TestTextRenderWithLayoutTrue < SimpleRouteCase
describe "Rendering text with :layout => true"
- get "/happy_path/render_text_with_layouts/render_text_with_layout"
+ get "/render_text/with_layout/with_layout_true"
assert_body "hello world, I'm here!"
assert_status 200
end
@@ -119,7 +124,7 @@ module HappyPath
class TestTextRenderWithCustomLayout < SimpleRouteCase
describe "Rendering text with :layout => 'greetings'"
- get "/happy_path/render_text_with_layouts/render_text_with_custom_layout"
+ get "/render_text/with_layout/with_custom_layout"
assert_body "hello world, I wish thee well."
assert_status 200
end
@@ -127,7 +132,7 @@ module HappyPath
class TestTextRenderWithLayoutFalse < SimpleRouteCase
describe "Rendering text with :layout => false"
- get "/happy_path/render_text_with_layouts/render_text_with_layout_false"
+ get "/render_text/with_layout/with_layout_false"
assert_body "hello world"
assert_status 200
end
@@ -135,7 +140,7 @@ module HappyPath
class TestTextRenderWithLayoutNil < SimpleRouteCase
describe "Rendering text with :layout => nil"
- get "/happy_path/render_text_with_layouts/render_text_with_layout_nil"
+ get "/render_text/with_layout/with_layout_nil"
assert_body "hello world"
assert_status 200
end
--
cgit v1.2.3
From 4f68311685831b940936130203c240fa23525c84 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 29 Apr 2009 12:19:17 -0700
Subject: Finished implementing render :text in Base2
---
.../lib/action_controller/abstract/renderer.rb | 13 +++++++++++++
actionpack/lib/action_controller/new_base/base.rb | 8 ++------
.../lib/action_controller/new_base/renderer.rb | 2 +-
actionpack/test/controller/render_test.rb | 17 +++++++++++++++++
actionpack/test/new_base/base_test.rb | 2 +-
actionpack/test/new_base/render_test.rb | 20 ++++++++++++++++++++
6 files changed, 54 insertions(+), 8 deletions(-)
create mode 100644 actionpack/test/new_base/render_test.rb
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index 37da2398ec..c1f420f7b4 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -1,6 +1,15 @@
require "action_controller/abstract/logger"
module AbstractController
+ class AbstractControllerError < StandardError; end
+ class DoubleRenderError < AbstractControllerError
+ DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"."
+
+ def initialize(message = nil)
+ super(message || DEFAULT_MESSAGE)
+ end
+ end
+
module Renderer
depends_on AbstractController::Logger
@@ -17,6 +26,10 @@ module AbstractController
end
def render(options = {})
+ unless response_body.nil?
+ raise AbstractController::DoubleRenderError, "OMG"
+ end
+
self.response_body = render_to_body(options)
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 6711cd932a..9f7a148b3c 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -40,23 +40,19 @@ module ActionController
controller.call(env).to_rack
end
- # :api: plugin
- def response_body=(body)
- @_response.body = body
- end
-
# :api: private
def call(env)
@_request = ActionDispatch::Request.new(env)
@_response = ActionDispatch::Response.new
process(@_request.parameters[:action])
+ @_response.body = response_body
@_response.prepare!
self
end
# :api: private
def to_rack
- response.to_a
+ @_response.to_a
end
end
end
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index ed34c46aed..9a965c18e8 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -17,7 +17,7 @@ module ActionController
_process_options(options)
- self.response_body = render_to_body(options)
+ super(options)
end
def render_to_body(options)
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 648e179a15..9149212a2d 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -129,6 +129,7 @@ class TestController < ActionController::Base
render :text => "hello world"
end
+ # :ported:
def render_text_hello_world_with_layout
@variable_for_layout = ", I'm here!"
render :text => "hello world", :layout => true
@@ -220,6 +221,7 @@ class TestController < ActionController::Base
render :json => {:hello => render_to_string(:partial => 'partial')}
end
+ # :ported:
def render_custom_code
render :text => "hello world", :status => 404
end
@@ -230,14 +232,17 @@ class TestController < ActionController::Base
end
end
+ # :ported:
def render_text_with_nil
render :text => nil
end
+ # :ported:
def render_text_with_false
render :text => false
end
+ # :ported:
def render_nothing_with_appendix
render :text => "appended"
end
@@ -272,6 +277,7 @@ class TestController < ActionController::Base
# let's just rely on the template
end
+ # :ported:
def blank_response
render :text => ' '
end
@@ -405,6 +411,7 @@ class TestController < ActionController::Base
render :template => "test/render_file_with_locals", :locals => { :secret => 'area51' }
end
+ # :ported:
def double_render
render :text => "hello"
render :text => "world"
@@ -508,6 +515,7 @@ class TestController < ActionController::Base
# Action template sets variable that's picked up by layout
end
+ # :addressed:
def render_text_with_assigns
@hello = "world"
render :text => "foo"
@@ -807,6 +815,7 @@ class RenderTest < ActionController::TestCase
assert_equal "Elastica", @response.body
end
+ # :ported:
def test_render_from_variable
get :render_hello_world_from_variable
assert_equal "hello david", @response.body
@@ -828,16 +837,19 @@ class RenderTest < ActionController::TestCase
assert_template "test/hello_world"
end
+ # :ported:
def test_render_text
get :render_text_hello_world
assert_equal "hello world", @response.body
end
+ # :ported:
def test_do_with_render_text_and_layout
get :render_text_hello_world_with_layout
assert_equal "hello world, I'm here!", @response.body
end
+ # :ported:
def test_do_with_render_action_and_layout_false
get :hello_world_with_layout_false
assert_equal 'Hello world!', @response.body
@@ -932,17 +944,20 @@ class RenderTest < ActionController::TestCase
assert_equal %(Element.replace("foo", "partial html");), @response.body
end
+ # :ported:
def test_render_text_with_nil
get :render_text_with_nil
assert_response 200
assert_equal ' ', @response.body
end
+ # :ported:
def test_render_text_with_false
get :render_text_with_false
assert_equal 'false', @response.body
end
+ # :ported:
def test_render_nothing_with_appendix
get :render_nothing_with_appendix
assert_response 200
@@ -1209,6 +1224,7 @@ class RenderTest < ActionController::TestCase
assert_equal "Hello world!", @response.body
end
+ # :ported:
def test_double_render
assert_raise(ActionController::DoubleRenderError) { get :double_render }
end
@@ -1237,6 +1253,7 @@ class RenderTest < ActionController::TestCase
assert_equal "Talking to the layout \nAction was here!", @response.body
end
+ # :addressed:
def test_render_text_with_assigns
get :render_text_with_assigns
assert_equal "world", assigns["hello"]
diff --git a/actionpack/test/new_base/base_test.rb b/actionpack/test/new_base/base_test.rb
index 95fdfd6b56..27d1a7f026 100644
--- a/actionpack/test/new_base/base_test.rb
+++ b/actionpack/test/new_base/base_test.rb
@@ -84,6 +84,6 @@ module Dispatching
def test_controller_name
assert_equal 'empty', EmptyController.controller_name
assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name
- end
+ end
end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb
new file mode 100644
index 0000000000..9ad79124b8
--- /dev/null
+++ b/actionpack/test/new_base/render_test.rb
@@ -0,0 +1,20 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
+
+module Render
+ class DoubleRenderController < ActionController::Base2
+ def index
+ render :text => "hello"
+ render :text => "world"
+ end
+ end
+
+ class TestBasic < SimpleRouteCase
+ describe "Rendering more than once"
+
+ test "raises an exception" do
+ assert_raises(AbstractController::DoubleRenderError) do
+ get "/render/double_render"
+ end
+ end
+ end
+end
\ No newline at end of file
--
cgit v1.2.3
From 0c3d9bc4c2b329cb754bfed1e465f99d058e1193 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 29 Apr 2009 16:33:24 -0700
Subject: Ported over render :template tests
---
actionpack/lib/action_controller/abstract/layouts.rb | 3 +--
actionpack/lib/action_controller/abstract/renderer.rb | 1 -
actionpack/lib/action_controller/new_base/renderer.rb | 4 ----
actionpack/test/controller/render_test.rb | 19 +++++++++++++++++++
actionpack/test/new_base/render_template_test.rb | 15 ++++++++++++++-
actionpack/test/new_base/test_helper.rb | 5 +++++
6 files changed, 39 insertions(+), 8 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 315d6151e9..f56b9dd914 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -50,8 +50,7 @@ module AbstractController
end
def _render_template(template, options)
- # layout = options[:_layout].is_a?(ActionView::Template) ? options[:_layout] : _layout_for_name(options[:_layout])
- _action_view._render_template_with_layout(template, options[:_layout])
+ _action_view._render_template_with_layout(template, options[:_layout], options)
end
private
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index c1f420f7b4..e9a7ab4004 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -40,7 +40,6 @@ module AbstractController
#
# :api: plugin
def render_to_body(options = {})
- options = {:_template_name => options} if options.is_a?(String)
name = options[:_template_name] || action_name
template = options[:_template] || view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix])
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 9a965c18e8..df07edbd90 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -21,10 +21,6 @@ module ActionController
end
def render_to_body(options)
- unless options.is_a?(Hash)
- options = {:action => options}
- end
-
if options.key?(:text)
options[:_template] = ActionView::TextTemplate.new(_text(options))
template = nil
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 9149212a2d..d4a18a673c 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -80,6 +80,7 @@ class TestController < ActionController::Base
fresh_when(:last_modified => Time.now.utc.beginning_of_day, :etag => [ :foo, 123 ])
end
+ # :ported:
def render_hello_world
render :template => "test/hello_world"
end
@@ -94,14 +95,17 @@ class TestController < ActionController::Base
render :template => "test/hello_world"
end
+ # :ported: compatibility
def render_hello_world_with_forward_slash
render :template => "/test/hello_world"
end
+ # :ported:
def render_template_in_top_directory
render :template => 'shared'
end
+ # :deprecated:
def render_template_in_top_directory_with_slash
render :template => '/shared'
end
@@ -251,6 +255,10 @@ class TestController < ActionController::Base
render :js => "alert('hello')"
end
+ # This test is testing 3 things:
+ # render :file in AV :ported:
+ # render :template in AC :ported:
+ # setting content type
def render_xml_hello
@name = "David"
render :template => "test/hello"
@@ -399,6 +407,7 @@ class TestController < ActionController::Base
render :layout => true, :inline => "Hello: <%= params[:name] %>"
end
+ # :ported:
def render_with_explicit_template
render :template => "test/hello_world"
end
@@ -407,6 +416,7 @@ class TestController < ActionController::Base
render "test/hello_world"
end
+ # :ported:
def render_with_explicit_template_with_locals
render :template => "test/render_file_with_locals", :locals => { :secret => 'area51' }
end
@@ -443,10 +453,15 @@ class TestController < ActionController::Base
render :action => "potential_conflicts"
end
+ # :deprecated:
+ # Tests being able to pick a .builder template over a .erb
+ # For instance, being able to have hello.xml.builder and hello.xml.erb
+ # and select one via "hello.builder" or "hello.erb"
def hello_world_from_rxml_using_action
render :action => "hello_world_from_rxml.builder"
end
+ # :deprecated:
def hello_world_from_rxml_using_template
render :template => "test/hello_world_from_rxml.builder"
end
@@ -798,17 +813,20 @@ class RenderTest < ActionController::TestCase
end
end
+ # :ported: compatibility
def test_render_with_forward_slash
get :render_hello_world_with_forward_slash
assert_template "test/hello_world"
end
+ # :ported:
def test_render_in_top_directory
get :render_template_in_top_directory
assert_template "shared"
assert_equal "Elastica", @response.body
end
+ # :ported:
def test_render_in_top_directory_with_slash
get :render_template_in_top_directory_with_slash
assert_template "shared"
@@ -1259,6 +1277,7 @@ class RenderTest < ActionController::TestCase
assert_equal "world", assigns["hello"]
end
+ # :ported:
def test_template_with_locals
get :render_with_explicit_template_with_locals
assert_equal "The secret is area51\n", @response.body
diff --git a/actionpack/test/new_base/render_template_test.rb b/actionpack/test/new_base/render_template_test.rb
index bc52eb019f..63769df082 100644
--- a/actionpack/test/new_base/render_template_test.rb
+++ b/actionpack/test/new_base/render_template_test.rb
@@ -5,7 +5,8 @@ module RenderTemplate
self.view_paths = [ActionView::Template::FixturePath.new(
"test/basic.html.erb" => "Hello from basic.html.erb",
- "shared.html.erb" => "Elastica"
+ "shared.html.erb" => "Elastica",
+ "locals.html.erb" => "The secret is <%= secret %>"
)]
def index
@@ -19,6 +20,10 @@ module RenderTemplate
def in_top_directory_with_slash
render :template => '/shared'
end
+
+ def with_locals
+ render :template => "locals", :locals => { :secret => 'area51' }
+ end
end
class TestWithoutLayout < SimpleRouteCase
@@ -44,6 +49,14 @@ module RenderTemplate
assert_body "Elastica"
assert_status 200
end
+
+ class TestTemplateRenderWithLocals < SimpleRouteCase
+ describe "rendering a template with local variables"
+
+ get "/render_template/without_layout/with_locals"
+ assert_body "The secret is area51"
+ assert_status 200
+ end
class WithLayoutController < ::ApplicationController
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index cc79d6faf7..b40cbb163f 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -58,6 +58,11 @@ module ActionController
end
end
+ def render_to_body(options = {})
+ options = {:template => options} if options.is_a?(String)
+ super
+ end
+
# append_view_path File.join(File.dirname(__FILE__), '..', 'fixtures')
CORE_METHODS = self.public_instance_methods
--
cgit v1.2.3
From 49834e088bf8d02a4f75793a42868f2aea8749a4 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 29 Apr 2009 17:32:39 -0700
Subject: Support implicit render and blank render
---
actionpack/lib/action_controller/abstract/base.rb | 13 ++++++++-
.../lib/action_controller/abstract/renderer.rb | 4 +--
.../lib/action_controller/new_base/renderer.rb | 9 +-----
.../test/new_base/render_implicit_action_test.rb | 32 +++++++++++-----------
actionpack/test/new_base/render_test.rb | 18 ++++++++++++
actionpack/test/new_base/test_helper.rb | 20 ++++++++++++++
6 files changed, 69 insertions(+), 27 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index ade7719cc0..a87a490a2d 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -29,10 +29,21 @@ module AbstractController
private
+ # It is possible for respond_to?(action_name) to be false and
+ # respond_to?(:action_missing) to be false if respond_to_action?
+ # is overridden in a subclass. For instance, ActionController::Base
+ # overrides it to include the case where a template matching the
+ # action_name is found.
def process_action
- respond_to?(action_name) ? send(action_name) : send(:action_missing, action_name)
+ if respond_to?(action_name) then send(action_name)
+ elsif respond_to?(:action_missing, true) then send(:action_missing, action_name)
+ end
end
+ # Override this to change the conditions that will raise an
+ # ActionNotFound error. If you accept a difference case,
+ # you must handle it by also overriding process_action and
+ # handling the case.
def respond_to_action?(action_name)
respond_to?(action_name) || respond_to?(:action_missing, true)
end
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index e9a7ab4004..716b213c75 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -42,9 +42,9 @@ module AbstractController
def render_to_body(options = {})
name = options[:_template_name] || action_name
- template = options[:_template] || view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix])
+ options[:_template] ||= view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix])
- _render_template(template, options)
+ _render_template(options[:_template], options)
end
# Raw rendering of a template to a string.
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index df07edbd90..096a63e406 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -7,14 +7,7 @@ module ActionController
super
end
- def render(action, options = {})
- # TODO: Move this into #render_to_body
- if action.is_a?(Hash)
- options, action = action, nil
- else
- options.merge! :action => action
- end
-
+ def render(options = {})
_process_options(options)
super(options)
diff --git a/actionpack/test/new_base/render_implicit_action_test.rb b/actionpack/test/new_base/render_implicit_action_test.rb
index 3afa444e3e..58f5cec181 100644
--- a/actionpack/test/new_base/render_implicit_action_test.rb
+++ b/actionpack/test/new_base/render_implicit_action_test.rb
@@ -4,25 +4,25 @@ module RenderImplicitAction
class SimpleController < ::ApplicationController
self.view_paths = [ActionView::Template::FixturePath.new(
"render_implicit_action/simple/hello_world.html.erb" => "Hello world!",
- "render_implicit_action/simple/hyphen-ated.html.erb" => "Hello hyphen-ated"
+ "render_implicit_action/simple/hyphen-ated.html.erb" => "Hello hyphen-ated!"
)]
def hello_world() end
end
- # class TestImplicitRender < SimpleRouteCase
- # describe "render a simple action with new explicit call to render"
- #
- # get "/render_implicit_action/simple/hello_world"
- # assert_body "Hello world!"
- # assert_status 200
- # end
- #
- # class TestImplicitWithSpecialCharactersRender < SimpleRouteCase
- # describe "render an action with a missing method and has special characters"
- #
- # get "/render_implicit_action/simple/hyphen-ated"
- # assert_body "Hello hyphen-ated!"
- # assert_status 200
- # end
+ class TestImplicitRender < SimpleRouteCase
+ describe "render a simple action with new explicit call to render"
+
+ get "/render_implicit_action/simple/hello_world"
+ assert_body "Hello world!"
+ assert_status 200
+ end
+
+ class TestImplicitWithSpecialCharactersRender < SimpleRouteCase
+ describe "render an action with a missing method and has special characters"
+
+ get "/render_implicit_action/simple/hyphen-ated"
+ assert_body "Hello hyphen-ated!"
+ assert_status 200
+ end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb
index 9ad79124b8..93bc8d854c 100644
--- a/actionpack/test/new_base/render_test.rb
+++ b/actionpack/test/new_base/render_test.rb
@@ -1,6 +1,24 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
module Render
+ class BlankRenderController < ActionController::Base2
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "render/blank_render/index.html.erb" => "Hello world!"
+ )]
+
+ def index
+ render
+ end
+ end
+
+ class TestBlankRender < SimpleRouteCase
+ describe "Render with blank"
+
+ get "/render/blank_render"
+ assert_body "Hello world!"
+ assert_status 200
+ end
+
class DoubleRenderController < ActionController::Base2
def index
render :text => "hello"
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index b40cbb163f..03af5a66a6 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -58,11 +58,31 @@ module ActionController
end
end
+ def render(action = action_name, options = {})
+ if action.is_a?(Hash)
+ options, action = action, nil
+ else
+ options.merge! :action => action
+ end
+
+ super(options)
+ end
+
def render_to_body(options = {})
options = {:template => options} if options.is_a?(String)
super
end
+ def process_action
+ ret = super
+ render if response_body.nil?
+ ret
+ end
+
+ def respond_to_action?(action_name)
+ super || view_paths.find_by_parts(action_name, {:formats => formats, :locales => [I18n.locale]}, controller_path)
+ end
+
# append_view_path File.join(File.dirname(__FILE__), '..', 'fixtures')
CORE_METHODS = self.public_instance_methods
--
cgit v1.2.3
From b98e496c039b7bde4a2de9c02809e0b4ee0679ae Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 29 Apr 2009 17:32:55 -0700
Subject: Support implicit and explicit content types
---
actionpack/lib/action_controller/new_base.rb | 1 +
.../lib/action_controller/new_base/content_type.rb | 15 +++
actionpack/lib/action_view/template/text.rb | 3 +-
actionpack/test/controller/content_type_test.rb | 10 ++
actionpack/test/new_base/content_type_test.rb | 111 +++++++++++++++++++++
actionpack/test/new_base/test_helper.rb | 1 +
6 files changed, 139 insertions(+), 2 deletions(-)
create mode 100644 actionpack/lib/action_controller/new_base/content_type.rb
create mode 100644 actionpack/test/new_base/content_type_test.rb
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index bfd8120e10..9c8a6d0216 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -1,4 +1,5 @@
module ActionController
+ autoload :ContentType, "action_controller/new_base/content_type"
autoload :HideActions, "action_controller/new_base/hide_actions"
autoload :Http, "action_controller/new_base/base"
autoload :Layouts, "action_controller/new_base/layouts"
diff --git a/actionpack/lib/action_controller/new_base/content_type.rb b/actionpack/lib/action_controller/new_base/content_type.rb
new file mode 100644
index 0000000000..d2206a31af
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/content_type.rb
@@ -0,0 +1,15 @@
+module ActionController
+ module ContentType
+
+ def render_to_body(options = {})
+ if content_type = options[:content_type]
+ response.content_type = content_type
+ end
+
+ ret = super
+ response.content_type ||= options[:_template].mime_type
+ ret
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb
index f81174d707..446c735ba3 100644
--- a/actionpack/lib/action_view/template/text.rb
+++ b/actionpack/lib/action_view/template/text.rb
@@ -3,7 +3,6 @@ module ActionView #:nodoc:
def render(*) self end
- def exempt_from_layout?() false end
-
+ def mime_type() Mime::HTML end
end
end
diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb
index 7377546631..64b8b10d5b 100644
--- a/actionpack/test/controller/content_type_test.rb
+++ b/actionpack/test/controller/content_type_test.rb
@@ -1,24 +1,29 @@
require 'abstract_unit'
class ContentTypeController < ActionController::Base
+ # :ported:
def render_content_type_from_body
response.content_type = Mime::RSS
render :text => "hello world!"
end
+ # :ported:
def render_defaults
render :text => "hello world!"
end
+ # :ported:
def render_content_type_from_render
render :text => "hello world!", :content_type => Mime::RSS
end
+ # :ported:
def render_charset_from_body
response.charset = "utf-16"
render :text => "hello world!"
end
+ # :ported:
def render_nil_charset_from_body
response.charset = nil
render :text => "hello world!"
@@ -60,6 +65,7 @@ class ContentTypeTest < ActionController::TestCase
@controller.logger = Logger.new(nil)
end
+ # :ported:
def test_render_defaults
get :render_defaults
assert_equal "utf-8", @response.charset
@@ -74,24 +80,28 @@ class ContentTypeTest < ActionController::TestCase
ContentTypeController.default_charset = "utf-8"
end
+ # :ported:
def test_content_type_from_body
get :render_content_type_from_body
assert_equal "application/rss+xml", @response.content_type
assert_equal "utf-8", @response.charset
end
+ # :ported:
def test_content_type_from_render
get :render_content_type_from_render
assert_equal "application/rss+xml", @response.content_type
assert_equal "utf-8", @response.charset
end
+ # :ported:
def test_charset_from_body
get :render_charset_from_body
assert_equal Mime::HTML, @response.content_type
assert_equal "utf-16", @response.charset
end
+ # :ported:
def test_nil_charset_from_body
get :render_nil_charset_from_body
assert_equal Mime::HTML, @response.content_type
diff --git a/actionpack/test/new_base/content_type_test.rb b/actionpack/test/new_base/content_type_test.rb
new file mode 100644
index 0000000000..10a28da496
--- /dev/null
+++ b/actionpack/test/new_base/content_type_test.rb
@@ -0,0 +1,111 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
+
+module ContentType
+ class BaseController < ActionController::Base2
+ def index
+ render :text => "Hello world!"
+ end
+
+ def set_on_response_obj
+ response.content_type = Mime::RSS
+ render :text => "Hello world!"
+ end
+
+ def set_on_render
+ render :text => "Hello world!", :content_type => Mime::RSS
+ end
+ end
+
+ class TestDefault < SimpleRouteCase
+ describe "a default response is HTML and UTF8"
+
+ get "/content_type/base"
+ assert_body "Hello world!"
+ assert_header "Content-Type", "text/html; charset=utf-8"
+ end
+
+ class TestSetOnResponseObj < SimpleRouteCase
+ describe "setting the content type of the response directly on the response object"
+
+ get "/content_type/base/set_on_response_obj"
+ assert_body "Hello world!"
+ assert_header "Content-Type", "application/rss+xml; charset=utf-8"
+ end
+
+ class TestSetOnRender < SimpleRouteCase
+ describe "setting the content type of the response as an option to render"
+
+ get "/content_type/base/set_on_render"
+ assert_body "Hello world!"
+ assert_header "Content-Type", "application/rss+xml; charset=utf-8"
+ end
+
+ class ImpliedController < ActionController::Base2
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "content_type/implied/i_am_html_erb.html.erb" => "Hello world!",
+ "content_type/implied/i_am_xml_erb.xml.erb" => "Hello world! ",
+ "content_type/implied/i_am_html_builder.html.builder" => "xml.p 'Hello'",
+ "content_type/implied/i_am_xml_builder.xml.builder" => "xml.awesome 'Hello'"
+ )]
+
+ def i_am_html_erb() end
+ def i_am_xml_erb() end
+ def i_am_html_builder() end
+ def i_am_xml_builder() end
+ end
+
+ class TestImpliedController < SimpleRouteCase
+ describe "the template's mime type is used if no content_type is specified"
+
+ test "sets Content-Type as text/html when rendering *.html.erb" do
+ get "/content_type/implied/i_am_html_erb"
+ assert_header "Content-Type", "text/html; charset=utf-8"
+ end
+
+ test "sets Content-Type as application/xml when rendering *.xml.erb" do
+ get "/content_type/implied/i_am_xml_erb"
+ assert_header "Content-Type", "application/xml; charset=utf-8"
+ end
+
+ test "sets Content-Type as text/html when rendering *.html.builder" do
+ get "/content_type/implied/i_am_html_builder"
+ assert_header "Content-Type", "text/html; charset=utf-8"
+ end
+
+ test "sets Content-Type as application/xml when rendering *.xml.builder" do
+ get "/content_type/implied/i_am_xml_builder"
+ assert_header "Content-Type", "application/xml; charset=utf-8"
+ end
+
+ end
+end
+
+module Charset
+ class BaseController < ActionController::Base2
+ def set_on_response_obj
+ response.charset = "utf-16"
+ render :text => "Hello world!"
+ end
+
+ def set_as_nil_on_response_obj
+ response.charset = nil
+ render :text => "Hello world!"
+ end
+ end
+
+ class TestSetOnResponseObj < SimpleRouteCase
+ describe "setting the charset of the response directly on the response object"
+
+ get "/charset/base/set_on_response_obj"
+ assert_body "Hello world!"
+ assert_header "Content-Type", "text/html; charset=utf-16"
+ end
+
+ class TestSetAsNilOnResponseObj < SimpleRouteCase
+ describe "setting the charset of the response as nil directly on the response object"
+
+ get "/charset/base/set_as_nil_on_response_obj"
+ assert_body "Hello world!"
+ assert_header "Content-Type", "text/html; charset=utf-8"
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index 03af5a66a6..d41c7283b7 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -42,6 +42,7 @@ module ActionController
use ActionController::UrlFor
use ActionController::Renderer
use ActionController::Layouts
+ use ActionController::ContentType
def self.inherited(klass)
::ActionController::Base2.subclasses << klass.to_s
--
cgit v1.2.3
From d58b57a3caf4ad434c2be4f63eecd9a1921c7c4a Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 29 Apr 2009 17:50:11 -0700
Subject: Move ContentType inline for now.
Trying to avoid premature proliferation of modules.
---
actionpack/lib/action_controller/new_base.rb | 1 -
actionpack/lib/action_controller/new_base/content_type.rb | 15 ---------------
actionpack/lib/action_controller/new_base/renderer.rb | 10 ++++++----
actionpack/test/new_base/test_helper.rb | 1 -
4 files changed, 6 insertions(+), 21 deletions(-)
delete mode 100644 actionpack/lib/action_controller/new_base/content_type.rb
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 9c8a6d0216..bfd8120e10 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -1,5 +1,4 @@
module ActionController
- autoload :ContentType, "action_controller/new_base/content_type"
autoload :HideActions, "action_controller/new_base/hide_actions"
autoload :Http, "action_controller/new_base/base"
autoload :Layouts, "action_controller/new_base/layouts"
diff --git a/actionpack/lib/action_controller/new_base/content_type.rb b/actionpack/lib/action_controller/new_base/content_type.rb
deleted file mode 100644
index d2206a31af..0000000000
--- a/actionpack/lib/action_controller/new_base/content_type.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-module ActionController
- module ContentType
-
- def render_to_body(options = {})
- if content_type = options[:content_type]
- response.content_type = content_type
- end
-
- ret = super
- response.content_type ||= options[:_template].mime_type
- ret
- end
-
- end
-end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 096a63e406..f21fd746b7 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -24,7 +24,9 @@ module ActionController
options[:_prefix] = _prefix
end
- super(options)
+ ret = super(options)
+ response.content_type ||= options[:_template].mime_type
+ ret
end
private
@@ -43,9 +45,9 @@ module ActionController
end
def _process_options(options)
- if status = options[:status]
- response.status = status.to_i
- end
+ status, content_type = options.values_at(:status, :content_type)
+ response.status = status.to_i if status
+ response.content_type = content_type if content_type
end
end
end
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index d41c7283b7..03af5a66a6 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -42,7 +42,6 @@ module ActionController
use ActionController::UrlFor
use ActionController::Renderer
use ActionController::Layouts
- use ActionController::ContentType
def self.inherited(klass)
::ActionController::Base2.subclasses << klass.to_s
--
cgit v1.2.3
From 4ee3e5b094463383891789f484e927b19fccc744 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Thu, 30 Apr 2009 15:13:40 -0700
Subject: Ported over the concept of public instance methods on controller
child classes as callable action methods
---
actionpack/lib/action_controller/abstract/base.rb | 48 +++++++++++++++++++----
actionpack/lib/action_controller/new_base/base.rb | 14 +++----
actionpack/test/controller/render_test.rb | 7 ++++
actionpack/test/new_base/render_test.rb | 10 +++++
actionpack/test/new_base/test_helper.rb | 10 ++---
5 files changed, 69 insertions(+), 20 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index a87a490a2d..3b85ba5565 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -4,13 +4,44 @@ module AbstractController
attr_internal :response_body
attr_internal :response_obj
attr_internal :action_name
-
- def self.process(action)
- new.process(action)
+
+ class << self
+ attr_reader :abstract
+
+ def abstract!
+ @abstract = true
+ end
+
+ alias_method :abstract?, :abstract
+
+ def internal_methods
+ controller = self
+ controller = controller.superclass until controller.abstract?
+ controller.public_instance_methods(true)
+ end
+
+ def process(action)
+ new.process(action)
+ end
+
+ def hidden_actions
+ []
+ end
+
+ def action_methods
+ @action_methods ||=
+ # All public instance methods of this class, including ancestors
+ public_instance_methods(true).map { |m| m.to_sym }.to_set -
+ # Except for public instance methods of Base and its ancestors
+ internal_methods.map { |m| m.to_sym } +
+ # Be sure to include shadowed public instance methods of this class
+ public_instance_methods(false).map { |m| m.to_sym } -
+ # And always exclude explicitly hidden actions
+ hidden_actions
+ end
end
- def self.inherited(klass)
- end
+ abstract!
def initialize
self.response_obj = {}
@@ -29,6 +60,10 @@ module AbstractController
private
+ def action_methods
+ self.class.action_methods
+ end
+
# It is possible for respond_to?(action_name) to be false and
# respond_to?(:action_missing) to be false if respond_to_action?
# is overridden in a subclass. For instance, ActionController::Base
@@ -45,8 +80,7 @@ module AbstractController
# you must handle it by also overriding process_action and
# handling the case.
def respond_to_action?(action_name)
- respond_to?(action_name) || respond_to?(:action_missing, true)
+ action_methods.include?(action_name) || respond_to?(:action_missing, true)
end
-
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 9f7a148b3c..00d161289e 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -1,5 +1,6 @@
module ActionController
class Http < AbstractController::Base
+ abstract!
# :api: public
attr_internal :request, :response, :params
@@ -19,18 +20,15 @@ module ActionController
# :api: public
def controller_path() self.class.controller_path end
-
- # :api: private
- def self.action_methods
- @action_names ||= Set.new(self.public_instance_methods - self::CORE_METHODS)
+
+ # :api: private
+ def self.internal_methods
+ ActionController::Http.public_instance_methods(true)
end
# :api: private
def self.action_names() action_methods end
- # :api: private
- def action_methods() self.class.action_names end
-
# :api: private
def action_names() action_methods end
@@ -44,7 +42,7 @@ module ActionController
def call(env)
@_request = ActionDispatch::Request.new(env)
@_response = ActionDispatch::Response.new
- process(@_request.parameters[:action])
+ process(@_request.parameters[:action].to_sym)
@_response.body = response_body
@_response.prepare!
self
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index d4a18a673c..e6b2ee7e9f 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -4,6 +4,7 @@ require 'pathname'
module Fun
class GamesController < ActionController::Base
+ # :ported:
def hello_world
end
end
@@ -116,6 +117,7 @@ class TestController < ActionController::Base
render :text => "hello #{@person}"
end
+ # :ported:
def render_action_hello_world
render :action => "hello_world"
end
@@ -839,17 +841,20 @@ class RenderTest < ActionController::TestCase
assert_equal "hello david", @response.body
end
+ # :ported:
def test_render_action
get :render_action_hello_world
assert_template "test/hello_world"
end
+ # :ported:
def test_render_action_hello_world_as_string
get :render_action_hello_world_as_string
assert_equal "Hello world!", @response.body
assert_template "test/hello_world"
end
+ # :ported:
def test_render_action_with_symbol
get :render_action_hello_world_with_symbol
assert_template "test/hello_world"
@@ -949,6 +954,7 @@ class RenderTest < ActionController::TestCase
assert_equal 'application/json', @response.content_type
end
+ # :ported:
def test_render_custom_code
get :render_custom_code
assert_response 404
@@ -1082,6 +1088,7 @@ class RenderTest < ActionController::TestCase
assert_template "test/hello_world"
end
+ # :ported:
def test_nested_rendering
@controller = Fun::GamesController.new
get :hello_world
diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb
index 93bc8d854c..bc7203f294 100644
--- a/actionpack/test/new_base/render_test.rb
+++ b/actionpack/test/new_base/render_test.rb
@@ -35,4 +35,14 @@ module Render
end
end
end
+
+ class TestRenderObjectMethod < SimpleRouteCase
+ describe "Methods on Object are not actions"
+
+ test "raises an exception" do
+ assert_raises(AbstractController::ActionNotFound) do
+ get "/render/blank_render/clone"
+ end
+ end
+ end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index 03af5a66a6..d58b83cf7b 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -34,6 +34,8 @@ end
module ActionController
class Base2 < Http
+ abstract!
+
use AbstractController::Callbacks
use AbstractController::Helpers
use AbstractController::Logger
@@ -80,15 +82,13 @@ module ActionController
end
def respond_to_action?(action_name)
- super || view_paths.find_by_parts(action_name, {:formats => formats, :locales => [I18n.locale]}, controller_path)
+ super || view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
end
-
- # append_view_path File.join(File.dirname(__FILE__), '..', 'fixtures')
-
- CORE_METHODS = self.public_instance_methods
end
class CompatibleBase2 < Base2
+ abstract!
+
use ActionController::Rails2Compatibility
end
end
--
cgit v1.2.3
From 69fd66916566f402620cc385689c36f61deb6ba1 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 1 May 2009 11:40:32 -0700
Subject: Committing the last changes before we start trying to get the old
tests to pass on the new base
---
actionpack/test/controller/render_test.rb | 11 +++++-
actionpack/test/new_base/render_layout_test.rb | 18 ++++++++--
actionpack/test/new_base/render_test.rb | 48 +++++++++++++++++++++++---
3 files changed, 70 insertions(+), 7 deletions(-)
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index e6b2ee7e9f..fb9b121fc9 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -292,6 +292,7 @@ class TestController < ActionController::Base
render :text => ' '
end
+ # :ported:
def layout_test
render :action => "hello_world"
end
@@ -299,7 +300,8 @@ class TestController < ActionController::Base
def builder_layout_test
render :action => "hello", :layout => "layouts/builder"
end
-
+
+ # :move: test this in ActionView
def builder_partial_test
render :action => "hello_world_container"
end
@@ -988,14 +990,17 @@ class RenderTest < ActionController::TestCase
assert_equal 'appended', @response.body
end
+ # :ported:
def test_attempt_to_access_object_method
assert_raise(ActionController::UnknownAction, "No action responded to [clone]") { get :clone }
end
+ # :ported:
def test_private_methods
assert_raise(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout }
end
+ # :ported:
def test_access_to_request_in_view
get :accessing_request_in_template
assert_equal "Hello: www.nextangle.com", @response.body
@@ -1006,11 +1011,13 @@ class RenderTest < ActionController::TestCase
assert_equal "Logger", @response.body
end
+ # :ported:
def test_access_to_action_name_in_view
get :accessing_action_name_in_template
assert_equal "accessing_action_name_in_template", @response.body
end
+ # :ported:
def test_access_to_controller_name_in_view
get :accessing_controller_name_in_template
assert_equal "test", @response.body # name is explicitly set to 'test' inside the controller.
@@ -1022,6 +1029,7 @@ class RenderTest < ActionController::TestCase
assert_equal "text/javascript", @response.content_type
end
+ # :ported:
def test_render_xml
get :render_xml_hello
assert_equal "\n Hello David
\nThis is grand!
\n\n", @response.body
@@ -1034,6 +1042,7 @@ class RenderTest < ActionController::TestCase
assert_equal "application/xml", @response.content_type
end
+ # :ported:
def test_render_xml_with_default
get :greeting
assert_equal "This is grand!
\n", @response.body
diff --git a/actionpack/test/new_base/render_layout_test.rb b/actionpack/test/new_base/render_layout_test.rb
index 07ea2f191e..5d28926cc6 100644
--- a/actionpack/test/new_base/render_layout_test.rb
+++ b/actionpack/test/new_base/render_layout_test.rb
@@ -5,12 +5,21 @@ module ControllerLayouts
self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/application.html.erb" => "OMG <%= yield %> KTHXBAI",
- "basic.html.erb" => "Hello world!"
+ "layouts/override.html.erb" => "Override! <%= yield %>",
+ "basic.html.erb" => "Hello world!"
)]
def index
render :template => "basic"
end
+
+ def override
+ render :template => "basic", :layout => "override"
+ end
+
+ def builder_override
+
+ end
end
class TestImplicitLayout < SimpleRouteCase
@@ -41,5 +50,10 @@ module ControllerLayouts
assert_status 200
end
-
+ class TestOverridingImplicitLayout < SimpleRouteCase
+ describe "overriding an implicit layout with render :layout option"
+
+ get "/controller_layouts/implicit/override"
+ assert_body "Override! Hello world!"
+ end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb
index bc7203f294..647aa01628 100644
--- a/actionpack/test/new_base/render_test.rb
+++ b/actionpack/test/new_base/render_test.rb
@@ -3,12 +3,29 @@ require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
module Render
class BlankRenderController < ActionController::Base2
self.view_paths = [ActionView::Template::FixturePath.new(
- "render/blank_render/index.html.erb" => "Hello world!"
+ "render/blank_render/index.html.erb" => "Hello world!",
+ "render/blank_render/access_request.html.erb" => "The request: <%= request.method.to_s.upcase %>",
+ "render/blank_render/access_action_name.html.erb" => "Action Name: <%= action_name %>",
+ "render/blank_render/access_controller_name.html.erb" => "Controller Name: <%= controller_name %>"
)]
def index
render
end
+
+ def access_request
+ render :action => "access_request"
+ end
+
+ def render_action_name
+ render :action => "access_action_name"
+ end
+
+ private
+
+ def secretz
+ render :text => "FAIL WHALE!"
+ end
end
class TestBlankRender < SimpleRouteCase
@@ -36,13 +53,36 @@ module Render
end
end
- class TestRenderObjectMethod < SimpleRouteCase
- describe "Methods on Object are not actions"
+ class TestOnlyRenderPublicActions < SimpleRouteCase
+ describe "Only public methods on actual controllers are callable actions"
- test "raises an exception" do
+ test "raises an exception when a method of Object is called" do
assert_raises(AbstractController::ActionNotFound) do
get "/render/blank_render/clone"
end
end
+
+ test "raises an exception when a private method is called" do
+ assert_raises(AbstractController::ActionNotFound) do
+ get "/render/blank_render/secretz"
+ end
+ end
+ end
+
+ class TestVariousObjectsAvailableInView < SimpleRouteCase
+ test "The request object is accessible in the view" do
+ get "/render/blank_render/access_request"
+ assert_body "The request: GET"
+ end
+
+ test "The action_name is accessible in the view" do
+ get "/render/blank_render/render_action_name"
+ assert_body "Action Name: render_action_name"
+ end
+
+ test "The controller_name is accessible in the view" do
+ get "/render/blank_render/access_controller_name"
+ assert_body "Controller Name: blank_render"
+ end
end
end
\ No newline at end of file
--
cgit v1.2.3
From b4903a8e34da77b96ea136ccd015c1634a8a5c2b Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 1 May 2009 16:01:37 -0700
Subject: Modify new_base to use String action_names for back-compat
---
actionpack/lib/action_controller/abstract/base.rb | 8 ++++----
actionpack/lib/action_controller/abstract/callbacks.rb | 4 ++--
actionpack/lib/action_controller/new_base/base.rb | 2 +-
actionpack/test/abstract_controller/abstract_controller_test.rb | 2 +-
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index 3b85ba5565..8a8e748c0e 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -21,7 +21,7 @@ module AbstractController
end
def process(action)
- new.process(action)
+ new.process(action.to_s)
end
def hidden_actions
@@ -31,11 +31,11 @@ module AbstractController
def action_methods
@action_methods ||=
# All public instance methods of this class, including ancestors
- public_instance_methods(true).map { |m| m.to_sym }.to_set -
+ public_instance_methods(true).map { |m| m.to_s }.to_set -
# Except for public instance methods of Base and its ancestors
- internal_methods.map { |m| m.to_sym } +
+ internal_methods.map { |m| m.to_s } +
# Be sure to include shadowed public instance methods of this class
- public_instance_methods(false).map { |m| m.to_sym } -
+ public_instance_methods(false).map { |m| m.to_s } -
# And always exclude explicitly hidden actions
hidden_actions
end
diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb
index c8b509081c..5f1607940a 100644
--- a/actionpack/lib/action_controller/abstract/callbacks.rb
+++ b/actionpack/lib/action_controller/abstract/callbacks.rb
@@ -14,11 +14,11 @@ module AbstractController
module ClassMethods
def _normalize_callback_options(options)
if only = options[:only]
- only = Array(only).map {|o| "action_name == :#{o}"}.join(" || ")
+ only = Array(only).map {|o| "action_name == '#{o}'"}.join(" || ")
options[:per_key] = {:if => only}
end
if except = options[:except]
- except = Array(except).map {|e| "action_name == :#{e}"}.join(" || ")
+ except = Array(except).map {|e| "action_name == '#{e}'"}.join(" || ")
options[:per_key] = {:unless => except}
end
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 00d161289e..f663900944 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -42,7 +42,7 @@ module ActionController
def call(env)
@_request = ActionDispatch::Request.new(env)
@_response = ActionDispatch::Response.new
- process(@_request.parameters[:action].to_sym)
+ process(@_request.parameters[:action])
@_response.body = response_body
@_response.prepare!
self
diff --git a/actionpack/test/abstract_controller/abstract_controller_test.rb b/actionpack/test/abstract_controller/abstract_controller_test.rb
index cf6fb5140d..c283a7319d 100644
--- a/actionpack/test/abstract_controller/abstract_controller_test.rb
+++ b/actionpack/test/abstract_controller/abstract_controller_test.rb
@@ -203,7 +203,7 @@ module AbstractController
private
def respond_to_action?(action_name)
- action_name != :fail
+ action_name.to_s != "fail"
end
end
--
cgit v1.2.3
From 918b119bd3310c15dab4eb8a3317cc2a32503119 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 1 May 2009 16:02:37 -0700
Subject: Add support for stripping "layouts/" from the layout name
---
actionpack/lib/action_controller/abstract/layouts.rb | 3 +++
actionpack/lib/action_controller/new_base/compatibility.rb | 5 +++++
2 files changed, 8 insertions(+)
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index f56b9dd914..eb3b73289d 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -57,6 +57,9 @@ module AbstractController
def _layout() end # This will be overwritten
+ # :api: plugin
+ # ====
+ # Override this to mutate the inbound layout name
def _layout_for_name(name)
unless [String, FalseClass, NilClass].include?(name.class)
raise ArgumentError, "String, false, or nil expected; you passed #{name.inspect}"
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index 8682493c8e..275a18abfd 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -8,5 +8,10 @@ module ActionController
super
end
+ def _layout_for_name(name)
+ name &&= name.sub(%r{^/?layouts/}, '')
+ super
+ end
+
end
end
\ No newline at end of file
--
cgit v1.2.3
From b1d34b3aa42beaf6a9fb93f114aed8fe08ebd9db Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 1 May 2009 16:03:46 -0700
Subject: Starting to get new_base to run on old tests
---
actionpack/lib/action_controller/new_base.rb | 1 +
actionpack/lib/action_controller/new_base/base.rb | 3 +
.../lib/action_controller/new_base/testing.rb | 23 +++
.../lib/action_controller/testing/process2.rb | 68 +++++++
actionpack/test/abstract_controller/test_helper.rb | 7 +-
actionpack/test/abstract_unit2.rb | 210 +++++++++++++++++++++
actionpack/test/controller/render_test.rb | 2 +-
actionpack/test/new_base/test_helper.rb | 2 +
8 files changed, 313 insertions(+), 3 deletions(-)
create mode 100644 actionpack/lib/action_controller/new_base/testing.rb
create mode 100644 actionpack/lib/action_controller/testing/process2.rb
create mode 100644 actionpack/test/abstract_unit2.rb
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index bfd8120e10..47621f0847 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -4,5 +4,6 @@ module ActionController
autoload :Layouts, "action_controller/new_base/layouts"
autoload :Rails2Compatibility, "action_controller/new_base/compatibility"
autoload :Renderer, "action_controller/new_base/renderer"
+ autoload :Testing, "action_controller/new_base/testing"
autoload :UrlFor, "action_controller/new_base/url_for"
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index f663900944..e24c494652 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -53,4 +53,7 @@ module ActionController
@_response.to_a
end
end
+
+ class Base < Http
+ end
end
diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb
new file mode 100644
index 0000000000..428f339b3d
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/testing.rb
@@ -0,0 +1,23 @@
+module ActionController
+ module Testing
+
+ # OMG MEGA HAX
+ def process_with_test(request, response)
+ @_request = request
+ @_response = response
+ ret = process(request.parameters[:action])
+ @_response.body = self.response_body
+ set_test_assigns
+ ret
+ end
+
+ def set_test_assigns
+ @assigns = {}
+ (instance_variable_names - self.class.protected_instance_variables).each do |var|
+ name, value = var[1..-1], instance_variable_get(var)
+ @assigns[name] = value
+ end
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb
new file mode 100644
index 0000000000..7111733d0d
--- /dev/null
+++ b/actionpack/lib/action_controller/testing/process2.rb
@@ -0,0 +1,68 @@
+require "action_controller/testing/process"
+
+module ActionController
+ module TestProcess2
+
+ # Executes a request simulating GET HTTP method and set/volley the response
+ def get(action, parameters = nil, session = nil, flash = nil)
+ process(action, parameters, session, flash, "GET")
+ end
+
+ # Executes a request simulating POST HTTP method and set/volley the response
+ def post(action, parameters = nil, session = nil, flash = nil)
+ process(action, parameters, session, flash, "POST")
+ end
+
+ # Executes a request simulating PUT HTTP method and set/volley the response
+ def put(action, parameters = nil, session = nil, flash = nil)
+ process(action, parameters, session, flash, "PUT")
+ end
+
+ # Executes a request simulating DELETE HTTP method and set/volley the response
+ def delete(action, parameters = nil, session = nil, flash = nil)
+ process(action, parameters, session, flash, "DELETE")
+ end
+
+ # Executes a request simulating HEAD HTTP method and set/volley the response
+ def head(action, parameters = nil, session = nil, flash = nil)
+ process(action, parameters, session, flash, "HEAD")
+ end
+
+ def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
+ # Sanity check for required instance variables so we can give an
+ # understandable error message.
+ %w(@controller @request @response).each do |iv_name|
+ if !(instance_variable_names.include?(iv_name) || instance_variable_names.include?(iv_name.to_sym)) || instance_variable_get(iv_name).nil?
+ raise "#{iv_name} is nil: make sure you set it in your test's setup method."
+ end
+ end
+
+ @request.recycle!
+ @response.recycle!
+
+ @html_document = nil
+ @request.env['REQUEST_METHOD'] = http_method
+
+ parameters ||= {}
+ @request.assign_parameters(@controller.class.controller_path, action.to_s, parameters)
+
+ @request.session = ActionController::TestSession.new(session) unless session.nil?
+ @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash
+ build_request_uri(action, parameters)
+
+ # Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
+ @controller.process_with_test(@request, @response)
+ end
+
+ def build_request_uri(action, parameters)
+ unless @request.env['REQUEST_URI']
+ options = @controller.__send__(:rewrite_options, parameters)
+ options.update(:only_path => true, :action => action)
+
+ url = ActionController::UrlRewriter.new(@request, parameters)
+ @request.set_REQUEST_URI(url.rewrite(options))
+ end
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/abstract_controller/test_helper.rb b/actionpack/test/abstract_controller/test_helper.rb
index b9248c6bbd..a0375a0e99 100644
--- a/actionpack/test/abstract_controller/test_helper.rb
+++ b/actionpack/test/abstract_controller/test_helper.rb
@@ -2,9 +2,13 @@ $:.unshift(File.dirname(__FILE__) + '/../../lib')
$:.unshift(File.dirname(__FILE__) + '/../../../activesupport/lib')
$:.unshift(File.dirname(__FILE__) + '/../lib')
+require 'rubygems'
require 'test/unit'
-require 'active_support'
+require 'active_support/core/all'
require 'active_support/test_case'
+require 'action_controller/abstract'
+require 'action_controller/new_base/base'
+require 'action_controller/new_base/renderer'
require 'action_controller'
require 'action_view/base'
require 'fixture_template'
@@ -17,7 +21,6 @@ rescue LoadError
# Debugging disabled. `gem install ruby-debug` to enable.
end
-require 'action_controller/abstract'
# require 'action_controller/abstract/base'
# require 'action_controller/abstract/renderer'
# require 'action_controller/abstract/layouts'
diff --git a/actionpack/test/abstract_unit2.rb b/actionpack/test/abstract_unit2.rb
new file mode 100644
index 0000000000..c1e2631ac2
--- /dev/null
+++ b/actionpack/test/abstract_unit2.rb
@@ -0,0 +1,210 @@
+$:.unshift(File.dirname(__FILE__) + '/../lib')
+$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
+$:.unshift(File.dirname(__FILE__) + '/lib')
+
+# HAX
+module ActionController
+
+end
+
+# TestCase
+# include TestProcess2
+
+
+require 'test/unit'
+require 'active_support'
+require 'active_support/core/all'
+require 'active_support/test_case'
+require 'action_controller/abstract'
+require 'action_controller/new_base'
+require 'action_controller/new_base/base'
+require 'action_controller/new_base/renderer' # HAX
+require 'action_controller'
+require 'fixture_template'
+require 'action_view/test_case'
+
+FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
+
+module ActionController
+ autoload :TestProcess2, 'action_controller/testing/process2'
+
+ class ActionControllerError < StandardError #:nodoc:
+ end
+
+ class SessionRestoreError < ActionControllerError #:nodoc:
+ end
+
+ class RenderError < ActionControllerError #:nodoc:
+ end
+
+ class RoutingError < ActionControllerError #:nodoc:
+ attr_reader :failures
+ def initialize(message, failures=[])
+ super(message)
+ @failures = failures
+ end
+ end
+
+ class MethodNotAllowed < ActionControllerError #:nodoc:
+ attr_reader :allowed_methods
+
+ def initialize(*allowed_methods)
+ super("Only #{allowed_methods.to_sentence(:locale => :en)} requests are allowed.")
+ @allowed_methods = allowed_methods
+ end
+
+ def allowed_methods_header
+ allowed_methods.map { |method_symbol| method_symbol.to_s.upcase } * ', '
+ end
+
+ def handle_response!(response)
+ response.headers['Allow'] ||= allowed_methods_header
+ end
+ end
+
+ class NotImplemented < MethodNotAllowed #:nodoc:
+ end
+
+ class UnknownController < ActionControllerError #:nodoc:
+ end
+
+ class UnknownAction < ActionControllerError #:nodoc:
+ end
+
+ class MissingFile < ActionControllerError #:nodoc:
+ end
+
+ class RenderError < ActionControllerError #:nodoc:
+ end
+
+ class SessionOverflowError < ActionControllerError #:nodoc:
+ DEFAULT_MESSAGE = 'Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.'
+
+ def initialize(message = nil)
+ super(message || DEFAULT_MESSAGE)
+ end
+ end
+
+ class UnknownHttpMethod < ActionControllerError #:nodoc:
+ end
+
+ class Base < Http
+ abstract!
+ #
+ cattr_accessor :relative_url_root
+ self.relative_url_root = ENV['RAILS_RELATIVE_URL_ROOT']
+
+ 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 @_headers @_params
+ @_flash @_response)
+ #
+
+ use AbstractController::Callbacks
+ use AbstractController::Helpers
+ use AbstractController::Logger
+
+ use ActionController::HideActions
+ use ActionController::UrlFor
+ use ActionController::Renderer
+ use ActionController::Layouts
+ use ActionController::Rails2Compatibility
+ use ActionController::Testing
+
+ def self.protect_from_forgery() end
+
+ def self.inherited(klass)
+ ::ActionController::Base.subclasses << klass.to_s
+ super
+ end
+
+ def self.subclasses
+ @subclasses ||= []
+ end
+
+ def self.app_loaded!
+ @subclasses.each do |subclass|
+ subclass.constantize._write_layout_method
+ end
+ end
+
+ def render(action = action_name, options = {})
+ if action.is_a?(Hash)
+ options, action = action, nil
+ else
+ options.merge! :action => action
+ end
+
+ super(options)
+ end
+
+ def render_to_body(options = {})
+ options = {:template => options} if options.is_a?(String)
+ super
+ end
+
+ def process_action
+ ret = super
+ render if response_body.nil?
+ ret
+ end
+
+ def respond_to_action?(action_name)
+ super || view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
+ end
+ end
+
+ Base.view_paths = FIXTURE_LOAD_PATH
+
+ class TestCase
+ include TestProcess2
+ setup do
+ ActionController::Routing::Routes.draw do |map|
+ map.connect ':controller/:action/:id'
+ end
+ end
+
+ def assert_template(options = {}, message = nil)
+ validate_response!
+
+ clean_backtrace do
+ case options
+ when NilClass, String
+ hax = @controller._action_view.instance_variable_get(:@_rendered)
+ rendered = (hax[:template] || []).map { |t| t.identifier }
+ msg = build_message(message,
+ "expecting > but rendering with >",
+ options, rendered.join(', '))
+ assert_block(msg) do
+ if options.nil?
+ hax[:template].blank?
+ else
+ rendered.any? { |t| t.match(options) }
+ end
+ end
+ when Hash
+ if expected_partial = options[:partial]
+ partials = hax[:partials]
+ if expected_count = options[:count]
+ 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)",
+ expected_partial, expected_count, actual_count)
+ assert(actual_count == expected_count.to_i, msg)
+ else
+ msg = build_message(message,
+ "expecting partial > but action rendered >",
+ options[:partial], partials.keys)
+ assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg)
+ end
+ else
+ assert hax[:partials].empty?,
+ "Expected no partials to be rendered"
+ end
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index fb9b121fc9..1e69ca894f 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -1,4 +1,4 @@
-require 'abstract_unit'
+require ENV['new_base'] ? 'abstract_unit2' : 'abstract_unit'
require 'controller/fake_models'
require 'pathname'
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index d58b83cf7b..6a71bd29c4 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -5,6 +5,8 @@ $:.unshift(File.dirname(__FILE__) + '/../lib')
require 'test/unit'
require 'active_support'
require 'active_support/test_case'
+require 'action_controller/new_base/base'
+require 'action_controller/new_base/renderer'
require 'action_controller'
require 'action_view/base'
require 'fixture_template'
--
cgit v1.2.3
From e046f36824fcc164c284a13524c6b4153010a4e1 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 1 May 2009 17:27:44 -0700
Subject: Renamed Base2 to Base and don't require old action_controller for new
Base
---
actionpack/lib/action_controller/new_base.rb | 17 ++++-
actionpack/lib/action_controller/new_base/base.rb | 87 +++++++++++-----------
.../action_controller/new_base/compatibility.rb | 21 ++++++
actionpack/lib/action_controller/new_base/http.rb | 56 ++++++++++++++
actionpack/lib/action_dispatch/middleware/stack.rb | 2 -
actionpack/test/abstract_controller/test_helper.rb | 13 +---
actionpack/test/new_base/base_test.rb | 6 +-
actionpack/test/new_base/content_type_test.rb | 6 +-
actionpack/test/new_base/render_action_test.rb | 6 +-
actionpack/test/new_base/render_template_test.rb | 4 +-
actionpack/test/new_base/render_test.rb | 4 +-
actionpack/test/new_base/render_text_test.rb | 6 +-
actionpack/test/new_base/test_helper.rb | 70 +----------------
13 files changed, 157 insertions(+), 141 deletions(-)
create mode 100644 actionpack/lib/action_controller/new_base/http.rb
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 47621f0847..b292fd579d 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -1,9 +1,22 @@
module ActionController
+ autoload :Base, "action_controller/new_base/base"
autoload :HideActions, "action_controller/new_base/hide_actions"
- autoload :Http, "action_controller/new_base/base"
+ autoload :Http, "action_controller/new_base/http"
autoload :Layouts, "action_controller/new_base/layouts"
autoload :Rails2Compatibility, "action_controller/new_base/compatibility"
autoload :Renderer, "action_controller/new_base/renderer"
autoload :Testing, "action_controller/new_base/testing"
autoload :UrlFor, "action_controller/new_base/url_for"
-end
\ No newline at end of file
+
+ # Ported modules
+ # require 'action_controller/routing'
+ autoload :Dispatcher, 'action_controller/dispatch/dispatcher'
+ autoload :PolymorphicRoutes, 'action_controller/routing/generation/polymorphic_routes'
+ autoload :Resources, 'action_controller/routing/resources'
+ autoload :SessionManagement, 'action_controller/base/session_management'
+
+ require 'action_controller/routing'
+end
+
+require 'action_dispatch'
+require 'action_view'
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index e24c494652..8af6ffbc92 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -1,59 +1,60 @@
module ActionController
- class Http < AbstractController::Base
+ class Base < Http
abstract!
- # :api: public
- attr_internal :request, :response, :params
-
- # :api: public
- def self.controller_name
- @controller_name ||= controller_path.split("/").last
- end
+ use AbstractController::Callbacks
+ use AbstractController::Helpers
+ use AbstractController::Logger
- # :api: public
- def controller_name() self.class.controller_name end
-
- # :api: public
- def self.controller_path
- @controller_path ||= self.name.sub(/Controller$/, '').underscore
- end
+ use ActionController::HideActions
+ use ActionController::UrlFor
+ use ActionController::Renderer
+ use ActionController::Layouts
+
+ # Legacy modules
+ include SessionManagement
- # :api: public
- def controller_path() self.class.controller_path end
+ # Rails 2.x compatibility
+ use ActionController::Rails2Compatibility
- # :api: private
- def self.internal_methods
- ActionController::Http.public_instance_methods(true)
+ def self.inherited(klass)
+ ::ActionController::Base.subclasses << klass.to_s
+ super
end
- # :api: private
- def self.action_names() action_methods end
+ def self.subclasses
+ @subclasses ||= []
+ end
- # :api: private
- def action_names() action_methods end
+ def self.app_loaded!
+ @subclasses.each do |subclass|
+ subclass.constantize._write_layout_method
+ end
+ end
- # :api: plugin
- def self.call(env)
- controller = new
- controller.call(env).to_rack
+ def render(action = action_name, options = {})
+ if action.is_a?(Hash)
+ options, action = action, nil
+ else
+ options.merge! :action => action
+ end
+
+ super(options)
end
- # :api: private
- def call(env)
- @_request = ActionDispatch::Request.new(env)
- @_response = ActionDispatch::Response.new
- process(@_request.parameters[:action])
- @_response.body = response_body
- @_response.prepare!
- self
+ def render_to_body(options = {})
+ options = {:template => options} if options.is_a?(String)
+ super
end
- # :api: private
- def to_rack
- @_response.to_a
+ def process_action
+ ret = super
+ render if response_body.nil?
+ ret
+ end
+
+ def respond_to_action?(action_name)
+ super || view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
end
end
-
- class Base < Http
- end
-end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index 275a18abfd..db471f7658 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -1,6 +1,27 @@
module ActionController
module Rails2Compatibility
+ # Temporary hax
+ setup do
+ cattr_accessor :session_options
+ self.send(:class_variable_set, "@@session_options", {})
+
+ cattr_accessor :allow_concurrency
+ self.send(:class_variable_set, "@@allow_concurrency", false)
+
+ cattr_accessor :param_parsers
+ self.send(:class_variable_set, "@@param_parsers", { Mime::MULTIPART_FORM => :multipart_form,
+ Mime::URL_ENCODED_FORM => :url_encoded_form,
+ Mime::XML => :xml_simple,
+ Mime::JSON => :json })
+
+ cattr_accessor :relative_url_root
+ self.send(:class_variable_set, "@@relative_url_root", ENV['RAILS_RELATIVE_URL_ROOT'])
+
+ cattr_accessor :default_charset
+ self.send(:class_variable_set, "@@default_charset", "utf-8")
+ end
+
def render_to_body(options)
if options.is_a?(Hash) && options.key?(:template)
options[:template].sub!(/^\//, '')
diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb
new file mode 100644
index 0000000000..f663900944
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/http.rb
@@ -0,0 +1,56 @@
+module ActionController
+ class Http < AbstractController::Base
+ abstract!
+
+ # :api: public
+ attr_internal :request, :response, :params
+
+ # :api: public
+ def self.controller_name
+ @controller_name ||= controller_path.split("/").last
+ end
+
+ # :api: public
+ def controller_name() self.class.controller_name end
+
+ # :api: public
+ def self.controller_path
+ @controller_path ||= self.name.sub(/Controller$/, '').underscore
+ end
+
+ # :api: public
+ def controller_path() self.class.controller_path end
+
+ # :api: private
+ def self.internal_methods
+ ActionController::Http.public_instance_methods(true)
+ end
+
+ # :api: private
+ def self.action_names() action_methods end
+
+ # :api: private
+ def action_names() action_methods end
+
+ # :api: plugin
+ def self.call(env)
+ controller = new
+ controller.call(env).to_rack
+ end
+
+ # :api: private
+ def call(env)
+ @_request = ActionDispatch::Request.new(env)
+ @_response = ActionDispatch::Response.new
+ process(@_request.parameters[:action])
+ @_response.body = response_body
+ @_response.prepare!
+ self
+ end
+
+ # :api: private
+ def to_rack
+ @_response.to_a
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
index ee5f28d5cb..52abd69a42 100644
--- a/actionpack/lib/action_dispatch/middleware/stack.rb
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -34,8 +34,6 @@ module ActionDispatch
else
@klass.to_s.constantize
end
- rescue NameError
- @klass
end
def active?
diff --git a/actionpack/test/abstract_controller/test_helper.rb b/actionpack/test/abstract_controller/test_helper.rb
index a0375a0e99..f0556e63e2 100644
--- a/actionpack/test/abstract_controller/test_helper.rb
+++ b/actionpack/test/abstract_controller/test_helper.rb
@@ -7,10 +7,7 @@ require 'test/unit'
require 'active_support/core/all'
require 'active_support/test_case'
require 'action_controller/abstract'
-require 'action_controller/new_base/base'
-require 'action_controller/new_base/renderer'
-require 'action_controller'
-require 'action_view/base'
+require 'action_view'
require 'fixture_template'
begin
@@ -19,10 +16,4 @@ begin
Debugger.start
rescue LoadError
# Debugging disabled. `gem install ruby-debug` to enable.
-end
-
-# require 'action_controller/abstract/base'
-# require 'action_controller/abstract/renderer'
-# require 'action_controller/abstract/layouts'
-# require 'action_controller/abstract/callbacks'
-# require 'action_controller/abstract/helpers'
\ No newline at end of file
+end
\ No newline at end of file
diff --git a/actionpack/test/new_base/base_test.rb b/actionpack/test/new_base/base_test.rb
index 27d1a7f026..a32653f128 100644
--- a/actionpack/test/new_base/base_test.rb
+++ b/actionpack/test/new_base/base_test.rb
@@ -2,7 +2,7 @@ require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
# Tests the controller dispatching happy path
module Dispatching
- class SimpleController < ActionController::Base2
+ class SimpleController < ActionController::Base
def index
render :text => "success"
end
@@ -69,9 +69,9 @@ module Dispatching
end
end
- class EmptyController < ActionController::Base2 ; end
+ class EmptyController < ActionController::Base ; end
module Submodule
- class ContainedEmptyController < ActionController::Base2 ; end
+ class ContainedEmptyController < ActionController::Base ; end
end
class ControllerClassTests < Test::Unit::TestCase
diff --git a/actionpack/test/new_base/content_type_test.rb b/actionpack/test/new_base/content_type_test.rb
index 10a28da496..a5c04e9cb6 100644
--- a/actionpack/test/new_base/content_type_test.rb
+++ b/actionpack/test/new_base/content_type_test.rb
@@ -1,7 +1,7 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
module ContentType
- class BaseController < ActionController::Base2
+ class BaseController < ActionController::Base
def index
render :text => "Hello world!"
end
@@ -40,7 +40,7 @@ module ContentType
assert_header "Content-Type", "application/rss+xml; charset=utf-8"
end
- class ImpliedController < ActionController::Base2
+ class ImpliedController < ActionController::Base
self.view_paths = [ActionView::Template::FixturePath.new(
"content_type/implied/i_am_html_erb.html.erb" => "Hello world!",
"content_type/implied/i_am_xml_erb.xml.erb" => "Hello world! ",
@@ -81,7 +81,7 @@ module ContentType
end
module Charset
- class BaseController < ActionController::Base2
+ class BaseController < ActionController::Base
def set_on_response_obj
response.charset = "utf-16"
render :text => "Hello world!"
diff --git a/actionpack/test/new_base/render_action_test.rb b/actionpack/test/new_base/render_action_test.rb
index 37b83fb681..348d70381b 100644
--- a/actionpack/test/new_base/render_action_test.rb
+++ b/actionpack/test/new_base/render_action_test.rb
@@ -3,7 +3,7 @@ require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
module RenderAction
# This has no layout and it works
- class BasicController < ActionController::Base2
+ class BasicController < ActionController::Base
self.view_paths = [ActionView::Template::FixturePath.new(
"render_action/basic/hello_world.html.erb" => "Hello world!"
@@ -203,7 +203,7 @@ end
module RenderActionWithControllerLayout
- class BasicController < ActionController::Base2
+ class BasicController < ActionController::Base
self.view_paths = self.view_paths = [ActionView::Template::FixturePath.new(
"render_action_with_controller_layout/basic/hello_world.html.erb" => "Hello World!",
"layouts/render_action_with_controller_layout/basic.html.erb" => "With Controller Layout! <%= yield %> KTHXBAI"
@@ -266,7 +266,7 @@ end
module RenderActionWithBothLayouts
- class BasicController < ActionController::Base2
+ class BasicController < ActionController::Base
self.view_paths = [ActionView::Template::FixturePath.new({
"render_action_with_both_layouts/basic/hello_world.html.erb" => "Hello World!",
"layouts/application.html.erb" => "OHAI <%= yield %> KTHXBAI",
diff --git a/actionpack/test/new_base/render_template_test.rb b/actionpack/test/new_base/render_template_test.rb
index 63769df082..c09eeb1926 100644
--- a/actionpack/test/new_base/render_template_test.rb
+++ b/actionpack/test/new_base/render_template_test.rb
@@ -1,7 +1,7 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
module RenderTemplate
- class WithoutLayoutController < ActionController::Base2
+ class WithoutLayoutController < ActionController::Base
self.view_paths = [ActionView::Template::FixturePath.new(
"test/basic.html.erb" => "Hello from basic.html.erb",
@@ -129,7 +129,7 @@ module RenderTemplate
end
module Compatibility
- class WithoutLayoutController < ActionController::CompatibleBase2
+ class WithoutLayoutController < ActionController::Base
self.view_paths = [ActionView::Template::FixturePath.new(
"test/basic.html.erb" => "Hello from basic.html.erb",
"shared.html.erb" => "Elastica"
diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb
index 647aa01628..b1867fdcc2 100644
--- a/actionpack/test/new_base/render_test.rb
+++ b/actionpack/test/new_base/render_test.rb
@@ -1,7 +1,7 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
module Render
- class BlankRenderController < ActionController::Base2
+ class BlankRenderController < ActionController::Base
self.view_paths = [ActionView::Template::FixturePath.new(
"render/blank_render/index.html.erb" => "Hello world!",
"render/blank_render/access_request.html.erb" => "The request: <%= request.method.to_s.upcase %>",
@@ -36,7 +36,7 @@ module Render
assert_status 200
end
- class DoubleRenderController < ActionController::Base2
+ class DoubleRenderController < ActionController::Base
def index
render :text => "hello"
render :text => "world"
diff --git a/actionpack/test/new_base/render_text_test.rb b/actionpack/test/new_base/render_text_test.rb
index d97c2ca0a6..39f2f7abbf 100644
--- a/actionpack/test/new_base/render_text_test.rb
+++ b/actionpack/test/new_base/render_text_test.rb
@@ -1,10 +1,10 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
-class ApplicationController < ActionController::Base2
+class ApplicationController < ActionController::Base
end
module RenderText
- class SimpleController < ActionController::Base2
+ class SimpleController < ActionController::Base
self.view_paths = [ActionView::Template::FixturePath.new]
def index
@@ -146,4 +146,4 @@ module RenderText
end
end
-ActionController::Base2.app_loaded!
\ No newline at end of file
+ActionController::Base.app_loaded!
\ No newline at end of file
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index 6a71bd29c4..547eb1ef72 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -5,10 +5,7 @@ $:.unshift(File.dirname(__FILE__) + '/../lib')
require 'test/unit'
require 'active_support'
require 'active_support/test_case'
-require 'action_controller/new_base/base'
-require 'action_controller/new_base/renderer'
-require 'action_controller'
-require 'action_view/base'
+require 'action_view'
require 'fixture_template'
begin
@@ -34,67 +31,6 @@ module Rails
end
end
-module ActionController
- class Base2 < Http
- abstract!
-
- use AbstractController::Callbacks
- use AbstractController::Helpers
- use AbstractController::Logger
-
- use ActionController::HideActions
- use ActionController::UrlFor
- use ActionController::Renderer
- use ActionController::Layouts
-
- def self.inherited(klass)
- ::ActionController::Base2.subclasses << klass.to_s
- super
- end
-
- def self.subclasses
- @subclasses ||= []
- end
-
- def self.app_loaded!
- @subclasses.each do |subclass|
- subclass.constantize._write_layout_method
- end
- end
-
- def render(action = action_name, options = {})
- if action.is_a?(Hash)
- options, action = action, nil
- else
- options.merge! :action => action
- end
-
- super(options)
- end
-
- def render_to_body(options = {})
- options = {:template => options} if options.is_a?(String)
- super
- end
-
- def process_action
- ret = super
- render if response_body.nil?
- ret
- end
-
- def respond_to_action?(action_name)
- super || view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
- end
- end
-
- class CompatibleBase2 < Base2
- abstract!
-
- use ActionController::Rails2Compatibility
- end
-end
-
# Temporary base class
class Rack::TestCase < ActiveSupport::TestCase
include Rack::Test::Methods
@@ -103,7 +39,7 @@ class Rack::TestCase < ActiveSupport::TestCase
ActionController::Base.session_options[:key] = "abc"
ActionController::Base.session_options[:secret] = ("*" * 30)
- controllers = ActionController::Base2.subclasses.map do |k|
+ controllers = ActionController::Base.subclasses.map do |k|
k.underscore.sub(/_controller$/, '')
end
@@ -171,7 +107,7 @@ class Rack::TestCase < ActiveSupport::TestCase
end
-class ::ApplicationController < ActionController::Base2
+class ::ApplicationController < ActionController::Base
end
class SimpleRouteCase < Rack::TestCase
--
cgit v1.2.3
From 7dd072d333040d2bb1197baa55fddfb9b72053bd Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 1 May 2009 17:53:20 -0700
Subject: A few more tweaks to get new Base running old render tests again
---
actionpack/lib/action_controller/new_base.rb | 8 ++++++--
actionpack/lib/action_controller/testing/process2.rb | 4 ++--
actionpack/test/abstract_unit2.rb | 15 ++-------------
3 files changed, 10 insertions(+), 17 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index b292fd579d..7098b812f6 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -10,10 +10,14 @@ module ActionController
# Ported modules
# require 'action_controller/routing'
- autoload :Dispatcher, 'action_controller/dispatch/dispatcher'
+ autoload :Dispatcher, 'action_controller/dispatch/dispatcher'
autoload :PolymorphicRoutes, 'action_controller/routing/generation/polymorphic_routes'
- autoload :Resources, 'action_controller/routing/resources'
+ autoload :RecordIdentifier, 'action_controller/record_identifier'
+ autoload :Resources, 'action_controller/routing/resources'
autoload :SessionManagement, 'action_controller/base/session_management'
+ autoload :TestCase, 'action_controller/testing/test_case'
+ autoload :UrlRewriter, 'action_controller/routing/generation/url_rewriter'
+ autoload :UrlWriter, 'action_controller/routing/generation/url_rewriter'
require 'action_controller/routing'
end
diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb
index 7111733d0d..d9af7add5f 100644
--- a/actionpack/lib/action_controller/testing/process2.rb
+++ b/actionpack/lib/action_controller/testing/process2.rb
@@ -1,7 +1,7 @@
require "action_controller/testing/process"
module ActionController
- module TestProcess2
+ module TestProcess
# Executes a request simulating GET HTTP method and set/volley the response
def get(action, parameters = nil, session = nil, flash = nil)
@@ -60,7 +60,7 @@ module ActionController
options.update(:only_path => true, :action => action)
url = ActionController::UrlRewriter.new(@request, parameters)
- @request.set_REQUEST_URI(url.rewrite(options))
+ @request.request_uri = url.rewrite(options)
end
end
diff --git a/actionpack/test/abstract_unit2.rb b/actionpack/test/abstract_unit2.rb
index c1e2631ac2..b95bfa0202 100644
--- a/actionpack/test/abstract_unit2.rb
+++ b/actionpack/test/abstract_unit2.rb
@@ -2,14 +2,6 @@ $:.unshift(File.dirname(__FILE__) + '/../lib')
$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
$:.unshift(File.dirname(__FILE__) + '/lib')
-# HAX
-module ActionController
-
-end
-
-# TestCase
-# include TestProcess2
-
require 'test/unit'
require 'active_support'
@@ -17,16 +9,13 @@ require 'active_support/core/all'
require 'active_support/test_case'
require 'action_controller/abstract'
require 'action_controller/new_base'
-require 'action_controller/new_base/base'
-require 'action_controller/new_base/renderer' # HAX
-require 'action_controller'
require 'fixture_template'
+require 'action_controller/testing/process2'
require 'action_view/test_case'
FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
module ActionController
- autoload :TestProcess2, 'action_controller/testing/process2'
class ActionControllerError < StandardError #:nodoc:
end
@@ -158,7 +147,7 @@ module ActionController
Base.view_paths = FIXTURE_LOAD_PATH
class TestCase
- include TestProcess2
+ include TestProcess
setup do
ActionController::Routing::Routes.draw do |map|
map.connect ':controller/:action/:id'
--
cgit v1.2.3
From ad2a1b5cb1afb0ea810cfdcac2ba1be95c55f1aa Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 1 May 2009 18:17:08 -0700
Subject: Get render :inline working
---
actionpack/lib/action_controller/new_base/layouts.rb | 2 +-
actionpack/lib/action_controller/new_base/renderer.rb | 4 ++++
actionpack/lib/action_controller/testing/process2.rb | 2 +-
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base/layouts.rb b/actionpack/lib/action_controller/new_base/layouts.rb
index a8e0809ac6..79abe40389 100644
--- a/actionpack/lib/action_controller/new_base/layouts.rb
+++ b/actionpack/lib/action_controller/new_base/layouts.rb
@@ -13,7 +13,7 @@ module ActionController
# render :text => ..., :layout => ...
# or
# render :anything_else
- if !options.key?(:text) || options.key?(:layout)
+ if (!options.key?(:text) && !options.key?(:inline)) || options.key?(:layout)
options[:_layout] = options.key?(:layout) ? _layout_for_option(options[:layout]) : _default_layout
end
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index f21fd746b7..4c4a74979b 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -17,6 +17,10 @@ module ActionController
if options.key?(:text)
options[:_template] = ActionView::TextTemplate.new(_text(options))
template = nil
+ elsif options.key?(:inline)
+ handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb")
+ template = ActionView::Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {})
+ options[:_template] = template
elsif options.key?(:template)
options[:_template_name] = options[:template]
elsif options.key?(:action)
diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb
index d9af7add5f..67b5afb9c5 100644
--- a/actionpack/lib/action_controller/testing/process2.rb
+++ b/actionpack/lib/action_controller/testing/process2.rb
@@ -49,7 +49,7 @@ module ActionController
@request.session = ActionController::TestSession.new(session) unless session.nil?
@request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash
build_request_uri(action, parameters)
-
+ @controller.params.merge!(parameters)
# Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
@controller.process_with_test(@request, @response)
end
--
cgit v1.2.3
From 72160d9f89481ea60c8268ff026099f07b1e5ed6 Mon Sep 17 00:00:00 2001
From: Yehuda Katz
Date: Sat, 2 May 2009 02:15:09 -0700
Subject: Implement FooController.action(:name)
* Rails actions are now Rack endpoints, and can be retrieved
via FooController.action(name) and called with an env
* Updated some tests that relied on the old internal
#process/#call implementation
---
actionpack/lib/action_controller/base/base.rb | 27 ++++++---------
actionpack/lib/action_controller/new_base/http.rb | 13 +++++--
.../lib/action_controller/routing/route_set.rb | 2 +-
.../lib/action_controller/testing/process.rb | 4 +++
actionpack/test/controller/filters_test.rb | 3 +-
actionpack/test/controller/helper_test.rb | 40 +++++++++++++++-------
actionpack/test/new_base/test_helper.rb | 2 +-
7 files changed, 57 insertions(+), 34 deletions(-)
diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb
index 99b5963891..243b7f8ae3 100644
--- a/actionpack/lib/action_controller/base/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -370,18 +370,18 @@ module ActionController #:nodoc:
attr_reader :template
class << self
- def call(env)
- # HACK: For global rescue to have access to the original request and response
- request = env["action_controller.rescue.request"] ||= ActionDispatch::Request.new(env)
- response = env["action_controller.rescue.response"] ||= ActionDispatch::Response.new
- process(request, response)
- end
-
- # Factory for the standard create, process loop where the controller is discarded after processing.
- def process(request, response) #:nodoc:
- new.process(request, response)
+ def action(name = nil)
+ @actions ||= {}
+ @actions[name] ||= proc do |env|
+ controller = new
+ # HACK: For global rescue to have access to the original request and response
+ request = env["action_controller.rescue.request"] ||= ActionDispatch::Request.new(env)
+ response = env["action_controller.rescue.response"] ||= ActionDispatch::Response.new
+ controller.action_name = name && name.to_s
+ controller.process(request, response).to_a
+ end
end
-
+
# Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController".
def controller_class_name
@controller_class_name ||= name.demodulize
@@ -518,7 +518,6 @@ module ActionController #:nodoc:
assign_shortcuts(request, response)
initialize_template_class(response)
initialize_current_url
- assign_names
log_processing
send(method, *arguments)
@@ -883,10 +882,6 @@ module ActionController #:nodoc:
@performed_render || @performed_redirect
end
- def assign_names
- @action_name = (params['action'] || 'index')
- end
-
def reset_variables_added_to_assigns
@template.instance_variable_set("@assigns_added", nil)
end
diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb
index f663900944..b7e3bfaa7e 100644
--- a/actionpack/lib/action_controller/new_base/http.rb
+++ b/actionpack/lib/action_controller/new_base/http.rb
@@ -39,13 +39,20 @@ module ActionController
end
# :api: private
- def call(env)
+ def call(name, env)
@_request = ActionDispatch::Request.new(env)
@_response = ActionDispatch::Response.new
- process(@_request.parameters[:action])
+ process(name)
@_response.body = response_body
@_response.prepare!
- self
+ to_rack
+ end
+
+ def self.action(name)
+ @actions ||= {}
+ @actions[name] ||= proc do |env|
+ new.call(name, env)
+ end
end
# :api: private
diff --git a/actionpack/lib/action_controller/routing/route_set.rb b/actionpack/lib/action_controller/routing/route_set.rb
index 70cd1f642d..45ad8a3a3b 100644
--- a/actionpack/lib/action_controller/routing/route_set.rb
+++ b/actionpack/lib/action_controller/routing/route_set.rb
@@ -430,7 +430,7 @@ module ActionController
def call(env)
request = ActionDispatch::Request.new(env)
app = Routing::Routes.recognize(request)
- app.call(env).to_a
+ app.action(request.parameters[:action] || 'index').call(env)
end
def recognize(request)
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 8315a160ad..3aad94cc10 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -131,7 +131,11 @@ module ActionController #:nodoc:
@request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash
build_request_uri(action, parameters)
+ @request.env["action_controller.rescue.request"] = @request
+ @request.env["action_controller.rescue.request"] = @response
+
Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
+ @controller.action_name = action.to_s
@controller.process(@request, @response)
end
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index 9e74538310..3b113131ae 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -602,8 +602,9 @@ class FilterTest < Test::Unit::TestCase
def test_dynamic_dispatch
%w(foo bar baz).each do |action|
request = ActionController::TestRequest.new
+ request.env["action_controller.rescue.request"] = request
request.query_parameters[:choose] = action
- response = DynamicDispatchController.process(request, ActionController::TestResponse.new)
+ response = DynamicDispatchController.action.call(request.env).last
assert_equal action, response.body
end
end
diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb
index 58addc123d..19cd5f4db2 100644
--- a/actionpack/test/controller/helper_test.rb
+++ b/actionpack/test/controller/helper_test.rb
@@ -101,20 +101,30 @@ class HelperTest < Test::Unit::TestCase
assert master_helper_methods.include?('delegate_attr=')
end
- def test_helper_for_nested_controller
+ def call_controller(klass, action)
request = ActionController::TestRequest.new
- response = ActionController::TestResponse.new
- request.action = 'render_hello_world'
+ request.env["action_controller.rescue.request"] = request
+ klass.action(action).call(request.env)
+ end
- assert_equal 'hello: Iz guuut!', Fun::GamesController.process(request, response).body
+ def test_helper_for_nested_controller
+ assert_equal 'hello: Iz guuut!',
+ call_controller(Fun::GamesController, "render_hello_world").last.body
+ # request = ActionController::TestRequest.new
+ # request.env["action_controller.rescue.request"] = request
+ #
+ # resp = Fun::GamesController.action(:render_hello_world).call(request.env)
+ # assert_equal 'hello: Iz guuut!', resp.last.body
end
def test_helper_for_acronym_controller
- request = ActionController::TestRequest.new
- response = ActionController::TestResponse.new
- request.action = 'test'
-
- assert_equal 'test: baz', Fun::PdfController.process(request, response).body
+ assert_equal "test: baz", call_controller(Fun::PdfController, "test").last.body
+ #
+ # request = ActionController::TestRequest.new
+ # response = ActionController::TestResponse.new
+ # request.action = 'test'
+ #
+ # assert_equal 'test: baz', Fun::PdfController.process(request, response).body
end
def test_all_helpers
@@ -204,6 +214,12 @@ class IsolatedHelpersTest < Test::Unit::TestCase
end
end
+ def call_controller(klass, action)
+ request = ActionController::TestRequest.new
+ request.env["action_controller.rescue.request"] = request
+ klass.action(action).call(request.env)
+ end
+
def setup
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@@ -211,14 +227,14 @@ class IsolatedHelpersTest < Test::Unit::TestCase
end
def test_helper_in_a
- assert_raise(ActionView::TemplateError) { A.process(@request, @response) }
+ assert_raise(ActionView::TemplateError) { call_controller(A, "index") }
end
def test_helper_in_b
- assert_equal 'B', B.process(@request, @response).body
+ assert_equal 'B', call_controller(B, "index").last.body
end
def test_helper_in_c
- assert_equal 'C', C.process(@request, @response).body
+ assert_equal 'C', call_controller(C, "index").last.body
end
end
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index 547eb1ef72..78662dc989 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -66,7 +66,7 @@ class Rack::TestCase < ActiveSupport::TestCase
end
def assert_body(body)
- assert_equal body, last_response.body
+ assert_equal body, Array.wrap(last_response.body).join
end
def self.assert_body(body)
--
cgit v1.2.3
From 3900f4007ee6463b8936af23c04017a900673866 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 2 May 2009 14:23:44 -0500
Subject: Deprecate assert_redirect_to's partial hash matching
---
actionpack/lib/action_controller/base/base.rb | 1 -
actionpack/lib/action_controller/base/redirect.rb | 4 ----
actionpack/lib/action_controller/testing/process.rb | 18 +++++++++---------
actionpack/lib/action_dispatch/http/response.rb | 2 --
.../lib/action_dispatch/testing/assertions/response.rb | 9 ++-------
.../lib/action_dispatch/testing/test_response.rb | 6 ++++++
.../test/controller/action_pack_assertions_test.rb | 8 +++++---
actionpack/test/controller/redirect_test.rb | 6 ++++--
8 files changed, 26 insertions(+), 28 deletions(-)
diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb
index 99b5963891..ef97986c0e 100644
--- a/actionpack/lib/action_controller/base/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -820,7 +820,6 @@ module ActionController #:nodoc:
@template = ActionView::Base.new(self.class.view_paths, {}, self, formats)
response.template = @template if response.respond_to?(:template=)
@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/redirect.rb b/actionpack/lib/action_controller/base/redirect.rb
index 2e92117e7c..4849caac0a 100644
--- a/actionpack/lib/action_controller/base/redirect.rb
+++ b/actionpack/lib/action_controller/base/redirect.rb
@@ -48,8 +48,6 @@ module ActionController
status = 302
end
- response.redirected_to = options
-
case options
# The scheme name consist of a letter followed by any combination of
# letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
@@ -82,8 +80,6 @@ module ActionController
# The response body is not reset here, see +erase_render_results+
def erase_redirect_results #:nodoc:
@performed_redirect = false
- response.redirected_to = nil
- response.redirected_to_method_params = nil
response.status = DEFAULT_RENDER_STATUS_CODE
response.headers.delete('Location')
end
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 8315a160ad..f62d18a1f9 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -45,17 +45,16 @@ module ActionController #:nodoc:
end
end
- # Integration test methods such as ActionController::Integration::Session#get
- # and ActionController::Integration::Session#post return objects of class
- # TestResponse, which represent the HTTP response results of the requested
- # controller actions.
- #
- # See Response for more information on controller response objects.
class TestResponse < ActionDispatch::TestResponse
def recycle!
- body_parts.clear
- headers.delete('ETag')
- headers.delete('Last-Modified')
+ @status = 200
+ @header = Rack::Utils::HeaderHash.new(DEFAULT_HEADERS)
+ @writer = lambda { |x| @body << x }
+ @block = nil
+ @length = 0
+ @body = []
+
+ @request = @template = nil
end
end
@@ -132,6 +131,7 @@ module ActionController #:nodoc:
build_request_uri(action, parameters)
Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
+
@controller.process(@request, @response)
end
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 2b969323ca..2618e284fe 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -34,8 +34,6 @@ module ActionDispatch # :nodoc:
DEFAULT_HEADERS = { "Cache-Control" => "no-cache" }
attr_accessor :request
- attr_accessor :redirected_to, :redirected_to_method_params
-
attr_writer :header
alias_method :headers=, :header=
diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb
index a72ce9084f..92e3da580e 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/response.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb
@@ -60,14 +60,9 @@ module ActionDispatch
validate_request!
assert_response(:redirect, message)
- return true if options == @response.redirected_to
+ return true if options == @response.location
- # Support partial arguments for hash redirections
- if options.is_a?(Hash) && @response.redirected_to.is_a?(Hash)
- return true if options.all? {|(key, value)| @response.redirected_to[key] == value}
- end
-
- redirected_to_after_normalisation = normalize_argument_to_redirection(@response.redirected_to)
+ redirected_to_after_normalisation = normalize_argument_to_redirection(@response.location)
options_after_normalisation = normalize_argument_to_redirection(options)
if redirected_to_after_normalisation != options_after_normalisation
diff --git a/actionpack/lib/action_dispatch/testing/test_response.rb b/actionpack/lib/action_dispatch/testing/test_response.rb
index 50c6d85828..c5464f1559 100644
--- a/actionpack/lib/action_dispatch/testing/test_response.rb
+++ b/actionpack/lib/action_dispatch/testing/test_response.rb
@@ -1,4 +1,10 @@
module ActionDispatch
+ # Integration test methods such as ActionController::Integration::Session#get
+ # and ActionController::Integration::Session#post return objects of class
+ # TestResponse, which represent the HTTP response results of the requested
+ # controller actions.
+ #
+ # See Response for more information on controller response objects.
class TestResponse < Response
def self.from_response(response)
new.tap do |resp|
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index 711640f9a9..60957a2f0e 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -514,9 +514,11 @@ class ActionPackHeaderTest < ActionController::TestCase
end
def test_rendering_xml_respects_content_type
- @response.headers['type'] = 'application/pdf'
- process :hello_xml_world
- assert_equal('application/pdf; charset=utf-8', @response.headers['Content-Type'])
+ pending do
+ @response.headers['type'] = 'application/pdf'
+ process :hello_xml_world
+ assert_equal('application/pdf; charset=utf-8', @response.headers['Content-Type'])
+ end
end
def test_render_text_with_custom_content_type
diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb
index 91e21db854..9ad63a1c60 100644
--- a/actionpack/test/controller/redirect_test.rb
+++ b/actionpack/test/controller/redirect_test.rb
@@ -234,8 +234,10 @@ class RedirectTest < ActionController::TestCase
end
def test_redirect_with_partial_params
- get :module_redirect
- assert_redirected_to :action => 'hello_world'
+ pending do
+ get :module_redirect
+ assert_redirected_to :action => 'hello_world'
+ end
end
def test_redirect_to_nil
--
cgit v1.2.3
From a8b75c480fc9774252f5976dcf1a614079822e56 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 2 May 2009 14:57:40 -0500
Subject: Functional test runner finalizes response just like the integration
test runner. In both runners, the @response object will now behave the same.
Some functional tests will need to be updated if they are relying on preprocessed data on the response.
---
.../lib/action_controller/testing/process.rb | 5 ++-
actionpack/lib/action_dispatch/http/response.rb | 2 +-
.../lib/action_dispatch/testing/test_response.rb | 18 ++++------
actionpack/test/controller/cookie_test.rb | 17 +++++----
actionpack/test/controller/render_test.rb | 22 ++++++------
actionpack/test/controller/send_file_test.rb | 8 ++---
actionpack/test/controller/test_test.rb | 4 ++-
actionpack/test/template/body_parts_test.rb | 6 +++-
actionpack/test/template/output_buffer_test.rb | 42 ++++++++++++----------
9 files changed, 66 insertions(+), 58 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index f62d18a1f9..b44ec2f94b 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -132,7 +132,10 @@ module ActionController #:nodoc:
Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
- @controller.process(@request, @response)
+ response = Rack::MockResponse.new(*@controller.process(@request, ActionDispatch::Response.new).to_a)
+ @response.request, @response.template = @request, @controller.template
+ @response.status, @response.headers, @response.body = response.status, response.headers, response.body
+ @response
end
def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil)
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 2618e284fe..133b4f7335 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -185,7 +185,7 @@ module ActionDispatch # :nodoc:
@writer = lambda { |x| callback.call(x) }
@body.call(self, self)
else
- @body.each(&callback)
+ @body.each { |part| callback.call(part.to_s) }
end
@writer = callback
diff --git a/actionpack/lib/action_dispatch/testing/test_response.rb b/actionpack/lib/action_dispatch/testing/test_response.rb
index c5464f1559..c35982e075 100644
--- a/actionpack/lib/action_dispatch/testing/test_response.rb
+++ b/actionpack/lib/action_dispatch/testing/test_response.rb
@@ -93,6 +93,12 @@ module ActionDispatch
ActiveSupport::Deprecation.warn("response.has_template_object? has been deprecated. Use tempate.assigns[name].nil? instead", caller)
!template_objects[name].nil?
end
+
+ # Returns binary content (downloadable file), converted to a String
+ def binary_content
+ ActiveSupport::Deprecation.warn("response.binary_content has been deprecated. Use response.body instead", caller)
+ body
+ end
end
include DeprecatedHelpers
@@ -121,17 +127,5 @@ module ActionDispatch
def client_error?
(400..499).include?(response_code)
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)
- require 'stringio'
-
- sio = StringIO.new
- body_parts.call(self, sio)
-
- sio.rewind
- sio.read
- end
end
end
diff --git a/actionpack/test/controller/cookie_test.rb b/actionpack/test/controller/cookie_test.rb
index c861982698..0f22714071 100644
--- a/actionpack/test/controller/cookie_test.rb
+++ b/actionpack/test/controller/cookie_test.rb
@@ -54,39 +54,38 @@ class CookieTest < ActionController::TestCase
def test_setting_cookie
get :authenticate
- assert_equal ["user_name=david; path=/"], @response.headers["Set-Cookie"]
+ assert_equal "user_name=david; path=/", @response.headers["Set-Cookie"]
assert_equal({"user_name" => "david"}, @response.cookies)
end
def test_setting_with_escapable_characters
get :set_with_with_escapable_characters
- assert_equal ["that+%26+guy=foo+%26+bar+%3D%3E+baz; path=/"], @response.headers["Set-Cookie"]
+ assert_equal "that+%26+guy=foo+%26+bar+%3D%3E+baz; path=/", @response.headers["Set-Cookie"]
assert_equal({"that & guy" => "foo & bar => baz"}, @response.cookies)
end
def test_setting_cookie_for_fourteen_days
get :authenticate_for_fourteen_days
- assert_equal ["user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT"], @response.headers["Set-Cookie"]
+ assert_equal "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT", @response.headers["Set-Cookie"]
assert_equal({"user_name" => "david"}, @response.cookies)
end
def test_setting_cookie_for_fourteen_days_with_symbols
get :authenticate_for_fourteen_days_with_symbols
- assert_equal ["user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT"], @response.headers["Set-Cookie"]
+ assert_equal "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT", @response.headers["Set-Cookie"]
assert_equal({"user_name" => "david"}, @response.cookies)
end
def test_setting_cookie_with_http_only
get :authenticate_with_http_only
- assert_equal ["user_name=david; path=/; HttpOnly"], @response.headers["Set-Cookie"]
+ assert_equal "user_name=david; path=/; HttpOnly", @response.headers["Set-Cookie"]
assert_equal({"user_name" => "david"}, @response.cookies)
end
def test_multiple_cookies
get :set_multiple_cookies
assert_equal 2, @response.cookies.size
- assert_equal "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT", @response.headers["Set-Cookie"][0]
- assert_equal "login=XJ-122; path=/", @response.headers["Set-Cookie"][1]
+ assert_equal "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT\nlogin=XJ-122; path=/", @response.headers["Set-Cookie"]
assert_equal({"login" => "XJ-122", "user_name" => "david"}, @response.cookies)
end
@@ -96,7 +95,7 @@ class CookieTest < ActionController::TestCase
def test_expiring_cookie
get :logout
- assert_equal ["user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"], @response.headers["Set-Cookie"]
+ assert_equal "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT", @response.headers["Set-Cookie"]
assert_equal({"user_name" => nil}, @response.cookies)
end
@@ -117,6 +116,6 @@ class CookieTest < ActionController::TestCase
def test_delete_cookie_with_path
get :delete_cookie_with_path
- assert_equal ["user_name=; path=/beaten; expires=Thu, 01-Jan-1970 00:00:00 GMT"], @response.headers["Set-Cookie"]
+ assert_equal "user_name=; path=/beaten; expires=Thu, 01-Jan-1970 00:00:00 GMT", @response.headers["Set-Cookie"]
end
end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 023bf0eeaa..dd2dd7a502 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -1293,15 +1293,15 @@ class RenderTest < ActionController::TestCase
def test_head_with_symbolic_status
get :head_with_symbolic_status, :status => "ok"
- assert_equal "200 OK", @response.status
+ assert_equal 200, @response.status
assert_response :ok
get :head_with_symbolic_status, :status => "not_found"
- assert_equal "404 Not Found", @response.status
+ assert_equal 404, @response.status
assert_response :not_found
get :head_with_symbolic_status, :status => "no_content"
- assert_equal "204 No Content", @response.status
+ assert_equal 204, @response.status
assert !@response.headers.include?('Content-Length')
assert_response :no_content
@@ -1322,7 +1322,7 @@ class RenderTest < ActionController::TestCase
def test_head_with_string_status
get :head_with_string_status, :status => "404 Eat Dirt"
assert_equal 404, @response.response_code
- assert_equal "Eat Dirt", @response.message
+ assert_equal "Not Found", @response.message
assert_response :not_found
end
@@ -1590,7 +1590,7 @@ class EtagRenderTest < ActionController::TestCase
def test_render_against_etag_request_should_304_when_match
@request.if_none_match = etag_for("hello david")
get :render_hello_world_from_variable
- assert_equal "304 Not Modified", @response.status
+ assert_equal 304, @response.status
assert @response.body.empty?
end
@@ -1603,13 +1603,13 @@ class EtagRenderTest < ActionController::TestCase
def test_render_against_etag_request_should_200_when_no_match
@request.if_none_match = etag_for("hello somewhere else")
get :render_hello_world_from_variable
- assert_equal "200 OK", @response.status
+ assert_equal 200, @response.status
assert !@response.body.empty?
end
def test_render_should_not_set_etag_when_last_modified_has_been_specified
get :render_hello_world_with_last_modified_set
- assert_equal "200 OK", @response.status
+ assert_equal 200, @response.status
assert_not_nil @response.last_modified
assert_nil @response.etag
assert @response.body.present?
@@ -1623,11 +1623,11 @@ class EtagRenderTest < ActionController::TestCase
@request.if_none_match = expected_etag
get :render_hello_world_from_variable
- assert_equal "304 Not Modified", @response.status
+ assert_equal 304, @response.status
@request.if_none_match = "\"diftag\""
get :render_hello_world_from_variable
- assert_equal "200 OK", @response.status
+ assert_equal 200, @response.status
end
def render_with_404_shouldnt_have_etag
@@ -1695,7 +1695,7 @@ class LastModifiedRenderTest < ActionController::TestCase
def test_request_not_modified
@request.if_modified_since = @last_modified
get :conditional_hello
- assert_equal "304 Not Modified", @response.status
+ assert_equal 304, @response.status
assert @response.body.blank?, @response.body
assert_equal @last_modified, @response.headers['Last-Modified']
end
@@ -1710,7 +1710,7 @@ class LastModifiedRenderTest < ActionController::TestCase
def test_request_modified
@request.if_modified_since = 'Thu, 16 Jul 2008 00:00:00 GMT'
get :conditional_hello
- assert_equal "200 OK", @response.status
+ assert_equal 200, @response.status
assert !@response.body.blank?
assert_equal @last_modified, @response.headers['Last-Modified']
end
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index 2e14a0a32c..6007ebef7a 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -44,12 +44,12 @@ class SendFileTest < ActionController::TestCase
response = nil
assert_nothing_raised { response = process('file') }
assert_not_nil response
- assert_kind_of Proc, response.body_parts
+ assert_kind_of Array, response.body_parts
require 'stringio'
output = StringIO.new
output.binmode
- assert_nothing_raised { response.body_parts.call(response, output) }
+ assert_nothing_raised { response.body_parts.each { |part| output << part.to_s } }
assert_equal file_data, output.string
end
@@ -149,13 +149,13 @@ class SendFileTest < ActionController::TestCase
define_method "test_send_#{method}_status" do
@controller.options = { :stream => false, :status => 500 }
assert_nothing_raised { assert_not_nil process(method) }
- assert_equal '500 Internal Server Error', @response.status
+ assert_equal 500, @response.status
end
define_method "test_default_send_#{method}_status" do
@controller.options = { :stream => false }
assert_nothing_raised { assert_not_nil process(method) }
- assert_equal ActionController::DEFAULT_RENDER_STATUS_CODE, @response.status
+ assert_equal 200, @response.status
end
end
end
diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb
index 919f9815ec..9e88188b9a 100644
--- a/actionpack/test/controller/test_test.rb
+++ b/actionpack/test/controller/test_test.rb
@@ -614,7 +614,9 @@ XML
def test_binary_content_works_with_send_file
get :test_send_file
- assert_nothing_raised(NoMethodError) { @response.binary_content }
+ assert_deprecated do
+ assert_nothing_raised(NoMethodError) { @response.binary_content }
+ end
end
protected
diff --git a/actionpack/test/template/body_parts_test.rb b/actionpack/test/template/body_parts_test.rb
index 5be8533293..e17092a452 100644
--- a/actionpack/test/template/body_parts_test.rb
+++ b/actionpack/test/template/body_parts_test.rb
@@ -16,7 +16,11 @@ class BodyPartsTest < ActionController::TestCase
def test_body_parts
get :index
- assert_equal RENDERINGS, @response.body_parts
+ pending do
+ # TestProcess buffers body_parts into body
+ # TODO: Rewrite test w/o going through process
+ assert_equal RENDERINGS, @response.body_parts
+ end
assert_equal RENDERINGS.join, @response.body
end
end
diff --git a/actionpack/test/template/output_buffer_test.rb b/actionpack/test/template/output_buffer_test.rb
index bc17f36783..3faea64db3 100644
--- a/actionpack/test/template/output_buffer_test.rb
+++ b/actionpack/test/template/output_buffer_test.rb
@@ -10,26 +10,32 @@ class OutputBufferTest < ActionController::TestCase
tests TestController
def test_flush_output_buffer
- # Start with the default body parts
- get :index
- assert_equal ['foo'], @response.body_parts
- assert_nil @controller.template.output_buffer
+ pending do
+ # TODO: This tests needs to be rewritten due
+ # The @response is not the same response object assigned
+ # to the @controller.template
- # Nil output buffer is skipped
- @controller.template.flush_output_buffer
- assert_nil @controller.template.output_buffer
- assert_equal ['foo'], @response.body_parts
+ # Start with the default body parts
+ get :index
+ assert_equal ['foo'], @response.body_parts
+ assert_nil @controller.template.output_buffer
- # Empty output buffer is skipped
- @controller.template.output_buffer = ''
- @controller.template.flush_output_buffer
- assert_equal '', @controller.template.output_buffer
- assert_equal ['foo'], @response.body_parts
+ # Nil output buffer is skipped
+ @controller.template.flush_output_buffer
+ assert_nil @controller.template.output_buffer
+ assert_equal ['foo'], @response.body_parts
- # Flushing appends the output buffer to the body parts
- @controller.template.output_buffer = 'bar'
- @controller.template.flush_output_buffer
- assert_equal '', @controller.template.output_buffer
- assert_equal ['foo', 'bar'], @response.body_parts
+ # Empty output buffer is skipped
+ @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
+ @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
end
--
cgit v1.2.3
From f32cf44870549c6cc5b6e6c84cffc1facf6ec38e Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 2 May 2009 15:29:18 -0500
Subject: Switch functional tests to run through the rack interface instead of
process
---
actionpack/lib/action_controller/base/base.rb | 12 ++++++++----
actionpack/lib/action_controller/dispatch/dispatcher.rb | 2 +-
actionpack/lib/action_controller/dispatch/rescue.rb | 2 +-
actionpack/lib/action_controller/routing/route_set.rb | 2 +-
actionpack/lib/action_controller/testing/process.rb | 13 +++++++++++--
actionpack/lib/action_dispatch/testing/test_request.rb | 5 +++++
actionpack/test/controller/caching_test.rb | 2 +-
7 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb
index ef97986c0e..eb65f59ddd 100644
--- a/actionpack/lib/action_controller/base/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -371,10 +371,7 @@ module ActionController #:nodoc:
class << self
def call(env)
- # HACK: For global rescue to have access to the original request and response
- request = env["action_controller.rescue.request"] ||= ActionDispatch::Request.new(env)
- response = env["action_controller.rescue.response"] ||= ActionDispatch::Response.new
- process(request, response)
+ new.call(env)
end
# Factory for the standard create, process loop where the controller is discarded after processing.
@@ -511,6 +508,13 @@ module ActionController #:nodoc:
end
public
+ def call(env)
+ # HACK: For global rescue to have access to the original request and response
+ request = env["action_dispatch.rescue.request"] ||= ActionDispatch::Request.new(env)
+ response = env["action_dispatch.rescue.response"] ||= ActionDispatch::Response.new
+ process(request, response).to_a
+ end
+
# Extracts the action_name from the request parameters and performs that action.
def process(request, response, method = :perform_action, *arguments) #:nodoc:
response.request = request
diff --git a/actionpack/lib/action_controller/dispatch/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb
index bb9d8bd063..25844bf2a2 100644
--- a/actionpack/lib/action_controller/dispatch/dispatcher.rb
+++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb
@@ -80,7 +80,7 @@ module ActionController
Routing::Routes.call(env)
rescue Exception => exception
if controller ||= (::ApplicationController rescue Base)
- controller.call_with_exception(env, exception).to_a
+ controller.call_with_exception(env, exception)
else
raise exception
end
diff --git a/actionpack/lib/action_controller/dispatch/rescue.rb b/actionpack/lib/action_controller/dispatch/rescue.rb
index df80ac0909..2f3b40c231 100644
--- a/actionpack/lib/action_controller/dispatch/rescue.rb
+++ b/actionpack/lib/action_controller/dispatch/rescue.rb
@@ -62,7 +62,7 @@ module ActionController #:nodoc:
def call_with_exception(env, exception) #:nodoc:
request = env["action_controller.rescue.request"] ||= ActionDispatch::Request.new(env)
response = env["action_controller.rescue.response"] ||= ActionDispatch::Response.new
- new.process(request, response, :rescue_action, exception)
+ new.process(request, response, :rescue_action, exception).to_a
end
end
diff --git a/actionpack/lib/action_controller/routing/route_set.rb b/actionpack/lib/action_controller/routing/route_set.rb
index 70cd1f642d..172b867bf0 100644
--- a/actionpack/lib/action_controller/routing/route_set.rb
+++ b/actionpack/lib/action_controller/routing/route_set.rb
@@ -430,7 +430,7 @@ module ActionController
def call(env)
request = ActionDispatch::Request.new(env)
app = Routing::Routes.recognize(request)
- app.call(env).to_a
+ app.call(env)
end
def recognize(request)
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index b44ec2f94b..49e8322491 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -35,12 +35,13 @@ module ActionController #:nodoc:
end
data = params.to_query
- @env['CONTENT_LENGTH'] = data.length
+ @env['CONTENT_LENGTH'] = data.length.to_s
@env['rack.input'] = StringIO.new(data)
end
def recycle!
@env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
+ @env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
@env['action_dispatch.request.query_parameters'] = {}
end
end
@@ -132,7 +133,15 @@ module ActionController #:nodoc:
Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
- response = Rack::MockResponse.new(*@controller.process(@request, ActionDispatch::Response.new).to_a)
+ env = @request.env
+ app = @controller
+
+ # TODO: Enable Lint
+ # app = Rack::Lint.new(app)
+
+ status, headers, body = app.call(env)
+ response = Rack::MockResponse.new(status, headers, body)
+
@response.request, @response.template = @request, @controller.template
@response.status, @response.headers, @response.body = response.status, response.headers, response.body
@response
diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb
index 5d8cd7e619..20288aa7a5 100644
--- a/actionpack/lib/action_dispatch/testing/test_request.rb
+++ b/actionpack/lib/action_dispatch/testing/test_request.rb
@@ -16,6 +16,7 @@ module ActionDispatch
def env
write_cookies!
+ delete_nil_values!
super
end
@@ -74,5 +75,9 @@ module ActionDispatch
@env['HTTP_COOKIE'] = @cookies.map { |name, value| "#{name}=#{value};" }.join(' ')
end
end
+
+ def delete_nil_values!
+ @env.delete_if { |k, v| v.nil? }
+ end
end
end
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index 10b904481d..6b9d1056a3 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -111,7 +111,7 @@ class PageCachingTest < ActionController::TestCase
end
def test_should_cache_ok_at_custom_path
- @request.stubs(:path).returns("/index.html")
+ @request.request_uri = "/index.html"
get :ok
assert_response :ok
assert File.exist?("#{FILE_STORE_PATH}/index.html")
--
cgit v1.2.3
From 24affdc88c4a4af03ce1ec5b23c3def18b90effe Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 2 May 2009 15:37:29 -0500
Subject: Deprecate Controller.process interface
---
actionpack/lib/action_controller/base/base.rb | 1 +
actionpack/test/controller/filters_test.rb | 2 +-
actionpack/test/controller/helper_test.rb | 20 +++++++++++---------
3 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb
index eb65f59ddd..60567454b1 100644
--- a/actionpack/lib/action_controller/base/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -376,6 +376,7 @@ module ActionController #:nodoc:
# Factory for the standard create, process loop where the controller is discarded after processing.
def process(request, response) #:nodoc:
+ ActiveSupport::Deprecation.warn("Controller.process has been deprecated. Use Controller.call instead", caller)
new.process(request, response)
end
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index 9e74538310..5876f55420 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -603,7 +603,7 @@ class FilterTest < Test::Unit::TestCase
%w(foo bar baz).each do |action|
request = ActionController::TestRequest.new
request.query_parameters[:choose] = action
- response = DynamicDispatchController.process(request, ActionController::TestResponse.new)
+ response = Rack::MockResponse.new(*DynamicDispatchController.call(request.env))
assert_equal action, response.body
end
end
diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb
index 58addc123d..e72bce1791 100644
--- a/actionpack/test/controller/helper_test.rb
+++ b/actionpack/test/controller/helper_test.rb
@@ -102,19 +102,19 @@ class HelperTest < Test::Unit::TestCase
end
def test_helper_for_nested_controller
- request = ActionController::TestRequest.new
- response = ActionController::TestResponse.new
+ request = ActionController::TestRequest.new
request.action = 'render_hello_world'
- assert_equal 'hello: Iz guuut!', Fun::GamesController.process(request, response).body
+ response = Rack::MockResponse.new(*Fun::GamesController.call(request.env))
+ assert_equal 'hello: Iz guuut!', response.body
end
def test_helper_for_acronym_controller
- request = ActionController::TestRequest.new
- response = ActionController::TestResponse.new
+ request = ActionController::TestRequest.new
request.action = 'test'
- assert_equal 'test: baz', Fun::PdfController.process(request, response).body
+ response = Rack::MockResponse.new(*Fun::PdfController.call(request.env))
+ assert_equal 'test: baz', response.body
end
def test_all_helpers
@@ -211,14 +211,16 @@ class IsolatedHelpersTest < Test::Unit::TestCase
end
def test_helper_in_a
- assert_raise(ActionView::TemplateError) { A.process(@request, @response) }
+ assert_raise(ActionView::TemplateError) { A.call(@request.env) }
end
def test_helper_in_b
- assert_equal 'B', B.process(@request, @response).body
+ response = Rack::MockResponse.new(*B.call(@request.env))
+ assert_equal 'B', response.body
end
def test_helper_in_c
- assert_equal 'C', C.process(@request, @response).body
+ response = Rack::MockResponse.new(*C.call(@request.env))
+ assert_equal 'C', response.body
end
end
--
cgit v1.2.3
From 945bf9c254b5bfb56df874c1a3f7f0f1e89dc8b8 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Sat, 2 May 2009 15:16:12 -0700
Subject: Check for sibling Active Support first
---
activerecord/lib/active_record.rb | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 500a90d6cb..1982ffc791 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -21,15 +21,10 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
-begin
- require 'active_support'
-rescue LoadError
- activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
- if File.directory?(activesupport_path)
- $:.unshift activesupport_path
- require 'active_support'
- end
+"#{File.dirname(__FILE__)}/../../activesupport/lib".tap do |path|
+ $:.unshift(path) if File.directory?(path)
end
+require 'active_support'
require 'active_support/core/all'
module ActiveRecord
--
cgit v1.2.3
From 1c6fcbfd2d67ce2b2faa29d956566b48e9a61188 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Sat, 2 May 2009 15:30:00 -0700
Subject: Fix implicit ordering expectation
---
actionpack/test/dispatch/test_request_test.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb
index 19b5e2988b..5da02b2ea6 100644
--- a/actionpack/test/dispatch/test_request_test.rb
+++ b/actionpack/test/dispatch/test_request_test.rb
@@ -40,6 +40,6 @@ class TestRequestTest < ActiveSupport::TestCase
req.cookies["login"] = "XJ-122"
assert_equal({"user_name" => "david", "login" => "XJ-122"}, req.cookies)
- assert_equal "login=XJ-122; user_name=david;", req.env["HTTP_COOKIE"]
+ assert_equal %w(login=XJ-122 user_name=david), req.env["HTTP_COOKIE"].split(/; ?/).sort
end
end
--
cgit v1.2.3
From 9047c9809deeb1aaa3735472287265720e5cd37f Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Sat, 2 May 2009 15:30:00 -0700
Subject: Fix implicit ordering expectation
---
actionpack/test/dispatch/test_request_test.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb
index 19b5e2988b..5da02b2ea6 100644
--- a/actionpack/test/dispatch/test_request_test.rb
+++ b/actionpack/test/dispatch/test_request_test.rb
@@ -40,6 +40,6 @@ class TestRequestTest < ActiveSupport::TestCase
req.cookies["login"] = "XJ-122"
assert_equal({"user_name" => "david", "login" => "XJ-122"}, req.cookies)
- assert_equal "login=XJ-122; user_name=david;", req.env["HTTP_COOKIE"]
+ assert_equal %w(login=XJ-122 user_name=david), req.env["HTTP_COOKIE"].split(/; ?/).sort
end
end
--
cgit v1.2.3
From 11af089cee0a0e744e267d32becfe2c66a586d31 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 2 May 2009 23:02:22 -0500
Subject: Extract ActionController rescue templates into Rescue and
ShowExceptions middleware.
This commit breaks all exception catching plugins like ExceptionNotifier. These plugins should be rewritten as middleware instead overriding Controller#rescue_action_in_public.
---
actionpack/lib/action_controller.rb | 2 +-
actionpack/lib/action_controller/base/base.rb | 9 +-
actionpack/lib/action_controller/base/rescue.rb | 50 +++
.../lib/action_controller/dispatch/dispatcher.rb | 16 +-
.../lib/action_controller/dispatch/middlewares.rb | 5 +
.../lib/action_controller/dispatch/rescue.rb | 185 -----------
.../templates/rescues/_request_and_response.erb | 24 --
.../dispatch/templates/rescues/_trace.erb | 26 --
.../dispatch/templates/rescues/diagnostics.erb | 10 -
.../dispatch/templates/rescues/layout.erb | 29 --
.../templates/rescues/missing_template.erb | 2 -
.../dispatch/templates/rescues/routing_error.erb | 10 -
.../dispatch/templates/rescues/template_error.erb | 21 --
.../dispatch/templates/rescues/unknown_action.erb | 2 -
actionpack/lib/action_dispatch.rb | 2 +
.../lib/action_dispatch/middleware/rescue.rb | 14 +
.../action_dispatch/middleware/show_exceptions.rb | 142 +++++++++
.../templates/rescues/_request_and_response.erb | 24 ++
.../middleware/templates/rescues/_trace.erb | 26 ++
.../middleware/templates/rescues/diagnostics.erb | 10 +
.../middleware/templates/rescues/layout.erb | 29 ++
.../templates/rescues/missing_template.erb | 2 +
.../middleware/templates/rescues/routing_error.erb | 10 +
.../templates/rescues/template_error.erb | 21 ++
.../templates/rescues/unknown_action.erb | 2 +
.../action_dispatch/testing/assertions/response.rb | 8 +-
.../test/controller/action_pack_assertions_test.rb | 2 +-
actionpack/test/controller/base_test.rb | 9 +-
actionpack/test/controller/caching_test.rb | 3 +
.../deprecation/deprecated_base_methods_test.rb | 6 -
actionpack/test/controller/dispatcher_test.rb | 13 -
actionpack/test/controller/filters_test.rb | 5 +
actionpack/test/controller/layout_test.rb | 3 +-
actionpack/test/controller/rescue_test.rb | 346 +++------------------
actionpack/test/dispatch/show_exceptions_test.rb | 103 ++++++
35 files changed, 509 insertions(+), 662 deletions(-)
create mode 100644 actionpack/lib/action_controller/base/rescue.rb
delete mode 100644 actionpack/lib/action_controller/dispatch/rescue.rb
delete mode 100644 actionpack/lib/action_controller/dispatch/templates/rescues/_request_and_response.erb
delete mode 100644 actionpack/lib/action_controller/dispatch/templates/rescues/_trace.erb
delete mode 100644 actionpack/lib/action_controller/dispatch/templates/rescues/diagnostics.erb
delete mode 100644 actionpack/lib/action_controller/dispatch/templates/rescues/layout.erb
delete mode 100644 actionpack/lib/action_controller/dispatch/templates/rescues/missing_template.erb
delete mode 100644 actionpack/lib/action_controller/dispatch/templates/rescues/routing_error.erb
delete mode 100644 actionpack/lib/action_controller/dispatch/templates/rescues/template_error.erb
delete mode 100644 actionpack/lib/action_controller/dispatch/templates/rescues/unknown_action.erb
create mode 100644 actionpack/lib/action_dispatch/middleware/rescue.rb
create mode 100644 actionpack/lib/action_dispatch/middleware/show_exceptions.rb
create mode 100644 actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb
create mode 100644 actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb
create mode 100644 actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb
create mode 100644 actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb
create mode 100644 actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.erb
create mode 100644 actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
create mode 100644 actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb
create mode 100644 actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb
create mode 100644 actionpack/test/dispatch/show_exceptions_test.rb
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index aee6b9dc9f..ab78bc9222 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -60,7 +60,7 @@ module ActionController
autoload :Redirector, 'action_controller/base/redirect'
autoload :Renderer, 'action_controller/base/render'
autoload :RequestForgeryProtection, 'action_controller/base/request_forgery_protection'
- autoload :Rescue, 'action_controller/dispatch/rescue'
+ autoload :Rescue, 'action_controller/base/rescue'
autoload :Resources, 'action_controller/routing/resources'
autoload :Responder, 'action_controller/base/responder'
autoload :Routing, 'action_controller/routing'
diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb
index 60567454b1..7bbde519cc 100644
--- a/actionpack/lib/action_controller/base/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -30,10 +30,6 @@ module ActionController #:nodoc:
def allowed_methods_header
allowed_methods.map { |method_symbol| method_symbol.to_s.upcase } * ', '
end
-
- def handle_response!(response)
- response.headers['Allow'] ||= allowed_methods_header
- end
end
class NotImplemented < MethodNotAllowed #:nodoc:
@@ -510,9 +506,8 @@ module ActionController #:nodoc:
public
def call(env)
- # HACK: For global rescue to have access to the original request and response
- request = env["action_dispatch.rescue.request"] ||= ActionDispatch::Request.new(env)
- response = env["action_dispatch.rescue.response"] ||= ActionDispatch::Response.new
+ request = ActionDispatch::Request.new(env)
+ response = ActionDispatch::Response.new
process(request, response).to_a
end
diff --git a/actionpack/lib/action_controller/base/rescue.rb b/actionpack/lib/action_controller/base/rescue.rb
new file mode 100644
index 0000000000..2717a06a37
--- /dev/null
+++ b/actionpack/lib/action_controller/base/rescue.rb
@@ -0,0 +1,50 @@
+module ActionController #:nodoc:
+ # Actions that fail to perform as expected throw exceptions. These
+ # exceptions can either be rescued for the public view (with a nice
+ # user-friendly explanation) or for the developers view (with tons of
+ # debugging information). The developers view is already implemented by
+ # the Action Controller, but the public view should be tailored to your
+ # specific application.
+ #
+ # The default behavior for public exceptions is to render a static html
+ # file with the name of the error code thrown. If no such file exists, an
+ # empty response is sent with the correct status code.
+ #
+ # You can override what constitutes a local request by overriding the
+ # local_request? method in your own controller. Custom rescue
+ # behavior is achieved by overriding the rescue_action_in_public
+ # and rescue_action_locally methods.
+ module Rescue
+ def self.included(base) #:nodoc:
+ base.send :include, ActiveSupport::Rescuable
+ base.extend(ClassMethods)
+
+ base.class_eval do
+ alias_method_chain :perform_action, :rescue
+ end
+ end
+
+ module ClassMethods
+ def rescue_action(env)
+ exception = env.delete('action_dispatch.rescue.exception')
+ request = ActionDispatch::Request.new(env)
+ response = ActionDispatch::Response.new
+ new.process(request, response, :rescue_action, exception).to_a
+ end
+ end
+
+ protected
+ # Exception handler called when the performance of an action raises
+ # an exception.
+ def rescue_action(exception)
+ rescue_with_handler(exception) || raise(exception)
+ end
+
+ private
+ def perform_action_with_rescue
+ perform_action_without_rescue
+ rescue Exception => exception
+ rescue_action(exception)
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/dispatch/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb
index 25844bf2a2..c0eb359547 100644
--- a/actionpack/lib/action_controller/dispatch/dispatcher.rb
+++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb
@@ -75,18 +75,10 @@ module ActionController
end
def _call(env)
- begin
- run_callbacks :before_dispatch
- Routing::Routes.call(env)
- rescue Exception => exception
- if controller ||= (::ApplicationController rescue Base)
- controller.call_with_exception(env, exception)
- else
- raise exception
- end
- ensure
- run_callbacks :after_dispatch, :enumerator => :reverse_each
- end
+ run_callbacks :before_dispatch
+ Routing::Routes.call(env)
+ ensure
+ run_callbacks :after_dispatch, :enumerator => :reverse_each
end
def flush_logger
diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb
index b5adbae746..31a7b00d28 100644
--- a/actionpack/lib/action_controller/dispatch/middlewares.rb
+++ b/actionpack/lib/action_controller/dispatch/middlewares.rb
@@ -3,6 +3,11 @@ use "Rack::Lock", :if => lambda {
}
use "ActionDispatch::Failsafe"
+use "ActionDispatch::ShowExceptions", lambda { ActionController::Base.consider_all_requests_local }
+use "ActionDispatch::Rescue", lambda {
+ controller = (::ApplicationController rescue ActionController::Base)
+ controller.method(:rescue_action)
+}
use lambda { ActionController::Base.session_store },
lambda { ActionController::Base.session_options }
diff --git a/actionpack/lib/action_controller/dispatch/rescue.rb b/actionpack/lib/action_controller/dispatch/rescue.rb
deleted file mode 100644
index 2f3b40c231..0000000000
--- a/actionpack/lib/action_controller/dispatch/rescue.rb
+++ /dev/null
@@ -1,185 +0,0 @@
-module ActionController #:nodoc:
- # Actions that fail to perform as expected throw exceptions. These
- # exceptions can either be rescued for the public view (with a nice
- # user-friendly explanation) or for the developers view (with tons of
- # debugging information). The developers view is already implemented by
- # the Action Controller, but the public view should be tailored to your
- # specific application.
- #
- # The default behavior for public exceptions is to render a static html
- # file with the name of the error code thrown. If no such file exists, an
- # empty response is sent with the correct status code.
- #
- # You can override what constitutes a local request by overriding the
- # local_request? method in your own controller. Custom rescue
- # behavior is achieved by overriding the rescue_action_in_public
- # and rescue_action_locally methods.
- module Rescue
- LOCALHOST = '127.0.0.1'.freeze
-
- DEFAULT_RESCUE_RESPONSE = :internal_server_error
- DEFAULT_RESCUE_RESPONSES = {
- 'ActionController::RoutingError' => :not_found,
- 'ActionController::UnknownAction' => :not_found,
- 'ActiveRecord::RecordNotFound' => :not_found,
- 'ActiveRecord::StaleObjectError' => :conflict,
- 'ActiveRecord::RecordInvalid' => :unprocessable_entity,
- 'ActiveRecord::RecordNotSaved' => :unprocessable_entity,
- 'ActionController::MethodNotAllowed' => :method_not_allowed,
- 'ActionController::NotImplemented' => :not_implemented,
- 'ActionController::InvalidAuthenticityToken' => :unprocessable_entity
- }
-
- DEFAULT_RESCUE_TEMPLATE = 'diagnostics'
- DEFAULT_RESCUE_TEMPLATES = {
- 'ActionView::MissingTemplate' => 'missing_template',
- 'ActionController::RoutingError' => 'routing_error',
- 'ActionController::UnknownAction' => 'unknown_action',
- 'ActionView::TemplateError' => 'template_error'
- }
-
- RESCUES_TEMPLATE_PATH = ActionView::Template::FileSystemPath.new(
- File.join(File.dirname(__FILE__), "templates"))
-
- def self.included(base) #:nodoc:
- base.cattr_accessor :rescue_responses
- base.rescue_responses = Hash.new(DEFAULT_RESCUE_RESPONSE)
- base.rescue_responses.update DEFAULT_RESCUE_RESPONSES
-
- base.cattr_accessor :rescue_templates
- base.rescue_templates = Hash.new(DEFAULT_RESCUE_TEMPLATE)
- base.rescue_templates.update DEFAULT_RESCUE_TEMPLATES
-
- base.extend(ClassMethods)
- base.send :include, ActiveSupport::Rescuable
-
- base.class_eval do
- alias_method_chain :perform_action, :rescue
- end
- end
-
- module ClassMethods
- def call_with_exception(env, exception) #:nodoc:
- request = env["action_controller.rescue.request"] ||= ActionDispatch::Request.new(env)
- response = env["action_controller.rescue.response"] ||= ActionDispatch::Response.new
- new.process(request, response, :rescue_action, exception).to_a
- end
- end
-
- protected
- # Exception handler called when the performance of an action raises
- # an exception.
- def rescue_action(exception)
- rescue_with_handler(exception) ||
- rescue_action_without_handler(exception)
- end
-
- # Overwrite to implement custom logging of errors. By default
- # logs as fatal.
- def log_error(exception) #:doc:
- ActiveSupport::Deprecation.silence do
- if ActionView::TemplateError === exception
- logger.fatal(exception.to_s)
- else
- logger.fatal(
- "\n#{exception.class} (#{exception.message}):\n " +
- clean_backtrace(exception).join("\n ") + "\n\n"
- )
- end
- end
- end
-
- # Overwrite to implement public exception handling (for requests
- # answering false to local_request? ). By default will call
- # render_optional_error_file. Override this method to provide more
- # user friendly error messages.
- def rescue_action_in_public(exception) #:doc:
- render_optional_error_file response_code_for_rescue(exception)
- end
-
- # Attempts to render a static error page based on the
- # status_code thrown, or just return headers if no such file
- # exists. At first, it will try to render a localized static page.
- # For example, if a 500 error is being handled Rails and locale is :da,
- # it will first attempt to render the file at public/500.da.html
- # then attempt to render public/500.html . If none of them exist,
- # the body of the response will be left empty.
- def render_optional_error_file(status_code)
- status = interpret_status(status_code)
- locale_path = "#{Rails.public_path}/#{status[0,3]}.#{I18n.locale}.html" if I18n.locale
- path = "#{Rails.public_path}/#{status[0,3]}.html"
-
- if locale_path && File.exist?(locale_path)
- render :file => locale_path, :status => status, :content_type => Mime::HTML
- elsif File.exist?(path)
- render :file => path, :status => status, :content_type => Mime::HTML
- else
- head status
- end
- end
-
- # True if the request came from localhost, 127.0.0.1. Override this
- # method if you wish to redefine the meaning of a local request to
- # include remote IP addresses or other criteria.
- def local_request? #:doc:
- request.remote_addr == LOCALHOST && request.remote_ip == LOCALHOST
- end
-
- # Render detailed diagnostics for unhandled exceptions rescued from
- # a controller action.
- def rescue_action_locally(exception)
- @template.instance_variable_set("@exception", exception)
- @template.instance_variable_set("@rescues_path", RESCUES_TEMPLATE_PATH)
- @template.instance_variable_set("@contents",
- @template._render_template(template_path_for_local_rescue(exception)))
-
- response.content_type = Mime::HTML
- response.status = interpret_status(response_code_for_rescue(exception))
-
- content = @template._render_template(rescues_path("layout"))
- render_for_text(content)
- end
-
- def rescue_action_without_handler(exception)
- log_error(exception) if logger
- erase_results if performed?
-
- # Let the exception alter the response if it wants.
- # For example, MethodNotAllowed sets the Allow header.
- if exception.respond_to?(:handle_response!)
- exception.handle_response!(response)
- end
-
- if consider_all_requests_local || local_request?
- rescue_action_locally(exception)
- else
- rescue_action_in_public(exception)
- end
- end
-
- private
- def perform_action_with_rescue #:nodoc:
- perform_action_without_rescue
- rescue Exception => exception
- rescue_action(exception)
- end
-
- def rescues_path(template_name)
- RESCUES_TEMPLATE_PATH.find_by_parts("rescues/#{template_name}.erb")
- end
-
- def template_path_for_local_rescue(exception)
- rescues_path(rescue_templates[exception.class.name])
- end
-
- def response_code_for_rescue(exception)
- rescue_responses[exception.class.name]
- end
-
- def clean_backtrace(exception)
- defined?(Rails) && Rails.respond_to?(:backtrace_cleaner) ?
- Rails.backtrace_cleaner.clean(exception.backtrace) :
- exception.backtrace
- end
- end
-end
diff --git a/actionpack/lib/action_controller/dispatch/templates/rescues/_request_and_response.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/_request_and_response.erb
deleted file mode 100644
index 64b34650b1..0000000000
--- a/actionpack/lib/action_controller/dispatch/templates/rescues/_request_and_response.erb
+++ /dev/null
@@ -1,24 +0,0 @@
-<% unless @exception.blamed_files.blank? %>
- <% if (hide = @exception.blamed_files.length > 8) %>
- Show blamed files
- <% end %>
- ><%=h @exception.describe_blame %>
-<% end %>
-
-<%
- clean_params = request.parameters.clone
- clean_params.delete("action")
- clean_params.delete("controller")
-
- request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n")
-%>
-
-Request
-Parameters :
<%=h request_dump %>
-
-Show session dump
-<%= debug(request.session.instance_variable_get("@data")) %>
-
-
-Response
-Headers :
<%=h response ? response.headers.inspect.gsub(',', ",\n") : 'None' %>
diff --git a/actionpack/lib/action_controller/dispatch/templates/rescues/_trace.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/_trace.erb
deleted file mode 100644
index bb2d8375bd..0000000000
--- a/actionpack/lib/action_controller/dispatch/templates/rescues/_trace.erb
+++ /dev/null
@@ -1,26 +0,0 @@
-<%
- traces = [
- ["Application Trace", @exception.application_backtrace],
- ["Framework Trace", @exception.framework_backtrace],
- ["Full Trace", @exception.clean_backtrace]
- ]
- names = traces.collect {|name, trace| name}
-%>
-
-RAILS_ROOT: <%= defined?(RAILS_ROOT) ? RAILS_ROOT : "unset" %>
-
-
- <% names.each do |name| %>
- <%
- show = "document.getElementById('#{name.gsub /\s/, '-'}').style.display='block';"
- hide = (names - [name]).collect {|hide_name| "document.getElementById('#{hide_name.gsub /\s/, '-'}').style.display='none';"}
- %>
-
<%= name %> <%= '|' unless names.last == name %>
- <% end %>
-
- <% traces.each do |name, trace| %>
-
;">
-
<%= trace.join "\n" %>
-
- <% end %>
-
diff --git a/actionpack/lib/action_controller/dispatch/templates/rescues/diagnostics.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/diagnostics.erb
deleted file mode 100644
index e5c647c826..0000000000
--- a/actionpack/lib/action_controller/dispatch/templates/rescues/diagnostics.erb
+++ /dev/null
@@ -1,10 +0,0 @@
-
- <%=h @exception.class.to_s %>
- <% if request.parameters['controller'] %>
- in <%=h request.parameters['controller'].humanize %>Controller<% if request.parameters['action'] %>#<%=h request.parameters['action'] %><% end %>
- <% end %>
-
-<%=h @exception.clean_message %>
-
-<%= @template._render_template(@rescues_path.find_by_parts("rescues/_trace.erb")) %>
-<%= @template._render_template(@rescues_path.find_by_parts("rescues/_request_and_response.erb")) %>
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/dispatch/templates/rescues/layout.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/layout.erb
deleted file mode 100644
index 4a04742e40..0000000000
--- a/actionpack/lib/action_controller/dispatch/templates/rescues/layout.erb
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
- Action Controller: Exception caught
-
-
-
-
-<%= @contents %>
-
-
-
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/dispatch/templates/rescues/missing_template.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/missing_template.erb
deleted file mode 100644
index dbfdf76947..0000000000
--- a/actionpack/lib/action_controller/dispatch/templates/rescues/missing_template.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-Template is missing
-<%=h @exception.message %>
diff --git a/actionpack/lib/action_controller/dispatch/templates/rescues/routing_error.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/routing_error.erb
deleted file mode 100644
index ccfa858cce..0000000000
--- a/actionpack/lib/action_controller/dispatch/templates/rescues/routing_error.erb
+++ /dev/null
@@ -1,10 +0,0 @@
-Routing Error
-
<%=h @exception.message %>
-<% unless @exception.failures.empty? %>
-
Failure reasons:
-
- <% @exception.failures.each do |route, reason| %>
- <%=h route.inspect.gsub('\\', '') %>
failed because <%=h reason.downcase %>
- <% end %>
-
-<% end %>
diff --git a/actionpack/lib/action_controller/dispatch/templates/rescues/template_error.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/template_error.erb
deleted file mode 100644
index 2e34e03bd5..0000000000
--- a/actionpack/lib/action_controller/dispatch/templates/rescues/template_error.erb
+++ /dev/null
@@ -1,21 +0,0 @@
-
- <%=h @exception.original_exception.class.to_s %> in
- <%=h request.parameters["controller"].capitalize if request.parameters["controller"]%>#<%=h request.parameters["action"] %>
-
-
-
- Showing <%=h @exception.file_name %> where line #<%=h @exception.line_number %> raised:
-
<%=h @exception.message %>
-
-
-Extracted source (around line #<%=h @exception.line_number %> ):
-
<%=h @exception.source_extract %>
-
-<%=h @exception.sub_template_message %>
-
-<% @real_exception = @exception
- @exception = @exception.original_exception || @exception %>
-<%= render :file => @rescues_path["rescues/_trace.erb"] %>
-<% @exception = @real_exception %>
-
-<%= render :file => @rescues_path["rescues/_request_and_response.erb"] %>
diff --git a/actionpack/lib/action_controller/dispatch/templates/rescues/unknown_action.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/unknown_action.erb
deleted file mode 100644
index 683379da10..0000000000
--- a/actionpack/lib/action_controller/dispatch/templates/rescues/unknown_action.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-Unknown action
-<%=h @exception.message %>
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 5f6202d153..5a082fa7e3 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -48,6 +48,8 @@ module ActionDispatch
autoload :Failsafe, 'action_dispatch/middleware/failsafe'
autoload :ParamsParser, 'action_dispatch/middleware/params_parser'
autoload :Reloader, 'action_dispatch/middleware/reloader'
+ autoload :Rescue, 'action_dispatch/middleware/rescue'
+ autoload :ShowExceptions, 'action_dispatch/middleware/show_exceptions'
autoload :MiddlewareStack, 'action_dispatch/middleware/stack'
autoload :Assertions, 'action_dispatch/testing/assertions'
diff --git a/actionpack/lib/action_dispatch/middleware/rescue.rb b/actionpack/lib/action_dispatch/middleware/rescue.rb
new file mode 100644
index 0000000000..1456825526
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/rescue.rb
@@ -0,0 +1,14 @@
+module ActionDispatch
+ class Rescue
+ def initialize(app, rescuer)
+ @app, @rescuer = app, rescuer
+ end
+
+ def call(env)
+ @app.call(env)
+ rescue Exception => exception
+ env['action_dispatch.rescue.exception'] = exception
+ @rescuer.call(env)
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
new file mode 100644
index 0000000000..791254cdf2
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
@@ -0,0 +1,142 @@
+module ActionDispatch
+ class ShowExceptions
+ include StatusCodes
+
+ LOCALHOST = '127.0.0.1'.freeze
+
+ DEFAULT_RESCUE_RESPONSE = :internal_server_error
+ DEFAULT_RESCUE_RESPONSES = {
+ 'ActionController::RoutingError' => :not_found,
+ 'ActionController::UnknownAction' => :not_found,
+ 'ActiveRecord::RecordNotFound' => :not_found,
+ 'ActiveRecord::StaleObjectError' => :conflict,
+ 'ActiveRecord::RecordInvalid' => :unprocessable_entity,
+ 'ActiveRecord::RecordNotSaved' => :unprocessable_entity,
+ 'ActionController::MethodNotAllowed' => :method_not_allowed,
+ 'ActionController::NotImplemented' => :not_implemented,
+ 'ActionController::InvalidAuthenticityToken' => :unprocessable_entity
+ }
+
+ DEFAULT_RESCUE_TEMPLATE = 'diagnostics'
+ DEFAULT_RESCUE_TEMPLATES = {
+ 'ActionView::MissingTemplate' => 'missing_template',
+ 'ActionController::RoutingError' => 'routing_error',
+ 'ActionController::UnknownAction' => 'unknown_action',
+ 'ActionView::TemplateError' => 'template_error'
+ }
+
+ RESCUES_TEMPLATE_PATH = File.join(File.dirname(__FILE__), 'templates')
+
+ cattr_accessor :rescue_responses
+ @@rescue_responses = Hash.new(DEFAULT_RESCUE_RESPONSE)
+ @@rescue_responses.update DEFAULT_RESCUE_RESPONSES
+
+ cattr_accessor :rescue_templates
+ @@rescue_templates = Hash.new(DEFAULT_RESCUE_TEMPLATE)
+ @@rescue_templates.update DEFAULT_RESCUE_TEMPLATES
+
+ def initialize(app, consider_all_requests_local = false)
+ @app = app
+ @consider_all_requests_local = consider_all_requests_local
+ end
+
+ def call(env)
+ @app.call(env)
+ rescue Exception => exception
+ log_error(exception) if logger
+
+ request = Request.new(env)
+ if @consider_all_requests_local || local_request?(request)
+ rescue_action_locally(request, exception)
+ else
+ rescue_action_in_public(exception)
+ end
+ end
+
+ private
+ # Render detailed diagnostics for unhandled exceptions rescued from
+ # a controller action.
+ def rescue_action_locally(request, exception)
+ template = ActionView::Base.new([RESCUES_TEMPLATE_PATH],
+ :template => template,
+ :request => request,
+ :exception => exception
+ )
+ file = "rescues/#{@@rescue_templates[exception.class.name]}.erb"
+ body = template.render(:file => file, :layout => 'rescues/layout.erb')
+
+ headers = {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}
+ status = status_code(exception)
+
+ [status, headers, body]
+ end
+
+ # Attempts to render a static error page based on the
+ # status_code thrown, or just return headers if no such file
+ # exists. At first, it will try to render a localized static page.
+ # For example, if a 500 error is being handled Rails and locale is :da,
+ # it will first attempt to render the file at public/500.da.html
+ # then attempt to render public/500.html . If none of them exist,
+ # the body of the response will be left empty.
+ def rescue_action_in_public(exception)
+ status = status_code(exception)
+ locale_path = "#{public_path}/#{status}.#{I18n.locale}.html" if I18n.locale
+ path = "#{public_path}/#{status}.html"
+
+ if locale_path && File.exist?(locale_path)
+ render_public_file(status, locale_path)
+ elsif File.exist?(path)
+ render_public_file(status, path)
+ else
+ [status, {'Content-Type' => 'text/html', 'Content-Length' => '0'}, []]
+ end
+ end
+
+ # True if the request came from localhost, 127.0.0.1.
+ def local_request?(request)
+ request.remote_addr == LOCALHOST && request.remote_ip == LOCALHOST
+ end
+
+ def render_public_file(status, path)
+ body = File.read(path)
+ [status, {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}, body]
+ end
+
+ def status_code(exception)
+ interpret_status(@@rescue_responses[exception.class.name]).to_i
+ end
+
+ def public_path
+ if defined?(Rails)
+ Rails.public_path
+ else
+ "public"
+ end
+ end
+
+ def log_error(exception) #:doc:
+ ActiveSupport::Deprecation.silence do
+ if ActionView::TemplateError === exception
+ logger.fatal(exception.to_s)
+ else
+ logger.fatal(
+ "\n#{exception.class} (#{exception.message}):\n " +
+ clean_backtrace(exception).join("\n ") + "\n\n"
+ )
+ end
+ end
+ end
+
+ def clean_backtrace(exception)
+ defined?(Rails) && Rails.respond_to?(:backtrace_cleaner) ?
+ Rails.backtrace_cleaner.clean(exception.backtrace) :
+ exception.backtrace
+ end
+
+ def logger
+ if defined?(Rails.logger)
+ Rails.logger
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb
new file mode 100644
index 0000000000..5224403dab
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb
@@ -0,0 +1,24 @@
+<% unless @exception.blamed_files.blank? %>
+ <% if (hide = @exception.blamed_files.length > 8) %>
+ Show blamed files
+ <% end %>
+ ><%=h @exception.describe_blame %>
+<% end %>
+
+<%
+ clean_params = @request.parameters.clone
+ clean_params.delete("action")
+ clean_params.delete("controller")
+
+ request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n")
+%>
+
+Request
+Parameters :
<%=h request_dump %>
+
+Show session dump
+<%= debug(@request.session.instance_variable_get("@data")) %>
+
+
+Response
+Headers :
<%=h @response ? @response.headers.inspect.gsub(',', ",\n") : 'None' %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb
new file mode 100644
index 0000000000..bb2d8375bd
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb
@@ -0,0 +1,26 @@
+<%
+ traces = [
+ ["Application Trace", @exception.application_backtrace],
+ ["Framework Trace", @exception.framework_backtrace],
+ ["Full Trace", @exception.clean_backtrace]
+ ]
+ names = traces.collect {|name, trace| name}
+%>
+
+RAILS_ROOT: <%= defined?(RAILS_ROOT) ? RAILS_ROOT : "unset" %>
+
+
+ <% names.each do |name| %>
+ <%
+ show = "document.getElementById('#{name.gsub /\s/, '-'}').style.display='block';"
+ hide = (names - [name]).collect {|hide_name| "document.getElementById('#{hide_name.gsub /\s/, '-'}').style.display='none';"}
+ %>
+
<%= name %> <%= '|' unless names.last == name %>
+ <% end %>
+
+ <% traces.each do |name, trace| %>
+
;">
+
<%= trace.join "\n" %>
+
+ <% end %>
+
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb
new file mode 100644
index 0000000000..693e56270a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb
@@ -0,0 +1,10 @@
+
+ <%=h @exception.class.to_s %>
+ <% if @request.parameters['controller'] %>
+ in <%=h @request.parameters['controller'].humanize %>Controller<% if @request.parameters['action'] %>#<%=h @request.parameters['action'] %><% end %>
+ <% end %>
+
+<%=h @exception.clean_message %>
+
+<%= render :file => "rescues/_trace.erb" %>
+<%= render :file => "rescues/_request_and_response.erb" %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb
new file mode 100644
index 0000000000..6c32fb17b8
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb
@@ -0,0 +1,29 @@
+
+
+ Action Controller: Exception caught
+
+
+
+
+<%= yield %>
+
+
+
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.erb
new file mode 100644
index 0000000000..dbfdf76947
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.erb
@@ -0,0 +1,2 @@
+Template is missing
+<%=h @exception.message %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
new file mode 100644
index 0000000000..ccfa858cce
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
@@ -0,0 +1,10 @@
+Routing Error
+
<%=h @exception.message %>
+<% unless @exception.failures.empty? %>
+
Failure reasons:
+
+ <% @exception.failures.each do |route, reason| %>
+ <%=h route.inspect.gsub('\\', '') %>
failed because <%=h reason.downcase %>
+ <% end %>
+
+<% end %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb
new file mode 100644
index 0000000000..02fa18211d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb
@@ -0,0 +1,21 @@
+
+ <%=h @exception.original_exception.class.to_s %> in
+ <%=h @request.parameters["controller"].capitalize if @request.parameters["controller"]%>#<%=h @request.parameters["action"] %>
+
+
+
+ Showing <%=h @exception.file_name %> where line #<%=h @exception.line_number %> raised:
+
<%=h @exception.message %>
+
+
+Extracted source (around line #<%=h @exception.line_number %> ):
+
<%=h @exception.source_extract %>
+
+<%=h @exception.sub_template_message %>
+
+<% @real_exception = @exception
+ @exception = @exception.original_exception || @exception %>
+<%= render :file => "rescues/_trace.erb" %>
+<% @exception = @real_exception %>
+
+<%= render :file => "rescues/_request_and_response.erb" %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb
new file mode 100644
index 0000000000..683379da10
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb
@@ -0,0 +1,2 @@
+Unknown action
+<%=h @exception.message %>
diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb
index 92e3da580e..501a7c4dfb 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/response.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb
@@ -31,13 +31,7 @@ module ActionDispatch
elsif type.is_a?(Symbol) && @response.response_code == ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[type]
assert_block("") { true } # to count the assertion
else
- if @controller && @response.error?
- 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
- assert_block(build_message(message, "Expected response to be a >, but was >", type, @response.response_code)) { false }
- end
+ assert_block(build_message(message, "Expected response to be a >, but was >", type, @response.response_code)) { false }
end
end
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index 60957a2f0e..484d3c5ce7 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -489,7 +489,7 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
get :index
assert_response :success
flunk 'Expected non-success response'
- rescue ActiveSupport::TestCase::Assertion => e
+ rescue RuntimeError => e
assert e.message.include?('FAIL')
end
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index f4517d06c4..0c54d61426 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -27,6 +27,7 @@ class EmptyController < ActionController::Base
end
class NonEmptyController < ActionController::Base
def public_action
+ render :nothing => true
end
hide_action :hidden_action
@@ -51,6 +52,7 @@ end
class DefaultUrlOptionsController < ActionController::Base
def default_url_options_action
+ render :nothing => true
end
def default_url_options(options = nil)
@@ -151,11 +153,8 @@ class PerformActionTest < ActionController::TestCase
def test_get_on_hidden_should_fail
use_controller NonEmptyController
- get :hidden_action
- assert_response 404
-
- get :another_hidden_action
- assert_response 404
+ assert_raise(ActionController::UnknownAction) { get :hidden_action }
+ assert_raise(ActionController::UnknownAction) { get :another_hidden_action }
end
def test_namespaced_action_should_log_module_name
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index 6b9d1056a3..560c09509b 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -149,6 +149,9 @@ class PageCachingTest < ActionController::TestCase
end
class ActionCachingTestController < ActionController::Base
+ rescue_from(Exception) { head 500 }
+ rescue_from(ActiveRecord::RecordNotFound) { head :not_found }
+
caches_action :index, :redirected, :forbidden, :if => Proc.new { |c| !c.request.format.json? }, :expires_in => 1.hour
caches_action :show, :cache_path => 'http://test.host/custom/show'
caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]};edit" : "http://test.host/edit" }
diff --git a/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb b/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb
index dd69a63020..0c02afea36 100644
--- a/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb
+++ b/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb
@@ -15,12 +15,6 @@ class DeprecatedBaseMethodsTest < ActionController::TestCase
tests Target
- def test_log_error_silences_deprecation_warnings
- get :raises_name_error
- rescue => e
- assert_not_deprecated { @controller.send :log_error, e }
- end
-
if defined? Test::Unit::Error
def test_assertion_failed_error_silences_deprecation_warnings
get :raises_name_error
diff --git a/actionpack/test/controller/dispatcher_test.rb b/actionpack/test/controller/dispatcher_test.rb
index c3bd113b86..b315232a7b 100644
--- a/actionpack/test/controller/dispatcher_test.rb
+++ b/actionpack/test/controller/dispatcher_test.rb
@@ -45,19 +45,6 @@ class DispatcherTest < Test::Unit::TestCase
def log_failsafe_exception(status, exception); end
end
- def test_failsafe_response
- Dispatcher.any_instance.expects(:_call).raises('b00m')
- ActionDispatch::Failsafe.any_instance.expects(:log_failsafe_exception)
-
- assert_nothing_raised do
- assert_equal [
- 500,
- {"Content-Type" => "text/html"},
- ["500 Internal Server Error "]
- ], dispatch
- end
- end
-
def test_prepare_callbacks
a = b = c = nil
Dispatcher.to_prepare { |*args| a = b = c = 1 }
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index 5876f55420..5fd3eb0446 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -169,6 +169,7 @@ class FilterTest < Test::Unit::TestCase
end
def public
+ render :text => 'ok'
end
end
@@ -177,6 +178,10 @@ class FilterTest < Test::Unit::TestCase
before_filter :find_record
before_filter :ensure_login
+ def index
+ render :text => 'ok'
+ end
+
private
def find_record
@ran_filter ||= []
diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb
index da3f7b0cb8..5b7d40d16d 100644
--- a/actionpack/test/controller/layout_test.rb
+++ b/actionpack/test/controller/layout_test.rb
@@ -205,8 +205,7 @@ end
class LayoutExceptionRaised < ActionController::TestCase
def test_exception_raised_when_layout_file_not_found
@controller = SetsNonExistentLayoutFile.new
- get :hello
- assert_kind_of ActionView::MissingTemplate, @controller.template.instance_eval { @exception }
+ assert_raise(ActionView::MissingTemplate) { get :hello }
end
end
diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb
index 894420a910..f745926b20 100644
--- a/actionpack/test/controller/rescue_test.rb
+++ b/actionpack/test/controller/rescue_test.rb
@@ -138,213 +138,88 @@ class RescueController < ActionController::Base
end
end
-class RescueControllerTest < ActionController::TestCase
- FIXTURE_PUBLIC = "#{File.dirname(__FILE__)}/../fixtures".freeze
-
- def setup
- super
- set_all_requests_local
- populate_exception_object
- end
-
- def set_all_requests_local
- RescueController.consider_all_requests_local = true
- @request.remote_addr = '1.2.3.4'
- @request.host = 'example.com'
- end
-
- def populate_exception_object
- begin
- raise 'foo'
- rescue => @exception
- end
- end
-
- def test_rescue_exceptions_raised_by_filters
- with_rails_root FIXTURE_PUBLIC do
- with_all_requests_local false do
- get :before_filter_raises
- end
- end
+class ExceptionInheritanceRescueController < ActionController::Base
- assert_response :internal_server_error
+ class ParentException < StandardError
end
- def test_rescue_action_locally_if_all_requests_local
- @controller.expects(:local_request?).never
- @controller.expects(:rescue_action_locally).with(@exception)
- @controller.expects(:rescue_action_in_public).never
-
- with_all_requests_local do
- @controller.send :rescue_action, @exception
- end
+ class ChildException < ParentException
end
- def test_rescue_action_locally_if_remote_addr_is_localhost
- @controller.expects(:local_request?).returns(true)
- @controller.expects(:rescue_action_locally).with(@exception)
- @controller.expects(:rescue_action_in_public).never
-
- with_all_requests_local false do
- @controller.send :rescue_action, @exception
- end
+ class GrandchildException < ChildException
end
- def test_rescue_action_in_public_otherwise
- @controller.expects(:local_request?).returns(false)
- @controller.expects(:rescue_action_locally).never
- @controller.expects(:rescue_action_in_public).with(@exception)
+ rescue_from ChildException, :with => lambda { head :ok }
+ rescue_from ParentException, :with => lambda { head :created }
+ rescue_from GrandchildException, :with => lambda { head :no_content }
- with_all_requests_local false do
- @controller.send :rescue_action, @exception
- end
+ def raise_parent_exception
+ raise ParentException
end
- def test_rescue_action_in_public_with_localized_error_file
- # Change locale
- old_locale = I18n.locale
- I18n.locale = :da
-
- with_rails_root FIXTURE_PUBLIC do
- with_all_requests_local false do
- get :raises
- end
- end
-
- assert_response :internal_server_error
- body = File.read("#{FIXTURE_PUBLIC}/public/500.da.html")
- assert_equal body, @response.body
- ensure
- I18n.locale = old_locale
+ def raise_child_exception
+ raise ChildException
end
- def test_rescue_action_in_public_with_error_file
- with_rails_root FIXTURE_PUBLIC do
- with_all_requests_local false do
- get :raises
- end
- end
-
- assert_response :internal_server_error
- body = File.read("#{FIXTURE_PUBLIC}/public/500.html")
- assert_equal body, @response.body
+ def raise_grandchild_exception
+ raise GrandchildException
end
+end
- def test_rescue_action_in_public_without_error_file
- with_rails_root '/tmp' do
- with_all_requests_local false do
- get :raises
- end
- end
-
- assert_response :internal_server_error
- assert_equal ' ', @response.body
+class ExceptionInheritanceRescueControllerTest < ActionController::TestCase
+ def test_bottom_first
+ get :raise_grandchild_exception
+ assert_response :no_content
end
- def test_rescue_unknown_action_in_public_with_error_file
- with_rails_root FIXTURE_PUBLIC do
- with_all_requests_local false do
- get :foobar_doesnt_exist
- end
- end
-
- assert_response :not_found
- body = File.read("#{FIXTURE_PUBLIC}/public/404.html")
- assert_equal body, @response.body
+ def test_inheritance_works
+ get :raise_child_exception
+ assert_response :created
end
+end
- def test_rescue_unknown_action_in_public_without_error_file
- with_rails_root '/tmp' do
- with_all_requests_local false do
- get :foobar_doesnt_exist
- end
- end
-
- assert_response :not_found
- assert_equal ' ', @response.body
+class ControllerInheritanceRescueController < ExceptionInheritanceRescueController
+ class FirstExceptionInChildController < StandardError
end
- def test_rescue_missing_template_in_public
- with_rails_root FIXTURE_PUBLIC do
- with_all_requests_local true do
- get :missing_template
- end
- end
-
- assert_response :internal_server_error
- assert @response.body.include?('missing_template'), "Response should include the template name."
+ class SecondExceptionInChildController < StandardError
end
- def test_rescue_action_locally
- get :raises
- assert_response :internal_server_error
- assert_template 'diagnostics.erb'
- assert @response.body.include?('RescueController#raises'), "Response should include controller and action."
- assert @response.body.include?("don't panic"), "Response should include exception message."
- end
+ rescue_from FirstExceptionInChildController, 'SecondExceptionInChildController', :with => lambda { head :gone }
- def test_local_request_when_remote_addr_is_localhost
- @controller.expects(:request).returns(@request).at_least_once
- with_remote_addr '127.0.0.1' do
- assert @controller.send(:local_request?)
- end
+ def raise_first_exception_in_child_controller
+ raise FirstExceptionInChildController
end
- def test_local_request_when_remote_addr_isnt_locahost
- @controller.expects(:request).returns(@request)
- with_remote_addr '1.2.3.4' do
- assert !@controller.send(:local_request?)
- end
+ def raise_second_exception_in_child_controller
+ raise SecondExceptionInChildController
end
+end
- def test_rescue_responses
- responses = ActionController::Base.rescue_responses
-
- assert_equal ActionController::Rescue::DEFAULT_RESCUE_RESPONSE, responses.default
- assert_equal ActionController::Rescue::DEFAULT_RESCUE_RESPONSE, responses[Exception.new]
-
- assert_equal :not_found, responses[ActionController::RoutingError.name]
- assert_equal :not_found, responses[ActionController::UnknownAction.name]
- assert_equal :not_found, responses['ActiveRecord::RecordNotFound']
- assert_equal :conflict, responses['ActiveRecord::StaleObjectError']
- assert_equal :unprocessable_entity, responses['ActiveRecord::RecordInvalid']
- assert_equal :unprocessable_entity, responses['ActiveRecord::RecordNotSaved']
- assert_equal :method_not_allowed, responses['ActionController::MethodNotAllowed']
- assert_equal :not_implemented, responses['ActionController::NotImplemented']
+class ControllerInheritanceRescueControllerTest < ActionController::TestCase
+ def test_first_exception_in_child_controller
+ get :raise_first_exception_in_child_controller
+ assert_response :gone
end
- def test_rescue_templates
- templates = ActionController::Base.rescue_templates
-
- assert_equal ActionController::Rescue::DEFAULT_RESCUE_TEMPLATE, templates.default
- assert_equal ActionController::Rescue::DEFAULT_RESCUE_TEMPLATE, templates[Exception.new]
-
- assert_equal 'missing_template', templates[ActionView::MissingTemplate.name]
- assert_equal 'routing_error', templates[ActionController::RoutingError.name]
- assert_equal 'unknown_action', templates[ActionController::UnknownAction.name]
- assert_equal 'template_error', templates[ActionView::TemplateError.name]
+ def test_second_exception_in_child_controller
+ get :raise_second_exception_in_child_controller
+ assert_response :gone
end
- def test_not_implemented
- with_all_requests_local false do
- with_rails_public_path(".") do
- head :not_implemented
- end
- end
- assert_response :not_implemented
- assert_equal "GET, PUT", @response.headers['Allow']
+ def test_exception_in_parent_controller
+ get :raise_parent_exception
+ assert_response :created
end
+end
- def test_method_not_allowed
- with_all_requests_local false do
- with_rails_public_path(".") do
- get :method_not_allowed
- end
- end
- assert_response :method_not_allowed
- assert_equal "GET, HEAD, PUT", @response.headers['Allow']
+class ApplicationController < ActionController::Base
+ rescue_from ActionController::RoutingError do
+ render :text => 'no way'
end
+end
+class RescueControllerTest < ActionController::TestCase
def test_rescue_handler
get :not_authorized
assert_response :forbidden
@@ -399,133 +274,6 @@ class RescueControllerTest < ActionController::TestCase
get :resource_unavailable_raise_as_string
assert_equal "RescueController::ResourceUnavailableToRescueAsString", @response.body
end
-
- protected
- def with_all_requests_local(local = true)
- old_local, ActionController::Base.consider_all_requests_local =
- ActionController::Base.consider_all_requests_local, local
- yield
- ensure
- ActionController::Base.consider_all_requests_local = old_local
- end
-
- def with_remote_addr(addr)
- old_remote_addr, @request.remote_addr = @request.remote_addr, addr
- yield
- ensure
- @request.remote_addr = old_remote_addr
- end
-
- def with_rails_public_path(rails_root)
- old_rails = Object.const_get(:Rails) rescue nil
- mod = Object.const_set(:Rails, Module.new)
- (class << mod; self; end).instance_eval do
- define_method(:public_path) { "#{rails_root}/public" }
- end
- yield
- ensure
- Object.module_eval { remove_const(:Rails) } if defined?(Rails)
- Object.const_set(:Rails, old_rails) if old_rails
- end
-
- def with_rails_root(path = nil,&block)
- old_rails_root = RAILS_ROOT if defined?(RAILS_ROOT)
- if path
- silence_warnings { Object.const_set(:RAILS_ROOT, path) }
- else
- Object.remove_const(:RAILS_ROOT) rescue nil
- end
-
- with_rails_public_path(path, &block)
-
- ensure
- if old_rails_root
- silence_warnings { Object.const_set(:RAILS_ROOT, old_rails_root) }
- else
- Object.remove_const(:RAILS_ROOT) rescue nil
- end
- end
-end
-
-class ExceptionInheritanceRescueController < ActionController::Base
-
- class ParentException < StandardError
- end
-
- class ChildException < ParentException
- end
-
- class GrandchildException < ChildException
- end
-
- rescue_from ChildException, :with => lambda { head :ok }
- rescue_from ParentException, :with => lambda { head :created }
- rescue_from GrandchildException, :with => lambda { head :no_content }
-
- def raise_parent_exception
- raise ParentException
- end
-
- def raise_child_exception
- raise ChildException
- end
-
- def raise_grandchild_exception
- raise GrandchildException
- end
-end
-
-class ExceptionInheritanceRescueControllerTest < ActionController::TestCase
- def test_bottom_first
- get :raise_grandchild_exception
- assert_response :no_content
- end
-
- def test_inheritance_works
- get :raise_child_exception
- assert_response :created
- end
-end
-
-class ControllerInheritanceRescueController < ExceptionInheritanceRescueController
- class FirstExceptionInChildController < StandardError
- end
-
- class SecondExceptionInChildController < StandardError
- end
-
- rescue_from FirstExceptionInChildController, 'SecondExceptionInChildController', :with => lambda { head :gone }
-
- def raise_first_exception_in_child_controller
- raise FirstExceptionInChildController
- end
-
- def raise_second_exception_in_child_controller
- raise SecondExceptionInChildController
- end
-end
-
-class ControllerInheritanceRescueControllerTest < ActionController::TestCase
- def test_first_exception_in_child_controller
- get :raise_first_exception_in_child_controller
- assert_response :gone
- end
-
- def test_second_exception_in_child_controller
- get :raise_second_exception_in_child_controller
- assert_response :gone
- end
-
- def test_exception_in_parent_controller
- get :raise_parent_exception
- assert_response :created
- end
-end
-
-class ApplicationController < ActionController::Base
- rescue_from ActionController::RoutingError do
- render :text => 'no way'
- end
end
class RescueTest < ActionController::IntegrationTest
diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb
new file mode 100644
index 0000000000..f8f562e7c1
--- /dev/null
+++ b/actionpack/test/dispatch/show_exceptions_test.rb
@@ -0,0 +1,103 @@
+require 'abstract_unit'
+
+module ActionDispatch
+ class ShowExceptions
+ private
+ def public_path
+ "#{FIXTURE_LOAD_PATH}/public"
+ end
+ end
+end
+
+class ShowExceptionsTest < ActionController::IntegrationTest
+ Boomer = lambda do |env|
+ req = ActionDispatch::Request.new(env)
+ case req.path
+ when "/not_found"
+ raise ActionController::UnknownAction
+ when "/method_not_allowed"
+ raise ActionController::MethodNotAllowed
+ when "/not_implemented"
+ raise ActionController::NotImplemented
+ when "/unprocessable_entity"
+ raise ActionController::InvalidAuthenticityToken
+ else
+ raise "puke!"
+ end
+ end
+
+ ProductionApp = ActionDispatch::ShowExceptions.new(Boomer, false)
+ DevelopmentApp = ActionDispatch::ShowExceptions.new(Boomer, true)
+
+ test "rescue in public from a remote ip" do
+ @integration_session = open_session(ProductionApp)
+ self.remote_addr = '208.77.188.166'
+
+ get "/"
+ assert_response 500
+ assert_equal "500 error fixture\n", body
+
+ get "/not_found"
+ assert_response 404
+ assert_equal "404 error fixture\n", body
+
+ get "/method_not_allowed"
+ assert_response 405
+ assert_equal "", body
+ end
+
+ test "rescue locally from a local request" do
+ @integration_session = open_session(ProductionApp)
+ self.remote_addr = '127.0.0.1'
+
+ get "/"
+ assert_response 500
+ assert_match /puke/, body
+
+ get "/not_found"
+ assert_response 404
+ assert_match /ActionController::UnknownAction/, body
+
+ get "/method_not_allowed"
+ assert_response 405
+ assert_match /ActionController::MethodNotAllowed/, body
+ end
+
+ test "localize public rescue message" do
+ # Change locale
+ old_locale = I18n.locale
+ I18n.locale = :da
+
+ begin
+ @integration_session = open_session(ProductionApp)
+ self.remote_addr = '208.77.188.166'
+
+ get "/"
+ assert_response 500
+ assert_equal "500 localized error fixture\n", body
+
+ get "/not_found"
+ assert_response 404
+ assert_equal "404 error fixture\n", body
+ ensure
+ I18n.locale = old_locale
+ end
+ end
+
+ test "always rescue locally in development mode" do
+ @integration_session = open_session(DevelopmentApp)
+ self.remote_addr = '208.77.188.166'
+
+ get "/"
+ assert_response 500
+ assert_match /puke/, body
+
+ get "/not_found"
+ assert_response 404
+ assert_match /ActionController::UnknownAction/, body
+
+ get "/method_not_allowed"
+ assert_response 405
+ assert_match /ActionController::MethodNotAllowed/, body
+ end
+end
--
cgit v1.2.3
From e0660192806fc1ec8b75654e69211f85c9f1256b Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sun, 3 May 2009 09:24:32 -0500
Subject: Show lazy middleware args in pretty print
---
actionpack/lib/action_dispatch/middleware/stack.rb | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
index ee5f28d5cb..ec8a9ca76e 100644
--- a/actionpack/lib/action_dispatch/middleware/stack.rb
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -61,7 +61,7 @@ module ActionDispatch
def inspect
str = klass.to_s
- args.each { |arg| str += ", #{arg.inspect}" }
+ args.each { |arg| str += ", #{build_args.inspect}" }
str
end
@@ -74,7 +74,6 @@ module ActionDispatch
end
private
-
def build_args
Array(args).map { |arg| arg.respond_to?(:call) ? arg.call : arg }
end
--
cgit v1.2.3
From bcc4537f2a0d37fc02d67e9564fa5c9c5555b3d5 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sun, 3 May 2009 09:41:40 -0500
Subject: Wrap dispatcher callbacks around the whole middleware chain. Kill
unnecessary Reloader middleware.
---
.../lib/action_controller/dispatch/dispatcher.rb | 45 +++++++++++-----------
actionpack/lib/action_dispatch.rb | 1 -
.../lib/action_dispatch/middleware/reloader.rb | 14 -------
3 files changed, 22 insertions(+), 38 deletions(-)
delete mode 100644 actionpack/lib/action_dispatch/middleware/reloader.rb
diff --git a/actionpack/lib/action_controller/dispatch/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb
index c0eb359547..cce3b6175d 100644
--- a/actionpack/lib/action_controller/dispatch/dispatcher.rb
+++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb
@@ -5,9 +5,9 @@ module ActionController
class << self
def define_dispatcher_callbacks(cache_classes)
unless cache_classes
- unless self.middleware.include?(ActionDispatch::Reloader)
- self.middleware.insert_after(ActionDispatch::Failsafe, ActionDispatch::Reloader)
- end
+ # Development mode callbacks
+ before_dispatch :reload_application
+ after_dispatch :cleanup_application
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
end
@@ -40,22 +40,11 @@ module ActionController
def run_prepare_callbacks
new.send :run_callbacks, :prepare_dispatch
end
-
- def reload_application
- # Run prepare callbacks before every request in development mode
- run_prepare_callbacks
-
- Routing::Routes.reload
- end
-
- def cleanup_application
- # Cleanup the application before processing the current request.
- ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
- ActiveSupport::Dependencies.clear
- ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
- end
end
+ cattr_accessor :router
+ self.router = Routing::Routes
+
cattr_accessor :middleware
self.middleware = ActionDispatch::MiddlewareStack.new do |middleware|
middlewares = File.join(File.dirname(__FILE__), "middlewares.rb")
@@ -66,21 +55,31 @@ module ActionController
define_callbacks :prepare_dispatch, :before_dispatch, :after_dispatch
def initialize
- @app = @@middleware.build(lambda { |env| self._call(env) })
+ @app = @@middleware.build(@@router)
freeze
end
def call(env)
- @app.call(env)
- end
-
- def _call(env)
run_callbacks :before_dispatch
- Routing::Routes.call(env)
+ @app.call(env)
ensure
run_callbacks :after_dispatch, :enumerator => :reverse_each
end
+ def reload_application
+ # Run prepare callbacks before every request in development mode
+ run_callbacks :prepare_dispatch
+
+ @@router.reload
+ end
+
+ def cleanup_application
+ # Cleanup the application before processing the current request.
+ ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
+ ActiveSupport::Dependencies.clear
+ ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
+ end
+
def flush_logger
Base.logger.flush
end
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 5a082fa7e3..c882930e64 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -47,7 +47,6 @@ module ActionDispatch
autoload :Failsafe, 'action_dispatch/middleware/failsafe'
autoload :ParamsParser, 'action_dispatch/middleware/params_parser'
- autoload :Reloader, 'action_dispatch/middleware/reloader'
autoload :Rescue, 'action_dispatch/middleware/rescue'
autoload :ShowExceptions, 'action_dispatch/middleware/show_exceptions'
autoload :MiddlewareStack, 'action_dispatch/middleware/stack'
diff --git a/actionpack/lib/action_dispatch/middleware/reloader.rb b/actionpack/lib/action_dispatch/middleware/reloader.rb
deleted file mode 100644
index 67313e30e4..0000000000
--- a/actionpack/lib/action_dispatch/middleware/reloader.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-module ActionDispatch
- class Reloader
- def initialize(app)
- @app = app
- end
-
- def call(env)
- ActionController::Dispatcher.reload_application
- @app.call(env)
- ensure
- ActionController::Dispatcher.cleanup_application
- end
- end
-end
--
cgit v1.2.3
From d3ee8756c8b09b8524a9599926b02ededd27319c Mon Sep 17 00:00:00 2001
From: Chris Kampmeier
Date: Sun, 3 May 2009 18:09:06 -0700
Subject: Don't use #tap before Active Support is available, since older
versions of ruby don't have native implementations
[#2603 state:committed]
Signed-off-by: Jeremy Kemper
---
activerecord/lib/active_record.rb | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 1982ffc791..06d6c87090 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -21,9 +21,8 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
-"#{File.dirname(__FILE__)}/../../activesupport/lib".tap do |path|
- $:.unshift(path) if File.directory?(path)
-end
+activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
+$:.unshift(activesupport_path) if File.directory?(activesupport_path)
require 'active_support'
require 'active_support/core/all'
--
cgit v1.2.3
From eb201e64c0b68aee6d0715d44cf48178204c4133 Mon Sep 17 00:00:00 2001
From: codebrulee
Date: Mon, 4 May 2009 12:36:22 -0400
Subject: Fixed Hash#from_xml with keys that are all caps.
Signed-off-by: Michael Koziarski
---
.../lib/active_support/core_ext/hash/conversions.rb | 2 +-
activesupport/test/core_ext/hash_ext_test.rb | 16 ++++++++++++++++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index f9dddec687..fe1f79050c 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -217,7 +217,7 @@ class Hash
case params.class.to_s
when "Hash"
params.inject({}) do |h,(k,v)|
- h[k.to_s.underscore.tr("-", "_")] = unrename_keys(v)
+ h[k.to_s.tr("-", "_")] = unrename_keys(v)
h
end
when "Array"
diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb
index d65a5323bf..ece5466abb 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -646,6 +646,22 @@ class HashToXmlTest < Test::Unit::TestCase
assert_equal expected_topic_hash, Hash.from_xml(topic_xml)["rsp"]["photos"]["photo"]
end
+ def test_all_caps_key_from_xml
+ test_xml = <<-EOT
+
+ Lorem Ipsum
+
+ EOT
+
+ expected_hash = {
+ "ABC3XYZ" => {
+ "TEST" => "Lorem Ipsum"
+ }
+ }
+
+ assert_equal expected_hash, Hash.from_xml(test_xml)
+ end
+
def test_empty_array_from_xml
blog_xml = <<-XML
--
cgit v1.2.3
From ccea98389abbf150b886c9f964b1def47f00f237 Mon Sep 17 00:00:00 2001
From: Murray Steele
Date: Fri, 1 May 2009 16:01:13 +0100
Subject: Providing support for :inverse_of as an option to associations.
You can now add an :inverse_of option to has_one, has_many and belongs_to associations. This is best described with an example:
class Man < ActiveRecord::Base
has_one :face, :inverse_of => :man
end
class Face < ActiveRecord::Base
belongs_to :man, :inverse_of => :face
end
m = Man.first
f = m.face
Without :inverse_of m and f.man would be different instances of the same object (f.man being pulled from the database again). With these new :inverse_of options m and f.man are the same in memory instance.
Currently :inverse_of supports has_one and has_many (but not the :through variants) associations. It also supplies inverse support for belongs_to associations where the inverse is a has_one and it's not a polymorphic.
Signed-off-by: Murray Steele
Signed-off-by: Jeremy Kemper
---
activerecord/lib/active_record/associations.rb | 12 +-
.../associations/association_collection.rb | 8 +-
.../associations/association_proxy.rb | 14 ++
.../associations/belongs_to_association.rb | 12 +-
.../associations/has_many_association.rb | 5 +
.../associations/has_many_through_association.rb | 10 +-
.../associations/has_one_association.rb | 11 +-
activerecord/lib/active_record/reflection.rb | 21 ++
.../associations/inverse_associations_test.rb | 252 +++++++++++++++++++++
activerecord/test/fixtures/faces.yml | 7 +
activerecord/test/fixtures/interests.yml | 29 +++
activerecord/test/fixtures/men.yml | 5 +
activerecord/test/fixtures/zines.yml | 5 +
activerecord/test/models/face.rb | 5 +
activerecord/test/models/interest.rb | 4 +
activerecord/test/models/man.rb | 7 +
activerecord/test/models/zine.rb | 3 +
activerecord/test/schema/schema.rb | 20 ++
18 files changed, 418 insertions(+), 12 deletions(-)
create mode 100644 activerecord/test/cases/associations/inverse_associations_test.rb
create mode 100644 activerecord/test/fixtures/faces.yml
create mode 100644 activerecord/test/fixtures/interests.yml
create mode 100644 activerecord/test/fixtures/men.yml
create mode 100644 activerecord/test/fixtures/zines.yml
create mode 100644 activerecord/test/models/face.rb
create mode 100644 activerecord/test/models/interest.rb
create mode 100644 activerecord/test/models/man.rb
create mode 100644 activerecord/test/models/zine.rb
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 2115878e32..0952b087d1 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1,4 +1,10 @@
module ActiveRecord
+ class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
+ def initialize(reflection)
+ super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{reflection.class_name})")
+ end
+ end
+
class HasManyThroughAssociationNotFoundError < ActiveRecordError #:nodoc:
def initialize(owner_class_name, reflection)
super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class_name}")
@@ -1488,7 +1494,7 @@ module ActiveRecord
:finder_sql, :counter_sql,
:before_add, :after_add, :before_remove, :after_remove,
:extend, :readonly,
- :validate
+ :validate, :inverse_of
]
def create_has_many_reflection(association_id, options, &extension)
@@ -1502,7 +1508,7 @@ module ActiveRecord
@@valid_keys_for_has_one_association = [
:class_name, :foreign_key, :remote, :select, :conditions, :order,
:include, :dependent, :counter_cache, :extend, :as, :readonly,
- :validate, :primary_key
+ :validate, :primary_key, :inverse_of
]
def create_has_one_reflection(association_id, options)
@@ -1521,7 +1527,7 @@ module ActiveRecord
@@valid_keys_for_belongs_to_association = [
:class_name, :foreign_key, :foreign_type, :remote, :select, :conditions,
:include, :dependent, :counter_cache, :extend, :polymorphic, :readonly,
- :validate, :touch
+ :validate, :touch, :inverse_of
]
def create_belongs_to_reflection(association_id, options)
diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb
index 3aef1b21e9..26987dde97 100644
--- a/activerecord/lib/active_record/associations/association_collection.rb
+++ b/activerecord/lib/active_record/associations/association_collection.rb
@@ -399,11 +399,14 @@ module ActiveRecord
find(:all)
end
- @reflection.options[:uniq] ? uniq(records) : records
+ records = @reflection.options[:uniq] ? uniq(records) : records
+ records.each do |record|
+ set_inverse_instance(record, @owner)
+ end
+ records
end
private
-
def create_record(attrs)
attrs.update(@reflection.options[:conditions]) if @reflection.options[:conditions].is_a?(Hash)
ensure_owner_is_not_new
@@ -433,6 +436,7 @@ module ActiveRecord
@target ||= [] unless loaded?
@target << record unless @reflection.options[:uniq] && @target.include?(record)
callback(:after_add, record)
+ set_inverse_instance(record, @owner)
record
end
diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb
index 241b9bfee0..e36b04ea95 100644
--- a/activerecord/lib/active_record/associations/association_proxy.rb
+++ b/activerecord/lib/active_record/associations/association_proxy.rb
@@ -53,6 +53,7 @@ module ActiveRecord
def initialize(owner, reflection)
@owner, @reflection = owner, reflection
+ reflection.check_validity!
Array(reflection.options[:extend]).each { |ext| proxy_extend(ext) }
reset
end
@@ -274,6 +275,19 @@ module ActiveRecord
def owner_quoted_id
@owner.quoted_id
end
+
+ def set_inverse_instance(record, instance)
+ return if record.nil? || !we_can_set_the_inverse_on_this?(record)
+ inverse_relationship = @reflection.inverse_of
+ unless inverse_relationship.nil?
+ record.send(:"set_#{inverse_relationship.name}_target", instance)
+ end
+ end
+
+ # Override in subclasses
+ def we_can_set_the_inverse_on_this?(record)
+ false
+ end
end
end
end
diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb
index f05c6be075..c88575048a 100644
--- a/activerecord/lib/active_record/associations/belongs_to_association.rb
+++ b/activerecord/lib/active_record/associations/belongs_to_association.rb
@@ -31,6 +31,8 @@ module ActiveRecord
@updated = true
end
+ set_inverse_instance(record, @owner)
+
loaded
record
end
@@ -41,18 +43,26 @@ module ActiveRecord
private
def find_target
- @reflection.klass.find(
+ the_target = @reflection.klass.find(
@owner[@reflection.primary_key_name],
:select => @reflection.options[:select],
:conditions => conditions,
:include => @reflection.options[:include],
:readonly => @reflection.options[:readonly]
)
+ set_inverse_instance(the_target, @owner)
+ the_target
end
def foreign_key_present
!@owner[@reflection.primary_key_name].nil?
end
+
+ # NOTE - for now, we're only supporting inverse setting from belongs_to back onto
+ # has_one associations.
+ def we_can_set_the_inverse_on_this?(record)
+ @reflection.has_inverse? && @reflection.inverse_of.macro == :has_one
+ end
end
end
end
diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb
index a2cbabfe0c..73dd50dd07 100644
--- a/activerecord/lib/active_record/associations/has_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_association.rb
@@ -116,6 +116,11 @@ module ActiveRecord
:create => create_scoping
}
end
+
+ def we_can_set_the_inverse_on_this?(record)
+ inverse = @reflection.inverse_of
+ return !inverse.nil?
+ end
end
end
end
diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb
index 1c091e7d5a..2dca84b911 100644
--- a/activerecord/lib/active_record/associations/has_many_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_through_association.rb
@@ -1,11 +1,6 @@
module ActiveRecord
module Associations
class HasManyThroughAssociation < HasManyAssociation #:nodoc:
- def initialize(owner, reflection)
- reflection.check_validity!
- super
- end
-
alias_method :new, :build
def create!(attrs = nil)
@@ -251,6 +246,11 @@ module ActiveRecord
def cached_counter_attribute_name
"#{@reflection.name}_count"
end
+
+ # NOTE - not sure that we can actually cope with inverses here
+ def we_can_set_the_inverse_on_this?(record)
+ false
+ end
end
end
end
diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb
index 1464227bb0..4908005d2e 100644
--- a/activerecord/lib/active_record/associations/has_one_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_association.rb
@@ -74,13 +74,15 @@ module ActiveRecord
private
def find_target
- @reflection.klass.find(:first,
+ the_target = @reflection.klass.find(:first,
:conditions => @finder_sql,
:select => @reflection.options[:select],
:order => @reflection.options[:order],
:include => @reflection.options[:include],
:readonly => @reflection.options[:readonly]
)
+ set_inverse_instance(the_target, @owner)
+ the_target
end
def construct_sql
@@ -117,8 +119,15 @@ module ActiveRecord
self.target = record
end
+ set_inverse_instance(record, @owner)
+
record
end
+
+ def we_can_set_the_inverse_on_this?(record)
+ inverse = @reflection.inverse_of
+ return !inverse.nil?
+ end
end
end
end
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index 2d4c1d5507..ec0175497d 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -212,6 +212,13 @@ module ActiveRecord
end
def check_validity!
+ check_validity_of_inverse!
+ end
+
+ def check_validity_of_inverse!
+ if has_inverse? && inverse_of.nil?
+ raise InverseOfAssociationNotFoundError.new(self)
+ end
end
def through_reflection
@@ -225,6 +232,18 @@ module ActiveRecord
nil
end
+ def has_inverse?
+ !@options[:inverse_of].nil?
+ end
+
+ def inverse_of
+ if has_inverse?
+ @inverse_of ||= klass.reflect_on_association(options[:inverse_of])
+ else
+ nil
+ end
+ end
+
private
def derive_class_name
class_name = name.to_s.camelize
@@ -300,6 +319,8 @@ module ActiveRecord
unless [:belongs_to, :has_many].include?(source_reflection.macro) && source_reflection.options[:through].nil?
raise HasManyThroughSourceAssociationMacroError.new(self)
end
+
+ check_validity_of_inverse!
end
def through_reflection_primary_key
diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb
new file mode 100644
index 0000000000..616f8dfbbe
--- /dev/null
+++ b/activerecord/test/cases/associations/inverse_associations_test.rb
@@ -0,0 +1,252 @@
+require "cases/helper"
+require 'models/man'
+require 'models/face'
+require 'models/interest'
+require 'models/zine'
+require 'models/club'
+require 'models/sponsor'
+
+class InverseAssociationTests < ActiveRecord::TestCase
+ def test_should_allow_for_inverse_of_options_in_associations
+ assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on has_many') do
+ Class.new(ActiveRecord::Base).has_many(:wheels, :inverse_of => :car)
+ end
+
+ assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on has_one') do
+ Class.new(ActiveRecord::Base).has_one(:engine, :inverse_of => :car)
+ end
+
+ assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on belongs_to') do
+ Class.new(ActiveRecord::Base).belongs_to(:car, :inverse_of => :driver)
+ end
+ end
+
+ def test_should_be_able_to_ask_a_reflection_if_it_has_an_inverse
+ has_one_with_inverse_ref = Man.reflect_on_association(:face)
+ assert has_one_with_inverse_ref.respond_to?(:has_inverse?)
+ assert has_one_with_inverse_ref.has_inverse?
+
+ has_many_with_inverse_ref = Man.reflect_on_association(:interests)
+ assert has_many_with_inverse_ref.respond_to?(:has_inverse?)
+ assert has_many_with_inverse_ref.has_inverse?
+
+ belongs_to_with_inverse_ref = Face.reflect_on_association(:man)
+ assert belongs_to_with_inverse_ref.respond_to?(:has_inverse?)
+ assert belongs_to_with_inverse_ref.has_inverse?
+
+ has_one_without_inverse_ref = Club.reflect_on_association(:sponsor)
+ assert has_one_without_inverse_ref.respond_to?(:has_inverse?)
+ assert !has_one_without_inverse_ref.has_inverse?
+
+ has_many_without_inverse_ref = Club.reflect_on_association(:memberships)
+ assert has_many_without_inverse_ref.respond_to?(:has_inverse?)
+ assert !has_many_without_inverse_ref.has_inverse?
+
+ belongs_to_without_inverse_ref = Sponsor.reflect_on_association(:sponsor_club)
+ assert belongs_to_without_inverse_ref.respond_to?(:has_inverse?)
+ assert !belongs_to_without_inverse_ref.has_inverse?
+ end
+
+ def test_should_be_able_to_ask_a_reflection_what_it_is_the_inverse_of
+ has_one_ref = Man.reflect_on_association(:face)
+ assert has_one_ref.respond_to?(:inverse_of)
+
+ has_many_ref = Man.reflect_on_association(:interests)
+ assert has_many_ref.respond_to?(:inverse_of)
+
+ belongs_to_ref = Face.reflect_on_association(:man)
+ assert belongs_to_ref.respond_to?(:inverse_of)
+ end
+
+ def test_inverse_of_method_should_supply_the_actual_reflection_instance_it_is_the_inverse_of
+ has_one_ref = Man.reflect_on_association(:face)
+ assert_equal Face.reflect_on_association(:man), has_one_ref.inverse_of
+
+ has_many_ref = Man.reflect_on_association(:interests)
+ assert_equal Interest.reflect_on_association(:man), has_many_ref.inverse_of
+
+ belongs_to_ref = Face.reflect_on_association(:man)
+ assert_equal Man.reflect_on_association(:face), belongs_to_ref.inverse_of
+ end
+
+ def test_associations_with_no_inverse_of_should_return_nil
+ has_one_ref = Club.reflect_on_association(:sponsor)
+ assert_nil has_one_ref.inverse_of
+
+ has_many_ref = Club.reflect_on_association(:memberships)
+ assert_nil has_many_ref.inverse_of
+
+ belongs_to_ref = Sponsor.reflect_on_association(:sponsor_club)
+ assert_nil belongs_to_ref.inverse_of
+ end
+end
+
+class InverseHasOneTests < ActiveRecord::TestCase
+ fixtures :men, :faces
+
+ def test_parent_instance_should_be_shared_with_child_on_find
+ m = Man.find(:first)
+ f = m.face
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
+ f.man.name = 'Mungo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+
+ def test_parent_instance_should_be_shared_with_newly_built_child
+ m = Man.find(:first)
+ f = m.build_face(:description => 'haunted')
+ assert_not_nil f.man
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
+ f.man.name = 'Mungo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to just-built-child-owned instance"
+ end
+
+ def test_parent_instance_should_be_shared_with_newly_created_child
+ m = Man.find(:first)
+ f = m.create_face(:description => 'haunted')
+ assert_not_nil f.man
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
+ f.man.name = 'Mungo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
+ end
+
+ def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
+ assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Man.find(:first).dirty_face }
+ end
+end
+
+class InverseHasManyTests < ActiveRecord::TestCase
+ fixtures :men, :interests
+
+ def test_parent_instance_should_be_shared_with_every_child_on_find
+ m = Man.find(:first)
+ is = m.interests
+ is.each do |i|
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+ end
+
+ def test_parent_instance_should_be_shared_with_newly_built_child
+ m = Man.find(:first)
+ i = m.interests.build(:topic => 'Industrial Revolution Re-enactment')
+ assert_not_nil i.man
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to just-built-child-owned instance"
+ end
+
+ def test_parent_instance_should_be_shared_with_newly_created_child
+ m = Man.find(:first)
+ i = m.interests.create(:topic => 'Industrial Revolution Re-enactment')
+ assert_not_nil i.man
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
+ end
+
+ def test_parent_instance_should_be_shared_with_poked_in_child
+ m = Man.find(:first)
+ i = Interest.create(:topic => 'Industrial Revolution Re-enactment')
+ m.interests << i
+ assert_not_nil i.man
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
+ end
+
+ def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
+ assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Man.find(:first).secret_interests }
+ end
+end
+
+class InverseBelongsToTests < ActiveRecord::TestCase
+ fixtures :men, :faces, :interests
+
+ def test_child_instance_should_be_shared_with_parent_on_find
+ f = Face.find(:first)
+ m = f.man
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
+ f.description = 'gormless'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
+ m.face.description = 'pleasing'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
+ end
+
+ def test_child_instance_should_be_shared_with_newly_built_parent
+ f = Face.find(:first)
+ m = f.build_man(:name => 'Charles')
+ assert_not_nil m.face
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
+ f.description = 'gormless'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
+ m.face.description = 'pleasing'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to just-built-parent-owned instance"
+ end
+
+ def test_child_instance_should_be_shared_with_newly_created_parent
+ f = Face.find(:first)
+ m = f.create_man(:name => 'Charles')
+ assert_not_nil m.face
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
+ f.description = 'gormless'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
+ m.face.description = 'pleasing'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to newly-created-parent-owned instance"
+ end
+
+ def test_should_not_try_to_set_inverse_instances_when_the_inverse_is_a_has_many
+ i = Interest.find(:first)
+ m = i.man
+ assert_not_nil m.interests
+ iz = m.interests.detect {|iz| iz.id == i.id}
+ assert_not_nil iz
+ assert_equal i.topic, iz.topic, "Interest topics should be the same before changes to child"
+ i.topic = 'Eating cheese with a spoon'
+ assert_not_equal i.topic, iz.topic, "Interest topics should not be the same after changes to child"
+ iz.topic = 'Cow tipping'
+ assert_not_equal i.topic, iz.topic, "Interest topics should not be the same after changes to parent-owned instance"
+ end
+
+ def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
+ assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Face.find(:first).horrible_man }
+ end
+end
+
+# NOTE - these tests might not be meaningful, ripped as they were from the parental_control plugin
+# which would guess the inverse rather than look for an explicit configuration option.
+class InverseMultipleHasManyInversesForSameModel < ActiveRecord::TestCase
+ fixtures :men, :interests, :zines
+
+ def test_that_we_can_load_associations_that_have_the_same_reciprocal_name_from_different_models
+ assert_nothing_raised(ActiveRecord::AssociationTypeMismatch) do
+ i = Interest.find(:first)
+ z = i.zine
+ m = i.man
+ end
+ end
+
+ def test_that_we_can_create_associations_that_have_the_same_reciprocal_name_from_different_models
+ assert_nothing_raised(ActiveRecord::AssociationTypeMismatch) do
+ i = Interest.find(:first)
+ i.build_zine(:title => 'Get Some in Winter! 2008')
+ i.build_man(:name => 'Gordon')
+ i.save!
+ end
+ end
+end
diff --git a/activerecord/test/fixtures/faces.yml b/activerecord/test/fixtures/faces.yml
new file mode 100644
index 0000000000..1dd2907cf7
--- /dev/null
+++ b/activerecord/test/fixtures/faces.yml
@@ -0,0 +1,7 @@
+trusting:
+ description: trusting
+ man: gordon
+
+weather_beaten:
+ description: weather beaten
+ man: steve
diff --git a/activerecord/test/fixtures/interests.yml b/activerecord/test/fixtures/interests.yml
new file mode 100644
index 0000000000..ec71890ab6
--- /dev/null
+++ b/activerecord/test/fixtures/interests.yml
@@ -0,0 +1,29 @@
+trainspotting:
+ topic: Trainspotting
+ zine: staying_in
+ man: gordon
+
+birdwatching:
+ topic: Birdwatching
+ zine: staying_in
+ man: gordon
+
+stamp_collecting:
+ topic: Stamp Collecting
+ zine: staying_in
+ man: gordon
+
+hunting:
+ topic: Hunting
+ zine: going_out
+ man: steve
+
+woodsmanship:
+ topic: Woodsmanship
+ zine: going_out
+ man: steve
+
+survial:
+ topic: Survival
+ zine: going_out
+ man: steve
diff --git a/activerecord/test/fixtures/men.yml b/activerecord/test/fixtures/men.yml
new file mode 100644
index 0000000000..c67429f925
--- /dev/null
+++ b/activerecord/test/fixtures/men.yml
@@ -0,0 +1,5 @@
+gordon:
+ name: Gordon
+
+steve:
+ name: Steve
diff --git a/activerecord/test/fixtures/zines.yml b/activerecord/test/fixtures/zines.yml
new file mode 100644
index 0000000000..07dce4db7e
--- /dev/null
+++ b/activerecord/test/fixtures/zines.yml
@@ -0,0 +1,5 @@
+staying_in:
+ title: Staying in '08
+
+going_out:
+ title: Outdoor Pursuits 2k+8
diff --git a/activerecord/test/models/face.rb b/activerecord/test/models/face.rb
new file mode 100644
index 0000000000..1540dbf741
--- /dev/null
+++ b/activerecord/test/models/face.rb
@@ -0,0 +1,5 @@
+class Face < ActiveRecord::Base
+ belongs_to :man, :inverse_of => :face
+ # This is a "broken" inverse_of for the purposes of testing
+ belongs_to :horrible_man, :class_name => 'Man', :inverse_of => :horrible_face
+end
diff --git a/activerecord/test/models/interest.rb b/activerecord/test/models/interest.rb
new file mode 100644
index 0000000000..d8291d00cc
--- /dev/null
+++ b/activerecord/test/models/interest.rb
@@ -0,0 +1,4 @@
+class Interest < ActiveRecord::Base
+ belongs_to :man, :inverse_of => :interests
+ belongs_to :zine, :inverse_of => :interests
+end
diff --git a/activerecord/test/models/man.rb b/activerecord/test/models/man.rb
new file mode 100644
index 0000000000..f40bc9d0fc
--- /dev/null
+++ b/activerecord/test/models/man.rb
@@ -0,0 +1,7 @@
+class Man < ActiveRecord::Base
+ has_one :face, :inverse_of => :man
+ has_many :interests, :inverse_of => :man
+ # These are "broken" inverse_of associations for the purposes of testing
+ has_one :dirty_face, :class_name => 'Face', :inverse_of => :dirty_man
+ has_many :secret_interests, :class_name => 'Interest', :inverse_of => :secret_man
+end
diff --git a/activerecord/test/models/zine.rb b/activerecord/test/models/zine.rb
new file mode 100644
index 0000000000..c2d0fdaf25
--- /dev/null
+++ b/activerecord/test/models/zine.rb
@@ -0,0 +1,3 @@
+class Zine < ActiveRecord::Base
+ has_many :interests, :inverse_of => :zine
+end
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 6918a4fcab..3b0e17c867 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -468,6 +468,26 @@ ActiveRecord::Schema.define do
end
end
+ # NOTE - the following 4 tables are used by models that have :inverse_of options on the associations
+ create_table :men, :force => true do |t|
+ t.string :name
+ end
+
+ create_table :faces, :force => true do |t|
+ t.string :description
+ t.integer :man_id
+ end
+
+ create_table :interests, :force => true do |t|
+ t.string :topic
+ t.integer :man_id
+ t.integer :zine_id
+ end
+
+ create_table :zines, :force => true do |t|
+ t.string :title
+ end
+
except 'SQLite' do
# fk_test_has_fk should be before fk_test_has_pk
create_table :fk_test_has_fk, :force => true do |t|
--
cgit v1.2.3
From b9f9dd8fe9d84c22450c1cf24b6c8a41eae8bbfd Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Mon, 4 May 2009 20:02:14 -0500
Subject: Fix console
---
railties/lib/console_app.rb | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/railties/lib/console_app.rb b/railties/lib/console_app.rb
index 5c8302634a..c944d49205 100644
--- a/railties/lib/console_app.rb
+++ b/railties/lib/console_app.rb
@@ -26,7 +26,8 @@ end
#reloads the environment
def reload!
puts "Reloading..."
- Dispatcher.cleanup_application
- Dispatcher.reload_application
+ dispatcher = ActionController::Dispatcher.new
+ dispatcher.cleanup_application
+ dispatcher.reload_application
true
end
--
cgit v1.2.3
From e3891601d137a400722cfd0f941b9195b0a8217b Mon Sep 17 00:00:00 2001
From: Tim Connor
Date: Mon, 4 May 2009 20:11:24 -0500
Subject: fix problems with requires in metal choking under development
reloading [#2579 state:resolved]
Signed-off-by: Joshua Peek
---
railties/lib/rails/rack/metal.rb | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/railties/lib/rails/rack/metal.rb b/railties/lib/rails/rack/metal.rb
index 7a616c7911..b031be29af 100644
--- a/railties/lib/rails/rack/metal.rb
+++ b/railties/lib/rails/rack/metal.rb
@@ -1,5 +1,6 @@
require 'active_support/ordered_hash'
require 'active_support/core_ext/class/attribute_accessors'
+require 'active_support/dependencies'
module Rails
module Rack
@@ -27,7 +28,7 @@ module Rails
load_list.map do |requested_metal|
if metal = all_metals[requested_metal]
- require metal
+ require_dependency metal
requested_metal.constantize
end
end.compact
--
cgit v1.2.3
From d4402c5554a0d3202fc22eb38c5c1a8c4b9afd93 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Mon, 4 May 2009 20:26:43 -0500
Subject: assert_redirect_to's partial hash matching was deprecated in 2-3
stable 7f1f16c01
---
actionpack/test/controller/redirect_test.rb | 7 -------
1 file changed, 7 deletions(-)
diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb
index 9ad63a1c60..13247f2d08 100644
--- a/actionpack/test/controller/redirect_test.rb
+++ b/actionpack/test/controller/redirect_test.rb
@@ -233,13 +233,6 @@ class RedirectTest < ActionController::TestCase
assert_redirected_to Workshop.new(5, true)
end
- def test_redirect_with_partial_params
- pending do
- get :module_redirect
- assert_redirected_to :action => 'hello_world'
- end
- end
-
def test_redirect_to_nil
assert_raise(ActionController::ActionControllerError) do
get :redirect_to_nil
--
cgit v1.2.3
From 2f42433f0a9d777e2a8f5fa05370ba464823933c Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Tue, 5 May 2009 21:40:53 -0700
Subject: Cherry-pick the inflector only
---
activemodel/lib/active_model/core.rb | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/activemodel/lib/active_model/core.rb b/activemodel/lib/active_model/core.rb
index b4b020defc..4201bcf158 100644
--- a/activemodel/lib/active_model/core.rb
+++ b/activemodel/lib/active_model/core.rb
@@ -1,12 +1,3 @@
-begin
- require 'active_support'
-rescue LoadError
- activesupport_path = "#{File.dirname(__FILE__)}/../../../activesupport/lib"
- if File.directory?(activesupport_path)
- $:.unshift activesupport_path
- require 'active_support'
- end
-end
-
-# So far, we only need the string inflections and not the rest of ActiveSupport.
+activesupport_path = "#{File.dirname(__FILE__)}/../../../activesupport/lib"
+$:.unshift(activesupport_path) if File.directory?(activesupport_path)
require 'active_support/inflector'
--
cgit v1.2.3
From a05cfb6df5336aa0369e6b27294dae3c418a75c6 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Tue, 5 May 2009 21:44:02 -0700
Subject: Prefer sibling Active Support
---
activeresource/lib/active_resource.rb | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/activeresource/lib/active_resource.rb b/activeresource/lib/active_resource.rb
index 2f0c8d1a8e..7a3faf445a 100644
--- a/activeresource/lib/active_resource.rb
+++ b/activeresource/lib/active_resource.rb
@@ -21,15 +21,9 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
-begin
- require 'active_support'
-rescue LoadError
- activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
- if File.directory?(activesupport_path)
- $:.unshift activesupport_path
- require 'active_support'
- end
-end
+activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
+$:.unshift(activesupport_path) if File.directory?(activesupport_path)
+require 'active_support'
require 'active_support/core/all'
require 'active_resource/formats'
--
cgit v1.2.3
From c585e263ab40101eb0fd71a1d24d0d704f4ce026 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Tue, 5 May 2009 21:50:53 -0700
Subject: Remove superfluous CGI require
---
activeresource/lib/active_resource/base.rb | 1 -
1 file changed, 1 deletion(-)
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index f9a461d02e..590d4f6232 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -1,5 +1,4 @@
require 'active_resource/connection'
-require 'cgi'
require 'set'
module ActiveResource
--
cgit v1.2.3
From 6d4a4fabbbb04c20cee51c4e374045cc75e2ec16 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 6 May 2009 00:14:55 -0700
Subject: Cherry pick Active Support dependencies. Autoload.
---
activeresource/lib/active_resource.rb | 11 +---
activeresource/lib/active_resource/base.rb | 16 ++++--
activeresource/lib/active_resource/connection.rb | 60 ++--------------------
.../lib/active_resource/custom_methods.rb | 4 ++
activeresource/lib/active_resource/exceptions.rb | 55 ++++++++++++++++++++
activeresource/lib/active_resource/formats.rb | 8 +--
.../lib/active_resource/formats/xml_format.rb | 2 +
activeresource/lib/active_resource/http_mock.rb | 7 ++-
activeresource/lib/active_resource/validations.rb | 7 +++
activeresource/test/abstract_unit.rb | 9 ++--
activeresource/test/base_test.rb | 2 +-
11 files changed, 100 insertions(+), 81 deletions(-)
create mode 100644 activeresource/lib/active_resource/exceptions.rb
diff --git a/activeresource/lib/active_resource.rb b/activeresource/lib/active_resource.rb
index 7a3faf445a..720abee72e 100644
--- a/activeresource/lib/active_resource.rb
+++ b/activeresource/lib/active_resource.rb
@@ -24,16 +24,7 @@
activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
$:.unshift(activesupport_path) if File.directory?(activesupport_path)
require 'active_support'
-require 'active_support/core/all'
-
-require 'active_resource/formats'
-require 'active_resource/base'
-require 'active_resource/validations'
-require 'active_resource/custom_methods'
module ActiveResource
- Base.class_eval do
- include Validations
- include CustomMethods
- end
+ autoload :Base, 'active_resource/base'
end
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index 590d4f6232..be022f5c44 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -1,7 +1,14 @@
-require 'active_resource/connection'
+require 'active_support/core_ext/class/attribute_accessors'
+require 'active_support/core_ext/class/inheritable_attributes'
+require 'active_support/core_ext/module/attr_accessor_with_default'
+require 'active_support/core_ext/module/delegation'
+require 'active_support/core_ext/module/aliasing'
require 'set'
module ActiveResource
+ autoload :Formats, 'active_resource/formats'
+ autoload :Connection, 'active_resource/connection'
+
# ActiveResource::Base is the main class for mapping RESTful resources as models in a Rails application.
#
# For an outline of what Active Resource is capable of, see link:files/vendor/rails/activeresource/README.html.
@@ -297,7 +304,7 @@ module ActiveResource
# Returns the current format, default is ActiveResource::Formats::XmlFormat.
def format
- read_inheritable_attribute(:format) || ActiveResource::Formats[:xml]
+ read_inheritable_attribute(:format) || ActiveResource::Formats::XmlFormat
end
# Sets the number of seconds after which requests to the REST API should time out.
@@ -894,7 +901,7 @@ module ActiveResource
# applicable depend on the configured encoding format.
def encode(options={})
case self.class.format
- when ActiveResource::Formats[:xml]
+ when ActiveResource::Formats::XmlFormat
self.class.format.encode(attributes, {:root => self.class.element_name}.merge(options))
else
self.class.format.encode(attributes, options)
@@ -1079,3 +1086,6 @@ module ActiveResource
end
end
end
+
+require 'active_resource/validations'
+require 'active_resource/custom_methods'
diff --git a/activeresource/lib/active_resource/connection.rb b/activeresource/lib/active_resource/connection.rb
index 80d5c95b68..6661469c5b 100644
--- a/activeresource/lib/active_resource/connection.rb
+++ b/activeresource/lib/active_resource/connection.rb
@@ -1,64 +1,12 @@
+require 'active_resource/exceptions'
+require 'active_resource/formats'
+require 'active_support/core_ext/benchmark'
require 'net/https'
require 'date'
require 'time'
require 'uri'
-require 'benchmark'
module ActiveResource
- class ConnectionError < StandardError # :nodoc:
- attr_reader :response
-
- def initialize(response, message = nil)
- @response = response
- @message = message
- end
-
- def to_s
- "Failed with #{response.code} #{response.message if response.respond_to?(:message)}"
- end
- end
-
- # Raised when a Timeout::Error occurs.
- class TimeoutError < ConnectionError
- def initialize(message)
- @message = message
- end
- def to_s; @message ;end
- end
-
- # 3xx Redirection
- class Redirection < ConnectionError # :nodoc:
- def to_s; response['Location'] ? "#{super} => #{response['Location']}" : super; end
- end
-
- # 4xx Client Error
- class ClientError < ConnectionError; end # :nodoc:
-
- # 400 Bad Request
- class BadRequest < ClientError; end # :nodoc
-
- # 401 Unauthorized
- class UnauthorizedAccess < ClientError; end # :nodoc
-
- # 403 Forbidden
- class ForbiddenAccess < ClientError; end # :nodoc
-
- # 404 Not Found
- class ResourceNotFound < ClientError; end # :nodoc:
-
- # 409 Conflict
- class ResourceConflict < ClientError; end # :nodoc:
-
- # 5xx Server Error
- class ServerError < ConnectionError; end # :nodoc:
-
- # 405 Method Not Allowed
- class MethodNotAllowed < ClientError # :nodoc:
- def allowed_methods
- @response['Allow'].split(',').map { |verb| verb.strip.downcase.to_sym }
- end
- end
-
# Class to handle connections to remote web services.
# This class is used by ActiveResource::Base to interface with REST
# services.
@@ -81,7 +29,7 @@ module ActiveResource
# The +site+ parameter is required and will set the +site+
# attribute to the URI for the remote resource service.
- def initialize(site, format = ActiveResource::Formats[:xml])
+ def initialize(site, format = ActiveResource::Formats::XmlFormat)
raise ArgumentError, 'Missing site URI' unless site
@user = @password = nil
self.site = site
diff --git a/activeresource/lib/active_resource/custom_methods.rb b/activeresource/lib/active_resource/custom_methods.rb
index 4647e8342c..0d05d06035 100644
--- a/activeresource/lib/active_resource/custom_methods.rb
+++ b/activeresource/lib/active_resource/custom_methods.rb
@@ -117,4 +117,8 @@ module ActiveResource
end
end
end
+
+ class Base
+ include CustomMethods
+ end
end
diff --git a/activeresource/lib/active_resource/exceptions.rb b/activeresource/lib/active_resource/exceptions.rb
new file mode 100644
index 0000000000..5e4b1d4487
--- /dev/null
+++ b/activeresource/lib/active_resource/exceptions.rb
@@ -0,0 +1,55 @@
+module ActiveResource
+ class ConnectionError < StandardError # :nodoc:
+ attr_reader :response
+
+ def initialize(response, message = nil)
+ @response = response
+ @message = message
+ end
+
+ def to_s
+ "Failed with #{response.code} #{response.message if response.respond_to?(:message)}"
+ end
+ end
+
+ # Raised when a Timeout::Error occurs.
+ class TimeoutError < ConnectionError
+ def initialize(message)
+ @message = message
+ end
+ def to_s; @message ;end
+ end
+
+ # 3xx Redirection
+ class Redirection < ConnectionError # :nodoc:
+ def to_s; response['Location'] ? "#{super} => #{response['Location']}" : super; end
+ end
+
+ # 4xx Client Error
+ class ClientError < ConnectionError; end # :nodoc:
+
+ # 400 Bad Request
+ class BadRequest < ClientError; end # :nodoc
+
+ # 401 Unauthorized
+ class UnauthorizedAccess < ClientError; end # :nodoc
+
+ # 403 Forbidden
+ class ForbiddenAccess < ClientError; end # :nodoc
+
+ # 404 Not Found
+ class ResourceNotFound < ClientError; end # :nodoc:
+
+ # 409 Conflict
+ class ResourceConflict < ClientError; end # :nodoc:
+
+ # 5xx Server Error
+ class ServerError < ConnectionError; end # :nodoc:
+
+ # 405 Method Not Allowed
+ class MethodNotAllowed < ClientError # :nodoc:
+ def allowed_methods
+ @response['Allow'].split(',').map { |verb| verb.strip.downcase.to_sym }
+ end
+ end
+end
diff --git a/activeresource/lib/active_resource/formats.rb b/activeresource/lib/active_resource/formats.rb
index 28864cf588..53b75b34e7 100644
--- a/activeresource/lib/active_resource/formats.rb
+++ b/activeresource/lib/active_resource/formats.rb
@@ -1,14 +1,14 @@
module ActiveResource
module Formats
+ autoload :XmlFormat, 'active_resource/formats/xml_format'
+ autoload :JsonFormat, 'active_resource/formats/json_format'
+
# Lookup the format class from a mime type reference symbol. Example:
#
# ActiveResource::Formats[:xml] # => ActiveResource::Formats::XmlFormat
# ActiveResource::Formats[:json] # => ActiveResource::Formats::JsonFormat
def self.[](mime_type_reference)
- ActiveResource::Formats.const_get(mime_type_reference.to_s.camelize + "Format")
+ ActiveResource::Formats.const_get(ActiveSupport::Inflector.camelize(mime_type_reference.to_s) + "Format")
end
end
end
-
-require 'active_resource/formats/xml_format'
-require 'active_resource/formats/json_format'
\ No newline at end of file
diff --git a/activeresource/lib/active_resource/formats/xml_format.rb b/activeresource/lib/active_resource/formats/xml_format.rb
index 86c6cec745..3b2575cfa1 100644
--- a/activeresource/lib/active_resource/formats/xml_format.rb
+++ b/activeresource/lib/active_resource/formats/xml_format.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/hash/conversions'
+
module ActiveResource
module Formats
module XmlFormat
diff --git a/activeresource/lib/active_resource/http_mock.rb b/activeresource/lib/active_resource/http_mock.rb
index 7d7e378436..aae2d6508c 100644
--- a/activeresource/lib/active_resource/http_mock.rb
+++ b/activeresource/lib/active_resource/http_mock.rb
@@ -1,4 +1,5 @@
require 'active_resource/connection'
+require 'active_support/core_ext/kernel/reporting'
module ActiveResource
class InvalidRequestError < StandardError; end #:nodoc:
@@ -129,7 +130,11 @@ module ActiveResource
def #{method}(path, #{'body, ' if has_body}headers)
request = ActiveResource::Request.new(:#{method}, path, #{has_body ? 'body, ' : 'nil, '}headers)
self.class.requests << request
- self.class.responses.assoc(request).try(:second) || raise(InvalidRequestError.new("No response recorded for \#{request}"))
+ if response = self.class.responses.assoc(request)
+ response[1]
+ else
+ raise InvalidRequestError.new("No response recorded for \#{request}")
+ end
end
EOE
end
diff --git a/activeresource/lib/active_resource/validations.rb b/activeresource/lib/active_resource/validations.rb
index 8d21f8adbb..da6084fe9f 100644
--- a/activeresource/lib/active_resource/validations.rb
+++ b/activeresource/lib/active_resource/validations.rb
@@ -1,3 +1,6 @@
+require 'active_resource/exceptions'
+require 'active_support/core_ext/array/wrap'
+
module ActiveResource
class ResourceInvalid < ClientError #:nodoc:
end
@@ -272,4 +275,8 @@ module ActiveResource
@errors ||= Errors.new(self)
end
end
+
+ class Base
+ include Validations
+ end
end
diff --git a/activeresource/test/abstract_unit.rb b/activeresource/test/abstract_unit.rb
index 0f11ea482a..3398f2dac7 100644
--- a/activeresource/test/abstract_unit.rb
+++ b/activeresource/test/abstract_unit.rb
@@ -5,19 +5,16 @@ gem 'mocha', '>= 0.9.5'
require 'mocha'
$:.unshift "#{File.dirname(__FILE__)}/../lib"
-$:.unshift "#{File.dirname(__FILE__)}/../../activesupport/lib"
require 'active_resource'
require 'active_resource/http_mock'
$:.unshift "#{File.dirname(__FILE__)}/../test"
require 'setter_trap'
+require 'logger'
ActiveResource::Base.logger = Logger.new("#{File.dirname(__FILE__)}/debug.log")
-def uses_gem(gem_name, test_name, version = '> 0')
- gem gem_name.to_s, version
- require gem_name.to_s
- yield
+begin
+ require 'ruby-debug'
rescue LoadError
- $stderr.puts "Skipping #{test_name} tests. `gem install #{gem_name}` and try again."
end
diff --git a/activeresource/test/base_test.rb b/activeresource/test/base_test.rb
index 6ed6f1a406..a6cef6b2ae 100644
--- a/activeresource/test/base_test.rb
+++ b/activeresource/test/base_test.rb
@@ -853,7 +853,7 @@ class BaseTest < Test::Unit::TestCase
def test_to_xml
matz = Person.find(1)
xml = matz.encode
- assert xml.starts_with?('')
+ assert xml.include?('')
assert xml.include?('Matz ')
assert xml.include?('1 ')
end
--
cgit v1.2.3
From bd7659e014482a25b7ab6c6242a2b0926dcfc4d2 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 6 May 2009 01:28:06 -0700
Subject: Fix old reference to ActionController::Failsafe
---
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 71366a4480..9d27488e8a 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -462,7 +462,7 @@ Run `rake gems:install` to install the missing gems.
if RAILS_CACHE.respond_to?(:middleware)
# Insert middleware to setup and teardown local cache for each request
- configuration.middleware.insert_after(:"ActionController::Failsafe", RAILS_CACHE.middleware)
+ configuration.middleware.insert_after(:"ActionDispatch::Failsafe", RAILS_CACHE.middleware)
end
end
end
--
cgit v1.2.3
From 201d8b17552c8c9eb96e2aca2f871e0fd9b96e15 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 6 May 2009 12:19:30 -0700
Subject: Fix tests on 1.8.6
---
activeresource/lib/active_resource/base.rb | 1 +
activeresource/test/base/load_test.rb | 1 +
2 files changed, 2 insertions(+)
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index be022f5c44..8a1236c9a8 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -3,6 +3,7 @@ require 'active_support/core_ext/class/inheritable_attributes'
require 'active_support/core_ext/module/attr_accessor_with_default'
require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/module/aliasing'
+require 'active_support/core_ext/object/misc'
require 'set'
module ActiveResource
diff --git a/activeresource/test/base/load_test.rb b/activeresource/test/base/load_test.rb
index a475fab34e..cd2103acb7 100644
--- a/activeresource/test/base/load_test.rb
+++ b/activeresource/test/base/load_test.rb
@@ -1,6 +1,7 @@
require 'abstract_unit'
require "fixtures/person"
require "fixtures/street_address"
+require 'active_support/core_ext/symbol'
module Highrise
class Note < ActiveResource::Base
--
cgit v1.2.3
From bfc1609a501fc3ed442685819de5bcdb5fbada1c Mon Sep 17 00:00:00 2001
From: Matt Jones
Date: Wed, 6 May 2009 19:35:54 -0500
Subject: Remove stray call to gems:unpack in gems:build:force
[#2266 state:committed]
Signed-off-by: Jeremy Kemper
---
railties/lib/tasks/gems.rake | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/railties/lib/tasks/gems.rake b/railties/lib/tasks/gems.rake
index efadb1da3b..7cf7061f38 100644
--- a/railties/lib/tasks/gems.rake
+++ b/railties/lib/tasks/gems.rake
@@ -27,8 +27,7 @@ namespace :gems 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) }
+ frozen_gems.each { |gem| gem.build(:force => true) }
end
end
--
cgit v1.2.3
From 783deae99a4850f597135146b19e7ee4622da94e Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 7 May 2009 10:03:39 -0500
Subject: Add test coverage to module setup extensions
---
activesupport/test/core_ext/module/setup_test.rb | 74 ++++++++++++++++++++++++
1 file changed, 74 insertions(+)
create mode 100644 activesupport/test/core_ext/module/setup_test.rb
diff --git a/activesupport/test/core_ext/module/setup_test.rb b/activesupport/test/core_ext/module/setup_test.rb
new file mode 100644
index 0000000000..132790f2ff
--- /dev/null
+++ b/activesupport/test/core_ext/module/setup_test.rb
@@ -0,0 +1,74 @@
+require 'abstract_unit'
+require 'active_support/core/time'
+require 'active_support/core_ext/module/setup'
+
+class SetupTest < Test::Unit::TestCase
+ module Baz
+ module ClassMethods
+ def baz
+ "baz"
+ end
+
+ def setup=(value)
+ @@setup = value
+ end
+
+ def setup
+ @@setup
+ end
+ end
+
+ setup do
+ self.setup = true
+ end
+
+ def baz
+ "baz"
+ end
+ end
+
+ module Bar
+ depends_on Baz
+
+ def bar
+ "bar"
+ end
+
+ def baz
+ "bar+" + super
+ end
+ end
+
+ def setup
+ @klass = Class.new
+ end
+
+ def test_module_is_included_normally
+ @klass.use(Baz)
+ assert_equal "baz", @klass.new.baz
+ assert_equal SetupTest::Baz, @klass.included_modules[0]
+
+ @klass.use(Baz)
+ assert_equal "baz", @klass.new.baz
+ assert_equal SetupTest::Baz, @klass.included_modules[0]
+ end
+
+ def test_class_methods_are_extended
+ @klass.use(Baz)
+ assert_equal "baz", @klass.baz
+ assert_equal SetupTest::Baz::ClassMethods, (class << @klass; self.included_modules; end)[0]
+ end
+
+ def test_setup_block_is_ran
+ @klass.use(Baz)
+ assert_equal true, @klass.setup
+ end
+
+ def test_modules_dependencies_are_met
+ @klass.use(Bar)
+ assert_equal "bar", @klass.new.bar
+ assert_equal "bar+baz", @klass.new.baz
+ assert_equal "baz", @klass.baz
+ assert_equal [SetupTest::Bar, SetupTest::Baz], @klass.included_modules[0..1]
+ end
+end
--
cgit v1.2.3
From 2854535b02bcee3668bda02c76c3105fc24730d3 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 7 May 2009 10:29:22 -0500
Subject: Make module dependency DSL opt in
---
.../lib/action_controller/abstract/helpers.rb | 2 +
.../lib/action_controller/abstract/layouts.rb | 5 +-
.../lib/action_controller/abstract/logger.rb | 2 +
.../lib/action_controller/abstract/renderer.rb | 2 +
.../lib/action_controller/new_base/layouts.rb | 2 +
.../lib/action_controller/new_base/renderer.rb | 2 +
.../test/abstract_controller/callbacks_test.rb | 2 +-
.../test/abstract_controller/layouts_test.rb | 6 +-
actionpack/test/new_base/test_helper.rb | 14 ++--
activesupport/lib/active_support.rb | 1 +
.../lib/active_support/core_ext/module.rb | 1 -
.../lib/active_support/core_ext/module/setup.rb | 26 --------
.../lib/active_support/dependency_module.rb | 24 +++++++
activesupport/test/core_ext/module/setup_test.rb | 74 ---------------------
activesupport/test/dependency_module_test.rb | 77 ++++++++++++++++++++++
15 files changed, 126 insertions(+), 114 deletions(-)
delete mode 100644 activesupport/lib/active_support/core_ext/module/setup.rb
create mode 100644 activesupport/lib/active_support/dependency_module.rb
delete mode 100644 activesupport/test/core_ext/module/setup_test.rb
create mode 100644 activesupport/test/dependency_module_test.rb
diff --git a/actionpack/lib/action_controller/abstract/helpers.rb b/actionpack/lib/action_controller/abstract/helpers.rb
index 1f0b38417b..ffcae29ddc 100644
--- a/actionpack/lib/action_controller/abstract/helpers.rb
+++ b/actionpack/lib/action_controller/abstract/helpers.rb
@@ -1,5 +1,7 @@
module AbstractController
module Helpers
+ extend ActiveSupport::DependencyModule
+
depends_on Renderer
setup do
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 0039e67c5a..76130f8dc0 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -1,8 +1,9 @@
module AbstractController
module Layouts
-
+ extend ActiveSupport::DependencyModule
+
depends_on Renderer
-
+
module ClassMethods
def layout(layout)
unless [String, Symbol, FalseClass, NilClass].include?(layout.class)
diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb
index 4117369bd4..bdb8defa0c 100644
--- a/actionpack/lib/action_controller/abstract/logger.rb
+++ b/actionpack/lib/action_controller/abstract/logger.rb
@@ -1,5 +1,7 @@
module AbstractController
module Logger
+ extend ActiveSupport::DependencyModule
+
setup do
cattr_accessor :logger
end
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index e31accbbfc..531eb28dcb 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -2,6 +2,8 @@ require "action_controller/abstract/logger"
module AbstractController
module Renderer
+ extend ActiveSupport::DependencyModule
+
depends_on AbstractController::Logger
setup do
diff --git a/actionpack/lib/action_controller/new_base/layouts.rb b/actionpack/lib/action_controller/new_base/layouts.rb
index a8e0809ac6..89d24fe92d 100644
--- a/actionpack/lib/action_controller/new_base/layouts.rb
+++ b/actionpack/lib/action_controller/new_base/layouts.rb
@@ -1,5 +1,7 @@
module ActionController
module Layouts
+ extend ActiveSupport::DependencyModule
+
depends_on ActionController::Renderer
depends_on AbstractController::Layouts
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index ed34c46aed..be4ea54c3b 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -1,5 +1,7 @@
module ActionController
module Renderer
+ extend ActiveSupport::DependencyModule
+
depends_on AbstractController::Renderer
def initialize(*)
diff --git a/actionpack/test/abstract_controller/callbacks_test.rb b/actionpack/test/abstract_controller/callbacks_test.rb
index 5fce30f478..89243b631e 100644
--- a/actionpack/test/abstract_controller/callbacks_test.rb
+++ b/actionpack/test/abstract_controller/callbacks_test.rb
@@ -4,7 +4,7 @@ module AbstractController
module Testing
class ControllerWithCallbacks < AbstractController::Base
- use AbstractController::Callbacks
+ include AbstractController::Callbacks
end
class Callback1 < ControllerWithCallbacks
diff --git a/actionpack/test/abstract_controller/layouts_test.rb b/actionpack/test/abstract_controller/layouts_test.rb
index 3d4570bfef..a305a30a54 100644
--- a/actionpack/test/abstract_controller/layouts_test.rb
+++ b/actionpack/test/abstract_controller/layouts_test.rb
@@ -5,9 +5,9 @@ module AbstractControllerTests
# Base controller for these tests
class Base < AbstractController::Base
- use AbstractController::Renderer
- use AbstractController::Layouts
-
+ include AbstractController::Renderer
+ include AbstractController::Layouts
+
self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
"layouts/hello.erb" => "With String <%= yield %>",
"layouts/hello_override.erb" => "With Override <%= yield %>",
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index d29449ddc1..89c29d9af3 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -26,14 +26,14 @@ require 'rack/test'
module ActionController
class Base2 < AbstractBase
- use AbstractController::Callbacks
- use AbstractController::Helpers
- use AbstractController::Logger
+ include AbstractController::Callbacks
+ include AbstractController::Helpers
+ include AbstractController::Logger
- use ActionController::HideActions
- use ActionController::UrlFor
- use ActionController::Renderer
- use ActionController::Layouts
+ include ActionController::HideActions
+ include ActionController::UrlFor
+ include ActionController::Renderer
+ include ActionController::Layouts
def self.inherited(klass)
::ActionController::Base2.subclasses << klass.to_s
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 0879535487..dab017770d 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -34,6 +34,7 @@ module ActiveSupport
autoload :Callbacks, 'active_support/callbacks'
autoload :NewCallbacks, 'active_support/new_callbacks'
autoload :ConcurrentHash, 'active_support/concurrent_hash'
+ autoload :DependencyModule, 'active_support/dependency_module'
autoload :Deprecation, 'active_support/deprecation'
autoload :Gzip, 'active_support/gzip'
autoload :Inflector, 'active_support/inflector'
diff --git a/activesupport/lib/active_support/core_ext/module.rb b/activesupport/lib/active_support/core_ext/module.rb
index fee91534e7..215c47b114 100644
--- a/activesupport/lib/active_support/core_ext/module.rb
+++ b/activesupport/lib/active_support/core_ext/module.rb
@@ -9,4 +9,3 @@ require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/module/loading'
require 'active_support/core_ext/module/model_naming'
require 'active_support/core_ext/module/synchronization'
-require 'active_support/core_ext/module/setup'
diff --git a/activesupport/lib/active_support/core_ext/module/setup.rb b/activesupport/lib/active_support/core_ext/module/setup.rb
deleted file mode 100644
index e6dfd0cf56..0000000000
--- a/activesupport/lib/active_support/core_ext/module/setup.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-class Module
- attr_accessor :_setup_block
- attr_accessor :_dependencies
-
- def setup(&blk)
- @_setup_block = blk
- end
-
- def use(mod)
- return if self < mod
-
- (mod._dependencies || []).each do |dep|
- use dep
- end
- # raise "Circular dependencies" if self < mod
- include mod
- extend mod.const_get("ClassMethods") if mod.const_defined?("ClassMethods")
- class_eval(&mod._setup_block) if mod._setup_block
- end
-
- def depends_on(mod)
- return if self < mod
- @_dependencies ||= []
- @_dependencies << mod
- end
-end
\ No newline at end of file
diff --git a/activesupport/lib/active_support/dependency_module.rb b/activesupport/lib/active_support/dependency_module.rb
new file mode 100644
index 0000000000..0e1cc67b53
--- /dev/null
+++ b/activesupport/lib/active_support/dependency_module.rb
@@ -0,0 +1,24 @@
+module ActiveSupport
+ module DependencyModule
+ def setup(&blk)
+ @_setup_block = blk
+ end
+
+ def append_features(base)
+ return if base < self
+ (@_dependencies ||= []).each { |dep| base.send(:include, dep) }
+ super
+ end
+
+ def included(base)
+ base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
+ base.class_eval(&@_setup_block) if instance_variable_defined?("@_setup_block")
+ end
+
+ def depends_on(mod)
+ return if self < mod
+ @_dependencies ||= []
+ @_dependencies << mod
+ end
+ end
+end
diff --git a/activesupport/test/core_ext/module/setup_test.rb b/activesupport/test/core_ext/module/setup_test.rb
deleted file mode 100644
index 132790f2ff..0000000000
--- a/activesupport/test/core_ext/module/setup_test.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-require 'abstract_unit'
-require 'active_support/core/time'
-require 'active_support/core_ext/module/setup'
-
-class SetupTest < Test::Unit::TestCase
- module Baz
- module ClassMethods
- def baz
- "baz"
- end
-
- def setup=(value)
- @@setup = value
- end
-
- def setup
- @@setup
- end
- end
-
- setup do
- self.setup = true
- end
-
- def baz
- "baz"
- end
- end
-
- module Bar
- depends_on Baz
-
- def bar
- "bar"
- end
-
- def baz
- "bar+" + super
- end
- end
-
- def setup
- @klass = Class.new
- end
-
- def test_module_is_included_normally
- @klass.use(Baz)
- assert_equal "baz", @klass.new.baz
- assert_equal SetupTest::Baz, @klass.included_modules[0]
-
- @klass.use(Baz)
- assert_equal "baz", @klass.new.baz
- assert_equal SetupTest::Baz, @klass.included_modules[0]
- end
-
- def test_class_methods_are_extended
- @klass.use(Baz)
- assert_equal "baz", @klass.baz
- assert_equal SetupTest::Baz::ClassMethods, (class << @klass; self.included_modules; end)[0]
- end
-
- def test_setup_block_is_ran
- @klass.use(Baz)
- assert_equal true, @klass.setup
- end
-
- def test_modules_dependencies_are_met
- @klass.use(Bar)
- assert_equal "bar", @klass.new.bar
- assert_equal "bar+baz", @klass.new.baz
- assert_equal "baz", @klass.baz
- assert_equal [SetupTest::Bar, SetupTest::Baz], @klass.included_modules[0..1]
- end
-end
diff --git a/activesupport/test/dependency_module_test.rb b/activesupport/test/dependency_module_test.rb
new file mode 100644
index 0000000000..d611b4056c
--- /dev/null
+++ b/activesupport/test/dependency_module_test.rb
@@ -0,0 +1,77 @@
+require 'abstract_unit'
+require 'active_support/dependency_module'
+
+class DependencyModuleTest < Test::Unit::TestCase
+ module Baz
+ extend ActiveSupport::DependencyModule
+
+ module ClassMethods
+ def baz
+ "baz"
+ end
+
+ def setup=(value)
+ @@setup = value
+ end
+
+ def setup
+ @@setup
+ end
+ end
+
+ setup do
+ self.setup = true
+ end
+
+ def baz
+ "baz"
+ end
+ end
+
+ module Bar
+ extend ActiveSupport::DependencyModule
+
+ depends_on Baz
+
+ def bar
+ "bar"
+ end
+
+ def baz
+ "bar+" + super
+ end
+ end
+
+ def setup
+ @klass = Class.new
+ end
+
+ def test_module_is_included_normally
+ @klass.send(:include, Baz)
+ assert_equal "baz", @klass.new.baz
+ assert_equal DependencyModuleTest::Baz, @klass.included_modules[0]
+
+ @klass.send(:include, Baz)
+ assert_equal "baz", @klass.new.baz
+ assert_equal DependencyModuleTest::Baz, @klass.included_modules[0]
+ end
+
+ def test_class_methods_are_extended
+ @klass.send(:include, Baz)
+ assert_equal "baz", @klass.baz
+ assert_equal DependencyModuleTest::Baz::ClassMethods, (class << @klass; self.included_modules; end)[0]
+ end
+
+ def test_setup_block_is_ran
+ @klass.send(:include, Baz)
+ assert_equal true, @klass.setup
+ end
+
+ def test_modules_dependencies_are_met
+ @klass.send(:include, Bar)
+ assert_equal "bar", @klass.new.bar
+ assert_equal "bar+baz", @klass.new.baz
+ assert_equal "baz", @klass.baz
+ assert_equal [DependencyModuleTest::Bar, DependencyModuleTest::Baz], @klass.included_modules[0..1]
+ end
+end
--
cgit v1.2.3
From af40fa6d036d86895e7be4ef46a615d44eb41ede Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 7 May 2009 10:38:57 -0500
Subject: Prefer "included" language over "setup"
---
actionpack/lib/action_controller/abstract/callbacks.rb | 11 +++++++----
actionpack/lib/action_controller/abstract/helpers.rb | 4 ++--
actionpack/lib/action_controller/abstract/logger.rb | 2 +-
actionpack/lib/action_controller/abstract/renderer.rb | 10 +++++-----
.../lib/action_controller/new_base/hide_actions.rb | 6 +++---
activesupport/lib/active_support/dependency_module.rb | 14 +++++++-------
activesupport/test/dependency_module_test.rb | 16 ++++++++--------
7 files changed, 33 insertions(+), 30 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb
index c8b509081c..d7faaf4236 100644
--- a/actionpack/lib/action_controller/abstract/callbacks.rb
+++ b/actionpack/lib/action_controller/abstract/callbacks.rb
@@ -1,10 +1,13 @@
module AbstractController
module Callbacks
- setup do
- include ActiveSupport::NewCallbacks
- define_callbacks :process_action
+ extend ActiveSupport::DependencyModule
+
+ depends_on ActiveSupport::NewCallbacks
+
+ included do
+ define_callbacks :process_action
end
-
+
def process_action
_run_process_action_callbacks(action_name) do
super
diff --git a/actionpack/lib/action_controller/abstract/helpers.rb b/actionpack/lib/action_controller/abstract/helpers.rb
index ffcae29ddc..62caa119e7 100644
--- a/actionpack/lib/action_controller/abstract/helpers.rb
+++ b/actionpack/lib/action_controller/abstract/helpers.rb
@@ -3,8 +3,8 @@ module AbstractController
extend ActiveSupport::DependencyModule
depends_on Renderer
-
- setup do
+
+ included do
extlib_inheritable_accessor :master_helper_module
self.master_helper_module = Module.new
end
diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb
index bdb8defa0c..5fb78f1755 100644
--- a/actionpack/lib/action_controller/abstract/logger.rb
+++ b/actionpack/lib/action_controller/abstract/logger.rb
@@ -2,7 +2,7 @@ module AbstractController
module Logger
extend ActiveSupport::DependencyModule
- setup do
+ included do
cattr_accessor :logger
end
end
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index 531eb28dcb..beb848f90e 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -5,15 +5,15 @@ module AbstractController
extend ActiveSupport::DependencyModule
depends_on AbstractController::Logger
-
- setup do
+
+ included do
attr_internal :formats
-
+
extlib_inheritable_accessor :_view_paths
-
+
self._view_paths ||= ActionView::PathSet.new
end
-
+
def _action_view
@_action_view ||= ActionView::Base.new(self.class.view_paths, {}, self)
end
diff --git a/actionpack/lib/action_controller/new_base/hide_actions.rb b/actionpack/lib/action_controller/new_base/hide_actions.rb
index 473a8ea72b..aa420442fb 100644
--- a/actionpack/lib/action_controller/new_base/hide_actions.rb
+++ b/actionpack/lib/action_controller/new_base/hide_actions.rb
@@ -1,10 +1,10 @@
module ActionController
module HideActions
- setup do
+ included do
extlib_inheritable_accessor :hidden_actions
- self.hidden_actions ||= Set.new
+ self.hidden_actions ||= Set.new
end
-
+
def action_methods() self.class.action_names end
def action_names() action_methods end
diff --git a/activesupport/lib/active_support/dependency_module.rb b/activesupport/lib/active_support/dependency_module.rb
index 0e1cc67b53..c690b49a2b 100644
--- a/activesupport/lib/active_support/dependency_module.rb
+++ b/activesupport/lib/active_support/dependency_module.rb
@@ -1,18 +1,18 @@
module ActiveSupport
module DependencyModule
- def setup(&blk)
- @_setup_block = blk
- end
-
def append_features(base)
return if base < self
(@_dependencies ||= []).each { |dep| base.send(:include, dep) }
super
end
- def included(base)
- base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
- base.class_eval(&@_setup_block) if instance_variable_defined?("@_setup_block")
+ def included(base = nil, &block)
+ if base.nil? && block_given?
+ @_included_block = block
+ else
+ base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
+ base.class_eval(&@_included_block) if instance_variable_defined?("@_included_block")
+ end
end
def depends_on(mod)
diff --git a/activesupport/test/dependency_module_test.rb b/activesupport/test/dependency_module_test.rb
index d611b4056c..07090d15a1 100644
--- a/activesupport/test/dependency_module_test.rb
+++ b/activesupport/test/dependency_module_test.rb
@@ -10,17 +10,17 @@ class DependencyModuleTest < Test::Unit::TestCase
"baz"
end
- def setup=(value)
- @@setup = value
+ def included_ran=(value)
+ @@included_ran = value
end
- def setup
- @@setup
+ def included_ran
+ @@included_ran
end
end
- setup do
- self.setup = true
+ included do
+ self.included_ran = true
end
def baz
@@ -62,9 +62,9 @@ class DependencyModuleTest < Test::Unit::TestCase
assert_equal DependencyModuleTest::Baz::ClassMethods, (class << @klass; self.included_modules; end)[0]
end
- def test_setup_block_is_ran
+ def test_included_block_is_ran
@klass.send(:include, Baz)
- assert_equal true, @klass.setup
+ assert_equal true, @klass.included_ran
end
def test_modules_dependencies_are_met
--
cgit v1.2.3
From a747ab5b20b9d543e9d311070e3b720c761ae716 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 7 May 2009 10:45:29 -0500
Subject: Whitespace!
---
actionpack/lib/action_controller/abstract.rb | 2 +-
actionpack/lib/action_controller/abstract/base.rb | 19 +++++++--------
.../lib/action_controller/abstract/callbacks.rb | 8 +++----
.../lib/action_controller/abstract/exceptions.rb | 2 +-
.../lib/action_controller/abstract/helpers.rb | 17 +++++++-------
.../lib/action_controller/abstract/layouts.rb | 27 +++++++++++-----------
.../lib/action_controller/abstract/logger.rb | 2 +-
.../lib/action_controller/abstract/renderer.rb | 19 ++++++++-------
actionpack/lib/action_controller/new_base.rb | 2 +-
actionpack/lib/action_controller/new_base/base.rb | 27 +++++++++++-----------
.../lib/action_controller/new_base/hide_actions.rb | 11 ++++-----
.../lib/action_controller/new_base/layouts.rb | 14 +++++------
.../lib/action_controller/new_base/renderer.rb | 23 +++++++++---------
.../lib/action_controller/new_base/url_for.rb | 6 ++---
14 files changed, 84 insertions(+), 95 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract.rb b/actionpack/lib/action_controller/abstract.rb
index 3f5c4a185f..9442d4559f 100644
--- a/actionpack/lib/action_controller/abstract.rb
+++ b/actionpack/lib/action_controller/abstract.rb
@@ -7,4 +7,4 @@ module AbstractController
autoload :Renderer, "action_controller/abstract/renderer"
# === Exceptions
autoload :ActionNotFound, "action_controller/abstract/exceptions"
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index ade7719cc0..39e9ad0440 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -1,41 +1,38 @@
module AbstractController
class Base
-
attr_internal :response_body
attr_internal :response_obj
attr_internal :action_name
-
+
def self.process(action)
new.process(action)
end
-
+
def self.inherited(klass)
end
-
+
def initialize
self.response_obj = {}
end
-
+
def process(action_name)
unless respond_to_action?(action_name)
raise ActionNotFound, "The action '#{action_name}' could not be found"
end
-
+
@_action_name = action_name
process_action
self.response_obj[:body] = self.response_body
self
end
-
+
private
-
def process_action
respond_to?(action_name) ? send(action_name) : send(:action_missing, action_name)
end
-
+
def respond_to_action?(action_name)
respond_to?(action_name) || respond_to?(:action_missing, true)
end
-
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb
index d7faaf4236..cb8aade0be 100644
--- a/actionpack/lib/action_controller/abstract/callbacks.rb
+++ b/actionpack/lib/action_controller/abstract/callbacks.rb
@@ -13,7 +13,7 @@ module AbstractController
super
end
end
-
+
module ClassMethods
def _normalize_callback_options(options)
if only = options[:only]
@@ -21,11 +21,11 @@ module AbstractController
options[:per_key] = {:if => only}
end
if except = options[:except]
- except = Array(except).map {|e| "action_name == :#{e}"}.join(" || ")
+ except = Array(except).map {|e| "action_name == :#{e}"}.join(" || ")
options[:per_key] = {:unless => except}
end
end
-
+
[:before, :after, :around].each do |filter|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
def #{filter}_filter(*names, &blk)
@@ -40,4 +40,4 @@ module AbstractController
end
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/abstract/exceptions.rb b/actionpack/lib/action_controller/abstract/exceptions.rb
index ec4680629b..a7d07868bb 100644
--- a/actionpack/lib/action_controller/abstract/exceptions.rb
+++ b/actionpack/lib/action_controller/abstract/exceptions.rb
@@ -1,3 +1,3 @@
module AbstractController
class ActionNotFound < StandardError ; end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/abstract/helpers.rb b/actionpack/lib/action_controller/abstract/helpers.rb
index 62caa119e7..38e3ce8127 100644
--- a/actionpack/lib/action_controller/abstract/helpers.rb
+++ b/actionpack/lib/action_controller/abstract/helpers.rb
@@ -8,14 +8,14 @@ module AbstractController
extlib_inheritable_accessor :master_helper_module
self.master_helper_module = Module.new
end
-
+
# def self.included(klass)
# klass.class_eval do
# extlib_inheritable_accessor :master_helper_module
# self.master_helper_module = Module.new
# end
# end
-
+
def _action_view
@_action_view ||= begin
av = super
@@ -23,19 +23,19 @@ module AbstractController
av
end
end
-
+
module ClassMethods
def inherited(klass)
klass.master_helper_module = Module.new
klass.master_helper_module.__send__ :include, master_helper_module
-
+
super
end
-
+
def add_template_helper(mod)
master_helper_module.module_eval { include mod }
end
-
+
def helper_method(*meths)
meths.flatten.each do |meth|
master_helper_module.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
@@ -45,7 +45,7 @@ module AbstractController
ruby_eval
end
end
-
+
def helper(*args, &blk)
args.flatten.each do |arg|
case arg
@@ -56,6 +56,5 @@ module AbstractController
master_helper_module.module_eval(&blk) if block_given?
end
end
-
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 76130f8dc0..69fe4efc19 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -9,18 +9,18 @@ module AbstractController
unless [String, Symbol, FalseClass, NilClass].include?(layout.class)
raise ArgumentError, "Layouts must be specified as a String, Symbol, false, or nil"
end
-
+
@_layout = layout || false # Converts nil to false
_write_layout_method
end
-
+
def _implied_layout_name
name.underscore
end
-
+
# Takes the specified layout and creates a _layout method to be called
# by _default_layout
- #
+ #
# If the specified layout is a:
# String:: return the string
# Symbol:: call the method specified by the symbol
@@ -49,35 +49,34 @@ module AbstractController
end
end
end
-
+
def _render_template(template, options)
_action_view._render_template_with_layout(template, options[:_layout])
end
-
+
private
-
def _layout() end # This will be overwritten
-
+
def _layout_for_name(name)
unless [String, FalseClass, NilClass].include?(name.class)
raise ArgumentError, "String, false, or nil expected; you passed #{name.inspect}"
end
-
+
name && view_paths.find_by_parts(name, {:formats => formats}, "layouts")
end
-
+
def _default_layout(require_layout = false)
if require_layout && !_layout
- raise ArgumentError,
+ raise ArgumentError,
"There was no default layout for #{self.class} in #{view_paths.inspect}"
end
-
+
begin
layout = _layout_for_name(_layout)
rescue NameError => e
- raise NoMethodError,
+ raise NoMethodError,
"You specified #{@_layout.inspect} as the layout, but no such method was found"
end
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb
index 5fb78f1755..c3bccd7778 100644
--- a/actionpack/lib/action_controller/abstract/logger.rb
+++ b/actionpack/lib/action_controller/abstract/logger.rb
@@ -6,4 +6,4 @@ module AbstractController
cattr_accessor :logger
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index beb848f90e..b5c31a27ee 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -15,22 +15,22 @@ module AbstractController
end
def _action_view
- @_action_view ||= ActionView::Base.new(self.class.view_paths, {}, self)
+ @_action_view ||= ActionView::Base.new(self.class.view_paths, {}, self)
end
-
+
def render(options = {})
self.response_body = render_to_body(options)
end
-
+
# Raw rendering of a template to a Rack-compatible body.
# ====
# @option _prefix The template's path prefix
# @option _layout The relative path to the layout template to use
- #
+ #
# :api: plugin
def render_to_body(options = {})
name = options[:_template_name] || action_name
-
+
template = options[:_template] || view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix])
_render_template(template, options)
end
@@ -39,7 +39,7 @@ module AbstractController
# ====
# @option _prefix The template's path prefix
# @option _layout The relative path to the layout template to use
- #
+ #
# :api: plugin
def render_to_string(options = {})
AbstractController::Renderer.body_to_s(render_to_body(options))
@@ -48,7 +48,7 @@ module AbstractController
def _render_template(template, options)
_action_view._render_template_with_layout(template)
end
-
+
def view_paths() _view_paths end
# Return a string representation of a Rack-compatible response body.
@@ -64,15 +64,14 @@ module AbstractController
end
module ClassMethods
-
def append_view_path(path)
self.view_paths << path
end
-
+
def view_paths
self._view_paths
end
-
+
def view_paths=(paths)
self._view_paths = paths.is_a?(ActionView::PathSet) ?
paths : ActionView::Base.process_view_paths(paths)
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 7c65f1cdc1..29dc3aaddc 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -4,4 +4,4 @@ module ActionController
autoload :Layouts, "action_controller/new_base/layouts"
autoload :Renderer, "action_controller/new_base/renderer"
autoload :UrlFor, "action_controller/new_base/url_for"
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 08e7a1a0e7..2dd5390c99 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -1,6 +1,5 @@
module ActionController
class AbstractBase < AbstractController::Base
-
# :api: public
attr_internal :request, :response, :params
@@ -12,46 +11,46 @@ module ActionController
# :api: public
def controller_name() self.class.controller_name end
- # :api: public
+ # :api: public
def self.controller_path
@controller_path ||= self.name.sub(/Controller$/, '').underscore
end
-
- # :api: public
+
+ # :api: public
def controller_path() self.class.controller_path end
-
- # :api: private
+
+ # :api: private
def self.action_methods
@action_names ||= Set.new(self.public_instance_methods - self::CORE_METHODS)
end
-
- # :api: private
+
+ # :api: private
def self.action_names() action_methods end
-
- # :api: private
+
+ # :api: private
def action_methods() self.class.action_names end
# :api: private
def action_names() action_methods end
-
+
# :api: plugin
def self.call(env)
controller = new
controller.call(env).to_rack
end
-
+
# :api: plugin
def response_body=(body)
@_response.body = body
end
-
+
# :api: private
def call(env)
@_request = ActionDispatch::Request.new(env)
@_response = ActionDispatch::Response.new
process(@_request.parameters[:action])
end
-
+
# :api: private
def to_rack
response.to_a
diff --git a/actionpack/lib/action_controller/new_base/hide_actions.rb b/actionpack/lib/action_controller/new_base/hide_actions.rb
index aa420442fb..422ea180c4 100644
--- a/actionpack/lib/action_controller/new_base/hide_actions.rb
+++ b/actionpack/lib/action_controller/new_base/hide_actions.rb
@@ -6,21 +6,20 @@ module ActionController
end
def action_methods() self.class.action_names end
- def action_names() action_methods end
-
+ def action_names() action_methods end
+
private
-
def respond_to_action?(action_name)
!hidden_actions.include?(action_name) && (super || respond_to?(:method_missing))
end
-
+
module ClassMethods
def hide_action(*args)
args.each do |arg|
self.hidden_actions << arg.to_s
end
end
-
+
def action_methods
@action_names ||= Set.new(super.reject {|name| self.hidden_actions.include?(name.to_s)})
end
@@ -28,4 +27,4 @@ module ActionController
def self.action_names() action_methods end
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/new_base/layouts.rb b/actionpack/lib/action_controller/new_base/layouts.rb
index 89d24fe92d..228162421d 100644
--- a/actionpack/lib/action_controller/new_base/layouts.rb
+++ b/actionpack/lib/action_controller/new_base/layouts.rb
@@ -4,13 +4,13 @@ module ActionController
depends_on ActionController::Renderer
depends_on AbstractController::Layouts
-
+
module ClassMethods
def _implied_layout_name
controller_path
end
end
-
+
def render_to_body(options)
# render :text => ..., :layout => ...
# or
@@ -18,22 +18,20 @@ module ActionController
if !options.key?(:text) || options.key?(:layout)
options[:_layout] = options.key?(:layout) ? _layout_for_option(options[:layout]) : _default_layout
end
-
+
super
end
-
+
private
-
def _layout_for_option(name)
case name
when String then _layout_for_name(name)
when true then _default_layout(true)
when false, nil then nil
else
- raise ArgumentError,
- "String, true, or false, expected for `layout'; you passed #{name.inspect}"
+ raise ArgumentError,
+ "String, true, or false, expected for `layout'; you passed #{name.inspect}"
end
end
-
end
end
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index be4ea54c3b..d7ea9ec4a5 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -3,22 +3,22 @@ module ActionController
extend ActiveSupport::DependencyModule
depends_on AbstractController::Renderer
-
+
def initialize(*)
self.formats = [:html]
super
end
-
+
def render(action, options = {})
# TODO: Move this into #render_to_body
if action.is_a?(Hash)
- options, action = action, nil
+ options, action = action, nil
else
options.merge! :action => action
end
-
+
_process_options(options)
-
+
self.response_body = render_to_body(options)
end
@@ -34,18 +34,17 @@ module ActionController
options[:_template_name] = options[:template]
elsif options.key?(:action)
options[:_template_name] = options[:action].to_s
- options[:_prefix] = _prefix
+ options[:_prefix] = _prefix
end
-
+
super(options)
end
-
+
private
-
def _prefix
controller_path
- end
-
+ end
+
def _text(options)
text = options[:text]
@@ -54,7 +53,7 @@ module ActionController
else text.to_s
end
end
-
+
def _process_options(options)
if status = options[:status]
response.status = status.to_i
diff --git a/actionpack/lib/action_controller/new_base/url_for.rb b/actionpack/lib/action_controller/new_base/url_for.rb
index af5b21012b..3179c8cd5b 100644
--- a/actionpack/lib/action_controller/new_base/url_for.rb
+++ b/actionpack/lib/action_controller/new_base/url_for.rb
@@ -16,7 +16,7 @@ module ActionController
# by this method.
def default_url_options(options = nil)
end
-
+
def rewrite_options(options) #:nodoc:
if defaults = default_url_options(options)
defaults.merge(options)
@@ -24,7 +24,7 @@ module ActionController
options
end
end
-
+
def url_for(options = {})
options ||= {}
case options
@@ -37,4 +37,4 @@ module ActionController
end
end
end
-end
\ No newline at end of file
+end
--
cgit v1.2.3
From 8ee0c598dbe3f9fd133e85c69c6e43f62056646c Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 7 May 2009 12:10:26 -0700
Subject: Tool for profiling resource usage in each require call.
$ ruby -Iactiveresource/lib tools/profile_requires.rb active_resource
91.84 KB 3220 obj 4.0 ms active_resource
83.86 KB 3108 obj 3.3 ms active_support
69.32 KB 2682 obj 2.6 ms active_support/vendor
33.98 KB 651 obj 0.6 ms i18n
94.40 KB 315 obj 4.0 ms 44 KB RSS
---
tools/profile_requires.rb | 75 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
create mode 100644 tools/profile_requires.rb
diff --git a/tools/profile_requires.rb b/tools/profile_requires.rb
new file mode 100644
index 0000000000..68d0de3d80
--- /dev/null
+++ b/tools/profile_requires.rb
@@ -0,0 +1,75 @@
+#!/usr/bin/env ruby
+# Example:
+# ruby -Iactivesupport/lib tools/profile_requires.rb active_support
+# ruby -Iactionpack/lib tools/profile_requires.rb action_controller
+abort 'Use REE so you can profile memory and object allocation' unless GC.respond_to?(:enable_stats)
+
+GC.enable_stats
+require 'rubygems'
+Gem.source_index
+require 'benchmark'
+
+module TrackHeapGrowth
+ class << self
+ attr_accessor :indent
+ attr_accessor :stats
+ end
+ self.indent = 0
+ self.stats = []
+
+ def track_growth(file)
+ TrackHeapGrowth.indent += 1
+ heap_before, objects_before = GC.allocated_size, ObjectSpace.allocated_objects
+ result = nil
+ elapsed = Benchmark.realtime { result = yield }
+ heap_after, objects_after = GC.allocated_size, ObjectSpace.allocated_objects
+ TrackHeapGrowth.indent -= 1
+ TrackHeapGrowth.stats << [file, TrackHeapGrowth.indent, elapsed, heap_after - heap_before, objects_after - objects_before] if result
+ result
+ end
+
+ def require(file, *args)
+ track_growth(file) { super }
+ end
+
+ def load(file, *args)
+ track_growth(file) { super }
+ end
+end
+
+Object.instance_eval { include TrackHeapGrowth }
+
+GC.start
+before = GC.allocated_size
+before_rss = `ps -o rss= -p #{Process.pid}`.to_i
+before_live_objects = ObjectSpace.live_objects
+
+path = ARGV.shift
+
+if mode = ARGV.shift
+ require 'ruby-prof'
+ RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
+ RubyProf.start
+end
+
+ENV['NO_RELOAD'] ||= '1'
+ENV['RAILS_ENV'] ||= 'development'
+elapsed = Benchmark.realtime { require path }
+results = RubyProf.stop if mode
+
+GC.start
+after_live_objects = ObjectSpace.live_objects
+after_rss = `ps -o rss= -p #{Process.pid}`.to_i
+after = GC.allocated_size
+usage = (after - before) / 1024.0
+
+if mode
+ File.open("profile_startup.#{mode}.tree", 'w') do |out|
+ RubyProf::CallTreePrinter.new(results).print(out)
+ end
+end
+
+TrackHeapGrowth.stats.reverse_each do |file, indent, sec, bytes, objects|
+ puts "%10.2f KB %10d obj %8.1f ms %s%s" % [bytes / 1024.0, objects, sec * 1000, ' ' * indent, file]
+end
+puts "%10.2f KB %10d obj %8.1f ms %d KB RSS" % [usage, after_live_objects - before_live_objects, elapsed * 1000, after_rss - before_rss]
--
cgit v1.2.3
From 49ed45213607ed6ce7e6c13c319bf55f916a0ac4 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 7 May 2009 18:27:50 -0700
Subject: Defer rake/contrib/sshpublisher require so basic tasks don't need the
full rake gem
---
activeresource/Rakefile | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/activeresource/Rakefile b/activeresource/Rakefile
index bf7bbb0201..c3cde26b6c 100644
--- a/activeresource/Rakefile
+++ b/activeresource/Rakefile
@@ -4,7 +4,6 @@ require 'rake/testtask'
require 'rake/rdoctask'
require 'rake/packagetask'
require 'rake/gempackagetask'
-require 'rake/contrib/sshpublisher'
require File.join(File.dirname(__FILE__), 'lib', 'active_resource', 'version')
@@ -117,12 +116,14 @@ end
desc "Publish the beta gem"
task :pgem => [:package] do
+ require 'rake/contrib/sshpublisher'
Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
`ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'`
end
desc "Publish the API documentation"
task :pdoc => [:rdoc] do
+ require 'rake/contrib/sshpublisher'
Rake::SshDirPublisher.new("wrath.rubyonrails.org", "public_html/ar", "doc").upload
end
--
cgit v1.2.3
From 4817bf94d135c44ddfae1a30acb15de989e3c86c Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 7 May 2009 18:39:03 -0700
Subject: Check for date/time methods that moved upstream in 1.9
---
activesupport/lib/active_support/core_ext/date/calculations.rb | 4 ++--
activesupport/lib/active_support/core_ext/date_time/conversions.rb | 6 +++---
activesupport/lib/active_support/core_ext/time/conversions.rb | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb
index 04a32edefd..1fe4ffb8e1 100644
--- a/activesupport/lib/active_support/core_ext/date/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -132,7 +132,7 @@ class Date
# Short-hand for years_since(1)
def next_year
years_since(1)
- end
+ end unless method_defined?(:next_year)
# Short-hand for months_ago(1)
def last_month
@@ -142,7 +142,7 @@ class Date
# Short-hand for months_since(1)
def next_month
months_since(1)
- end
+ end unless method_defined?(:next_month)
# Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00)
def beginning_of_week
diff --git a/activesupport/lib/active_support/core_ext/date_time/conversions.rb b/activesupport/lib/active_support/core_ext/date_time/conversions.rb
index ddfa8d610d..5f01bc4fd6 100644
--- a/activesupport/lib/active_support/core_ext/date_time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/conversions.rb
@@ -58,7 +58,7 @@ class DateTime
# Converts self to a Ruby Date object; time portion is discarded
def to_date
::Date.new(year, month, day)
- end
+ end unless method_defined?(:to_date)
# Attempts to convert self to a Ruby Time object; returns self if out of range of Ruby Time class
# If self has an offset other than 0, self will just be returned unaltered, since there's no clean way to map it to a Time
@@ -69,12 +69,12 @@ class DateTime
# To be able to keep Times, Dates and DateTimes interchangeable on conversions
def to_datetime
self
- end
+ end unless method_defined?(:to_datetime)
# Converts datetime to an appropriate format for use in XML
def xmlschema
strftime("%Y-%m-%dT%H:%M:%S%Z")
- end if RUBY_VERSION < '1.9'
+ end unless method_defined?(:xmlschema)
# Converts self to a floating-point number of seconds since the Unix epoch
def to_f
diff --git a/activesupport/lib/active_support/core_ext/time/conversions.rb b/activesupport/lib/active_support/core_ext/time/conversions.rb
index 94e01597a9..6d9c080442 100644
--- a/activesupport/lib/active_support/core_ext/time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/time/conversions.rb
@@ -69,7 +69,7 @@ class Time
# In this case, it simply returns +self+.
def to_time
self
- end
+ end unless method_defined?(:to_time)
# Converts a Time instance to a Ruby DateTime instance, preserving UTC offset.
#
--
cgit v1.2.3
From ef6f22ab2aadf619c993527150490d6d48a719c6 Mon Sep 17 00:00:00 2001
From: Frederick Cheung
Date: Thu, 7 May 2009 01:03:52 +0100
Subject: honour inverse_of when preloading associations
Signed-off-by: Michael Koziarski
---
.../lib/active_record/association_preload.rb | 4 ++-
.../associations/inverse_associations_test.rb | 33 ++++++++++++++++++++++
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb
index e4ab69aa1b..967fff4d6f 100644
--- a/activerecord/lib/active_record/association_preload.rb
+++ b/activerecord/lib/active_record/association_preload.rb
@@ -126,6 +126,7 @@ module ActiveRecord
association_proxy = parent_record.send(reflection_name)
association_proxy.loaded
association_proxy.target.push(*[associated_record].flatten)
+ association_proxy.__send__(:set_inverse_instance, associated_record, parent_record)
end
end
@@ -152,7 +153,8 @@ module ActiveRecord
seen_keys[associated_record[key].to_s] = true
mapped_records = id_to_record_map[associated_record[key].to_s]
mapped_records.each do |mapped_record|
- mapped_record.send("set_#{reflection_name}_target", associated_record)
+ association_proxy = mapped_record.send("set_#{reflection_name}_target", associated_record)
+ association_proxy.__send__(:set_inverse_instance, associated_record, mapped_record)
end
end
end
diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb
index 616f8dfbbe..d123837efd 100644
--- a/activerecord/test/cases/associations/inverse_associations_test.rb
+++ b/activerecord/test/cases/associations/inverse_associations_test.rb
@@ -94,6 +94,17 @@ class InverseHasOneTests < ActiveRecord::TestCase
assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
end
+
+ def test_parent_instance_should_be_shared_with_eager_loaded_child_on_find
+ m = Man.find(:first, :include => :face)
+ f = m.face
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
+ f.man.name = 'Mungo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+
def test_parent_instance_should_be_shared_with_newly_built_child
m = Man.find(:first)
f = m.build_face(:description => 'haunted')
@@ -136,6 +147,18 @@ class InverseHasManyTests < ActiveRecord::TestCase
end
end
+ def test_parent_instance_should_be_shared_with_eager_loaded_children
+ m = Man.find(:first, :include => :interests)
+ is = m.interests
+ is.each do |i|
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+ end
+
def test_parent_instance_should_be_shared_with_newly_built_child
m = Man.find(:first)
i = m.interests.build(:topic => 'Industrial Revolution Re-enactment')
@@ -188,6 +211,16 @@ class InverseBelongsToTests < ActiveRecord::TestCase
assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
end
+ def test_eager_loaded_child_instance_should_be_shared_with_parent_on_find
+ f = Face.find(:first, :include => :man)
+ m = f.man
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
+ f.description = 'gormless'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
+ m.face.description = 'pleasing'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
+ end
+
def test_child_instance_should_be_shared_with_newly_built_parent
f = Face.find(:first)
m = f.build_man(:name => 'Charles')
--
cgit v1.2.3
From 235775de291787bba6b7bc3c58e791216c3b5090 Mon Sep 17 00:00:00 2001
From: Frederick Cheung
Date: Thu, 7 May 2009 01:43:15 +0100
Subject: honour :inverse_of for joins based include
Signed-off-by: Michael Koziarski
---
activerecord/lib/active_record/associations.rb | 10 ++++++--
.../associations/inverse_associations_test.rb | 28 ++++++++++++++++++++++
2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 0952b087d1..2928b0bf83 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1916,21 +1916,27 @@ module ActiveRecord
return nil if record.id.to_s != join.parent.record_id(row).to_s or row[join.aliased_primary_key].nil?
association = join.instantiate(row)
collection.target.push(association)
+ collection.__send__(:set_inverse_instance, association, record)
when :has_one
return if record.id.to_s != join.parent.record_id(row).to_s
return if record.instance_variable_defined?("@#{join.reflection.name}")
association = join.instantiate(row) unless row[join.aliased_primary_key].nil?
- record.send("set_#{join.reflection.name}_target", association)
+ set_target_and_inverse(join, association, record)
when :belongs_to
return if record.id.to_s != join.parent.record_id(row).to_s or row[join.aliased_primary_key].nil?
association = join.instantiate(row)
- record.send("set_#{join.reflection.name}_target", association)
+ set_target_and_inverse(join, association, record)
else
raise ConfigurationError, "unknown macro: #{join.reflection.macro}"
end
return association
end
+ def set_target_and_inverse(join, association, record)
+ association_proxy = record.send("set_#{join.reflection.name}_target", association)
+ association_proxy.__send__(:set_inverse_instance, association, record)
+ end
+
class JoinBase # :nodoc:
attr_reader :active_record, :table_joins
delegate :table_name, :column_names, :primary_key, :reflections, :sanitize_sql, :to => :active_record
diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb
index d123837efd..47f83db112 100644
--- a/activerecord/test/cases/associations/inverse_associations_test.rb
+++ b/activerecord/test/cases/associations/inverse_associations_test.rb
@@ -103,6 +103,14 @@ class InverseHasOneTests < ActiveRecord::TestCase
assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
f.man.name = 'Mungo'
assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
+
+ m = Man.find(:first, :include => :face, :order => 'faces.id')
+ f = m.face
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
+ f.man.name = 'Mungo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
end
def test_parent_instance_should_be_shared_with_newly_built_child
@@ -157,6 +165,17 @@ class InverseHasManyTests < ActiveRecord::TestCase
i.man.name = 'Mungo'
assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
end
+
+ m = Man.find(:first, :include => :interests, :order => 'interests.id')
+ is = m.interests
+ is.each do |i|
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+
end
def test_parent_instance_should_be_shared_with_newly_built_child
@@ -219,6 +238,15 @@ class InverseBelongsToTests < ActiveRecord::TestCase
assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
m.face.description = 'pleasing'
assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
+
+
+ f = Face.find(:first, :include => :man, :order => 'men.id')
+ m = f.man
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
+ f.description = 'gormless'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
+ m.face.description = 'pleasing'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
end
def test_child_instance_should_be_shared_with_newly_built_parent
--
cgit v1.2.3
From 9e0cfdb7f951c0446cdfd3b2cc26443712fe657a Mon Sep 17 00:00:00 2001
From: Ken Collins
Date: Sat, 9 May 2009 18:35:31 -0400
Subject: ActiveSupport::OrderedHash#to_a method returns an ordered set of
arrays. Matches ruby1.9's Hash#to_a.
Signed-off-by: Michael Koziarski
[#2629 state:committed]
---
activesupport/lib/active_support/ordered_hash.rb | 4 ++++
activesupport/test/ordered_hash_test.rb | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb
index fed8094a24..33fd2a29b9 100644
--- a/activesupport/lib/active_support/ordered_hash.rb
+++ b/activesupport/lib/active_support/ordered_hash.rb
@@ -57,6 +57,10 @@ module ActiveSupport
self
end
+ def to_a
+ @keys.map { |key| [ key, self[key] ] }
+ end
+
def each_key
@keys.each { |key| yield key }
end
diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb
index 7cd8c8a8f4..6fccbbdc41 100644
--- a/activesupport/test/ordered_hash_test.rb
+++ b/activesupport/test/ordered_hash_test.rb
@@ -51,6 +51,10 @@ class OrderedHashTest < Test::Unit::TestCase
assert_same @ordered_hash, @ordered_hash.to_hash
end
+ def test_to_a
+ assert_equal @keys.zip(@values), @ordered_hash.to_a
+ end
+
def test_has_key
assert_equal true, @ordered_hash.has_key?('blue')
assert_equal true, @ordered_hash.key?('blue')
--
cgit v1.2.3
From 026b78f9076216990bddb1aa5d83d23a647c02a5 Mon Sep 17 00:00:00 2001
From: Anthony Crumley
Date: Mon, 4 May 2009 09:49:43 -0500
Subject: Fixed eager load error on find with include => [:table_name] and hash
conditions like {:table_name => {:column => 'value'}}
Signed-off-by: Michael Koziarski
---
activerecord/lib/active_record/associations.rb | 20 ++++++++++++++++----
activerecord/test/cases/associations/eager_test.rb | 12 ++++++++++++
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 2928b0bf83..781a0290e8 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1671,17 +1671,29 @@ module ActiveRecord
string.scan(/([\.a-zA-Z_]+).?\./).flatten
end
+ def tables_in_hash(hash)
+ return [] if hash.blank?
+ tables = hash.map do |key, value|
+ if value.is_a?(Hash)
+ key.to_s
+ else
+ tables_in_string(key) if key.is_a?(String)
+ end
+ end
+ tables.flatten.compact
+ end
+
def conditions_tables(options)
# look in both sets of conditions
conditions = [scope(:find, :conditions), options[:conditions]].inject([]) do |all, cond|
case cond
when nil then all
- when Array then all << cond.first
- when Hash then all << cond.keys
- else all << cond
+ when Array then all << tables_in_string(cond.first)
+ when Hash then all << tables_in_hash(cond)
+ else all << tables_in_string(cond)
end
end
- tables_in_string(conditions.join(' '))
+ conditions.flatten
end
def order_tables(options)
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index 40723814c5..d23f86b700 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -223,6 +223,18 @@ class EagerAssociationTest < ActiveRecord::TestCase
end
end
+ def test_eager_association_loading_with_belongs_to_and_conditions_hash
+ comments = []
+ assert_nothing_raised do
+ comments = Comment.find(:all, :include => :post, :conditions => {:posts => {:id => 4}}, :limit => 3, :order => 'comments.id')
+ end
+ assert_equal 3, comments.length
+ assert_equal [5,6,7], comments.collect { |c| c.id }
+ assert_no_queries do
+ comments.first.post
+ end
+ end
+
def test_eager_association_loading_with_belongs_to_and_conditions_string_with_quoted_table_name
quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
assert_nothing_raised do
--
cgit v1.2.3
From 9010ed27559ed5ab89ea71b4b16f4c8e56d03dbb Mon Sep 17 00:00:00 2001
From: Mike Breen
Date: Sun, 10 May 2009 15:02:00 +1200
Subject: Allow you to pass :all_blank to :reject_if option to automatically
create a Proc that will reject any record with blank attributes.
---
activerecord/lib/active_record/nested_attributes.rb | 11 ++++++++++-
activerecord/test/cases/nested_attributes_test.rb | 18 +++++++++++++++++-
activerecord/test/models/pirate.rb | 2 ++
activerecord/test/schema/schema.rb | 1 +
4 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index e3122d195a..dfad2901c5 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -180,10 +180,14 @@ module ActiveRecord
# and the Proc should return either +true+ or +false+. When no Proc
# is specified a record will be built for all attribute hashes that
# do not have a _delete that evaluates to true.
+ # Passing :all_blank instead of a Proc will create a proc
+ # that will reject a record where all the attributes are blank.
#
# Examples:
# # creates avatar_attributes=
# accepts_nested_attributes_for :avatar, :reject_if => proc { |attributes| attributes['name'].blank? }
+ # # creates avatar_attributes=
+ # accepts_nested_attributes_for :avatar, :reject_if => :all_blank
# # creates avatar_attributes= and posts_attributes=
# accepts_nested_attributes_for :avatar, :posts, :allow_destroy => true
def accepts_nested_attributes_for(*attr_names)
@@ -201,7 +205,12 @@ module ActiveRecord
end
reflection.options[:autosave] = true
- self.reject_new_nested_attributes_procs[association_name.to_sym] = options[:reject_if]
+
+ self.reject_new_nested_attributes_procs[association_name.to_sym] = if options[:reject_if] == :all_blank
+ proc { |attributes| attributes.all? {|k,v| v.blank?} }
+ else
+ options[:reject_if]
+ end
# def pirate_attributes=(attributes)
# assign_nested_attributes_for_one_to_one_association(:pirate, attributes, false)
diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
index cd6277c24b..f1741ed54d 100644
--- a/activerecord/test/cases/nested_attributes_test.rb
+++ b/activerecord/test/cases/nested_attributes_test.rb
@@ -31,11 +31,27 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
end
def test_should_add_a_proc_to_reject_new_nested_attributes_procs
- [:parrots, :birds].each do |name|
+ [:parrots, :birds, :birds_with_reject_all_blank].each do |name|
assert_instance_of Proc, Pirate.reject_new_nested_attributes_procs[name]
end
end
+ def test_should_not_build_a_new_record_if_reject_all_blank_returns_false
+ pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
+ pirate.birds_with_reject_all_blank_attributes = [{:name => '', :color => ''}]
+ pirate.save!
+
+ assert pirate.birds_with_reject_all_blank.empty?
+ end
+
+ def test_should_build_a_new_record_if_reject_all_blank_does_not_return_false
+ pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
+ pirate.birds_with_reject_all_blank_attributes = [{:name => 'Tweetie', :color => ''}]
+ pirate.save!
+
+ assert_equal 1, pirate.birds_with_reject_all_blank.count
+ end
+
def test_should_raise_an_ArgumentError_for_non_existing_associations
assert_raise_with_message ArgumentError, "No association found for name `honesty'. Has it been defined yet?" do
Pirate.accepts_nested_attributes_for :honesty
diff --git a/activerecord/test/models/pirate.rb b/activerecord/test/models/pirate.rb
index 238917bf30..acf53fce8b 100644
--- a/activerecord/test/models/pirate.rb
+++ b/activerecord/test/models/pirate.rb
@@ -28,11 +28,13 @@ class Pirate < ActiveRecord::Base
:after_add => proc {|p,b| p.ship_log << "after_adding_proc_bird_#{b.id || ''}"},
:before_remove => proc {|p,b| p.ship_log << "before_removing_proc_bird_#{b.id}"},
:after_remove => proc {|p,b| p.ship_log << "after_removing_proc_bird_#{b.id}"}
+ has_many :birds_with_reject_all_blank, :class_name => "Bird"
accepts_nested_attributes_for :parrots, :birds, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
accepts_nested_attributes_for :ship, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
accepts_nested_attributes_for :parrots_with_method_callbacks, :parrots_with_proc_callbacks,
:birds_with_method_callbacks, :birds_with_proc_callbacks, :allow_destroy => true
+ accepts_nested_attributes_for :birds_with_reject_all_blank, :reject_if => :all_blank
validates_presence_of :catchphrase
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 3b0e17c867..6fb918c60e 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -57,6 +57,7 @@ ActiveRecord::Schema.define do
create_table :birds, :force => true do |t|
t.string :name
+ t.string :color
t.integer :pirate_id
end
--
cgit v1.2.3
From 2e7409f035236c719c5b1567c4bb3e65a5e543bc Mon Sep 17 00:00:00 2001
From: Alexander Dymo
Date: Thu, 7 May 2009 03:19:17 +0300
Subject: Change spelling of Kyev timezone to Kyiv [#2613 state:resolved]
---
activesupport/CHANGELOG | 2 ++
activesupport/lib/active_support/values/time_zone.rb | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index ca5ab13a46..032f0fb9c1 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Change spelling of Kyev timezone to Kyiv #2613 [Alexander Dymo]
+
* Add ActiveSupport.parse_json_times to disable time parsing in JSON backends that don't support it or don't need it. [rick]
* Add pluggable JSON backends with support for the JSON gem. [rick]
diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb
index e2d759aa50..b37dae1c2a 100644
--- a/activesupport/lib/active_support/values/time_zone.rb
+++ b/activesupport/lib/active_support/values/time_zone.rb
@@ -92,7 +92,7 @@ module ActiveSupport
"Bucharest" => "Europe/Bucharest",
"Cairo" => "Africa/Cairo",
"Helsinki" => "Europe/Helsinki",
- "Kyev" => "Europe/Kiev",
+ "Kyiv" => "Europe/Kiev",
"Riga" => "Europe/Riga",
"Sofia" => "Europe/Sofia",
"Tallinn" => "Europe/Tallinn",
@@ -336,7 +336,7 @@ module ActiveSupport
"Copenhagen", "Madrid", "Paris", "Amsterdam", "Berlin",
"Bern", "Rome", "Stockholm", "Vienna",
"West Central Africa" ],
- [ 7_200, "Bucharest", "Cairo", "Helsinki", "Kyev", "Riga", "Sofia",
+ [ 7_200, "Bucharest", "Cairo", "Helsinki", "Kyiv", "Riga", "Sofia",
"Tallinn", "Vilnius", "Athens", "Istanbul", "Minsk",
"Jerusalem", "Harare", "Pretoria" ],
[ 10_800, "Moscow", "St. Petersburg", "Volgograd", "Kuwait", "Riyadh",
--
cgit v1.2.3
From 4932f7b38f72104819022abca0c952ba6f9888cb Mon Sep 17 00:00:00 2001
From: David Heinemeier Hansson
Date: Mon, 11 May 2009 19:08:13 +0200
Subject: Added db/seeds.rb as a default file for storing seed data for the
database. Can be loaded with rake db:seed (or created alongside the db with
db:setup). (This is also known as the "Stop Putting Gawd Damn Seed Data In
Your Migrations" feature) [DHH]
---
railties/CHANGELOG | 5 +++++
railties/Rakefile | 3 +++
railties/configs/seeds.rb | 7 +++++++
.../generators/applications/app/app_generator.rb | 5 +++++
railties/lib/tasks/databases.rake | 13 +++++++++++--
5 files changed, 31 insertions(+), 2 deletions(-)
create mode 100644 railties/configs/seeds.rb
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index 98e3a861e8..8e7dfb38cc 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,3 +1,8 @@
+*Edge*
+
+* Added db/seeds.rb as a default file for storing seed data for the database. Can be loaded with rake db:seed (or created alongside the db with db:setup). (This is also known as the "Stop Putting Gawd Damn Seed Data In Your Migrations" feature) [DHH]
+
+
*2.3.2 [Final] (March 15, 2009)*
* Remove outdated script/plugin options [Pratik Naik]
diff --git a/railties/Rakefile b/railties/Rakefile
index 9cd102df0f..4247742664 100644
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -200,11 +200,14 @@ task :copy_configs do
cp "configs/locales/en.yml", "#{PKG_DESTINATION}/config/locales/en.yml"
+ cp "configs/seeds.rb", "#{PKG_DESTINATION}/db/seeds.rb"
+
cp "environments/boot.rb", "#{PKG_DESTINATION}/config/boot.rb"
cp "environments/environment.rb", "#{PKG_DESTINATION}/config/environment.rb"
cp "environments/production.rb", "#{PKG_DESTINATION}/config/environments/production.rb"
cp "environments/development.rb", "#{PKG_DESTINATION}/config/environments/development.rb"
cp "environments/test.rb", "#{PKG_DESTINATION}/config/environments/test.rb"
+
end
task :copy_binfiles do
diff --git a/railties/configs/seeds.rb b/railties/configs/seeds.rb
new file mode 100644
index 0000000000..3174d0cb8a
--- /dev/null
+++ b/railties/configs/seeds.rb
@@ -0,0 +1,7 @@
+# This file should contain all the record creation needed to seed the database with its default values.
+# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
+#
+# Examples:
+#
+# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
+# Major.create(:name => 'Daley', :city => cities.first)
diff --git a/railties/lib/rails_generator/generators/applications/app/app_generator.rb b/railties/lib/rails_generator/generators/applications/app/app_generator.rb
index 2c31d89538..c8c2239f34 100644
--- a/railties/lib/rails_generator/generators/applications/app/app_generator.rb
+++ b/railties/lib/rails_generator/generators/applications/app/app_generator.rb
@@ -125,6 +125,7 @@ class AppGenerator < Rails::Generator::Base
create_database_configuration_file(m)
create_routes_file(m)
create_locale_file(m)
+ create_seeds_file(m)
create_initializer_files(m)
create_environment_files(m)
end
@@ -176,6 +177,10 @@ class AppGenerator < Rails::Generator::Base
m.file "configs/routes.rb", "config/routes.rb"
end
+ def create_seeds_file(m)
+ m.file "configs/seeds.rb", "db/seeds.rb"
+ end
+
def create_initializer_files(m)
%w(
backtrace_silencers
diff --git a/railties/lib/tasks/databases.rake b/railties/lib/tasks/databases.rake
index 9588fabb2d..cdab5d8bb0 100644
--- a/railties/lib/tasks/databases.rake
+++ b/railties/lib/tasks/databases.rake
@@ -156,8 +156,8 @@ namespace :db do
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
end
- desc 'Drops and recreates the database from db/schema.rb for the current environment.'
- task :reset => ['db:drop', 'db:create', 'db:schema:load']
+ desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
+ task :reset => [ 'db:drop', 'db:setup' ]
desc "Retrieves the charset for the current environment's database"
task :charset => :environment do
@@ -206,6 +206,15 @@ namespace :db do
end
end
+ desc 'Create the database, load the schema, and initialize with the seed data'
+ task :setup => [ 'db:create', 'db:schema:load', 'db:seed' ]
+
+ desc 'Load the seed data from db/seeds.rb'
+ task :seed => :environment do
+ seed_file = File.join(Rails.root, 'db', 'seeds.rb')
+ load(seed_file) if File.exist?(seed_file)
+ end
+
namespace :fixtures do
desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
task :load => :environment do
--
cgit v1.2.3
From 030dfe3f831aacd60bbfa525dfac4cd5921b6530 Mon Sep 17 00:00:00 2001
From: Yehuda Katz
Date: Mon, 11 May 2009 10:22:07 -0700
Subject: More community code review :)
---
actionpack/lib/action_controller/abstract/base.rb | 3 +--
.../lib/action_controller/abstract/helpers.rb | 9 +--------
.../lib/action_controller/abstract/renderer.rb | 4 ++--
actionpack/lib/action_view/template/text.rb | 2 ++
.../abstract_controller_test.rb | 20 ++++++++++----------
.../test/abstract_controller/callbacks_test.rb | 18 +++++++++---------
actionpack/test/abstract_controller/helper_test.rb | 2 +-
.../test/abstract_controller/layouts_test.rb | 22 +++++++++++-----------
8 files changed, 37 insertions(+), 43 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index 8a8e748c0e..ab9aed0b26 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -54,7 +54,6 @@ module AbstractController
@_action_name = action_name
process_action
- self.response_obj[:body] = self.response_body
self
end
@@ -71,7 +70,7 @@ module AbstractController
# action_name is found.
def process_action
if respond_to?(action_name) then send(action_name)
- elsif respond_to?(:action_missing, true) then send(:action_missing, action_name)
+ elsif respond_to?(:action_missing, true) then action_missing(action_name)
end
end
diff --git a/actionpack/lib/action_controller/abstract/helpers.rb b/actionpack/lib/action_controller/abstract/helpers.rb
index 1f0b38417b..370e3a79ee 100644
--- a/actionpack/lib/action_controller/abstract/helpers.rb
+++ b/actionpack/lib/action_controller/abstract/helpers.rb
@@ -6,14 +6,7 @@ module AbstractController
extlib_inheritable_accessor :master_helper_module
self.master_helper_module = Module.new
end
-
- # def self.included(klass)
- # klass.class_eval do
- # extlib_inheritable_accessor :master_helper_module
- # self.master_helper_module = Module.new
- # end
- # end
-
+
def _action_view
@_action_view ||= begin
av = super
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index 716b213c75..bed7f75b2f 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -20,13 +20,13 @@ module AbstractController
self._view_paths ||= ActionView::PathSet.new
end
-
+
def _action_view
@_action_view ||= ActionView::Base.new(self.class.view_paths, {}, self)
end
def render(options = {})
- unless response_body.nil?
+ if response_body
raise AbstractController::DoubleRenderError, "OMG"
end
diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb
index 446c735ba3..8477115211 100644
--- a/actionpack/lib/action_view/template/text.rb
+++ b/actionpack/lib/action_view/template/text.rb
@@ -1,5 +1,7 @@
module ActionView #:nodoc:
class TextTemplate < String #:nodoc:
+
+ def identifier() self end
def render(*) self end
diff --git a/actionpack/test/abstract_controller/abstract_controller_test.rb b/actionpack/test/abstract_controller/abstract_controller_test.rb
index c283a7319d..28f9ac5820 100644
--- a/actionpack/test/abstract_controller/abstract_controller_test.rb
+++ b/actionpack/test/abstract_controller/abstract_controller_test.rb
@@ -20,7 +20,7 @@ module AbstractController
class TestBasic < ActiveSupport::TestCase
test "dispatching works" do
result = Me.process(:index)
- assert_equal "Hello world", result.response_obj[:body]
+ assert_equal "Hello world", result.response_body
end
end
@@ -69,27 +69,27 @@ module AbstractController
class TestRenderer < ActiveSupport::TestCase
test "rendering templates works" do
result = Me2.process(:index)
- assert_equal "Hello from index.erb", result.response_obj[:body]
+ assert_equal "Hello from index.erb", result.response_body
end
test "rendering passes ivars to the view" do
result = Me2.process(:action_with_ivars)
- assert_equal "Hello from index_with_ivars.erb", result.response_obj[:body]
+ assert_equal "Hello from index_with_ivars.erb", result.response_body
end
test "rendering with no template name" do
result = Me2.process(:naked_render)
- assert_equal "Hello from naked_render.erb", result.response_obj[:body]
+ assert_equal "Hello from naked_render.erb", result.response_body
end
test "rendering to a rack body" do
result = Me2.process(:rendering_to_body)
- assert_equal "Hello from naked_render.erb", result.response_obj[:body]
+ assert_equal "Hello from naked_render.erb", result.response_body
end
test "rendering to a string" do
result = Me2.process(:rendering_to_string)
- assert_equal "Hello from naked_render.erb", result.response_obj[:body]
+ assert_equal "Hello from naked_render.erb", result.response_body
end
end
@@ -121,12 +121,12 @@ module AbstractController
class TestPrefixedViews < ActiveSupport::TestCase
test "templates are located inside their 'prefix' folder" do
result = Me3.process(:index)
- assert_equal "Hello from me3/index.erb", result.response_obj[:body]
+ assert_equal "Hello from me3/index.erb", result.response_body
end
test "templates included their format" do
result = Me3.process(:formatted)
- assert_equal "Hello from me3/formatted.html.erb", result.response_obj[:body]
+ assert_equal "Hello from me3/formatted.html.erb", result.response_body
end
end
@@ -174,7 +174,7 @@ module AbstractController
class TestLayouts < ActiveSupport::TestCase
test "layouts are included" do
result = Me4.process(:index)
- assert_equal "Me4 Enter : Hello from me4/index.erb : Exit", result.response_obj[:body]
+ assert_equal "Me4 Enter : Hello from me4/index.erb : Exit", result.response_body
end
end
@@ -211,7 +211,7 @@ module AbstractController
class TestRespondToAction < ActiveSupport::TestCase
def assert_dispatch(klass, body = "success", action = :index)
- response = klass.process(action).response_obj[:body]
+ response = klass.process(action).response_body
assert_equal body, response
end
diff --git a/actionpack/test/abstract_controller/callbacks_test.rb b/actionpack/test/abstract_controller/callbacks_test.rb
index 5fce30f478..7137129823 100644
--- a/actionpack/test/abstract_controller/callbacks_test.rb
+++ b/actionpack/test/abstract_controller/callbacks_test.rb
@@ -22,7 +22,7 @@ module AbstractController
class TestCallbacks < ActiveSupport::TestCase
test "basic callbacks work" do
result = Callback1.process(:index)
- assert_equal "Hello world", result.response_obj[:body]
+ assert_equal "Hello world", result.response_body
end
end
@@ -53,7 +53,7 @@ module AbstractController
class TestCallbacks < ActiveSupport::TestCase
test "before_filter works" do
result = Callback2.process(:index)
- assert_equal "Hello world", result.response_obj[:body]
+ assert_equal "Hello world", result.response_body
end
test "after_filter works" do
@@ -84,7 +84,7 @@ module AbstractController
class TestCallbacks < ActiveSupport::TestCase
test "before_filter works with procs" do
result = Callback3.process(:index)
- assert_equal "Hello world", result.response_obj[:body]
+ assert_equal "Hello world", result.response_body
end
test "after_filter works with procs" do
@@ -119,12 +119,12 @@ module AbstractController
class TestCallbacks < ActiveSupport::TestCase
test "when :only is specified, a before filter is triggered on that action" do
result = CallbacksWithConditions.process(:index)
- assert_equal "Hello, World", result.response_obj[:body]
+ assert_equal "Hello, World", result.response_body
end
test "when :only is specified, a before filter is not triggered on other actions" do
result = CallbacksWithConditions.process(:sekrit_data)
- assert_equal "true", result.response_obj[:body]
+ assert_equal "true", result.response_body
end
test "when :except is specified, an after filter is not triggered on that action" do
@@ -159,12 +159,12 @@ module AbstractController
class TestCallbacks < ActiveSupport::TestCase
test "when :only is specified with an array, a before filter is triggered on that action" do
result = CallbacksWithArrayConditions.process(:index)
- assert_equal "Hello, World", result.response_obj[:body]
+ assert_equal "Hello, World", result.response_body
end
test "when :only is specified with an array, a before filter is not triggered on other actions" do
result = CallbacksWithArrayConditions.process(:sekrit_data)
- assert_equal "true", result.response_obj[:body]
+ assert_equal "true", result.response_body
end
test "when :except is specified with an array, an after filter is not triggered on that action" do
@@ -184,12 +184,12 @@ module AbstractController
class TestCallbacks < ActiveSupport::TestCase
test "when a callback is modified in a child with :only, it works for the :only action" do
result = ChangedConditions.process(:index)
- assert_equal "Hello world", result.response_obj[:body]
+ assert_equal "Hello world", result.response_body
end
test "when a callback is modified in a child with :only, it does not work for other actions" do
result = ChangedConditions.process(:not_index)
- assert_equal "", result.response_obj[:body]
+ assert_equal "", result.response_body
end
end
diff --git a/actionpack/test/abstract_controller/helper_test.rb b/actionpack/test/abstract_controller/helper_test.rb
index 6284fa4f70..15c89b4d24 100644
--- a/actionpack/test/abstract_controller/helper_test.rb
+++ b/actionpack/test/abstract_controller/helper_test.rb
@@ -35,7 +35,7 @@ module AbstractController
class TestHelpers < ActiveSupport::TestCase
def test_helpers
result = MyHelpers1.process(:index)
- assert_equal "Hello World : Included", result.response_obj[:body]
+ assert_equal "Hello World : Included", result.response_body
end
end
diff --git a/actionpack/test/abstract_controller/layouts_test.rb b/actionpack/test/abstract_controller/layouts_test.rb
index 078e0037a8..961e7ce6d3 100644
--- a/actionpack/test/abstract_controller/layouts_test.rb
+++ b/actionpack/test/abstract_controller/layouts_test.rb
@@ -152,12 +152,12 @@ module AbstractControllerTests
class TestBase < ActiveSupport::TestCase
test "when no layout is specified, and no default is available, render without a layout" do
result = Blank.process(:index)
- assert_equal "Hello blank!", result.response_obj[:body]
+ assert_equal "Hello blank!", result.response_body
end
test "when layout is specified as a string, render with that layout" do
result = WithString.process(:index)
- assert_equal "With String Hello string!", result.response_obj[:body]
+ assert_equal "With String Hello string!", result.response_body
end
test "when layout is specified as a string, but the layout is missing, raise an exception" do
@@ -166,22 +166,22 @@ module AbstractControllerTests
test "when layout is specified as false, do not use a layout" do
result = WithFalseLayout.process(:index)
- assert_equal "Hello false!", result.response_obj[:body]
+ assert_equal "Hello false!", result.response_body
end
test "when layout is specified as nil, do not use a layout" do
result = WithNilLayout.process(:index)
- assert_equal "Hello nil!", result.response_obj[:body]
+ assert_equal "Hello nil!", result.response_body
end
test "when layout is specified as a symbol, call the requested method and use the layout returned" do
result = WithSymbol.process(:index)
- assert_equal "OMGHI2U Hello symbol!", result.response_obj[:body]
+ assert_equal "OMGHI2U Hello symbol!", result.response_body
end
test "when layout is specified as a symbol and the method returns nil, don't use a layout" do
result = WithSymbolReturningNil.process(:index)
- assert_equal "Hello nilz!", result.response_obj[:body]
+ assert_equal "Hello nilz!", result.response_body
end
test "when the layout is specified as a symbol and the method doesn't exist, raise an exception" do
@@ -194,28 +194,28 @@ module AbstractControllerTests
test "when a child controller does not have a layout, use the parent controller layout" do
result = WithStringChild.process(:index)
- assert_equal "With String Hello string!", result.response_obj[:body]
+ assert_equal "With String Hello string!", result.response_body
end
test "when a child controller has specified a layout, use that layout and not the parent controller layout" do
result = WithStringOverriddenChild.process(:index)
- assert_equal "With Override Hello string!", result.response_obj[:body]
+ assert_equal "With Override Hello string!", result.response_body
end
test "when a child controller has an implied layout, use that layout and not the parent controller layout" do
result = WithStringImpliedChild.process(:index)
- assert_equal "With Implied Hello string!", result.response_obj[:body]
+ assert_equal "With Implied Hello string!", result.response_body
end
test "when a child controller specifies layout nil, do not use the parent layout" do
result = WithNilChild.process(:index)
- assert_equal "Hello string!", result.response_obj[:body]
+ assert_equal "Hello string!", result.response_body
end
test "when a grandchild has no layout specified, the child has an implied layout, and the " \
"parent has specified a layout, use the child controller layout" do
result = WithChildOfImplied.process(:index)
- assert_equal "With Implied Hello string!", result.response_obj[:body]
+ assert_equal "With Implied Hello string!", result.response_body
end
test "raises an exception when specifying layout true" do
--
cgit v1.2.3
From a2f3684cecb361db2bf5f7ec0b6de0603868ffd5 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Mon, 11 May 2009 10:57:59 -0700
Subject: Ported fresh_when into a ConditionalGet module
---
actionpack/lib/action_controller/new_base.rb | 1 +
actionpack/lib/action_controller/new_base/base.rb | 1 +
.../action_controller/new_base/conditional_get.rb | 42 +++++++++++++++++++
.../lib/action_controller/new_base/testing.rb | 1 +
actionpack/test/new_base/etag_test.rb | 47 ++++++++++++++++++++++
5 files changed, 92 insertions(+)
create mode 100644 actionpack/lib/action_controller/new_base/conditional_get.rb
create mode 100644 actionpack/test/new_base/etag_test.rb
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 7098b812f6..8a7de1476c 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -1,5 +1,6 @@
module ActionController
autoload :Base, "action_controller/new_base/base"
+ autoload :ConditionalGet, "action_controller/new_base/conditional_get"
autoload :HideActions, "action_controller/new_base/hide_actions"
autoload :Http, "action_controller/new_base/http"
autoload :Layouts, "action_controller/new_base/layouts"
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 8af6ffbc92..40f507b6e7 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -10,6 +10,7 @@ module ActionController
use ActionController::UrlFor
use ActionController::Renderer
use ActionController::Layouts
+ use ActionController::ConditionalGet
# Legacy modules
include SessionManagement
diff --git a/actionpack/lib/action_controller/new_base/conditional_get.rb b/actionpack/lib/action_controller/new_base/conditional_get.rb
new file mode 100644
index 0000000000..16104c51fc
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/conditional_get.rb
@@ -0,0 +1,42 @@
+module ActionController
+ module ConditionalGet
+
+ # Sets the etag, last_modified, or both on the response and renders a
+ # "304 Not Modified" response if the request is already fresh.
+ #
+ # Parameters:
+ # * :etag
+ # * :last_modified
+ # * :public By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches).
+ #
+ # Example:
+ #
+ # def show
+ # @article = Article.find(params[:id])
+ # fresh_when(:etag => @article, :last_modified => @article.created_at.utc, :public => true)
+ # end
+ #
+ # This will render the show template if the request isn't sending a matching etag or
+ # If-Modified-Since header and just a "304 Not Modified" response if there's a match.
+ #
+ def fresh_when(options)
+ options.assert_valid_keys(:etag, :last_modified, :public)
+
+ response.etag = options[:etag] if options[:etag]
+ response.last_modified = options[:last_modified] if options[:last_modified]
+
+ if options[:public]
+ cache_control = response.headers["Cache-Control"].split(",").map {|k| k.strip }
+ cache_control.delete("private")
+ cache_control.delete("no-cache")
+ cache_control << "public"
+ response.headers["Cache-Control"] = cache_control.join(', ')
+ end
+
+ if request.fresh?(response)
+ head :not_modified
+ end
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb
index 428f339b3d..181c5c0ecd 100644
--- a/actionpack/lib/action_controller/new_base/testing.rb
+++ b/actionpack/lib/action_controller/new_base/testing.rb
@@ -7,6 +7,7 @@ module ActionController
@_response = response
ret = process(request.parameters[:action])
@_response.body = self.response_body
+ @_response.prepare!
set_test_assigns
ret
end
diff --git a/actionpack/test/new_base/etag_test.rb b/actionpack/test/new_base/etag_test.rb
new file mode 100644
index 0000000000..7af5febfb3
--- /dev/null
+++ b/actionpack/test/new_base/etag_test.rb
@@ -0,0 +1,47 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
+
+module Etags
+
+ class BasicController < ActionController::Base
+
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "etags/basic/base.html.erb" => "Hello from without_layout.html.erb",
+ "layouts/etags.html.erb" => "teh <%= yield %> tagz"
+ )]
+
+ def without_layout
+ render :action => "base"
+ end
+
+ def with_layout
+ render :action => "base", :layout => "etag"
+ end
+
+ end
+
+ class TestBasic < SimpleRouteCase
+ describe "Rendering without any special etag options returns an etag that is an MD5 hash of its text"
+
+ test "an action without a layout" do
+ get "/etags/basic/without_layout"
+ body = "Hello from without_layout.html.erb"
+ assert_body body
+ assert_header "Etag", etag_for(body)
+ assert_status 200
+ end
+
+ test "an action with a layout" do
+ get "/etags/basic/with_layout"
+ body = "teh Hello from without_layout.html.erb tagz"
+ assert_body body
+ assert_header "Etag", etag_for(body)
+ assert_status 200
+ end
+
+ def etag_for(text)
+ %("#{Digest::MD5.hexdigest(text)}")
+ end
+ end
+
+
+end
\ No newline at end of file
--
cgit v1.2.3
From e1854e0b199fba352ddcaa58a3af168e8cc70e3a Mon Sep 17 00:00:00 2001
From: Douglas F Shearer
Date: Thu, 7 May 2009 23:58:07 +0100
Subject: ActiveSupport::OrderedHash[1,2,3,4] creates an OrderedHash instead of
a Hash.
[#2615 state:committed]
Signed-off-by: Jeremy Kemper
---
activesupport/lib/active_support/ordered_hash.rb | 10 ++++++++++
activesupport/test/ordered_hash_test.rb | 6 ++++++
2 files changed, 16 insertions(+)
diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb
index 33fd2a29b9..8d1c0f5160 100644
--- a/activesupport/lib/active_support/ordered_hash.rb
+++ b/activesupport/lib/active_support/ordered_hash.rb
@@ -10,6 +10,16 @@ module ActiveSupport
@keys = []
end
+ def self.[](*args)
+ ordered_hash = new
+ args.each_with_index { |val,ind|
+ # Only every second value is a key.
+ next if ind % 2 != 0
+ ordered_hash[val] = args[ind + 1]
+ }
+ ordered_hash
+ end
+
def initialize_copy(other)
super
# make a deep copy of keys
diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb
index 6fccbbdc41..647938dd87 100644
--- a/activesupport/test/ordered_hash_test.rb
+++ b/activesupport/test/ordered_hash_test.rb
@@ -162,4 +162,10 @@ class OrderedHashTest < Test::Unit::TestCase
def test_inspect
assert @ordered_hash.inspect.include?(@hash.inspect)
end
+
+ def test_alternate_initialization
+ alternate = ActiveSupport::OrderedHash[1,2,3,4]
+ assert_kind_of ActiveSupport::OrderedHash, alternate
+ assert_equal [1, 3], alternate.keys
+ end
end
--
cgit v1.2.3
From c1d120a71e74aa3ccab6dc28a5406b87a51a69c1 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Mon, 11 May 2009 11:48:38 -0700
Subject: Don't run the action if callbacks are halted.
In AbstractController, this means that response_body is not empty
---
actionpack/lib/action_controller/abstract/callbacks.rb | 2 +-
activesupport/lib/active_support/new_callbacks.rb | 2 +-
activesupport/test/new_callbacks_test.rb | 14 +++++++++++---
3 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb
index 5f1607940a..f3210a040a 100644
--- a/actionpack/lib/action_controller/abstract/callbacks.rb
+++ b/actionpack/lib/action_controller/abstract/callbacks.rb
@@ -2,7 +2,7 @@ module AbstractController
module Callbacks
setup do
include ActiveSupport::NewCallbacks
- define_callbacks :process_action
+ define_callbacks :process_action, "response_body"
end
def process_action
diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb
index 2ae7b006c7..9316d6d2b6 100644
--- a/activesupport/lib/active_support/new_callbacks.rb
+++ b/activesupport/lib/active_support/new_callbacks.rb
@@ -316,7 +316,7 @@ module ActiveSupport
each do |callback|
method << callback.start(key, options)
end
- method << "yield self if block_given?"
+ method << "yield self if block_given? && !halted"
reverse_each do |callback|
method << callback.end(key, options)
end
diff --git a/activesupport/test/new_callbacks_test.rb b/activesupport/test/new_callbacks_test.rb
index 8c887e1bf1..dec6106ac1 100644
--- a/activesupport/test/new_callbacks_test.rb
+++ b/activesupport/test/new_callbacks_test.rb
@@ -365,7 +365,7 @@ module NewCallbacksTest
save_callback :after, :third
- attr_reader :history
+ attr_reader :history, :saved
def initialize
@history = []
end
@@ -390,7 +390,9 @@ module NewCallbacksTest
end
def save
- _run_save_callbacks
+ _run_save_callbacks do
+ @saved = true
+ end
end
end
@@ -400,6 +402,12 @@ module NewCallbacksTest
terminator.save
assert_equal ["first", "second", "third", "second", "first"], terminator.history
end
+
+ def test_block_never_called_if_terminated
+ obj = CallbackTerminator.new
+ obj.save
+ assert !obj.saved
+ end
end
class HyphenatedKeyTest < Test::Unit::TestCase
@@ -407,6 +415,6 @@ module NewCallbacksTest
obj = HyphenatedCallbacks.new
obj.save
assert_equal obj.stuff, "OMG"
- end
+ end
end
end
--
cgit v1.2.3
From 94ee9d245289a36207847a684b51dbd1c7a6a4eb Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Mon, 11 May 2009 12:04:43 -0700
Subject: Ported ConditionalGet to new Base
---
actionpack/lib/action_controller/new_base/base.rb | 1 +
.../action_controller/new_base/compatibility.rb | 3 +
.../action_controller/new_base/conditional_get.rb | 91 +++++++++++++++++++++-
actionpack/lib/action_controller/new_base/http.rb | 1 +
.../lib/action_controller/new_base/testing.rb | 1 +
actionpack/lib/action_view/template/text.rb | 2 +
actionpack/test/controller/render_test.rb | 8 +-
7 files changed, 102 insertions(+), 5 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 40f507b6e7..313b9a5e1f 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -14,6 +14,7 @@ module ActionController
# Legacy modules
include SessionManagement
+ include ActionDispatch::StatusCodes
# Rails 2.x compatibility
use ActionController::Rails2Compatibility
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index db471f7658..3b1a74ec0c 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -26,6 +26,9 @@ module ActionController
if options.is_a?(Hash) && options.key?(:template)
options[:template].sub!(/^\//, '')
end
+
+ options[:text] = nil if options[:nothing] == true
+
super
end
diff --git a/actionpack/lib/action_controller/new_base/conditional_get.rb b/actionpack/lib/action_controller/new_base/conditional_get.rb
index 16104c51fc..e1407e671a 100644
--- a/actionpack/lib/action_controller/new_base/conditional_get.rb
+++ b/actionpack/lib/action_controller/new_base/conditional_get.rb
@@ -36,7 +36,96 @@ module ActionController
if request.fresh?(response)
head :not_modified
end
- end
+ end
+
+ # Return a response that has no content (merely headers). The options
+ # argument is interpreted to be a hash of header names and values.
+ # This allows you to easily return a response that consists only of
+ # significant headers:
+ #
+ # head :created, :location => person_path(@person)
+ #
+ # It can also be used to return exceptional conditions:
+ #
+ # return head(:method_not_allowed) unless request.post?
+ # return head(:bad_request) unless valid_request?
+ # render
+ def head(*args)
+ if args.length > 2
+ raise ArgumentError, "too many arguments to head"
+ elsif args.empty?
+ raise ArgumentError, "too few arguments to head"
+ end
+ options = args.extract_options!
+ status = interpret_status(args.shift || options.delete(:status) || :ok)
+
+ options.each do |key, value|
+ headers[key.to_s.dasherize.split(/-/).map { |v| v.capitalize }.join("-")] = value.to_s
+ end
+
+ render :nothing => true, :status => status
+ end
+
+ # Sets the etag and/or last_modified on the response and checks it against
+ # the client request. If the request doesn't match the options provided, the
+ # request is considered stale and should be generated from scratch. Otherwise,
+ # it's fresh and we don't need to generate anything and a reply of "304 Not Modified" is sent.
+ #
+ # Parameters:
+ # * :etag
+ # * :last_modified
+ # * :public By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches).
+ #
+ # Example:
+ #
+ # def show
+ # @article = Article.find(params[:id])
+ #
+ # if stale?(:etag => @article, :last_modified => @article.created_at.utc)
+ # @statistics = @article.really_expensive_call
+ # respond_to do |format|
+ # # all the supported formats
+ # end
+ # end
+ # end
+ def stale?(options)
+ fresh_when(options)
+ !request.fresh?(response)
+ end
+
+ # Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a "private" instruction, so that
+ # intermediate caches shouldn't cache the response.
+ #
+ # Examples:
+ # expires_in 20.minutes
+ # expires_in 3.hours, :public => true
+ # expires in 3.hours, 'max-stale' => 5.hours, :public => true
+ #
+ # This method will overwrite an existing Cache-Control header.
+ # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
+ def expires_in(seconds, options = {}) #:doc:
+ cache_control = response.headers["Cache-Control"].split(",").map {|k| k.strip }
+
+ cache_control << "max-age=#{seconds}"
+ cache_control.delete("no-cache")
+ if options[:public]
+ cache_control.delete("private")
+ cache_control << "public"
+ else
+ cache_control << "private"
+ end
+
+ # This allows for additional headers to be passed through like 'max-stale' => 5.hours
+ cache_control += options.symbolize_keys.reject{|k,v| k == :public || k == :private }.map{ |k,v| v == true ? k.to_s : "#{k.to_s}=#{v.to_s}"}
+
+ response.headers["Cache-Control"] = cache_control.join(', ')
+ end
+
+ # Sets a HTTP 1.1 Cache-Control header of "no-cache" so no caching should occur by the browser or
+ # intermediate caches (like caching proxy servers).
+ def expires_now #:doc:
+ response.headers["Cache-Control"] = "no-cache"
+ end
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb
index b7e3bfaa7e..f269fe70db 100644
--- a/actionpack/lib/action_controller/new_base/http.rb
+++ b/actionpack/lib/action_controller/new_base/http.rb
@@ -42,6 +42,7 @@ module ActionController
def call(name, env)
@_request = ActionDispatch::Request.new(env)
@_response = ActionDispatch::Response.new
+ @_response.request = request
process(name)
@_response.body = response_body
@_response.prepare!
diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb
index 181c5c0ecd..106990b9ba 100644
--- a/actionpack/lib/action_controller/new_base/testing.rb
+++ b/actionpack/lib/action_controller/new_base/testing.rb
@@ -5,6 +5,7 @@ module ActionController
def process_with_test(request, response)
@_request = request
@_response = response
+ @_response.request = request
ret = process(request.parameters[:action])
@_response.body = self.response_body
@_response.prepare!
diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb
index 8477115211..a777021a12 100644
--- a/actionpack/lib/action_view/template/text.rb
+++ b/actionpack/lib/action_view/template/text.rb
@@ -6,5 +6,7 @@ module ActionView #:nodoc:
def render(*) self end
def mime_type() Mime::HTML end
+
+ def partial?() false end
end
end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 1e69ca894f..635b0f5342 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -1660,13 +1660,13 @@ class EtagRenderTest < ActionController::TestCase
def test_render_against_etag_request_should_200_when_no_match
@request.if_none_match = etag_for("hello somewhere else")
get :render_hello_world_from_variable
- assert_equal "200 OK", @response.status
+ assert_equal 200, @response.status.to_i
assert !@response.body.empty?
end
def test_render_should_not_set_etag_when_last_modified_has_been_specified
get :render_hello_world_with_last_modified_set
- assert_equal "200 OK", @response.status
+ assert_equal 200, @response.status.to_i
assert_not_nil @response.last_modified
assert_nil @response.etag
assert @response.body.present?
@@ -1752,7 +1752,7 @@ class LastModifiedRenderTest < ActionController::TestCase
def test_request_not_modified
@request.if_modified_since = @last_modified
get :conditional_hello
- assert_equal "304 Not Modified", @response.status
+ assert_equal 304, @response.status.to_i
assert @response.body.blank?, @response.body
assert_equal @last_modified, @response.headers['Last-Modified']
end
@@ -1767,7 +1767,7 @@ class LastModifiedRenderTest < ActionController::TestCase
def test_request_modified
@request.if_modified_since = 'Thu, 16 Jul 2008 00:00:00 GMT'
get :conditional_hello
- assert_equal "200 OK", @response.status
+ assert_equal 200, @response.status.to_i
assert !@response.body.blank?
assert_equal @last_modified, @response.headers['Last-Modified']
end
--
cgit v1.2.3
From ddbeb15a5e7e0c3c5f316ccf65b557bc5311a6c4 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Mon, 11 May 2009 12:01:08 -0700
Subject: Revert "Fixed bug with polymorphic has_one :as pointing to an STI
record"
[#2594 state:open]
This reverts commit 99c103be1165da9c8299bc0977188ecf167e06a5.
---
.../lib/active_record/associations/has_one_association.rb | 2 +-
.../test/cases/associations/has_one_associations_test.rb | 9 +--------
activerecord/test/fixtures/organizations.yml | 4 +---
activerecord/test/fixtures/sponsors.yml | 4 +---
activerecord/test/models/organization.rb | 4 ----
activerecord/test/schema/schema.rb | 3 +--
6 files changed, 5 insertions(+), 21 deletions(-)
diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb
index 4908005d2e..b72b84343b 100644
--- a/activerecord/lib/active_record/associations/has_one_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_association.rb
@@ -90,7 +90,7 @@ module ActiveRecord
when @reflection.options[:as]
@finder_sql =
"#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_id = #{owner_quoted_id} AND " +
- "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.name.to_s)}"
+ "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.base_class.name.to_s)}"
else
@finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{owner_quoted_id}"
end
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index 3984945f9f..1ddb3f49bf 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -2,11 +2,9 @@ require "cases/helper"
require 'models/developer'
require 'models/project'
require 'models/company'
-require 'models/sponsor'
-require 'models/organization'
class HasOneAssociationsTest < ActiveRecord::TestCase
- fixtures :accounts, :companies, :developers, :projects, :developers_projects, :organizations, :sponsors
+ fixtures :accounts, :companies, :developers, :projects, :developers_projects
def setup
Account.destroyed_account_ids.clear
@@ -308,9 +306,4 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
Firm.find(@firm.id, :include => :account).save!
end
end
-
- def test_polymorphic_sti
- assert_equal organizations(:sponsorable), sponsors(:org_sponsor).sponsorable
- assert_equal sponsors(:org_sponsor), organizations(:sponsorable).sponsor
- end
end
diff --git a/activerecord/test/fixtures/organizations.yml b/activerecord/test/fixtures/organizations.yml
index 05d620fbc6..25295bff87 100644
--- a/activerecord/test/fixtures/organizations.yml
+++ b/activerecord/test/fixtures/organizations.yml
@@ -2,6 +2,4 @@ nsa:
name: No Such Agency
discordians:
name: Discordians
-sponsorable:
- name: We Need Money
- type: SponsorableOrganization
+
diff --git a/activerecord/test/fixtures/sponsors.yml b/activerecord/test/fixtures/sponsors.yml
index 97a7784047..42df8957d1 100644
--- a/activerecord/test/fixtures/sponsors.yml
+++ b/activerecord/test/fixtures/sponsors.yml
@@ -6,6 +6,4 @@ boring_club_sponsor_for_groucho:
sponsorable: some_other_guy (Member)
crazy_club_sponsor_for_groucho:
sponsor_club: crazy_club
- sponsorable: some_other_guy (Member)
-org_sponsor:
- sponsorable: sponsorable (SponsorableOrganization)
\ No newline at end of file
+ sponsorable: some_other_guy (Member)
\ No newline at end of file
diff --git a/activerecord/test/models/organization.rb b/activerecord/test/models/organization.rb
index 5d1308354d..d79d5037c8 100644
--- a/activerecord/test/models/organization.rb
+++ b/activerecord/test/models/organization.rb
@@ -1,8 +1,4 @@
class Organization < ActiveRecord::Base
has_many :member_details
has_many :members, :through => :member_details
-end
-
-class SponsorableOrganization < Organization
- has_one :sponsor, :as => :sponsorable
end
\ No newline at end of file
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 6fb918c60e..a776cd974b 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -284,7 +284,6 @@ ActiveRecord::Schema.define do
create_table :organizations, :force => true do |t|
t.string :name
- t.string :type
end
create_table :owners, :primary_key => :owner_id ,:force => true do |t|
@@ -390,7 +389,7 @@ ActiveRecord::Schema.define do
create_table :sponsors, :force => true do |t|
t.integer :club_id
t.integer :sponsorable_id
- t.string :sponsorable_type
+ t.string :sponsorable_type
end
create_table :subscribers, :force => true, :id => false do |t|
--
cgit v1.2.3
From 6694bd46f59eb9b9b23afbd0d9484fd87e8fe350 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Mon, 11 May 2009 12:45:26 -0700
Subject: Aliased AbstractController::ActionNotFound to
ActionController::UnknownAction
---
actionpack/lib/action_controller/new_base/compatibility.rb | 13 ++++++++-----
actionpack/lib/action_controller/testing/process2.rb | 1 +
actionpack/test/abstract_unit2.rb | 3 ---
actionpack/test/controller/render_test.rb | 5 +++--
4 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index 3b1a74ec0c..b6e15a4e0d 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -3,6 +3,9 @@ module ActionController
# Temporary hax
setup do
+ ::ActionController::UnknownAction = ::AbstractController::ActionNotFound
+ ::ActionController::DoubleRenderError = ::AbstractController::DoubleRenderError
+
cattr_accessor :session_options
self.send(:class_variable_set, "@@session_options", {})
@@ -31,11 +34,11 @@ module ActionController
super
end
-
- def _layout_for_name(name)
- name &&= name.sub(%r{^/?layouts/}, '')
- super
- end
+
+ def _layout_for_name(name)
+ name &&= name.sub(%r{^/?layouts/}, '')
+ super
+ end
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb
index 67b5afb9c5..18b7335450 100644
--- a/actionpack/lib/action_controller/testing/process2.rb
+++ b/actionpack/lib/action_controller/testing/process2.rb
@@ -39,6 +39,7 @@ module ActionController
@request.recycle!
@response.recycle!
+ @controller.response_body = nil
@html_document = nil
@request.env['REQUEST_METHOD'] = http_method
diff --git a/actionpack/test/abstract_unit2.rb b/actionpack/test/abstract_unit2.rb
index b95bfa0202..680043fab0 100644
--- a/actionpack/test/abstract_unit2.rb
+++ b/actionpack/test/abstract_unit2.rb
@@ -57,9 +57,6 @@ module ActionController
class UnknownController < ActionControllerError #:nodoc:
end
- class UnknownAction < ActionControllerError #:nodoc:
- end
-
class MissingFile < ActionControllerError #:nodoc:
end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 635b0f5342..414b84c029 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -1680,11 +1680,12 @@ class EtagRenderTest < ActionController::TestCase
@request.if_none_match = expected_etag
get :render_hello_world_from_variable
- assert_equal "304 Not Modified", @response.status
+ assert_equal 304, @response.status.to_i
+ @response = ActionController::TestResponse.new
@request.if_none_match = "\"diftag\""
get :render_hello_world_from_variable
- assert_equal "200 OK", @response.status
+ assert_equal 200, @response.status.to_i
end
def render_with_404_shouldnt_have_etag
--
cgit v1.2.3
From 0f6e764e4060b75ea8a335e6971209a08bf8b40a Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Mon, 11 May 2009 14:48:58 -0700
Subject: Fixed a bug with handling render options
---
.../action_controller/new_base/compatibility.rb | 9 +++
.../lib/action_controller/new_base/renderer.rb | 4 +-
actionpack/test/abstract_unit2.rb | 65 +---------------------
3 files changed, 12 insertions(+), 66 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index b6e15a4e0d..505675ec4d 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -23,6 +23,15 @@ module ActionController
cattr_accessor :default_charset
self.send(:class_variable_set, "@@default_charset", "utf-8")
+
+ cattr_reader :protected_instance_variables
+ self.send(:class_variable_set, "@@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 @_headers @_params
+ @_flash @_response))
+ end
+
+ module ClassMethods
+ def protect_from_forgery() end
end
def render_to_body(options)
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 4c4a74979b..bedd1d7a23 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -23,8 +23,8 @@ module ActionController
options[:_template] = template
elsif options.key?(:template)
options[:_template_name] = options[:template]
- elsif options.key?(:action)
- options[:_template_name] = options[:action].to_s
+ else
+ options[:_template_name] = (options[:action] || action_name).to_s
options[:_prefix] = _prefix
end
diff --git a/actionpack/test/abstract_unit2.rb b/actionpack/test/abstract_unit2.rb
index 680043fab0..95e7b2e273 100644
--- a/actionpack/test/abstract_unit2.rb
+++ b/actionpack/test/abstract_unit2.rb
@@ -74,71 +74,8 @@ module ActionController
class UnknownHttpMethod < ActionControllerError #:nodoc:
end
- class Base < Http
- abstract!
- #
- cattr_accessor :relative_url_root
- self.relative_url_root = ENV['RAILS_RELATIVE_URL_ROOT']
-
- 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 @_headers @_params
- @_flash @_response)
- #
-
- use AbstractController::Callbacks
- use AbstractController::Helpers
- use AbstractController::Logger
-
- use ActionController::HideActions
- use ActionController::UrlFor
- use ActionController::Renderer
- use ActionController::Layouts
- use ActionController::Rails2Compatibility
+ class Base
use ActionController::Testing
-
- def self.protect_from_forgery() end
-
- def self.inherited(klass)
- ::ActionController::Base.subclasses << klass.to_s
- super
- end
-
- def self.subclasses
- @subclasses ||= []
- end
-
- def self.app_loaded!
- @subclasses.each do |subclass|
- subclass.constantize._write_layout_method
- end
- end
-
- def render(action = action_name, options = {})
- if action.is_a?(Hash)
- options, action = action, nil
- else
- options.merge! :action => action
- end
-
- super(options)
- end
-
- def render_to_body(options = {})
- options = {:template => options} if options.is_a?(String)
- super
- end
-
- def process_action
- ret = super
- render if response_body.nil?
- ret
- end
-
- def respond_to_action?(action_name)
- super || view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
- end
end
Base.view_paths = FIXTURE_LOAD_PATH
--
cgit v1.2.3
From 0cac68d3bed3e6bf8ec2eb994858e4a179046941 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Mon, 11 May 2009 15:03:24 -0700
Subject: Revert "Whitespace!"
This reverts commit a747ab5b20b9d543e9d311070e3b720c761ae716.
---
actionpack/lib/action_controller/abstract.rb | 2 +-
actionpack/lib/action_controller/abstract/base.rb | 19 ++++++++-------
.../lib/action_controller/abstract/callbacks.rb | 8 +++----
.../lib/action_controller/abstract/exceptions.rb | 2 +-
.../lib/action_controller/abstract/helpers.rb | 17 +++++++-------
.../lib/action_controller/abstract/layouts.rb | 27 +++++++++++-----------
.../lib/action_controller/abstract/logger.rb | 2 +-
.../lib/action_controller/abstract/renderer.rb | 19 +++++++--------
actionpack/lib/action_controller/new_base.rb | 2 +-
actionpack/lib/action_controller/new_base/base.rb | 27 +++++++++++-----------
.../lib/action_controller/new_base/hide_actions.rb | 11 +++++----
.../lib/action_controller/new_base/layouts.rb | 14 ++++++-----
.../lib/action_controller/new_base/renderer.rb | 23 +++++++++---------
.../lib/action_controller/new_base/url_for.rb | 6 ++---
14 files changed, 95 insertions(+), 84 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract.rb b/actionpack/lib/action_controller/abstract.rb
index 9442d4559f..3f5c4a185f 100644
--- a/actionpack/lib/action_controller/abstract.rb
+++ b/actionpack/lib/action_controller/abstract.rb
@@ -7,4 +7,4 @@ module AbstractController
autoload :Renderer, "action_controller/abstract/renderer"
# === Exceptions
autoload :ActionNotFound, "action_controller/abstract/exceptions"
-end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index 39e9ad0440..ade7719cc0 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -1,38 +1,41 @@
module AbstractController
class Base
+
attr_internal :response_body
attr_internal :response_obj
attr_internal :action_name
-
+
def self.process(action)
new.process(action)
end
-
+
def self.inherited(klass)
end
-
+
def initialize
self.response_obj = {}
end
-
+
def process(action_name)
unless respond_to_action?(action_name)
raise ActionNotFound, "The action '#{action_name}' could not be found"
end
-
+
@_action_name = action_name
process_action
self.response_obj[:body] = self.response_body
self
end
-
+
private
+
def process_action
respond_to?(action_name) ? send(action_name) : send(:action_missing, action_name)
end
-
+
def respond_to_action?(action_name)
respond_to?(action_name) || respond_to?(:action_missing, true)
end
+
end
-end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb
index cb8aade0be..d7faaf4236 100644
--- a/actionpack/lib/action_controller/abstract/callbacks.rb
+++ b/actionpack/lib/action_controller/abstract/callbacks.rb
@@ -13,7 +13,7 @@ module AbstractController
super
end
end
-
+
module ClassMethods
def _normalize_callback_options(options)
if only = options[:only]
@@ -21,11 +21,11 @@ module AbstractController
options[:per_key] = {:if => only}
end
if except = options[:except]
- except = Array(except).map {|e| "action_name == :#{e}"}.join(" || ")
+ except = Array(except).map {|e| "action_name == :#{e}"}.join(" || ")
options[:per_key] = {:unless => except}
end
end
-
+
[:before, :after, :around].each do |filter|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
def #{filter}_filter(*names, &blk)
@@ -40,4 +40,4 @@ module AbstractController
end
end
end
-end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/exceptions.rb b/actionpack/lib/action_controller/abstract/exceptions.rb
index a7d07868bb..ec4680629b 100644
--- a/actionpack/lib/action_controller/abstract/exceptions.rb
+++ b/actionpack/lib/action_controller/abstract/exceptions.rb
@@ -1,3 +1,3 @@
module AbstractController
class ActionNotFound < StandardError ; end
-end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/helpers.rb b/actionpack/lib/action_controller/abstract/helpers.rb
index 38e3ce8127..62caa119e7 100644
--- a/actionpack/lib/action_controller/abstract/helpers.rb
+++ b/actionpack/lib/action_controller/abstract/helpers.rb
@@ -8,14 +8,14 @@ module AbstractController
extlib_inheritable_accessor :master_helper_module
self.master_helper_module = Module.new
end
-
+
# def self.included(klass)
# klass.class_eval do
# extlib_inheritable_accessor :master_helper_module
# self.master_helper_module = Module.new
# end
# end
-
+
def _action_view
@_action_view ||= begin
av = super
@@ -23,19 +23,19 @@ module AbstractController
av
end
end
-
+
module ClassMethods
def inherited(klass)
klass.master_helper_module = Module.new
klass.master_helper_module.__send__ :include, master_helper_module
-
+
super
end
-
+
def add_template_helper(mod)
master_helper_module.module_eval { include mod }
end
-
+
def helper_method(*meths)
meths.flatten.each do |meth|
master_helper_module.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
@@ -45,7 +45,7 @@ module AbstractController
ruby_eval
end
end
-
+
def helper(*args, &blk)
args.flatten.each do |arg|
case arg
@@ -56,5 +56,6 @@ module AbstractController
master_helper_module.module_eval(&blk) if block_given?
end
end
+
end
-end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 69fe4efc19..76130f8dc0 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -9,18 +9,18 @@ module AbstractController
unless [String, Symbol, FalseClass, NilClass].include?(layout.class)
raise ArgumentError, "Layouts must be specified as a String, Symbol, false, or nil"
end
-
+
@_layout = layout || false # Converts nil to false
_write_layout_method
end
-
+
def _implied_layout_name
name.underscore
end
-
+
# Takes the specified layout and creates a _layout method to be called
# by _default_layout
- #
+ #
# If the specified layout is a:
# String:: return the string
# Symbol:: call the method specified by the symbol
@@ -49,34 +49,35 @@ module AbstractController
end
end
end
-
+
def _render_template(template, options)
_action_view._render_template_with_layout(template, options[:_layout])
end
-
+
private
+
def _layout() end # This will be overwritten
-
+
def _layout_for_name(name)
unless [String, FalseClass, NilClass].include?(name.class)
raise ArgumentError, "String, false, or nil expected; you passed #{name.inspect}"
end
-
+
name && view_paths.find_by_parts(name, {:formats => formats}, "layouts")
end
-
+
def _default_layout(require_layout = false)
if require_layout && !_layout
- raise ArgumentError,
+ raise ArgumentError,
"There was no default layout for #{self.class} in #{view_paths.inspect}"
end
-
+
begin
layout = _layout_for_name(_layout)
rescue NameError => e
- raise NoMethodError,
+ raise NoMethodError,
"You specified #{@_layout.inspect} as the layout, but no such method was found"
end
end
end
-end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb
index c3bccd7778..5fb78f1755 100644
--- a/actionpack/lib/action_controller/abstract/logger.rb
+++ b/actionpack/lib/action_controller/abstract/logger.rb
@@ -6,4 +6,4 @@ module AbstractController
cattr_accessor :logger
end
end
-end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index b5c31a27ee..beb848f90e 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -15,22 +15,22 @@ module AbstractController
end
def _action_view
- @_action_view ||= ActionView::Base.new(self.class.view_paths, {}, self)
+ @_action_view ||= ActionView::Base.new(self.class.view_paths, {}, self)
end
-
+
def render(options = {})
self.response_body = render_to_body(options)
end
-
+
# Raw rendering of a template to a Rack-compatible body.
# ====
# @option _prefix The template's path prefix
# @option _layout The relative path to the layout template to use
- #
+ #
# :api: plugin
def render_to_body(options = {})
name = options[:_template_name] || action_name
-
+
template = options[:_template] || view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix])
_render_template(template, options)
end
@@ -39,7 +39,7 @@ module AbstractController
# ====
# @option _prefix The template's path prefix
# @option _layout The relative path to the layout template to use
- #
+ #
# :api: plugin
def render_to_string(options = {})
AbstractController::Renderer.body_to_s(render_to_body(options))
@@ -48,7 +48,7 @@ module AbstractController
def _render_template(template, options)
_action_view._render_template_with_layout(template)
end
-
+
def view_paths() _view_paths end
# Return a string representation of a Rack-compatible response body.
@@ -64,14 +64,15 @@ module AbstractController
end
module ClassMethods
+
def append_view_path(path)
self.view_paths << path
end
-
+
def view_paths
self._view_paths
end
-
+
def view_paths=(paths)
self._view_paths = paths.is_a?(ActionView::PathSet) ?
paths : ActionView::Base.process_view_paths(paths)
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 29dc3aaddc..7c65f1cdc1 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -4,4 +4,4 @@ module ActionController
autoload :Layouts, "action_controller/new_base/layouts"
autoload :Renderer, "action_controller/new_base/renderer"
autoload :UrlFor, "action_controller/new_base/url_for"
-end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 2dd5390c99..08e7a1a0e7 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -1,5 +1,6 @@
module ActionController
class AbstractBase < AbstractController::Base
+
# :api: public
attr_internal :request, :response, :params
@@ -11,46 +12,46 @@ module ActionController
# :api: public
def controller_name() self.class.controller_name end
- # :api: public
+ # :api: public
def self.controller_path
@controller_path ||= self.name.sub(/Controller$/, '').underscore
end
-
- # :api: public
+
+ # :api: public
def controller_path() self.class.controller_path end
-
- # :api: private
+
+ # :api: private
def self.action_methods
@action_names ||= Set.new(self.public_instance_methods - self::CORE_METHODS)
end
-
- # :api: private
+
+ # :api: private
def self.action_names() action_methods end
-
- # :api: private
+
+ # :api: private
def action_methods() self.class.action_names end
# :api: private
def action_names() action_methods end
-
+
# :api: plugin
def self.call(env)
controller = new
controller.call(env).to_rack
end
-
+
# :api: plugin
def response_body=(body)
@_response.body = body
end
-
+
# :api: private
def call(env)
@_request = ActionDispatch::Request.new(env)
@_response = ActionDispatch::Response.new
process(@_request.parameters[:action])
end
-
+
# :api: private
def to_rack
response.to_a
diff --git a/actionpack/lib/action_controller/new_base/hide_actions.rb b/actionpack/lib/action_controller/new_base/hide_actions.rb
index 422ea180c4..aa420442fb 100644
--- a/actionpack/lib/action_controller/new_base/hide_actions.rb
+++ b/actionpack/lib/action_controller/new_base/hide_actions.rb
@@ -6,20 +6,21 @@ module ActionController
end
def action_methods() self.class.action_names end
- def action_names() action_methods end
-
+ def action_names() action_methods end
+
private
+
def respond_to_action?(action_name)
!hidden_actions.include?(action_name) && (super || respond_to?(:method_missing))
end
-
+
module ClassMethods
def hide_action(*args)
args.each do |arg|
self.hidden_actions << arg.to_s
end
end
-
+
def action_methods
@action_names ||= Set.new(super.reject {|name| self.hidden_actions.include?(name.to_s)})
end
@@ -27,4 +28,4 @@ module ActionController
def self.action_names() action_methods end
end
end
-end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/layouts.rb b/actionpack/lib/action_controller/new_base/layouts.rb
index 228162421d..89d24fe92d 100644
--- a/actionpack/lib/action_controller/new_base/layouts.rb
+++ b/actionpack/lib/action_controller/new_base/layouts.rb
@@ -4,13 +4,13 @@ module ActionController
depends_on ActionController::Renderer
depends_on AbstractController::Layouts
-
+
module ClassMethods
def _implied_layout_name
controller_path
end
end
-
+
def render_to_body(options)
# render :text => ..., :layout => ...
# or
@@ -18,20 +18,22 @@ module ActionController
if !options.key?(:text) || options.key?(:layout)
options[:_layout] = options.key?(:layout) ? _layout_for_option(options[:layout]) : _default_layout
end
-
+
super
end
-
+
private
+
def _layout_for_option(name)
case name
when String then _layout_for_name(name)
when true then _default_layout(true)
when false, nil then nil
else
- raise ArgumentError,
- "String, true, or false, expected for `layout'; you passed #{name.inspect}"
+ raise ArgumentError,
+ "String, true, or false, expected for `layout'; you passed #{name.inspect}"
end
end
+
end
end
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index d7ea9ec4a5..be4ea54c3b 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -3,22 +3,22 @@ module ActionController
extend ActiveSupport::DependencyModule
depends_on AbstractController::Renderer
-
+
def initialize(*)
self.formats = [:html]
super
end
-
+
def render(action, options = {})
# TODO: Move this into #render_to_body
if action.is_a?(Hash)
- options, action = action, nil
+ options, action = action, nil
else
options.merge! :action => action
end
-
+
_process_options(options)
-
+
self.response_body = render_to_body(options)
end
@@ -34,17 +34,18 @@ module ActionController
options[:_template_name] = options[:template]
elsif options.key?(:action)
options[:_template_name] = options[:action].to_s
- options[:_prefix] = _prefix
+ options[:_prefix] = _prefix
end
-
+
super(options)
end
-
+
private
+
def _prefix
controller_path
- end
-
+ end
+
def _text(options)
text = options[:text]
@@ -53,7 +54,7 @@ module ActionController
else text.to_s
end
end
-
+
def _process_options(options)
if status = options[:status]
response.status = status.to_i
diff --git a/actionpack/lib/action_controller/new_base/url_for.rb b/actionpack/lib/action_controller/new_base/url_for.rb
index 3179c8cd5b..af5b21012b 100644
--- a/actionpack/lib/action_controller/new_base/url_for.rb
+++ b/actionpack/lib/action_controller/new_base/url_for.rb
@@ -16,7 +16,7 @@ module ActionController
# by this method.
def default_url_options(options = nil)
end
-
+
def rewrite_options(options) #:nodoc:
if defaults = default_url_options(options)
defaults.merge(options)
@@ -24,7 +24,7 @@ module ActionController
options
end
end
-
+
def url_for(options = {})
options ||= {}
case options
@@ -37,4 +37,4 @@ module ActionController
end
end
end
-end
+end
\ No newline at end of file
--
cgit v1.2.3
From a2875bec9a31702a385d2f34e66843ddbe4e9db2 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp
Date: Mon, 11 May 2009 22:23:47 -0400
Subject: Use DependencyModule for included hooks in ActiveRecord
---
activerecord/lib/active_record/aggregations.rb | 4 +--
.../lib/active_record/association_preload.rb | 4 +--
activerecord/lib/active_record/associations.rb | 6 ++--
.../lib/active_record/attribute_methods.rb | 22 ++++++++-----
.../lib/active_record/autosave_association.rb | 13 ++++----
activerecord/lib/active_record/batches.rb | 4 +--
activerecord/lib/active_record/calculations.rb | 5 ++-
activerecord/lib/active_record/callbacks.rb | 12 ++++---
activerecord/lib/active_record/dirty.rb | 21 ++++++------
activerecord/lib/active_record/fixtures.rb | 38 ++++++++++------------
.../lib/active_record/locking/optimistic.rb | 16 ++++-----
activerecord/lib/active_record/named_scope.rb | 9 +++--
.../lib/active_record/nested_attributes.rb | 9 ++---
activerecord/lib/active_record/observer.rb | 4 +--
activerecord/lib/active_record/reflection.rb | 4 +--
.../active_record/serializers/json_serializer.rb | 7 ++--
activerecord/lib/active_record/timestamp.rb | 12 ++++---
activerecord/lib/active_record/transactions.rb | 12 +++----
activerecord/lib/active_record/validations.rb | 15 ++++-----
.../associations/eager_load_nested_include_test.rb | 13 ++++----
activerecord/test/cases/repair_helper.rb | 6 +---
21 files changed, 111 insertions(+), 125 deletions(-)
diff --git a/activerecord/lib/active_record/aggregations.rb b/activerecord/lib/active_record/aggregations.rb
index 1eefebb3b3..359e70f5ed 100644
--- a/activerecord/lib/active_record/aggregations.rb
+++ b/activerecord/lib/active_record/aggregations.rb
@@ -1,8 +1,6 @@
module ActiveRecord
module Aggregations # :nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- end
+ extend ActiveSupport::DependencyModule
def clear_aggregation_cache #:nodoc:
self.class.reflect_on_all_aggregations.to_a.each do |assoc|
diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb
index 967fff4d6f..5df76bb183 100644
--- a/activerecord/lib/active_record/association_preload.rb
+++ b/activerecord/lib/active_record/association_preload.rb
@@ -1,9 +1,7 @@
module ActiveRecord
# See ActiveRecord::AssociationPreload::ClassMethods for documentation.
module AssociationPreload #:nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- end
+ extend ActiveSupport::DependencyModule
# Implements the details of eager loading of ActiveRecord associations.
# Application developers should not use this module directly.
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 781a0290e8..e2dd36158f 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -77,6 +77,8 @@ module ActiveRecord
# See ActiveRecord::Associations::ClassMethods for documentation.
module Associations # :nodoc:
+ extend ActiveSupport::DependencyModule
+
# These classes will be loaded when associations are created.
# So there is no need to eager load them.
autoload :AssociationCollection, 'active_record/associations/association_collection'
@@ -89,10 +91,6 @@ module ActiveRecord
autoload :HasOneAssociation, 'active_record/associations/has_one_association'
autoload :HasOneThroughAssociation, 'active_record/associations/has_one_through_association'
- def self.included(base)
- base.extend(ClassMethods)
- end
-
# Clears out the association cache
def clear_association_cache #:nodoc:
self.class.reflect_on_all_associations.to_a.each do |assoc|
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index 3ffc48941c..8d68d77eac 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -1,17 +1,21 @@
module ActiveRecord
module AttributeMethods #:nodoc:
+ extend ActiveSupport::DependencyModule
+
DEFAULT_SUFFIXES = %w(= ? _before_type_cast)
ATTRIBUTE_TYPES_CACHED_BY_DEFAULT = [:datetime, :timestamp, :time, :date]
- def self.included(base)
- base.extend ClassMethods
- base.attribute_method_suffix(*DEFAULT_SUFFIXES)
- base.cattr_accessor :attribute_types_cached_by_default, :instance_writer => false
- base.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
- base.cattr_accessor :time_zone_aware_attributes, :instance_writer => false
- base.time_zone_aware_attributes = false
- base.class_inheritable_accessor :skip_time_zone_conversion_for_attributes, :instance_writer => false
- base.skip_time_zone_conversion_for_attributes = []
+ included do
+ attribute_method_suffix(*DEFAULT_SUFFIXES)
+
+ cattr_accessor :attribute_types_cached_by_default, :instance_writer => false
+ self.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
+
+ cattr_accessor :time_zone_aware_attributes, :instance_writer => false
+ self.time_zone_aware_attributes = false
+
+ class_inheritable_accessor :skip_time_zone_conversion_for_attributes, :instance_writer => false
+ self.skip_time_zone_conversion_for_attributes = []
end
# Declare and check for suffixed attribute methods.
diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb
index 9717ca3d8b..4ab2818282 100644
--- a/activerecord/lib/active_record/autosave_association.rb
+++ b/activerecord/lib/active_record/autosave_association.rb
@@ -125,16 +125,15 @@ module ActiveRecord
# post.author.name = ''
# post.save(false) # => true
module AutosaveAssociation
+ extend ActiveSupport::DependencyModule
+
ASSOCIATION_TYPES = %w{ has_one belongs_to has_many has_and_belongs_to_many }
- def self.included(base)
- base.class_eval do
- base.extend(ClassMethods)
- alias_method_chain :reload, :autosave_associations
+ included do
+ alias_method_chain :reload, :autosave_associations
- ASSOCIATION_TYPES.each do |type|
- base.send("valid_keys_for_#{type}_association") << :autosave
- end
+ ASSOCIATION_TYPES.each do |type|
+ send("valid_keys_for_#{type}_association") << :autosave
end
end
diff --git a/activerecord/lib/active_record/batches.rb b/activerecord/lib/active_record/batches.rb
index 5a6cecd4ad..4836601297 100644
--- a/activerecord/lib/active_record/batches.rb
+++ b/activerecord/lib/active_record/batches.rb
@@ -1,8 +1,6 @@
module ActiveRecord
module Batches # :nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- end
+ extend ActiveSupport::DependencyModule
# When processing large numbers of records, it's often a good idea to do
# so in batches to prevent memory ballooning.
diff --git a/activerecord/lib/active_record/calculations.rb b/activerecord/lib/active_record/calculations.rb
index f077818d3b..7afa7c49bd 100644
--- a/activerecord/lib/active_record/calculations.rb
+++ b/activerecord/lib/active_record/calculations.rb
@@ -1,9 +1,8 @@
module ActiveRecord
module Calculations #:nodoc:
+ extend ActiveSupport::DependencyModule
+
CALCULATIONS_OPTIONS = [:conditions, :joins, :order, :select, :group, :having, :distinct, :limit, :offset, :include, :from]
- def self.included(base)
- base.extend(ClassMethods)
- end
module ClassMethods
# Count operates using three different approaches.
diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb
index e375037b5b..a77fdb1c13 100644
--- a/activerecord/lib/active_record/callbacks.rb
+++ b/activerecord/lib/active_record/callbacks.rb
@@ -211,21 +211,23 @@ module ActiveRecord
# needs to be aware of it because an ordinary +save+ will raise such exception
# instead of quietly returning +false+.
module Callbacks
+ extend ActiveSupport::DependencyModule
+
CALLBACKS = %w(
after_find after_initialize before_save after_save before_create after_create before_update after_update before_validation
after_validation before_validation_on_create after_validation_on_create before_validation_on_update
after_validation_on_update before_destroy after_destroy
)
- def self.included(base) #:nodoc:
- base.extend Observable
+ included do
+ extend Observable
[:create_or_update, :valid?, :create, :update, :destroy].each do |method|
- base.send :alias_method_chain, method, :callbacks
+ alias_method_chain method, :callbacks
end
- base.send :include, ActiveSupport::Callbacks
- base.define_callbacks *CALLBACKS
+ include ActiveSupport::Callbacks
+ define_callbacks *CALLBACKS
end
# Is called when the object was instantiated by one of the finders, like Base.find .
diff --git a/activerecord/lib/active_record/dirty.rb b/activerecord/lib/active_record/dirty.rb
index 4a2510aa63..fac6ca40d3 100644
--- a/activerecord/lib/active_record/dirty.rb
+++ b/activerecord/lib/active_record/dirty.rb
@@ -34,20 +34,21 @@ module ActiveRecord
# person.name << 'by'
# person.name_change # => ['uncle bob', 'uncle bobby']
module Dirty
+ extend ActiveSupport::DependencyModule
+
DIRTY_SUFFIXES = ['_changed?', '_change', '_will_change!', '_was']
- def self.included(base)
- base.attribute_method_suffix *DIRTY_SUFFIXES
- base.alias_method_chain :write_attribute, :dirty
- base.alias_method_chain :save, :dirty
- base.alias_method_chain :save!, :dirty
- base.alias_method_chain :update, :dirty
- base.alias_method_chain :reload, :dirty
+ included do
+ attribute_method_suffix *DIRTY_SUFFIXES
- base.superclass_delegating_accessor :partial_updates
- base.partial_updates = true
+ alias_method_chain :write_attribute, :dirty
+ alias_method_chain :save, :dirty
+ alias_method_chain :save!, :dirty
+ alias_method_chain :update, :dirty
+ alias_method_chain :reload, :dirty
- base.send(:extend, ClassMethods)
+ superclass_delegating_accessor :partial_updates
+ self.partial_updates = true
end
# Do any attributes have unsaved changes?
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index c6501113bf..91b4b4e182 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -805,27 +805,25 @@ end
module ActiveRecord
module TestFixtures
- def self.included(base)
- base.class_eval do
- setup :setup_fixtures
- teardown :teardown_fixtures
-
- superclass_delegating_accessor :fixture_path
- superclass_delegating_accessor :fixture_table_names
- superclass_delegating_accessor :fixture_class_names
- superclass_delegating_accessor :use_transactional_fixtures
- superclass_delegating_accessor :use_instantiated_fixtures # true, false, or :no_instances
- superclass_delegating_accessor :pre_loaded_fixtures
-
- self.fixture_table_names = []
- self.use_transactional_fixtures = false
- self.use_instantiated_fixtures = true
- self.pre_loaded_fixtures = false
-
- self.fixture_class_names = {}
- end
+ extend ActiveSupport::DependencyModule
+
+ included do
+ setup :setup_fixtures
+ teardown :teardown_fixtures
+
+ superclass_delegating_accessor :fixture_path
+ superclass_delegating_accessor :fixture_table_names
+ superclass_delegating_accessor :fixture_class_names
+ superclass_delegating_accessor :use_transactional_fixtures
+ superclass_delegating_accessor :use_instantiated_fixtures # true, false, or :no_instances
+ superclass_delegating_accessor :pre_loaded_fixtures
+
+ self.fixture_table_names = []
+ self.use_transactional_fixtures = false
+ self.use_instantiated_fixtures = true
+ self.pre_loaded_fixtures = false
- base.extend ClassMethods
+ self.fixture_class_names = {}
end
module ClassMethods
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index 7fa7e267d8..cf4f8864c6 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -42,17 +42,17 @@ module ActiveRecord
# To override the name of the lock_version column, invoke the set_locking_column method.
# This method uses the same syntax as set_table_name
module Optimistic
- def self.included(base) #:nodoc:
- base.extend ClassMethods
+ extend ActiveSupport::DependencyModule
- base.cattr_accessor :lock_optimistically, :instance_writer => false
- base.lock_optimistically = true
+ included do
+ cattr_accessor :lock_optimistically, :instance_writer => false
+ self.lock_optimistically = true
- base.alias_method_chain :update, :lock
- base.alias_method_chain :destroy, :lock
- base.alias_method_chain :attributes_from_column_definition, :lock
+ alias_method_chain :update, :lock
+ alias_method_chain :destroy, :lock
+ alias_method_chain :attributes_from_column_definition, :lock
- class << base
+ class << self
alias_method :locking_column=, :set_locking_column
end
end
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index 3df7089096..32bb36c07c 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -1,5 +1,7 @@
module ActiveRecord
module NamedScope
+ extend ActiveSupport::DependencyModule
+
# All subclasses of ActiveRecord::Base have one named scope:
# * scoped - which allows for the creation of anonymous \scopes, on the fly: Shirt.scoped(:conditions => {:color => 'red'}).scoped(:include => :washing_instructions)
#
@@ -7,11 +9,8 @@ module ActiveRecord
# intermediate values (scopes) around as first-class objects is convenient.
#
# You can define a scope that applies to all finders using ActiveRecord::Base.default_scope.
- def self.included(base)
- base.class_eval do
- extend ClassMethods
- named_scope :scoped, lambda { |scope| scope }
- end
+ included do
+ named_scope :scoped, lambda { |scope| scope }
end
module ClassMethods
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index dfad2901c5..1ea2f53fd8 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -1,9 +1,10 @@
module ActiveRecord
module NestedAttributes #:nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- base.class_inheritable_accessor :reject_new_nested_attributes_procs, :instance_writer => false
- base.reject_new_nested_attributes_procs = {}
+ extend ActiveSupport::DependencyModule
+
+ included do
+ class_inheritable_accessor :reject_new_nested_attributes_procs, :instance_writer => false
+ self.reject_new_nested_attributes_procs = {}
end
# == Nested Attributes
diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb
index b35e407cc1..1ca76c7b2f 100644
--- a/activerecord/lib/active_record/observer.rb
+++ b/activerecord/lib/active_record/observer.rb
@@ -3,9 +3,7 @@ require 'set'
module ActiveRecord
module Observing # :nodoc:
- def self.included(base)
- base.extend ClassMethods
- end
+ extend ActiveSupport::DependencyModule
module ClassMethods
# Activates the observers assigned. Examples:
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index ec0175497d..3747ba449d 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -1,8 +1,6 @@
module ActiveRecord
module Reflection # :nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- end
+ extend ActiveSupport::DependencyModule
# Reflection allows you to interrogate Active Record classes and objects about their associations and aggregations.
# This information can, for example, be used in a form builder that took an Active Record object and created input
diff --git a/activerecord/lib/active_record/serializers/json_serializer.rb b/activerecord/lib/active_record/serializers/json_serializer.rb
index 48df15d2c0..d376fd5e1b 100644
--- a/activerecord/lib/active_record/serializers/json_serializer.rb
+++ b/activerecord/lib/active_record/serializers/json_serializer.rb
@@ -2,9 +2,10 @@ require 'active_support/json'
module ActiveRecord #:nodoc:
module Serialization
- def self.included(base)
- base.cattr_accessor :include_root_in_json, :instance_writer => false
- base.extend ClassMethods
+ extend ActiveSupport::DependencyModule
+
+ included do
+ cattr_accessor :include_root_in_json, :instance_writer => false
end
# Returns a JSON string representing the model. Some configuration is
diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb
index d9e1ef351f..3734e170af 100644
--- a/activerecord/lib/active_record/timestamp.rb
+++ b/activerecord/lib/active_record/timestamp.rb
@@ -8,12 +8,14 @@ module ActiveRecord
# Timestamps are in the local timezone by default but you can use UTC by setting
# ActiveRecord::Base.default_timezone = :utc
module Timestamp
- def self.included(base) #:nodoc:
- base.alias_method_chain :create, :timestamps
- base.alias_method_chain :update, :timestamps
+ extend ActiveSupport::DependencyModule
- base.class_inheritable_accessor :record_timestamps, :instance_writer => false
- base.record_timestamps = true
+ included do
+ alias_method_chain :create, :timestamps
+ alias_method_chain :update, :timestamps
+
+ class_inheritable_accessor :record_timestamps, :instance_writer => false
+ self.record_timestamps = true
end
# Saves the record with the updated_at/on attributes set to the current time.
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index b059eb7f6f..471a81dfb5 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -3,16 +3,14 @@ require 'thread'
module ActiveRecord
# See ActiveRecord::Transactions::ClassMethods for documentation.
module Transactions
+ extend ActiveSupport::DependencyModule
+
class TransactionError < ActiveRecordError # :nodoc:
end
- def self.included(base)
- base.extend(ClassMethods)
-
- base.class_eval do
- [:destroy, :save, :save!].each do |method|
- alias_method_chain method, :transactions
- end
+ included do
+ [:destroy, :save, :save!].each do |method|
+ alias_method_chain method, :transactions
end
end
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index e6b61e0b35..9907a3c9b7 100644
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -301,17 +301,16 @@ module ActiveRecord
#
# An Errors object is automatically created for every Active Record.
module Validations
+ extend ActiveSupport::DependencyModule
+
VALIDATIONS = %w( validate validate_on_create validate_on_update )
- def self.included(base) # :nodoc:
- base.extend ClassMethods
- base.class_eval do
- alias_method_chain :save, :validation
- alias_method_chain :save!, :validation
- end
+ included do
+ alias_method_chain :save, :validation
+ alias_method_chain :save!, :validation
- base.send :include, ActiveSupport::Callbacks
- base.define_callbacks *VALIDATIONS
+ include ActiveSupport::Callbacks
+ define_callbacks *VALIDATIONS
end
# Active Record classes can implement validations in several ways. The highest level, easiest to read,
diff --git a/activerecord/test/cases/associations/eager_load_nested_include_test.rb b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
index 677226ec89..5f824f9c74 100644
--- a/activerecord/test/cases/associations/eager_load_nested_include_test.rb
+++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
@@ -6,13 +6,12 @@ require 'models/category'
require 'models/categorization'
module Remembered
- def self.included(base)
- base.extend ClassMethods
- base.class_eval do
- after_create :remember
- protected
- def remember; self.class.remembered << self; end
- end
+ extend ActiveSupport::DependencyModule
+
+ included do
+ after_create :remember
+ protected
+ def remember; self.class.remembered << self; end
end
module ClassMethods
diff --git a/activerecord/test/cases/repair_helper.rb b/activerecord/test/cases/repair_helper.rb
index 0155668811..686bfee46d 100644
--- a/activerecord/test/cases/repair_helper.rb
+++ b/activerecord/test/cases/repair_helper.rb
@@ -1,11 +1,7 @@
module ActiveRecord
module Testing
module RepairHelper
- def self.included(base)
- base.class_eval do
- extend ClassMethods
- end
- end
+ extend ActiveSupport::DependencyModule
module Toolbox
def self.record_validations(*model_classes)
--
cgit v1.2.3
From 22c5667c2ef46d6723c1805d3adc52dc8e92429b Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Mon, 11 May 2009 19:49:11 -0700
Subject: Defer rake/contrib/sshpublisher require so we can use the stdlib rake
instead of the full gem
---
actionpack/Rakefile | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 18610ed773..ef76eedfd7 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -4,7 +4,6 @@ require 'rake/testtask'
require 'rake/rdoctask'
require 'rake/packagetask'
require 'rake/gempackagetask'
-require 'rake/contrib/sshpublisher'
require File.join(File.dirname(__FILE__), 'lib', 'action_pack', 'version')
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
@@ -143,12 +142,14 @@ task :update_js => [ :update_scriptaculous ]
desc "Publish the API documentation"
task :pgem => [:package] do
+ require 'rake/contrib/sshpublisher'
Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
`ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'`
end
desc "Publish the API documentation"
task :pdoc => [:rdoc] do
+ require 'rake/contrib/sshpublisher'
Rake::SshDirPublisher.new("wrath.rubyonrails.org", "public_html/ap", "doc").upload
end
--
cgit v1.2.3
From 72ca7c591c9eace150c0ebab1633d691a1ef12cf Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Tue, 12 May 2009 10:53:00 -0700
Subject: Fixed new callbacks to not call the action when a callback sets the
response body
---
.../lib/action_controller/abstract/callbacks.rb | 2 +-
actionpack/test/abstract_controller/callbacks_test.rb | 19 +++++++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb
index 6e15b3e81b..3aff83a209 100644
--- a/actionpack/lib/action_controller/abstract/callbacks.rb
+++ b/actionpack/lib/action_controller/abstract/callbacks.rb
@@ -5,7 +5,7 @@ module AbstractController
depends_on ActiveSupport::NewCallbacks
included do
- define_callbacks :process_action
+ define_callbacks :process_action, "response_body"
end
def process_action
diff --git a/actionpack/test/abstract_controller/callbacks_test.rb b/actionpack/test/abstract_controller/callbacks_test.rb
index 410b1e57a6..1de60868c3 100644
--- a/actionpack/test/abstract_controller/callbacks_test.rb
+++ b/actionpack/test/abstract_controller/callbacks_test.rb
@@ -193,5 +193,24 @@ module AbstractController
end
end
+ class SetsResponseBody < ControllerWithCallbacks
+ before_filter :set_body
+
+ def index
+ self.response_body = "Fail"
+ end
+
+ def set_body
+ self.response_body = "Success"
+ end
+ end
+
+ class TestHalting < ActiveSupport::TestCase
+ test "when a callback sets the response body, the action should not be invoked" do
+ result = SetsResponseBody.process(:index)
+ assert_equal "Success", result.response_body
+ end
+ end
+
end
end
\ No newline at end of file
--
cgit v1.2.3
From 216309c16519d94a9e0aebf758029a78696ab8d6 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Tue, 12 May 2009 16:21:34 -0700
Subject: Implemented redirects and partial rendering in new base.
---
actionpack/lib/action_controller/abstract/base.rb | 10 +++
.../lib/action_controller/abstract/layouts.rb | 2 +-
.../lib/action_controller/abstract/renderer.rb | 29 ++++----
actionpack/lib/action_controller/base/redirect.rb | 4 +-
actionpack/lib/action_controller/new_base.rb | 1 +
actionpack/lib/action_controller/new_base/base.rb | 79 ++++++++++++++++++++--
.../action_controller/new_base/compatibility.rb | 42 ++++++++----
actionpack/lib/action_controller/new_base/http.rb | 6 ++
.../lib/action_controller/new_base/layouts.rb | 2 +-
.../lib/action_controller/new_base/redirector.rb | 19 ++++++
.../lib/action_controller/new_base/renderer.rb | 27 ++++++--
.../lib/action_controller/testing/process.rb | 10 +--
.../lib/action_controller/testing/process2.rb | 1 +
actionpack/lib/action_dispatch/http/response.rb | 6 --
actionpack/lib/action_view/render/partials.rb | 32 +++++----
actionpack/lib/action_view/render/rendering.rb | 5 ++
actionpack/test/abstract_unit.rb | 4 ++
actionpack/test/abstract_unit2.rb | 69 ++++++++++---------
actionpack/test/controller/render_test.rb | 4 +-
actionpack/test/new_base/redirect_test.rb | 1 +
20 files changed, 251 insertions(+), 102 deletions(-)
create mode 100644 actionpack/lib/action_controller/new_base/redirector.rb
create mode 100644 actionpack/test/new_base/redirect_test.rb
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index ab9aed0b26..c9e1081b23 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -1,4 +1,14 @@
module AbstractController
+ class Error < StandardError; end
+
+ class DoubleRenderError < Error
+ DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"."
+
+ def initialize(message = nil)
+ super(message || DEFAULT_MESSAGE)
+ end
+ end
+
class Base
attr_internal :response_body
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index e48b8b2b4b..35d5e85ed9 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -51,7 +51,7 @@ module AbstractController
end
def _render_template(template, options)
- _action_view._render_template_with_layout(template, options[:_layout], options)
+ _action_view._render_template_from_controller(template, options[:_layout], options, options[:_partial])
end
private
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index b58688c9da..f2044a35ec 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -1,15 +1,6 @@
require "action_controller/abstract/logger"
module AbstractController
- class AbstractControllerError < StandardError; end
- class DoubleRenderError < AbstractControllerError
- DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"."
-
- def initialize(message = nil)
- super(message || DEFAULT_MESSAGE)
- end
- end
-
module Renderer
extend ActiveSupport::DependencyModule
@@ -27,12 +18,12 @@ module AbstractController
@_action_view ||= ActionView::Base.new(self.class.view_paths, {}, self)
end
- def render(options = {})
+ def render(*args)
if response_body
raise AbstractController::DoubleRenderError, "OMG"
end
- self.response_body = render_to_body(options)
+ self.response_body = render_to_body(*args)
end
# Raw rendering of a template to a Rack-compatible body.
@@ -43,10 +34,16 @@ module AbstractController
# :api: plugin
def render_to_body(options = {})
name = options[:_template_name] || action_name
-
- options[:_template] ||= view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix])
-
- _render_template(options[:_template], options)
+
+ # TODO: Refactor so we can just use the normal template logic for this
+ if options[:_partial_object]
+ _action_view._render_partial_from_controller(options)
+ else
+ options[:_template] ||= view_paths.find_by_parts(name.to_s, {:formats => formats},
+ options[:_prefix], options[:_partial])
+
+ _render_template(options[:_template], options)
+ end
end
# Raw rendering of a template to a string.
@@ -60,7 +57,7 @@ module AbstractController
end
def _render_template(template, options)
- _action_view._render_template_with_layout(template)
+ _action_view._render_template_from_controller(template, nil, options, options[:_partial])
end
def view_paths() _view_paths end
diff --git a/actionpack/lib/action_controller/base/redirect.rb b/actionpack/lib/action_controller/base/redirect.rb
index 4849caac0a..7e10f614e2 100644
--- a/actionpack/lib/action_controller/base/redirect.rb
+++ b/actionpack/lib/action_controller/base/redirect.rb
@@ -70,7 +70,9 @@ module ActionController
def redirect_to_full_url(url, status)
raise DoubleRenderError if performed?
logger.info("Redirected to #{url}") if logger && logger.info?
- response.redirect(url, interpret_status(status))
+ response.status = interpret_status(status)
+ response.location = url.gsub(/[\r\n]/, '')
+ response.body = "You are being redirected ."
@performed_redirect = true
end
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 8a7de1476c..1f215bb6f1 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -5,6 +5,7 @@ module ActionController
autoload :Http, "action_controller/new_base/http"
autoload :Layouts, "action_controller/new_base/layouts"
autoload :Rails2Compatibility, "action_controller/new_base/compatibility"
+ autoload :Redirector, "action_controller/new_base/redirector"
autoload :Renderer, "action_controller/new_base/renderer"
autoload :Testing, "action_controller/new_base/testing"
autoload :UrlFor, "action_controller/new_base/url_for"
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 4892886341..1adcc9c71f 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -8,6 +8,7 @@ module ActionController
include ActionController::HideActions
include ActionController::UrlFor
+ include ActionController::Redirector
include ActionController::Renderer
include ActionController::Layouts
include ActionController::ConditionalGet
@@ -34,19 +35,83 @@ module ActionController
end
end
- def render(action = action_name, options = {})
+ def render_to_body(action = nil, options = {})
if action.is_a?(Hash)
options, action = action, nil
- else
- options.merge! :action => action
+ elsif action.is_a?(String) || action.is_a?(Symbol)
+ key = case action = action.to_s
+ when %r{^/} then :file
+ when %r{/} then :template
+ else :action
+ end
+ options.merge! key => action
+ elsif action
+ options.merge! :partial => action
+ end
+
+ if options.key?(:action) && options[:action].to_s.index("/")
+ options[:template] = options.delete(:action)
end
- super(options)
+ # options = {:template => options.to_s} if options.is_a?(String) || options.is_a?(Symbol)
+ super(options) || " "
end
- def render_to_body(options = {})
- options = {:template => options} if options.is_a?(String)
- super
+ # Redirects the browser to the target specified in +options+. This parameter can take one of three forms:
+ #
+ # * Hash - The URL will be generated by calling url_for with the +options+.
+ # * Record - The URL will be generated by calling url_for with the +options+, which will reference a named URL for that record.
+ # * String starting with protocol:// (like http:// ) - Is passed straight through as the target for redirection.
+ # * String not containing a protocol - The current protocol and host is prepended to the string.
+ # * :back - Back to the page that issued the request. Useful for forms that are triggered from multiple places.
+ # Short-hand for redirect_to(request.env["HTTP_REFERER"])
+ #
+ # Examples:
+ # redirect_to :action => "show", :id => 5
+ # redirect_to post
+ # redirect_to "http://www.rubyonrails.org"
+ # redirect_to "/images/screenshot.jpg"
+ # redirect_to articles_url
+ # redirect_to :back
+ #
+ # The redirection happens as a "302 Moved" header unless otherwise specified.
+ #
+ # Examples:
+ # redirect_to post_url(@post), :status=>:found
+ # redirect_to :action=>'atom', :status=>:moved_permanently
+ # redirect_to post_url(@post), :status=>301
+ # redirect_to :action=>'atom', :status=>302
+ #
+ # When using redirect_to :back , if there is no referrer,
+ # RedirectBackError will be raised. You may specify some fallback
+ # behavior for this case by rescuing RedirectBackError.
+ def redirect_to(options = {}, response_status = {}) #:doc:
+ raise ActionControllerError.new("Cannot redirect to nil!") if options.nil?
+
+ status = if options.is_a?(Hash) && options.key?(:status)
+ interpret_status(options.delete(:status))
+ elsif response_status.key?(:status)
+ interpret_status(response_status[:status])
+ else
+ 302
+ end
+
+ url = case options
+ # The scheme name consist of a letter followed by any combination of
+ # letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
+ # characters; and is terminated by a colon (":").
+ when %r{^\w[\w\d+.-]*:.*}
+ options
+ when String
+ request.protocol + request.host_with_port + options
+ when :back
+ raise RedirectBackError unless refer = request.headers["Referer"]
+ refer
+ else
+ url_for(options)
+ end
+
+ super(url, status)
end
def process_action
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index 4655a94923..d17f498b60 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -8,27 +8,40 @@ module ActionController
::ActionController::DoubleRenderError = ::AbstractController::DoubleRenderError
cattr_accessor :session_options
- self.send(:class_variable_set, "@@session_options", {})
+ self.session_options = {}
cattr_accessor :allow_concurrency
- self.send(:class_variable_set, "@@allow_concurrency", false)
+ self.allow_concurrency = false
cattr_accessor :param_parsers
- self.send(:class_variable_set, "@@param_parsers", { Mime::MULTIPART_FORM => :multipart_form,
- Mime::URL_ENCODED_FORM => :url_encoded_form,
- Mime::XML => :xml_simple,
- Mime::JSON => :json })
+ self.param_parsers = { Mime::MULTIPART_FORM => :multipart_form,
+ Mime::URL_ENCODED_FORM => :url_encoded_form,
+ Mime::XML => :xml_simple,
+ Mime::JSON => :json }
cattr_accessor :relative_url_root
- self.send(:class_variable_set, "@@relative_url_root", ENV['RAILS_RELATIVE_URL_ROOT'])
+ self.relative_url_root = ENV['RAILS_RELATIVE_URL_ROOT']
cattr_accessor :default_charset
- self.send(:class_variable_set, "@@default_charset", "utf-8")
+ self.default_charset = "utf-8"
- cattr_reader :protected_instance_variables
- self.send(:class_variable_set, "@@protected_instance_variables", %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller
+ # cattr_reader :protected_instance_variables
+ cattr_accessor :protected_instance_variables
+ self.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 @_headers @_params
- @_flash @_response))
+ @_flash @_response)
+
+ # Indicates whether or not optimise the generated named
+ # route helper methods
+ cattr_accessor :optimise_named_routes
+ self.optimise_named_routes = true
+
+ cattr_accessor :resources_path_names
+ self.resources_path_names = { :new => 'new', :edit => 'edit' }
+
+ # Controls the resource action separator
+ cattr_accessor :resource_action_separator
+ self.resource_action_separator = "/"
end
module ClassMethods
@@ -38,7 +51,12 @@ module ActionController
raise env["action_dispatch.rescue.exception"]
end
end
-
+
+ def initialize(*)
+ super
+ @template = _action_view
+ end
+
def render_to_body(options)
if options.is_a?(Hash) && options.key?(:template)
options[:template].sub!(/^\//, '')
diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb
index f269fe70db..fb6041a04e 100644
--- a/actionpack/lib/action_controller/new_base/http.rb
+++ b/actionpack/lib/action_controller/new_base/http.rb
@@ -38,6 +38,12 @@ module ActionController
controller.call(env).to_rack
end
+ delegate :headers, :to => "@_response"
+
+ def params
+ @_params ||= @_request.parameters
+ end
+
# :api: private
def call(name, env)
@_request = ActionDispatch::Request.new(env)
diff --git a/actionpack/lib/action_controller/new_base/layouts.rb b/actionpack/lib/action_controller/new_base/layouts.rb
index e851eb5f9a..bf5b14c4e1 100644
--- a/actionpack/lib/action_controller/new_base/layouts.rb
+++ b/actionpack/lib/action_controller/new_base/layouts.rb
@@ -15,7 +15,7 @@ module ActionController
# render :text => ..., :layout => ...
# or
# render :anything_else
- if (!options.key?(:text) && !options.key?(:inline)) || options.key?(:layout)
+ if (!options.key?(:text) && !options.key?(:inline) && !options.key?(:partial)) || options.key?(:layout)
options[:_layout] = options.key?(:layout) ? _layout_for_option(options[:layout]) : _default_layout
end
diff --git a/actionpack/lib/action_controller/new_base/redirector.rb b/actionpack/lib/action_controller/new_base/redirector.rb
new file mode 100644
index 0000000000..ff7b74341c
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/redirector.rb
@@ -0,0 +1,19 @@
+module ActionController
+ class RedirectBackError < AbstractController::Error #:nodoc:
+ DEFAULT_MESSAGE = 'No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify request.env["HTTP_REFERER"].'
+
+ def initialize(message = nil)
+ super(message || DEFAULT_MESSAGE)
+ end
+ end
+
+ module Redirector
+ def redirect_to(url, status) #:doc:
+ raise AbstractController::DoubleRenderError if response_body
+ logger.info("Redirected to #{url}") if logger && logger.info?
+ response.status = status
+ response.location = url.gsub(/[\r\n]/, '')
+ self.response_body = "You are being redirected ."
+ end
+ end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 41e3dfbe23..8a9f230603 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -9,13 +9,9 @@ module ActionController
super
end
- def render(options = {})
+ def render_to_body(options)
_process_options(options)
- super(options)
- end
-
- def render_to_body(options)
if options.key?(:text)
options[:_template] = ActionView::TextTemplate.new(_text(options))
template = nil
@@ -25,12 +21,18 @@ module ActionController
options[:_template] = template
elsif options.key?(:template)
options[:_template_name] = options[:template]
+ elsif options.key?(:file)
+ options[:_template_name] = options[:file]
+ elsif options.key?(:partial)
+ _render_partial(options[:partial], options)
else
options[:_template_name] = (options[:action] || action_name).to_s
options[:_prefix] = _prefix
end
ret = super(options)
+
+ options[:_template] ||= _action_view._partial
response.content_type ||= options[:_template].mime_type
ret
end
@@ -49,6 +51,21 @@ module ActionController
else text.to_s
end
end
+
+ def _render_partial(partial, options)
+ case partial
+ when true
+ options[:_prefix] = _prefix
+ when String
+ options[:_prefix] = _prefix unless partial.index('/')
+ options[:_template_name] = partial
+ else
+ options[:_partial_object] = true
+ return
+ end
+
+ options[:_partial] = options[:object] || true
+ end
def _process_options(options)
status, content_type = options.values_at(:status, :content_type)
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 21023ac101..936f97ecb5 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -161,11 +161,13 @@ module ActionController #:nodoc:
alias xhr :xml_http_request
def assigns(key = nil)
- if key.nil?
- @controller.template.assigns
- else
- @controller.template.assigns[key.to_s]
+ assigns = {}
+ @controller.instance_variable_names.each do |ivar|
+ next if ActionController::Base.protected_instance_variables.include?(ivar)
+ assigns[ivar[1..-1]] = @controller.instance_variable_get(ivar)
end
+
+ key.nil? ? assigns : assigns[key.to_s]
end
def session
diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb
index 18b7335450..e9a79369b9 100644
--- a/actionpack/lib/action_controller/testing/process2.rb
+++ b/actionpack/lib/action_controller/testing/process2.rb
@@ -50,6 +50,7 @@ module ActionController
@request.session = ActionController::TestSession.new(session) unless session.nil?
@request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash
build_request_uri(action, parameters)
+ @controller.request = @request
@controller.params.merge!(parameters)
# Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
@controller.process_with_test(@request, @response)
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 133b4f7335..c3b5a68f40 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -156,12 +156,6 @@ module ActionDispatch # :nodoc:
end
end
- def redirect(url, status)
- self.status = status
- self.location = url.gsub(/[\r\n]/, '')
- self.body = "You are being redirected ."
- end
-
def sending_file?
headers["Content-Transfer-Encoding"] == "binary"
end
diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb
index 43f8a1edf8..f2429e8cef 100644
--- a/actionpack/lib/action_view/render/partials.rb
+++ b/actionpack/lib/action_view/render/partials.rb
@@ -171,11 +171,21 @@ module ActionView
# <% end %>
module Partials
extend ActiveSupport::Memoizable
+ extend ActiveSupport::DependencyModule
+
+ included do
+ attr_accessor :_partial
+ end
+
+ def _render_partial_from_controller(*args)
+ @assigns_added = false
+ _render_partial(*args)
+ end
def _render_partial(options = {}) #:nodoc:
options[:locals] ||= {}
- case path = partial = options[:partial]
+ case path = partial = options[:partial]
when *_array_like_objects
return _render_partial_collection(partial, options)
else
@@ -222,16 +232,7 @@ module ActionView
ensure
@_proc_for_layout = nil
end
-
- def _render_partial_with_layout(layout, options)
- if layout
- prefix = controller && !layout.include?("/") ? controller.controller_path : nil
- layout = find_by_parts(layout, {:formats => formats}, prefix, true)
- end
- content = _render_partial(options)
- return _render_content_with_layout(content, layout, options[:locals])
- end
-
+
def _deprecated_ivar_assign(template)
if respond_to?(:controller)
ivar = :"@#{template.variable_name}"
@@ -287,13 +288,17 @@ module ActionView
locals = (options[:locals] ||= {})
object ||= locals[:object] || locals[template.variable_name]
- _set_locals(object, locals, template, options)
+ _set_locals(object, locals, template, options)
+
+ self._partial = template
+
_render_template(template, locals)
end
end
def _set_locals(object, locals, template, options)
object ||= _deprecated_ivar_assign(template)
+
locals[:object] = locals[template.variable_name] = object
locals[options[:as]] = object if options[:as]
end
@@ -316,6 +321,9 @@ module ActionView
locals[template.counter_name] = index
index += 1
+
+ self._partial = template
+
_render_template(template, locals)
end.join(spacer)
end
diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb
index 6e368f27eb..fe785e7b20 100644
--- a/actionpack/lib/action_view/render/rendering.rb
+++ b/actionpack/lib/action_view/render/rendering.rb
@@ -95,6 +95,11 @@ module ActionView
layout ? _render_content_with_layout(text, layout, options[:locals]) : text
end
+ def _render_template_from_controller(*args)
+ @assigns_added = nil
+ _render_template_with_layout(*args)
+ end
+
def _render_template_with_layout(template, layout = nil, options = {}, partial = false)
if controller && logger
logger.info("Rendering #{template.identifier}" +
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index b07e6e5f3a..825ac9a46c 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -1,3 +1,6 @@
+if ENV["new_base"]
+ require "abstract_unit2"
+else
$:.unshift(File.dirname(__FILE__) + '/../lib')
$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
$:.unshift(File.dirname(__FILE__) + '/fixtures/helpers')
@@ -38,3 +41,4 @@ ORIGINAL_LOCALES = I18n.available_locales.map(&:to_s).sort
FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
ActionController::Base.view_paths = FIXTURE_LOAD_PATH
+end
\ No newline at end of file
diff --git a/actionpack/test/abstract_unit2.rb b/actionpack/test/abstract_unit2.rb
index 95e7b2e273..2fdaba7342 100644
--- a/actionpack/test/abstract_unit2.rb
+++ b/actionpack/test/abstract_unit2.rb
@@ -75,7 +75,7 @@ module ActionController
end
class Base
- use ActionController::Testing
+ include ActionController::Testing
end
Base.view_paths = FIXTURE_LOAD_PATH
@@ -89,43 +89,42 @@ module ActionController
end
def assert_template(options = {}, message = nil)
- validate_response!
-
- clean_backtrace do
- case options
- when NilClass, String
- hax = @controller._action_view.instance_variable_get(:@_rendered)
- rendered = (hax[:template] || []).map { |t| t.identifier }
- msg = build_message(message,
- "expecting > but rendering with >",
- options, rendered.join(', '))
- assert_block(msg) do
- if options.nil?
- hax[:template].blank?
- else
- rendered.any? { |t| t.match(options) }
- end
+ validate_request!
+
+ hax = @controller._action_view.instance_variable_get(:@_rendered)
+
+ case options
+ when NilClass, String
+ rendered = (hax[:template] || []).map { |t| t.identifier }
+ msg = build_message(message,
+ "expecting > but rendering with >",
+ options, rendered.join(', '))
+ assert_block(msg) do
+ if options.nil?
+ hax[:template].blank?
+ else
+ rendered.any? { |t| t.match(options) }
end
- when Hash
- if expected_partial = options[:partial]
- partials = hax[:partials]
- if expected_count = options[:count]
- 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)",
- expected_partial, expected_count, actual_count)
- assert(actual_count == expected_count.to_i, msg)
- else
- msg = build_message(message,
- "expecting partial > but action rendered >",
- options[:partial], partials.keys)
- assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg)
- end
+ end
+ when Hash
+ if expected_partial = options[:partial]
+ partials = hax[:partials]
+ if expected_count = options[:count]
+ 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)",
+ expected_partial, expected_count, actual_count)
+ assert(actual_count == expected_count.to_i, msg)
else
- assert hax[:partials].empty?,
- "Expected no partials to be rendered"
+ msg = build_message(message,
+ "expecting partial > but action rendered >",
+ options[:partial], partials.keys)
+ assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg)
end
+ else
+ assert hax[:partials].empty?,
+ "Expected no partials to be rendered"
end
end
end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index a58d9b08b5..4cea050a1e 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -1,4 +1,4 @@
-require ENV['new_base'] ? 'abstract_unit2' : 'abstract_unit'
+require 'abstract_unit'
require 'controller/fake_models'
require 'pathname'
@@ -1647,7 +1647,7 @@ class EtagRenderTest < ActionController::TestCase
def test_render_against_etag_request_should_304_when_match
@request.if_none_match = etag_for("hello david")
get :render_hello_world_from_variable
- assert_equal 304, @response.status
+ assert_equal 304, @response.status.to_i
assert @response.body.empty?
end
diff --git a/actionpack/test/new_base/redirect_test.rb b/actionpack/test/new_base/redirect_test.rb
new file mode 100644
index 0000000000..e591ebd05f
--- /dev/null
+++ b/actionpack/test/new_base/redirect_test.rb
@@ -0,0 +1 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
\ No newline at end of file
--
cgit v1.2.3
From 4c963972fd0fb696e857540351f7558f027ec962 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Tue, 12 May 2009 14:21:29 -0700
Subject: Defer rake/contrib requires so we can use the stdlib rake instead of
the full gem
---
Rakefile | 2 +-
railties/Rakefile | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/Rakefile b/Rakefile
index 8f4c891074..b3f7c8b642 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,6 +1,5 @@
require 'rake'
require 'rake/rdoctask'
-require 'rake/contrib/sshpublisher'
env = %(PKG_BUILD="#{ENV['PKG_BUILD']}") if ENV['PKG_BUILD']
@@ -74,6 +73,7 @@ end
desc "Publish API docs for Rails as a whole and for each component"
task :pdoc => :rdoc do
+ require 'rake/contrib/sshpublisher'
Rake::SshDirPublisher.new("wrath.rubyonrails.org", "public_html/api", "doc/rdoc").upload
PROJECTS.each do |project|
system %(cd #{project} && #{env} #{$0} pdoc)
diff --git a/railties/Rakefile b/railties/Rakefile
index 4247742664..7637293007 100644
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -2,7 +2,6 @@ require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'
require 'rake/gempackagetask'
-require 'rake/contrib/rubyforgepublisher'
require 'date'
require 'rbconfig'
@@ -344,12 +343,14 @@ end
# Publishing -------------------------------------------------------
desc "Publish the rails gem"
task :pgem => [:gem] do
+ require 'rake/contrib/sshpublisher'
Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
`ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'`
end
desc "Publish the guides"
task :pguides => :guides do
+ require 'rake/contrib/sshpublisher'
mkdir_p 'pkg'
`tar -czf pkg/guides.gz guides/output`
Rake::SshFilePublisher.new("web.rubyonrails.org", "/u/sites/guides.rubyonrails.org/public", "pkg", "guides.gz").upload
@@ -358,6 +359,7 @@ end
desc "Publish the release files to RubyForge."
task :release => [ :package ] do
+ require 'rake/contrib/rubyforgepublisher'
require 'rubyforge'
packages = %w( gem ).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" }
--
cgit v1.2.3
From e9c5750bd1bb15b2d551ee014f06bd5019f2357d Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Tue, 12 May 2009 17:55:45 -0700
Subject: Preserve ordering
---
tools/profile_requires | 81 +++++++++++++++++++++++++++++++++++++++++++++++
tools/profile_requires.rb | 75 -------------------------------------------
2 files changed, 81 insertions(+), 75 deletions(-)
create mode 100755 tools/profile_requires
delete mode 100644 tools/profile_requires.rb
diff --git a/tools/profile_requires b/tools/profile_requires
new file mode 100755
index 0000000000..be7770b3e5
--- /dev/null
+++ b/tools/profile_requires
@@ -0,0 +1,81 @@
+#!/usr/bin/env ruby
+# Example:
+# ruby -Iactivesupport/lib tools/profile_requires.rb active_support
+# ruby -Iactionpack/lib tools/profile_requires.rb action_controller
+abort 'Use REE so you can profile memory and object allocation' unless GC.respond_to?(:enable_stats)
+
+GC.enable_stats
+require 'rubygems'
+Gem.source_index
+require 'benchmark'
+
+module TrackHeapGrowth
+ class << self
+ attr_accessor :indent
+ attr_accessor :stats
+ end
+ self.indent = 0
+ self.stats = []
+
+ def track_growth(file)
+ TrackHeapGrowth.stats << [file, TrackHeapGrowth.indent]
+ TrackHeapGrowth.indent += 1
+ heap_before, objects_before = GC.allocated_size, ObjectSpace.allocated_objects
+ result = nil
+ elapsed = Benchmark.realtime { result = yield }
+ heap_after, objects_after = GC.allocated_size, ObjectSpace.allocated_objects
+ TrackHeapGrowth.indent -= 1
+ TrackHeapGrowth.stats.pop if TrackHeapGrowth.stats.last.first == file
+ TrackHeapGrowth.stats << [file, TrackHeapGrowth.indent, elapsed, heap_after - heap_before, objects_after - objects_before] if result
+ result
+ end
+
+ def require(file, *args)
+ track_growth(file) { super }
+ end
+
+ def load(file, *args)
+ track_growth(file) { super }
+ end
+end
+
+Object.instance_eval { include TrackHeapGrowth }
+
+GC.start
+before = GC.allocated_size
+before_rss = `ps -o rss= -p #{Process.pid}`.to_i
+before_live_objects = ObjectSpace.live_objects
+
+path = ARGV.shift
+
+if mode = ARGV.shift
+ require 'ruby-prof'
+ RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
+ RubyProf.start
+end
+
+ENV['NO_RELOAD'] ||= '1'
+ENV['RAILS_ENV'] ||= 'development'
+elapsed = Benchmark.realtime { require path }
+results = RubyProf.stop if mode
+
+GC.start
+after_live_objects = ObjectSpace.live_objects
+after_rss = `ps -o rss= -p #{Process.pid}`.to_i
+after = GC.allocated_size
+usage = (after - before) / 1024.0
+
+if mode
+ File.open("profile_startup.#{mode}.tree", 'w') do |out|
+ RubyProf::CallTreePrinter.new(results).print(out)
+ end
+end
+
+TrackHeapGrowth.stats.each do |file, indent, sec, bytes, objects|
+ if sec
+ puts "%10.2f KB %10d obj %8.1f ms %s%s" % [bytes / 1024.0, objects, sec * 1000, ' ' * indent, file]
+ else
+ puts "#{' ' * (42 + indent)}#{file}"
+ end
+end
+puts "%10.2f KB %10d obj %8.1f ms %d KB RSS" % [usage, after_live_objects - before_live_objects, elapsed * 1000, after_rss - before_rss]
diff --git a/tools/profile_requires.rb b/tools/profile_requires.rb
deleted file mode 100644
index 68d0de3d80..0000000000
--- a/tools/profile_requires.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env ruby
-# Example:
-# ruby -Iactivesupport/lib tools/profile_requires.rb active_support
-# ruby -Iactionpack/lib tools/profile_requires.rb action_controller
-abort 'Use REE so you can profile memory and object allocation' unless GC.respond_to?(:enable_stats)
-
-GC.enable_stats
-require 'rubygems'
-Gem.source_index
-require 'benchmark'
-
-module TrackHeapGrowth
- class << self
- attr_accessor :indent
- attr_accessor :stats
- end
- self.indent = 0
- self.stats = []
-
- def track_growth(file)
- TrackHeapGrowth.indent += 1
- heap_before, objects_before = GC.allocated_size, ObjectSpace.allocated_objects
- result = nil
- elapsed = Benchmark.realtime { result = yield }
- heap_after, objects_after = GC.allocated_size, ObjectSpace.allocated_objects
- TrackHeapGrowth.indent -= 1
- TrackHeapGrowth.stats << [file, TrackHeapGrowth.indent, elapsed, heap_after - heap_before, objects_after - objects_before] if result
- result
- end
-
- def require(file, *args)
- track_growth(file) { super }
- end
-
- def load(file, *args)
- track_growth(file) { super }
- end
-end
-
-Object.instance_eval { include TrackHeapGrowth }
-
-GC.start
-before = GC.allocated_size
-before_rss = `ps -o rss= -p #{Process.pid}`.to_i
-before_live_objects = ObjectSpace.live_objects
-
-path = ARGV.shift
-
-if mode = ARGV.shift
- require 'ruby-prof'
- RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
- RubyProf.start
-end
-
-ENV['NO_RELOAD'] ||= '1'
-ENV['RAILS_ENV'] ||= 'development'
-elapsed = Benchmark.realtime { require path }
-results = RubyProf.stop if mode
-
-GC.start
-after_live_objects = ObjectSpace.live_objects
-after_rss = `ps -o rss= -p #{Process.pid}`.to_i
-after = GC.allocated_size
-usage = (after - before) / 1024.0
-
-if mode
- File.open("profile_startup.#{mode}.tree", 'w') do |out|
- RubyProf::CallTreePrinter.new(results).print(out)
- end
-end
-
-TrackHeapGrowth.stats.reverse_each do |file, indent, sec, bytes, objects|
- puts "%10.2f KB %10d obj %8.1f ms %s%s" % [bytes / 1024.0, objects, sec * 1000, ' ' * indent, file]
-end
-puts "%10.2f KB %10d obj %8.1f ms %d KB RSS" % [usage, after_live_objects - before_live_objects, elapsed * 1000, after_rss - before_rss]
--
cgit v1.2.3
From a7ccc7c79fa69cea3b7d19bcaa4df3c2932238d8 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Tue, 12 May 2009 17:58:37 -0700
Subject: Remove support for deprecated validation message interpolation format
---
activerecord/lib/active_record.rb | 1 -
.../i18n_interpolation_deprecation.rb | 26 -----------------
activerecord/test/cases/validations_i18n_test.rb | 34 +++++-----------------
3 files changed, 8 insertions(+), 53 deletions(-)
delete mode 100644 activerecord/lib/active_record/i18n_interpolation_deprecation.rb
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 06d6c87090..c9e9a84ce7 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -75,5 +75,4 @@ module ActiveRecord
end
end
-require 'active_record/i18n_interpolation_deprecation'
I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
diff --git a/activerecord/lib/active_record/i18n_interpolation_deprecation.rb b/activerecord/lib/active_record/i18n_interpolation_deprecation.rb
deleted file mode 100644
index cd634e1b8d..0000000000
--- a/activerecord/lib/active_record/i18n_interpolation_deprecation.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# Deprecates the use of the former message interpolation syntax in activerecord
-# as in "must have %d characters". The new syntax uses explicit variable names
-# as in "{{value}} must have {{count}} characters".
-
-require 'i18n/backend/simple'
-module I18n
- module Backend
- class Simple
- DEPRECATED_INTERPOLATORS = { '%d' => '{{count}}', '%s' => '{{value}}' }
-
- protected
- def interpolate_with_deprecated_syntax(locale, string, values = {})
- return string unless string.is_a?(String)
-
- string = string.gsub(/%d|%s/) do |s|
- instead = DEPRECATED_INTERPOLATORS[s]
- ActiveSupport::Deprecation.warn "using #{s} in messages is deprecated; use #{instead} instead."
- instead
- end
-
- interpolate_without_deprecated_syntax(locale, string, values)
- end
- alias_method_chain :interpolate, :deprecated_syntax
- end
- end
-end
\ No newline at end of file
diff --git a/activerecord/test/cases/validations_i18n_test.rb b/activerecord/test/cases/validations_i18n_test.rb
index 66982346e9..20d1369a64 100644
--- a/activerecord/test/cases/validations_i18n_test.rb
+++ b/activerecord/test/cases/validations_i18n_test.rb
@@ -38,35 +38,17 @@ class ActiveRecordValidationsI18nTests < ActiveSupport::TestCase
end
end
- def test_default_error_messages_is_deprecated
- assert_deprecated('ActiveRecord::Errors.default_error_messages') do
- ActiveRecord::Errors.default_error_messages
+ def test_percent_s_interpolation_syntax_in_error_messages_was_deprecated
+ assert_not_deprecated do
+ default = "%s interpolation syntax was deprecated"
+ assert_equal default, I18n.t(:does_not_exist, :default => default, :value => 'this')
end
end
- def test_percent_s_interpolation_syntax_in_error_messages_still_works
- ActiveSupport::Deprecation.silence do
- result = I18n.t :does_not_exist, :default => "%s interpolation syntax is deprecated", :value => 'this'
- assert_equal result, "this interpolation syntax is deprecated"
- end
- end
-
- def test_percent_s_interpolation_syntax_in_error_messages_is_deprecated
- assert_deprecated('using %s in messages') do
- I18n.t :does_not_exist, :default => "%s interpolation syntax is deprected", :value => 'this'
- end
- end
-
- def test_percent_d_interpolation_syntax_in_error_messages_still_works
- ActiveSupport::Deprecation.silence do
- result = I18n.t :does_not_exist, :default => "%d interpolation syntaxes are deprecated", :count => 2
- assert_equal result, "2 interpolation syntaxes are deprecated"
- end
- end
-
- def test_percent_d_interpolation_syntax_in_error_messages_is_deprecated
- assert_deprecated('using %d in messages') do
- I18n.t :does_not_exist, :default => "%d interpolation syntaxes are deprected", :count => 2
+ def test_percent_d_interpolation_syntax_in_error_messages_was_deprecated
+ assert_not_deprecated do
+ default = "%d interpolation syntaxes are deprecated"
+ assert_equal default, I18n.t(:does_not_exist, :default => default, :count => 2)
end
end
--
cgit v1.2.3
From fa5da8ad54d68ea0484825845eb6f6a8e8bca361 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 13 May 2009 01:06:53 -0700
Subject: isolated_test task
---
actionpack/Rakefile | 6 ++++++
activerecord/Rakefile | 20 ++++++++++++++------
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index ef76eedfd7..6ce8179646 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -34,6 +34,12 @@ Rake::TestTask.new(:test_action_pack) do |t|
t.verbose = true
#t.warning = true
end
+task :isolated_test do
+ ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
+ Dir.glob("test/{controller,dispatch,template}/**/*_test.rb").all? do |file|
+ system(ruby, '-Ilib:test', file)
+ end or raise "Failures"
+end
desc 'ActiveRecord Integration Tests'
Rake::TestTask.new(:test_active_record_integration) do |t|
diff --git a/activerecord/Rakefile b/activerecord/Rakefile
index 5905c67e29..892d52f30d 100644
--- a/activerecord/Rakefile
+++ b/activerecord/Rakefile
@@ -33,20 +33,28 @@ task :test => defined?(JRUBY_VERSION) ?
%w(test_jdbcmysql test_jdbcsqlite3 test_jdbcpostgresql) :
%w(test_mysql test_sqlite3 test_postgresql)
-for adapter in %w( mysql postgresql sqlite sqlite3 firebird db2 oracle sybase openbase frontbase jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb )
+%w( mysql postgresql sqlite sqlite3 firebird db2 oracle sybase openbase frontbase jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb ).each do |adapter|
Rake::TestTask.new("test_#{adapter}") { |t|
- if adapter =~ /jdbc/
- t.libs << "test" << "test/connections/jdbc_#{adapter}"
- else
- t.libs << "test" << "test/connections/native_#{adapter}"
- end
+ connection_path = "test/connections/#{adapter =~ /jdbc/ ? 'jdbc' : 'native'}_#{adapter}"
adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z]+/]
+ t.libs << "test" << connection_path
t.test_files=Dir.glob( "test/cases/**/*_test{,_#{adapter_short}}.rb" ).sort
t.verbose = true
}
+ task "isolated_test_#{adapter}" do
+ connection_path = "test/connections/#{adapter =~ /jdbc/ ? 'jdbc' : 'native'}_#{adapter}"
+ adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z]+/]
+ puts [adapter, adapter_short, connection_path].inspect
+ ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
+ Dir["test/cases/**/*_test{,_#{adapter_short}}.rb"].all? do |file|
+ system(ruby, "-Ilib:test:#{connection_path}", file)
+ end or raise "Failures"
+ end
+
namespace adapter do
task :test => "test_#{adapter}"
+ task :isolated_test => "isolated_test_#{adapter}"
end
end
--
cgit v1.2.3
From e8550ee0329586b32de425e905c7af7e65bc78a8 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 13 May 2009 01:10:37 -0700
Subject: Cherry-pick core extensions
---
Rakefile | 2 +-
actionmailer/Rakefile | 6 ++++++
actionmailer/lib/action_mailer/vendor/tmail.rb | 1 +
actionpack/lib/action_controller.rb | 13 +++----------
actionpack/lib/action_controller/base/base.rb | 2 ++
.../action_controller/base/chained/benchmarking.rb | 2 +-
.../action_controller/base/http_authentication.rb | 6 ++++--
actionpack/lib/action_controller/base/layout.rb | 4 ++++
.../lib/action_controller/record_identifier.rb | 2 ++
actionpack/lib/action_controller/routing/builder.rb | 2 ++
actionpack/lib/action_controller/routing/route.rb | 8 +++++---
actionpack/lib/action_controller/testing/process.rb | 1 +
actionpack/lib/action_dispatch.rb | 13 +++----------
actionpack/lib/action_dispatch/http/mime_type.rb | 1 +
actionpack/lib/action_dispatch/http/request.rb | 1 +
actionpack/lib/action_dispatch/http/response.rb | 1 +
actionpack/lib/action_view.rb | 13 +++----------
actionpack/lib/action_view/base.rb | 3 +++
actionpack/lib/action_view/helpers/form_helper.rb | 9 +++++----
actionpack/lib/action_view/template/handlers/erb.rb | 1 +
actionpack/test/abstract_controller/test_helper.rb | 4 ++--
actionpack/test/abstract_unit2.rb | 3 +--
actionpack/test/controller/addresses_render_test.rb | 1 +
actionpack/test/controller/base_test.rb | 1 +
actionpack/test/controller/capture_test.rb | 1 +
actionpack/test/controller/helper_test.rb | 1 +
activemodel/Rakefile | 6 ++++++
activemodel/test/state_machine/event_test.rb | 1 +
.../test/state_machine/state_transition_test.rb | 1 +
activerecord/Rakefile | 3 +++
activerecord/lib/active_record.rb | 1 -
activerecord/lib/active_record/associations.rb | 2 ++
activerecord/lib/active_record/attribute_methods.rb | 2 ++
activerecord/lib/active_record/base.rb | 21 +++++++++++++++------
.../connection_adapters/abstract/connection_pool.rb | 1 +
.../connection_adapters/abstract/quoting.rb | 2 ++
.../connection_adapters/abstract_adapter.rb | 2 ++
.../connection_adapters/mysql_adapter.rb | 1 +
.../connection_adapters/postgresql_adapter.rb | 1 +
.../connection_adapters/sqlite3_adapter.rb | 6 +++---
.../connection_adapters/sqlite_adapter.rb | 1 +
activerecord/lib/active_record/dirty.rb | 4 +++-
activerecord/lib/active_record/fixtures.rb | 1 +
activerecord/lib/active_record/migration.rb | 10 +++++-----
activerecord/lib/active_record/named_scope.rb | 3 +++
activerecord/lib/active_record/nested_attributes.rb | 3 +++
activerecord/lib/active_record/schema_dumper.rb | 4 ++--
activerecord/lib/active_record/serialization.rb | 17 +++++++++--------
.../lib/active_record/serializers/xml_serializer.rb | 5 ++++-
activerecord/lib/active_record/validations.rb | 5 ++---
activerecord/test/cases/aggregations_test.rb | 1 +
.../associations/eager_load_nested_include_test.rb | 1 +
.../has_and_belongs_to_many_associations_test.rb | 1 +
activerecord/test/cases/base_test.rb | 1 +
activerecord/test/cases/finder_test.rb | 5 +++--
activerecord/test/cases/helper.rb | 5 +++++
activerecord/test/cases/named_scope_test.rb | 3 ++-
activerecord/test/cases/nested_attributes_test.rb | 1 +
activerecord/test/models/company_in_module.rb | 2 ++
activeresource/Rakefile | 7 +++++++
activeresource/lib/active_resource/base.rb | 4 +++-
activeresource/test/base/custom_methods_test.rb | 1 +
activeresource/test/base/load_test.rb | 1 +
activeresource/test/base_test.rb | 1 +
activesupport/Rakefile | 2 +-
.../active_support/core_ext/object/conversions.rb | 3 +++
railties/Rakefile | 1 +
railties/lib/initializer.rb | 2 +-
railties/lib/rails/plugin.rb | 2 ++
railties/test/abstract_unit.rb | 1 -
railties/test/plugin_test_helper.rb | 1 -
71 files changed, 168 insertions(+), 83 deletions(-)
diff --git a/Rakefile b/Rakefile
index b3f7c8b642..58e1247600 100644
--- a/Rakefile
+++ b/Rakefile
@@ -12,7 +12,7 @@ end
desc 'Run all tests by default'
task :default => :test
-%w(test rdoc pgem package release).each do |task_name|
+%w(test isolated_test rdoc pgem package release).each do |task_name|
desc "Run #{task_name} task for all projects"
task task_name do
PROJECTS.each do |project|
diff --git a/actionmailer/Rakefile b/actionmailer/Rakefile
index f06f18ff76..24c25abc8b 100644
--- a/actionmailer/Rakefile
+++ b/actionmailer/Rakefile
@@ -28,6 +28,12 @@ Rake::TestTask.new { |t|
t.warning = false
}
+task :isolated_test do
+ ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
+ Dir.glob("test/*_test.rb").all? do |file|
+ system(ruby, '-Ilib:test', file)
+ end or raise "Failures"
+end
# Generate the RDoc documentation
Rake::RDocTask.new { |rdoc|
diff --git a/actionmailer/lib/action_mailer/vendor/tmail.rb b/actionmailer/lib/action_mailer/vendor/tmail.rb
index 51d36cdd0d..60555605f6 100644
--- a/actionmailer/lib/action_mailer/vendor/tmail.rb
+++ b/actionmailer/lib/action_mailer/vendor/tmail.rb
@@ -12,6 +12,7 @@ end
require 'tmail'
+require 'active_support/core_ext/kernel/reporting'
silence_warnings do
TMail::Encoder.const_set("MAX_LINE_LEN", 200)
end
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index ab78bc9222..39083a84e9 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -21,16 +21,9 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
-begin
- require 'active_support'
-rescue LoadError
- activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
- if File.directory?(activesupport_path)
- $:.unshift activesupport_path
- require 'active_support'
- end
-end
-require 'active_support/core/all'
+activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
+$:.unshift activesupport_path if File.directory?(activesupport_path)
+require 'active_support'
require File.join(File.dirname(__FILE__), "action_pack")
diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb
index d25801b17b..2813e71d12 100644
--- a/actionpack/lib/action_controller/base/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -1,5 +1,7 @@
require 'action_controller/deprecated'
require 'set'
+require 'active_support/core_ext/class/inheritable_attributes'
+require 'active_support/core_ext/module/attr_internal'
module ActionController #:nodoc:
class ActionControllerError < StandardError #:nodoc:
diff --git a/actionpack/lib/action_controller/base/chained/benchmarking.rb b/actionpack/lib/action_controller/base/chained/benchmarking.rb
index 066150f58a..66e9e9c31d 100644
--- a/actionpack/lib/action_controller/base/chained/benchmarking.rb
+++ b/actionpack/lib/action_controller/base/chained/benchmarking.rb
@@ -1,4 +1,4 @@
-require 'benchmark'
+require 'active_support/core_ext/benchmark'
module ActionController #:nodoc:
# The benchmarking module times the performance of actions and reports to the logger. If the Active Record
diff --git a/actionpack/lib/action_controller/base/http_authentication.rb b/actionpack/lib/action_controller/base/http_authentication.rb
index b6b5267c66..fa8ecea408 100644
--- a/actionpack/lib/action_controller/base/http_authentication.rb
+++ b/actionpack/lib/action_controller/base/http_authentication.rb
@@ -1,3 +1,5 @@
+require 'active_support/base64'
+
module ActionController
module HttpAuthentication
# Makes it dead easy to do HTTP Basic authentication.
@@ -276,7 +278,7 @@ module ActionController
t = time.to_i
hashed = [t, secret_key]
digest = ::Digest::MD5.hexdigest(hashed.join(":"))
- Base64.encode64("#{t}:#{digest}").gsub("\n", '')
+ ActiveSupport::Base64.encode64("#{t}:#{digest}").gsub("\n", '')
end
# Might want a shorter timeout depending on whether the request
@@ -285,7 +287,7 @@ module ActionController
# allow a user to use new nonce without prompting user again for their
# username and password.
def validate_nonce(request, value, seconds_to_timeout=5*60)
- t = Base64.decode64(value).split(":").first.to_i
+ t = ActiveSupport::Base64.decode64(value).split(":").first.to_i
nonce(t) == value && (t - Time.now.to_i).abs <= seconds_to_timeout
end
diff --git a/actionpack/lib/action_controller/base/layout.rb b/actionpack/lib/action_controller/base/layout.rb
index 1ad5191c73..cf5f46a32b 100644
--- a/actionpack/lib/action_controller/base/layout.rb
+++ b/actionpack/lib/action_controller/base/layout.rb
@@ -1,3 +1,7 @@
+require 'active_support/core_ext/enumerable'
+require 'active_support/core_ext/class/delegating_attributes'
+require 'active_support/core_ext/class/inheritable_attributes'
+
module ActionController #:nodoc:
module Layout #:nodoc:
def self.included(base)
diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb
index 6bda27e23a..b4408e4e1d 100644
--- a/actionpack/lib/action_controller/record_identifier.rb
+++ b/actionpack/lib/action_controller/record_identifier.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/module'
+
module ActionController
# The record identifier encapsulates a number of naming conventions for dealing with records, like Active Records or
# Active Resources or pretty much any other model type that has an id. These patterns are then used to try elevate
diff --git a/actionpack/lib/action_controller/routing/builder.rb b/actionpack/lib/action_controller/routing/builder.rb
index d9590c88b8..42ad12e1ea 100644
--- a/actionpack/lib/action_controller/routing/builder.rb
+++ b/actionpack/lib/action_controller/routing/builder.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/hash/except'
+
module ActionController
module Routing
class RouteBuilder #:nodoc:
diff --git a/actionpack/lib/action_controller/routing/route.rb b/actionpack/lib/action_controller/routing/route.rb
index e2077edad8..eba05a3c5a 100644
--- a/actionpack/lib/action_controller/routing/route.rb
+++ b/actionpack/lib/action_controller/routing/route.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/object/misc'
+
module ActionController
module Routing
class Route #:nodoc:
@@ -65,7 +67,7 @@ module ActionController
# map.connect '/page/:id', :controller => 'pages', :action => 'show', :id => /\d+/
#
def parameter_shell
- @parameter_shell ||= returning({}) do |shell|
+ @parameter_shell ||= {}.tap do |shell|
requirements.each do |key, requirement|
shell[key] = requirement unless requirement.is_a? Regexp
end
@@ -76,7 +78,7 @@ module ActionController
# includes keys that appear inside the path, and keys that have requirements
# placed upon them.
def significant_keys
- @significant_keys ||= returning([]) do |sk|
+ @significant_keys ||= [].tap do |sk|
segments.each { |segment| sk << segment.key if segment.respond_to? :key }
sk.concat requirements.keys
sk.uniq!
@@ -86,7 +88,7 @@ module ActionController
# Return a hash of key/value pairs representing the keys in the route that
# have defaults, or which are specified by non-regexp requirements.
def defaults
- @defaults ||= returning({}) do |hash|
+ @defaults ||= {}.tap do |hash|
segments.each do |segment|
next unless segment.respond_to? :default
hash[segment.key] = segment.default unless segment.default.nil?
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 936f97ecb5..8f4358c33e 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -1,4 +1,5 @@
require 'rack/session/abstract/id'
+require 'active_support/core_ext/object/conversions'
module ActionController #:nodoc:
class TestRequest < ActionDispatch::TestRequest #:nodoc:
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index c882930e64..27d229835a 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -21,16 +21,9 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
-begin
- require 'active_support'
-rescue LoadError
- activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
- if File.directory?(activesupport_path)
- $:.unshift activesupport_path
- require 'active_support'
- end
-end
-require 'active_support/core/all'
+activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
+$:.unshift activesupport_path if File.directory?(activesupport_path)
+require 'active_support'
begin
gem 'rack', '~> 1.1.pre'
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index 02ad7f7d94..dfcf3a558f 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -1,4 +1,5 @@
require 'set'
+require 'active_support/core_ext/class/attribute_accessors'
module Mime
SET = []
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index e4f3a8f125..13ff049a97 100755
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -3,6 +3,7 @@ require 'stringio'
require 'strscan'
require 'active_support/memoizable'
+require 'active_support/core_ext/hash/indifferent_access'
module ActionDispatch
class Request < Rack::Request
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index c3b5a68f40..edb522ff49 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -1,4 +1,5 @@
require 'digest/md5'
+require 'active_support/core_ext/module/delegation'
module ActionDispatch # :nodoc:
# Represents an HTTP response generated by a controller action. One can use
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index dd352f9ce0..c3786af439 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -21,16 +21,9 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
-begin
- require 'active_support'
-rescue LoadError
- activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
- if File.directory?(activesupport_path)
- $:.unshift activesupport_path
- require 'active_support'
- end
-end
-require 'active_support/core/all'
+activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
+$:.unshift activesupport_path if File.directory?(activesupport_path)
+require 'active_support'
require File.join(File.dirname(__FILE__), "action_pack")
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 44bd401631..56f0b5ef4f 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -1,3 +1,6 @@
+require 'active_support/core_ext/module/attr_internal'
+require 'active_support/core_ext/module/delegation'
+
module ActionView #:nodoc:
class ActionViewError < StandardError #:nodoc:
end
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index a59829b23f..beef661a37 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -2,6 +2,7 @@ require 'cgi'
require 'action_view/helpers/date_helper'
require 'action_view/helpers/tag_helper'
require 'action_view/helpers/form_tag_helper'
+require 'active_support/core_ext/class/inheritable_attributes'
module ActionView
module Helpers
@@ -1039,8 +1040,8 @@ module ActionView
end
end
- class Base
- cattr_accessor :default_form_builder
- self.default_form_builder = ::ActionView::Helpers::FormBuilder
+ class << Base
+ attr_accessor :default_form_builder
end
-end
\ No newline at end of file
+ Base.default_form_builder = ::ActionView::Helpers::FormBuilder
+end
diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb
index a20b1b0cd3..fdcb108ffc 100644
--- a/actionpack/lib/action_view/template/handlers/erb.rb
+++ b/actionpack/lib/action_view/template/handlers/erb.rb
@@ -1,4 +1,5 @@
require 'erb'
+require 'active_support/core_ext/class/attribute_accessors'
module ActionView
module TemplateHandlers
diff --git a/actionpack/test/abstract_controller/test_helper.rb b/actionpack/test/abstract_controller/test_helper.rb
index a08ab5a6d7..915054f7fb 100644
--- a/actionpack/test/abstract_controller/test_helper.rb
+++ b/actionpack/test/abstract_controller/test_helper.rb
@@ -4,7 +4,7 @@ $:.unshift(File.dirname(__FILE__) + '/../lib')
require 'rubygems'
require 'test/unit'
-require 'active_support/core/all'
+require 'active_support'
require 'active_support/test_case'
require 'action_controller/abstract'
require 'action_view'
@@ -18,4 +18,4 @@ begin
Debugger.start
rescue LoadError
# Debugging disabled. `gem install ruby-debug` to enable.
-end
\ No newline at end of file
+end
diff --git a/actionpack/test/abstract_unit2.rb b/actionpack/test/abstract_unit2.rb
index 2fdaba7342..932f594ad2 100644
--- a/actionpack/test/abstract_unit2.rb
+++ b/actionpack/test/abstract_unit2.rb
@@ -5,7 +5,6 @@ $:.unshift(File.dirname(__FILE__) + '/lib')
require 'test/unit'
require 'active_support'
-require 'active_support/core/all'
require 'active_support/test_case'
require 'action_controller/abstract'
require 'action_controller/new_base'
@@ -129,4 +128,4 @@ module ActionController
end
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/test/controller/addresses_render_test.rb b/actionpack/test/controller/addresses_render_test.rb
index 2f092b6731..2d2a2745b0 100644
--- a/actionpack/test/controller/addresses_render_test.rb
+++ b/actionpack/test/controller/addresses_render_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'logger'
class Address
def Address.count(conditions = nil, join = nil)
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index 0c54d61426..a09db95d7d 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'logger'
require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late
# Provide some controller to run the tests on.
diff --git a/actionpack/test/controller/capture_test.rb b/actionpack/test/controller/capture_test.rb
index 9a0976ca9f..06a5af6b32 100644
--- a/actionpack/test/controller/capture_test.rb
+++ b/actionpack/test/controller/capture_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'logger'
class CaptureController < ActionController::Base
def self.controller_name; "test"; end
diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb
index 19cd5f4db2..7b8096fccc 100644
--- a/actionpack/test/controller/helper_test.rb
+++ b/actionpack/test/controller/helper_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/core_ext/kernel/reporting'
ActionController::Base.helpers_dir = File.dirname(__FILE__) + '/../fixtures/helpers'
diff --git a/activemodel/Rakefile b/activemodel/Rakefile
index 4b60f8d682..544f49310a 100755
--- a/activemodel/Rakefile
+++ b/activemodel/Rakefile
@@ -11,6 +11,12 @@ Rake::TestTask.new do |t|
t.verbose = true
t.warning = true
end
+task :isolated_test do
+ ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
+ Dir.glob("test/**/*_test.rb").all? do |file|
+ system(ruby, '-Ilib:test', file)
+ end or raise "Failures"
+end
# Generate the RDoc documentation
Rake::RDocTask.new do |rdoc|
diff --git a/activemodel/test/state_machine/event_test.rb b/activemodel/test/state_machine/event_test.rb
index 64dc8c4875..05e7c78e8a 100644
--- a/activemodel/test/state_machine/event_test.rb
+++ b/activemodel/test/state_machine/event_test.rb
@@ -1,4 +1,5 @@
require 'test_helper'
+require 'active_model/state_machine/event'
class EventTest < ActiveModel::TestCase
def setup
diff --git a/activemodel/test/state_machine/state_transition_test.rb b/activemodel/test/state_machine/state_transition_test.rb
index b59ff5a6a7..966396fab1 100644
--- a/activemodel/test/state_machine/state_transition_test.rb
+++ b/activemodel/test/state_machine/state_transition_test.rb
@@ -1,4 +1,5 @@
require 'test_helper'
+require 'active_model/state_machine/state_transition'
class StateTransitionTest < ActiveModel::TestCase
test 'should set from, to, and opts attr readers' do
diff --git a/activerecord/Rakefile b/activerecord/Rakefile
index 892d52f30d..0b3f50d17e 100644
--- a/activerecord/Rakefile
+++ b/activerecord/Rakefile
@@ -32,6 +32,9 @@ desc 'Run mysql, sqlite, and postgresql tests'
task :test => defined?(JRUBY_VERSION) ?
%w(test_jdbcmysql test_jdbcsqlite3 test_jdbcpostgresql) :
%w(test_mysql test_sqlite3 test_postgresql)
+task :isolated_test => defined?(JRUBY_VERSION) ?
+ %w(isolated_test_jdbcmysql isolated_test_jdbcsqlite3 isolated_test_jdbcpostgresql) :
+ %w(isolated_test_mysql isolated_test_sqlite3 isolated_test_postgresql)
%w( mysql postgresql sqlite sqlite3 firebird db2 oracle sybase openbase frontbase jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb ).each do |adapter|
Rake::TestTask.new("test_#{adapter}") { |t|
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index c9e9a84ce7..2d98239052 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -24,7 +24,6 @@
activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
$:.unshift(activesupport_path) if File.directory?(activesupport_path)
require 'active_support'
-require 'active_support/core/all'
module ActiveRecord
# TODO: Review explicit loads to see if they will automatically be handled by the initilizer.
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index e2dd36158f..c5e4df4950 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/module/delegation'
+
module ActiveRecord
class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
def initialize(reflection)
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index 8d68d77eac..55d9a4d15d 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/enumerable'
+
module ActiveRecord
module AttributeMethods #:nodoc:
extend ActiveSupport::DependencyModule
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 97c36a675d..b9ba727a3f 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1,6 +1,15 @@
require 'yaml'
require 'set'
require 'active_support/dependencies'
+require 'active_support/core_ext/class/attribute_accessors'
+require 'active_support/core_ext/class/delegating_attributes'
+require 'active_support/core_ext/class/inheritable_attributes'
+require 'active_support/core_ext/array/extract_options'
+require 'active_support/core_ext/hash/deep_merge'
+require 'active_support/core_ext/hash/indifferent_access'
+require 'active_support/core_ext/hash/slice'
+require 'active_support/core_ext/string/behavior'
+require 'active_support/core/time'
module ActiveRecord #:nodoc:
# Generic Active Record exception class.
@@ -1888,7 +1897,7 @@ module ActiveRecord #:nodoc:
else
find(:#{finder}, options.merge(finder_options))
end
- #{'result || raise(RecordNotFound, "Couldn\'t find #{name} with #{attributes.to_a.collect {|pair| "#{pair.first} = #{pair.second}"}.join(\', \')}")' if bang}
+ #{'result || raise(RecordNotFound, "Couldn\'t find #{name} with #{attributes.to_a.collect { |pair| pair.join(\' = \') }.join(\', \')}")' if bang}
end
}, __FILE__, __LINE__
send(method_id, *arguments)
@@ -2610,11 +2619,11 @@ module ActiveRecord #:nodoc:
# Note: The new instance will share a link to the same attributes as the original class. So any change to the attributes in either
# instance will affect the other.
def becomes(klass)
- returning klass.new do |became|
- became.instance_variable_set("@attributes", @attributes)
- became.instance_variable_set("@attributes_cache", @attributes_cache)
- became.instance_variable_set("@new_record", new_record?)
- end
+ became = klass.new
+ became.instance_variable_set("@attributes", @attributes)
+ became.instance_variable_set("@attributes_cache", @attributes_cache)
+ became.instance_variable_set("@new_record", new_record?)
+ became
end
# Updates a single attribute and saves the record without going through the normal validation procedure.
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index e8e736bf38..500dafdc2e 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -1,5 +1,6 @@
require 'monitor'
require 'set'
+require 'active_support/core_ext/module/synchronization'
module ActiveRecord
# Raised when a connection could not be obtained within the connection
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
index 3a7bf35248..720fba29e9 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/big_decimal/conversions'
+
module ActiveRecord
module ConnectionAdapters # :nodoc:
module Quoting
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index a8cd9f033b..91b111ab55 100755
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -12,6 +12,8 @@ require 'active_record/connection_adapters/abstract/connection_pool'
require 'active_record/connection_adapters/abstract/connection_specification'
require 'active_record/connection_adapters/abstract/query_cache'
+require 'active_support/core_ext/benchmark'
+
module ActiveRecord
module ConnectionAdapters # :nodoc:
# ActiveRecord supports multiple database systems. AbstractAdapter and
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index 9300df28ee..d5536e4d67 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -1,4 +1,5 @@
require 'active_record/connection_adapters/abstract_adapter'
+require 'active_support/core_ext/kernel/requires'
require 'set'
module MysqlCompat #:nodoc:
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 4961793866..002696d2c4 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -1,4 +1,5 @@
require 'active_record/connection_adapters/abstract_adapter'
+require 'active_support/core_ext/kernel/requires'
begin
require_library_or_gem 'pg'
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index 75420f69aa..5eef692d05 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -25,9 +25,9 @@ module ActiveRecord
module ConnectionAdapters #:nodoc:
class SQLite3Adapter < SQLiteAdapter # :nodoc:
def table_structure(table_name)
- returning structure = @connection.table_info(quote_table_name(table_name)) do
- raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
- end
+ structure = @connection.table_info(quote_table_name(table_name))
+ raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
+ structure
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
index 05334a830a..c9d0c9574f 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
@@ -1,4 +1,5 @@
require 'active_record/connection_adapters/abstract_adapter'
+require 'active_support/core_ext/kernel/requires'
module ActiveRecord
class Base
diff --git a/activerecord/lib/active_record/dirty.rb b/activerecord/lib/active_record/dirty.rb
index fac6ca40d3..ac84f6b209 100644
--- a/activerecord/lib/active_record/dirty.rb
+++ b/activerecord/lib/active_record/dirty.rb
@@ -168,7 +168,9 @@ module ActiveRecord
module ClassMethods
def self.extended(base)
- base.metaclass.alias_method_chain(:alias_attribute, :dirty)
+ class << base
+ alias_method_chain :alias_attribute, :dirty
+ end
end
def alias_attribute_with_dirty(new_name, old_name)
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 91b4b4e182..e30fcf9a4f 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -3,6 +3,7 @@ require 'yaml'
require 'csv'
require 'active_support/dependencies'
require 'active_support/test_case'
+require 'active_support/core_ext/logger'
if RUBY_VERSION < '1.9'
module YAML #:nodoc:
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index 657acd6dc0..a7be3539d5 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -511,11 +511,11 @@ module ActiveRecord
raise DuplicateMigrationNameError.new(name.camelize)
end
- klasses << returning(MigrationProxy.new) do |migration|
- migration.name = name.camelize
- migration.version = version
- migration.filename = file
- end
+ migration = MigrationProxy.new
+ migration.name = name.camelize
+ migration.version = version
+ migration.filename = file
+ klasses << migration
end
migrations = migrations.sort_by(&:version)
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index 32bb36c07c..07f98dc743 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -1,3 +1,6 @@
+require 'active_support/core_ext/array'
+require 'active_support/core_ext/hash/except'
+
module ActiveRecord
module NamedScope
extend ActiveSupport::DependencyModule
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index 1ea2f53fd8..c532d3dfa3 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -1,3 +1,6 @@
+require 'active_support/core_ext/hash/except'
+require 'active_support/core_ext/object/try'
+
module ActiveRecord
module NestedAttributes #:nodoc:
extend ActiveSupport::DependencyModule
diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb
index 557a554966..de530a3456 100644
--- a/activerecord/lib/active_record/schema_dumper.rb
+++ b/activerecord/lib/active_record/schema_dumper.rb
@@ -1,5 +1,5 @@
require 'stringio'
-require 'bigdecimal'
+require 'active_support/core_ext/big_decimal'
module ActiveRecord
# This class is used to dump the database schema for some connection to some
@@ -176,4 +176,4 @@ HEADER
end
end
end
-end
\ No newline at end of file
+end
diff --git a/activerecord/lib/active_record/serialization.rb b/activerecord/lib/active_record/serialization.rb
index 78f66c3a73..7959f2b510 100644
--- a/activerecord/lib/active_record/serialization.rb
+++ b/activerecord/lib/active_record/serialization.rb
@@ -1,5 +1,3 @@
-require 'active_support/json'
-
module ActiveRecord #:nodoc:
module Serialization
class Serializer #:nodoc:
@@ -73,16 +71,19 @@ module ActiveRecord #:nodoc:
end
def serializable_record
- returning(serializable_record = {}) do
- serializable_names.each { |name| serializable_record[name] = @record.send(name) }
- add_includes do |association, records, opts|
+ record = {}
+ serializable_names.each { |name| record[name] = @record.send(name) }
+
+ add_includes do |association, records, opts|
+ record[association] =
if records.is_a?(Enumerable)
- serializable_record[association] = records.collect { |r| self.class.new(r, opts).serializable_record }
+ records.collect { |r| self.class.new(r, opts).serializable_record }
else
- serializable_record[association] = self.class.new(records, opts).serializable_record
+ self.class.new(records, opts).serializable_record
end
- end
end
+
+ record
end
def serialize
diff --git a/activerecord/lib/active_record/serializers/xml_serializer.rb b/activerecord/lib/active_record/serializers/xml_serializer.rb
index fa75874603..4eaf9531e2 100644
--- a/activerecord/lib/active_record/serializers/xml_serializer.rb
+++ b/activerecord/lib/active_record/serializers/xml_serializer.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/hash/conversions'
+
module ActiveRecord #:nodoc:
module Serialization
# Builds an XML document to represent the model. Some configuration is
@@ -165,8 +167,9 @@ module ActiveRecord #:nodoc:
class XmlSerializer < ActiveRecord::Serialization::Serializer #:nodoc:
def builder
@builder ||= begin
+ require 'builder' unless defined? ::Builder
options[:indent] ||= 2
- builder = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
+ builder = options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent])
unless options[:skip_instruct]
builder.instruct!
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index 9907a3c9b7..b6e848fa79 100644
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -1,5 +1,3 @@
-require 'builder'
-
module ActiveRecord
# Raised by save! and create! when the record is invalid. Use the
# +record+ method to retrieve the record which did not validate.
@@ -247,9 +245,10 @@ module ActiveRecord
# # Address can't be blank
# #
def to_xml(options={})
+ require 'builder' unless defined? ::Builder
options[:root] ||= "errors"
options[:indent] ||= 2
- options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
+ options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent])
options[:builder].instruct! unless options.delete(:skip_instruct)
options[:builder].errors do |e|
diff --git a/activerecord/test/cases/aggregations_test.rb b/activerecord/test/cases/aggregations_test.rb
index 4e0e1c7f15..8b6ec04018 100644
--- a/activerecord/test/cases/aggregations_test.rb
+++ b/activerecord/test/cases/aggregations_test.rb
@@ -1,5 +1,6 @@
require "cases/helper"
require 'models/customer'
+require 'active_support/core_ext/exception'
class AggregationsTest < ActiveRecord::TestCase
fixtures :customers
diff --git a/activerecord/test/cases/associations/eager_load_nested_include_test.rb b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
index 5f824f9c74..cb7fe9698b 100644
--- a/activerecord/test/cases/associations/eager_load_nested_include_test.rb
+++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
@@ -4,6 +4,7 @@ require 'models/author'
require 'models/comment'
require 'models/category'
require 'models/categorization'
+require 'active_support/core_ext/array/random_access'
module Remembered
extend ActiveSupport::DependencyModule
diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
index 5e8b2cadfc..8dc95806b9 100644
--- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
@@ -24,6 +24,7 @@ require 'models/club'
require 'models/member'
require 'models/membership'
require 'models/sponsor'
+require 'active_support/core_ext/string/conversions'
class ProjectWithAfterCreateHook < ActiveRecord::Base
set_table_name 'projects'
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 7ca2807f7e..59aa6953e3 100755
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -18,6 +18,7 @@ require 'models/minimalistic'
require 'models/warehouse_thing'
require 'models/parrot'
require 'rexml/document'
+require 'active_support/core_ext/exception'
class Category < ActiveRecord::Base; end
class Categorization < ActiveRecord::Base; end
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index 28eb311618..ad4588db69 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -485,8 +485,9 @@ class FinderTest < ActiveRecord::TestCase
assert_equal "foo in (#{quoted_nil})", bind('foo in (?)', [])
end
- def test_bind_string
- assert_equal ActiveRecord::Base.connection.quote(''), bind('?', '')
+ def test_bind_empty_string
+ quoted_empty = ActiveRecord::Base.connection.quote('')
+ assert_equal quoted_empty, bind('?', '')
end
def test_bind_chars
diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb
index 1ec52ac24d..05e92433cd 100644
--- a/activerecord/test/cases/helper.rb
+++ b/activerecord/test/cases/helper.rb
@@ -15,6 +15,11 @@ require 'connection'
require 'cases/repair_helper'
+begin
+ require 'ruby-debug'
+rescue LoadError
+end
+
# Show backtraces for deprecated behavior for quicker cleanup.
ActiveSupport::Deprecation.debug = true
diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb
index ae6a54a5bd..7dcea6d42e 100644
--- a/activerecord/test/cases/named_scope_test.rb
+++ b/activerecord/test/cases/named_scope_test.rb
@@ -1,4 +1,5 @@
require "cases/helper"
+require 'active_support/core_ext/array/random_access'
require 'models/post'
require 'models/topic'
require 'models/comment'
@@ -265,7 +266,7 @@ class NamedScopeTest < ActiveRecord::TestCase
end
def test_rand_should_select_a_random_object_from_proxy
- assert Topic.approved.rand.is_a?(Topic)
+ assert_kind_of Topic, Topic.approved.rand
end
def test_should_use_where_in_query_for_named_scope
diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
index f1741ed54d..f31275163d 100644
--- a/activerecord/test/cases/nested_attributes_test.rb
+++ b/activerecord/test/cases/nested_attributes_test.rb
@@ -4,6 +4,7 @@ require "models/ship"
require "models/bird"
require "models/parrot"
require "models/treasure"
+require 'active_support/hash_with_indifferent_access'
module AssertRaiseWithMessage
def assert_raise_with_message(expected_exception, expected_message)
diff --git a/activerecord/test/models/company_in_module.rb b/activerecord/test/models/company_in_module.rb
index 7f02403d5a..3c34efbe16 100644
--- a/activerecord/test/models/company_in_module.rb
+++ b/activerecord/test/models/company_in_module.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/object/misc'
+
module MyApplication
module Business
class Company < ActiveRecord::Base
diff --git a/activeresource/Rakefile b/activeresource/Rakefile
index c3cde26b6c..eb5b1dd1ac 100644
--- a/activeresource/Rakefile
+++ b/activeresource/Rakefile
@@ -34,6 +34,13 @@ Rake::TestTask.new { |t|
t.verbose = true
t.warning = true
}
+task :isolated_test do
+ ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
+ activesupport_path = "#{File.dirname(__FILE__)}/../activesupport/lib"
+ Dir.glob("test/**/*_test.rb").all? do |file|
+ system(ruby, "-Ilib:test:#{activesupport_path}", file)
+ end or raise "Failures"
+end
# Generate the RDoc documentation
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index 8a1236c9a8..dc24e713ff 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -1,8 +1,10 @@
+require 'active_support'
require 'active_support/core_ext/class/attribute_accessors'
require 'active_support/core_ext/class/inheritable_attributes'
require 'active_support/core_ext/module/attr_accessor_with_default'
require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/module/aliasing'
+require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/object/misc'
require 'set'
@@ -1027,7 +1029,7 @@ module ActiveResource
private
# Tries to find a resource for a given collection name; if it fails, then the resource is created
def find_or_create_resource_for_collection(name)
- find_or_create_resource_for(name.to_s.singularize)
+ find_or_create_resource_for(ActiveSupport::Inflector.singularize(name.to_s))
end
# Tries to find a resource in a non empty list of nested modules
diff --git a/activeresource/test/base/custom_methods_test.rb b/activeresource/test/base/custom_methods_test.rb
index 61887f4ec7..2d81549a65 100644
--- a/activeresource/test/base/custom_methods_test.rb
+++ b/activeresource/test/base/custom_methods_test.rb
@@ -1,6 +1,7 @@
require 'abstract_unit'
require 'fixtures/person'
require 'fixtures/street_address'
+require 'active_support/core_ext/hash/conversions'
class CustomMethodsTest < Test::Unit::TestCase
def setup
diff --git a/activeresource/test/base/load_test.rb b/activeresource/test/base/load_test.rb
index cd2103acb7..035bd965c2 100644
--- a/activeresource/test/base/load_test.rb
+++ b/activeresource/test/base/load_test.rb
@@ -2,6 +2,7 @@ require 'abstract_unit'
require "fixtures/person"
require "fixtures/street_address"
require 'active_support/core_ext/symbol'
+require 'active_support/core_ext/hash/conversions'
module Highrise
class Note < ActiveResource::Base
diff --git a/activeresource/test/base_test.rb b/activeresource/test/base_test.rb
index a6cef6b2ae..82d3b2ae96 100644
--- a/activeresource/test/base_test.rb
+++ b/activeresource/test/base_test.rb
@@ -3,6 +3,7 @@ require "fixtures/person"
require "fixtures/customer"
require "fixtures/street_address"
require "fixtures/beast"
+require 'active_support/core_ext/hash/conversions'
class BaseTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/Rakefile b/activesupport/Rakefile
index a4e8200a43..c3ea09d424 100644
--- a/activesupport/Rakefile
+++ b/activesupport/Rakefile
@@ -22,8 +22,8 @@ Rake::TestTask.new { |t|
t.warning = true
}
task :isolated_test do
+ ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
Dir['test/**/*_test.rb'].all? do |file|
- ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
system(ruby, '-Ilib:test', file)
end or raise "Failures"
end
diff --git a/activesupport/lib/active_support/core_ext/object/conversions.rb b/activesupport/lib/active_support/core_ext/object/conversions.rb
index 278b856c45..638f0decc1 100644
--- a/activesupport/lib/active_support/core_ext/object/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/object/conversions.rb
@@ -1,3 +1,6 @@
+require 'active_support/core_ext/array/conversions'
+require 'active_support/core_ext/hash/conversions'
+
class Object
# Alias of to_s .
def to_param
diff --git a/railties/Rakefile b/railties/Rakefile
index 7637293007..133a603ed6 100644
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -31,6 +31,7 @@ task :test do
system(ruby, '-Itest', "-I#{File.dirname(__FILE__)}/../activesupport/lib", file)
end or raise "Failures"
end
+task :isolated_test => :test
Rake::TestTask.new("regular_test") do |t|
t.libs << 'test' << "#{File.dirname(__FILE__)}/../activesupport/lib"
diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index 9d27488e8a..40000f0dfd 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -264,8 +264,8 @@ module Rails
# 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) }
+ require 'active_support/core/all'
rescue LoadError => e
# Re-raise as RuntimeError because Mongrel would swallow LoadError.
raise e.to_s
diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb
index 0f924724cd..e66166306a 100644
--- a/railties/lib/rails/plugin.rb
+++ b/railties/lib/rails/plugin.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/kernel/reporting'
+
module Rails
# The Plugin class should be an object which provides the following methods:
#
diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb
index ffd60ee662..0addcb8bf3 100644
--- a/railties/test/abstract_unit.rb
+++ b/railties/test/abstract_unit.rb
@@ -13,7 +13,6 @@ 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 adb62de665..55d1a1fa96 100644
--- a/railties/test/plugin_test_helper.rb
+++ b/railties/test/plugin_test_helper.rb
@@ -3,7 +3,6 @@ $:.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 4f291fa528e5faad03def69ae7ac98224ab859db Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 13 May 2009 11:55:19 -0700
Subject: Simple examples for require profiling
---
activerecord/examples/simple.rb | 14 ++++++++++++++
activeresource/examples/simple.rb | 16 ++++++++++++++++
tools/profile_requires | 4 ++--
3 files changed, 32 insertions(+), 2 deletions(-)
create mode 100644 activerecord/examples/simple.rb
create mode 100644 activeresource/examples/simple.rb
diff --git a/activerecord/examples/simple.rb b/activerecord/examples/simple.rb
new file mode 100644
index 0000000000..c12f746992
--- /dev/null
+++ b/activerecord/examples/simple.rb
@@ -0,0 +1,14 @@
+$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
+require 'active_record'
+
+class Person < ActiveRecord::Base
+ establish_connection :adapter => 'sqlite3', :database => 'foobar.db'
+ connection.create_table table_name, :force => true do |t|
+ t.string :name
+ end
+end
+
+bob = Person.create!(:name => 'bob')
+puts Person.all.inspect
+bob.destroy
+puts Person.all.inspect
diff --git a/activeresource/examples/simple.rb b/activeresource/examples/simple.rb
new file mode 100644
index 0000000000..b20ef61670
--- /dev/null
+++ b/activeresource/examples/simple.rb
@@ -0,0 +1,16 @@
+$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
+require 'active_resource'
+require 'active_resource/http_mock'
+require 'active_support/core_ext/hash/conversions'
+
+ActiveSupport::XmlMini.backend = ENV['XMLMINI'] || 'REXML'
+ActiveResource::HttpMock.respond_to do |mock|
+ mock.get '/people/1.xml', {}, { :id => 1, :name => 'bob' }.to_xml(:root => 'person')
+end
+
+class Person < ActiveResource::Base
+ self.site = 'http://localhost/'
+end
+
+bob = Person.find(1)
+puts bob.inspect
diff --git a/tools/profile_requires b/tools/profile_requires
index be7770b3e5..0fd11c7d41 100755
--- a/tools/profile_requires
+++ b/tools/profile_requires
@@ -1,7 +1,7 @@
#!/usr/bin/env ruby
# Example:
-# ruby -Iactivesupport/lib tools/profile_requires.rb active_support
-# ruby -Iactionpack/lib tools/profile_requires.rb action_controller
+# tools/profile_requires activesupport/lib/active_support.rb
+# tools/profile_requires activeresource/examples/simple.rb
abort 'Use REE so you can profile memory and object allocation' unless GC.respond_to?(:enable_stats)
GC.enable_stats
--
cgit v1.2.3
From 49a84ff69ca4fc4db821ca3b5a5926d07832c845 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 13 May 2009 17:00:36 -0700
Subject: Ported over render :file tests.
---
actionpack/test/controller/render_js_test.rb | 37 +++
actionpack/test/controller/render_json_test.rb | 80 ++++++
actionpack/test/controller/render_other_test.rb | 222 ++++++++++++++++
actionpack/test/controller/render_test.rb | 334 +-----------------------
actionpack/test/controller/render_xml_test.rb | 81 ++++++
actionpack/test/new_base/render_file_test.rb | 110 ++++++++
actionpack/test/new_base/render_layout_test.rb | 18 +-
actionpack/test/new_base/test_helper.rb | 24 ++
8 files changed, 585 insertions(+), 321 deletions(-)
create mode 100644 actionpack/test/controller/render_js_test.rb
create mode 100644 actionpack/test/controller/render_json_test.rb
create mode 100644 actionpack/test/controller/render_other_test.rb
create mode 100644 actionpack/test/controller/render_xml_test.rb
create mode 100644 actionpack/test/new_base/render_file_test.rb
diff --git a/actionpack/test/controller/render_js_test.rb b/actionpack/test/controller/render_js_test.rb
new file mode 100644
index 0000000000..7b50242910
--- /dev/null
+++ b/actionpack/test/controller/render_js_test.rb
@@ -0,0 +1,37 @@
+require 'abstract_unit'
+require 'controller/fake_models'
+require 'pathname'
+
+class TestController < ActionController::Base
+ protect_from_forgery
+
+ def render_vanilla_js_hello
+ render :js => "alert('hello')"
+ end
+
+ def greeting
+ # let's just rely on the template
+ end
+
+ def partial
+ render :partial => 'partial'
+ end
+end
+
+class RenderTest < ActionController::TestCase
+ def test_render_vanilla_js
+ get :render_vanilla_js_hello
+ assert_equal "alert('hello')", @response.body
+ assert_equal "text/javascript", @response.content_type
+ end
+
+ def test_render_with_default_from_accept_header
+ xhr :get, :greeting
+ assert_equal "$(\"body\").visualEffect(\"highlight\");", @response.body
+ end
+
+ def test_should_render_js_partial
+ xhr :get, :partial, :format => 'js'
+ assert_equal 'partial js', @response.body
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/controller/render_json_test.rb b/actionpack/test/controller/render_json_test.rb
new file mode 100644
index 0000000000..233b2dfd89
--- /dev/null
+++ b/actionpack/test/controller/render_json_test.rb
@@ -0,0 +1,80 @@
+require 'abstract_unit'
+require 'controller/fake_models'
+require 'pathname'
+
+class TestController < ActionController::Base
+ protect_from_forgery
+
+ def render_json_nil
+ render :json => nil
+ end
+
+ def render_json_hello_world
+ render :json => ActiveSupport::JSON.encode(:hello => 'world')
+ end
+
+ def render_json_hello_world_with_callback
+ render :json => ActiveSupport::JSON.encode(:hello => 'world'), :callback => 'alert'
+ end
+
+ def render_json_with_custom_content_type
+ render :json => ActiveSupport::JSON.encode(:hello => 'world'), :content_type => 'text/javascript'
+ end
+
+ def render_symbol_json
+ render :json => ActiveSupport::JSON.encode(:hello => 'world')
+ end
+
+ def render_json_with_render_to_string
+ render :json => {:hello => render_to_string(:partial => 'partial')}
+ end
+end
+
+class RenderTest < ActionController::TestCase
+ tests TestController
+
+ def setup
+ # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get
+ # a more accurate simulation of what happens in "real life".
+ super
+ @controller.logger = Logger.new(nil)
+
+ @request.host = "www.nextangle.com"
+ end
+
+ def test_render_json_nil
+ get :render_json_nil
+ assert_equal 'null', @response.body
+ assert_equal 'application/json', @response.content_type
+ end
+
+ def test_render_json
+ get :render_json_hello_world
+ assert_equal '{"hello":"world"}', @response.body
+ assert_equal 'application/json', @response.content_type
+ end
+
+ def test_render_json_with_callback
+ get :render_json_hello_world_with_callback
+ assert_equal 'alert({"hello":"world"})', @response.body
+ assert_equal 'application/json', @response.content_type
+ end
+
+ def test_render_json_with_custom_content_type
+ get :render_json_with_custom_content_type
+ assert_equal '{"hello":"world"}', @response.body
+ assert_equal 'text/javascript', @response.content_type
+ end
+
+ def test_render_symbol_json
+ get :render_symbol_json
+ assert_equal '{"hello":"world"}', @response.body
+ assert_equal 'application/json', @response.content_type
+ end
+
+ def test_render_json_with_render_to_string
+ get :render_json_with_render_to_string
+ assert_equal '{"hello":"partial html"}', @response.body
+ assert_equal 'application/json', @response.content_type
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/controller/render_other_test.rb b/actionpack/test/controller/render_other_test.rb
new file mode 100644
index 0000000000..ddbdd2d213
--- /dev/null
+++ b/actionpack/test/controller/render_other_test.rb
@@ -0,0 +1,222 @@
+require 'abstract_unit'
+require 'controller/fake_models'
+require 'pathname'
+
+class TestController < ActionController::Base
+ protect_from_forgery
+
+ module RenderTestHelper
+ def rjs_helper_method_from_module
+ page.visual_effect :highlight
+ end
+ end
+
+ helper RenderTestHelper
+ helper do
+ def rjs_helper_method(value)
+ page.visual_effect :highlight, value
+ end
+ end
+
+ def enum_rjs_test
+ render :update do |page|
+ page.select('.product').each do |value|
+ page.rjs_helper_method_from_module
+ page.rjs_helper_method(value)
+ page.sortable(value, :url => { :action => "order" })
+ page.draggable(value)
+ end
+ end
+ end
+
+ def render_explicit_html_template
+ end
+
+ def render_custom_code_rjs
+ render :update, :status => 404 do |page|
+ page.replace :foo, :partial => 'partial'
+ end
+ end
+
+ def render_implicit_html_template
+ end
+
+ def render_js_with_explicit_template
+ @project_id = 4
+ render :template => 'test/delete_with_js'
+ end
+
+ def render_js_with_explicit_action_template
+ @project_id = 4
+ render :action => 'delete_with_js'
+ end
+
+ def delete_with_js
+ @project_id = 4
+ end
+
+ def update_page
+ render :update do |page|
+ page.replace_html 'balance', '$37,000,000.00'
+ page.visual_effect :highlight, 'balance'
+ end
+ end
+
+ def update_page_with_instance_variables
+ @money = '$37,000,000.00'
+ @div_id = 'balance'
+ render :update do |page|
+ page.replace_html @div_id, @money
+ page.visual_effect :highlight, @div_id
+ end
+ end
+
+ def update_page_with_view_method
+ render :update do |page|
+ page.replace_html 'person', pluralize(2, 'person')
+ end
+ end
+
+ def partial_as_rjs
+ render :update do |page|
+ page.replace :foo, :partial => 'partial'
+ end
+ end
+
+ def respond_to_partial_as_rjs
+ respond_to do |format|
+ format.js do
+ render :update do |page|
+ page.replace :foo, :partial => 'partial'
+ end
+ end
+ end
+ end
+
+ def render_alternate_default
+ # For this test, the method "default_render" is overridden:
+ @alternate_default_render = lambda do
+ render :update do |page|
+ page.replace :foo, :partial => 'partial'
+ end
+ end
+ end
+
+private
+ def determine_layout
+ case action_name
+ when "render_js_with_explicit_template",
+ "render_js_with_explicit_action_template",
+ "delete_with_js", "update_page", "update_page_with_instance_variables"
+
+ "layouts/standard"
+ when "action_talk_to_layout", "layout_overriding_layout"
+ "layouts/talk_from_action"
+ when "render_implicit_html_template_from_xhr_request"
+ (request.xhr? ? 'layouts/xhr' : 'layouts/standard')
+ end
+ end
+end
+
+class RenderTest < ActionController::TestCase
+ tests TestController
+
+ def setup
+ # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get
+ # a more accurate simulation of what happens in "real life".
+ super
+ @controller.logger = Logger.new(nil)
+
+ @request.host = "www.nextangle.com"
+ end
+
+ def test_enum_rjs_test
+ ActiveSupport::SecureRandom.stubs(:base64).returns("asdf")
+ get :enum_rjs_test
+ body = %{
+ $$(".product").each(function(value, index) {
+ new Effect.Highlight(element,{});
+ new Effect.Highlight(value,{});
+ Sortable.create(value, {onUpdate:function(){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value) + '&authenticity_token=' + encodeURIComponent('asdf')})}});
+ new Draggable(value, {});
+ });
+ }.gsub(/^ /, '').strip
+ assert_equal body, @response.body
+ end
+
+ def test_explicitly_rendering_an_html_template_with_implicit_html_template_renders_should_be_possible_from_an_rjs_template
+ [:js, "js"].each do |format|
+ assert_nothing_raised do
+ get :render_explicit_html_template, :format => format
+ assert_equal %(document.write("Hello world\\n");), @response.body
+ end
+ end
+ end
+
+ def test_render_custom_code_rjs
+ get :render_custom_code_rjs
+ assert_response 404
+ assert_equal %(Element.replace("foo", "partial html");), @response.body
+ end
+
+ def test_render_in_an_rjs_template_should_pick_html_templates_when_available
+ [:js, "js"].each do |format|
+ assert_nothing_raised do
+ get :render_implicit_html_template, :format => format
+ assert_equal %(document.write("Hello world\\n");), @response.body
+ end
+ end
+ end
+
+ def test_render_rjs_template_explicitly
+ get :render_js_with_explicit_template
+ assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
+ end
+
+ def test_rendering_rjs_action_explicitly
+ get :render_js_with_explicit_action_template
+ assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
+ end
+
+ def test_render_rjs_with_default
+ get :delete_with_js
+ assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
+ end
+
+ def test_update_page
+ get :update_page
+ assert_template nil
+ assert_equal 'text/javascript; charset=utf-8', @response.headers['Content-Type']
+ assert_equal 2, @response.body.split($/).length
+ end
+
+ def test_update_page_with_instance_variables
+ get :update_page_with_instance_variables
+ assert_template nil
+ assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"]
+ assert_match /balance/, @response.body
+ assert_match /\$37/, @response.body
+ end
+
+ def test_update_page_with_view_method
+ get :update_page_with_view_method
+ assert_template nil
+ assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"]
+ assert_match /2 people/, @response.body
+ end
+
+ def test_should_render_html_formatted_partial_with_rjs
+ xhr :get, :partial_as_rjs
+ assert_equal %(Element.replace("foo", "partial html");), @response.body
+ end
+
+ def test_should_render_html_formatted_partial_with_rjs_and_js_format
+ xhr :get, :respond_to_partial_as_rjs
+ assert_equal %(Element.replace("foo", "partial html");), @response.body
+ end
+
+ def test_should_render_with_alternate_default_render
+ xhr :get, :render_alternate_default
+ assert_equal %(Element.replace("foo", "partial html");), @response.body
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 4cea050a1e..469e8601d0 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -145,18 +145,21 @@ class TestController < ActionController::Base
render :layout => false
end
+ # :ported:
def render_file_with_instance_variables
@secret = 'in the sauce'
path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb')
render :file => path
end
+ # :ported:
def render_file_as_string_with_instance_variables
@secret = 'in the sauce'
path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb'))
render path
end
+ # :ported:
def render_file_not_using_full_path
@secret = 'in the sauce'
render :file => 'test/render_file_with_ivar'
@@ -203,41 +206,11 @@ class TestController < ActionController::Base
render :inline => "<%= controller_name %>"
end
- def render_json_nil
- render :json => nil
- end
-
- def render_json_hello_world
- render :json => ActiveSupport::JSON.encode(:hello => 'world')
- end
-
- def render_json_hello_world_with_callback
- render :json => ActiveSupport::JSON.encode(:hello => 'world'), :callback => 'alert'
- end
-
- def render_json_with_custom_content_type
- render :json => ActiveSupport::JSON.encode(:hello => 'world'), :content_type => 'text/javascript'
- end
-
- def render_symbol_json
- render :json => ActiveSupport::JSON.encode(:hello => 'world')
- end
-
- def render_json_with_render_to_string
- render :json => {:hello => render_to_string(:partial => 'partial')}
- end
-
# :ported:
def render_custom_code
render :text => "hello world", :status => 404
end
- def render_custom_code_rjs
- render :update, :status => 404 do |page|
- page.replace :foo, :partial => 'partial'
- end
- end
-
# :ported:
def render_text_with_nil
render :text => nil
@@ -253,10 +226,6 @@ class TestController < ActionController::Base
render :text => "appended"
end
- def render_vanilla_js_hello
- render :js => "alert('hello')"
- end
-
# This test is testing 3 things:
# render :file in AV :ported:
# render :template in AC :ported:
@@ -271,10 +240,6 @@ class TestController < ActionController::Base
render "test/hello"
end
- def render_xml_with_custom_content_type
- render :xml => " ", :content_type => "application/atomsvc+xml"
- end
-
def render_line_offset
render :inline => '<% raise %>', :locals => {:foo => 'bar'}
end
@@ -331,12 +296,6 @@ class TestController < ActionController::Base
:locals => { :local_name => name }
end
- def render_implicit_html_template
- end
-
- def render_explicit_html_template
- end
-
def render_implicit_html_template_from_xhr_request
end
@@ -470,66 +429,6 @@ class TestController < ActionController::Base
render :template => "test/hello_world_from_rxml.builder"
end
- module RenderTestHelper
- def rjs_helper_method_from_module
- page.visual_effect :highlight
- end
- end
-
- helper RenderTestHelper
- helper do
- def rjs_helper_method(value)
- page.visual_effect :highlight, value
- end
- end
-
- def enum_rjs_test
- render :update do |page|
- page.select('.product').each do |value|
- page.rjs_helper_method_from_module
- page.rjs_helper_method(value)
- page.sortable(value, :url => { :action => "order" })
- page.draggable(value)
- end
- end
- end
-
- def delete_with_js
- @project_id = 4
- end
-
- def render_js_with_explicit_template
- @project_id = 4
- render :template => 'test/delete_with_js'
- end
-
- def render_js_with_explicit_action_template
- @project_id = 4
- render :action => 'delete_with_js'
- end
-
- def update_page
- render :update do |page|
- page.replace_html 'balance', '$37,000,000.00'
- page.visual_effect :highlight, 'balance'
- end
- end
-
- def update_page_with_instance_variables
- @money = '$37,000,000.00'
- @div_id = 'balance'
- render :update do |page|
- page.replace_html @div_id, @money
- page.visual_effect :highlight, @div_id
- end
- end
-
- def update_page_with_view_method
- render :update do |page|
- page.replace_html 'person', pluralize(2, 'person')
- end
- end
-
def action_talk_to_layout
# Action template sets variable that's picked up by layout
end
@@ -573,25 +472,6 @@ class TestController < ActionController::Base
head :forbidden, :x_custom_header => "something"
end
- def render_with_location
- render :xml => " ", :location => "http://example.com", :status => 201
- end
-
- def render_with_object_location
- customer = Customer.new("Some guy", 1)
- render :xml => " ", :location => customer_url(customer), :status => :created
- end
-
- def render_with_to_xml
- to_xmlable = Class.new do
- def to_xml
- " "
- end
- end.new
-
- render :xml => to_xmlable
- end
-
def render_using_layout_around_block
render :action => "using_layout_around_block"
end
@@ -608,22 +488,6 @@ class TestController < ActionController::Base
render :partial => 'partial.html.erb'
end
- def partial_as_rjs
- render :update do |page|
- page.replace :foo, :partial => 'partial'
- end
- end
-
- def respond_to_partial_as_rjs
- respond_to do |format|
- format.js do
- render :update do |page|
- page.replace :foo, :partial => 'partial'
- end
- end
- end
- end
-
def partial
render :partial => 'partial'
end
@@ -880,82 +744,54 @@ class RenderTest < ActionController::TestCase
assert_equal 'Hello world!', @response.body
end
+ # :ported:
def test_render_file_with_instance_variables
get :render_file_with_instance_variables
assert_equal "The secret is in the sauce\n", @response.body
end
+ # :ported:
def test_render_file_as_string_with_instance_variables
get :render_file_as_string_with_instance_variables
assert_equal "The secret is in the sauce\n", @response.body
end
+ # :ported:
def test_render_file_not_using_full_path
get :render_file_not_using_full_path
assert_equal "The secret is in the sauce\n", @response.body
end
+ # :ported:
def test_render_file_not_using_full_path_with_dot_in_path
get :render_file_not_using_full_path_with_dot_in_path
assert_equal "The secret is in the sauce\n", @response.body
end
+ # :ported:
def test_render_file_using_pathname
get :render_file_using_pathname
assert_equal "The secret is in the sauce\n", @response.body
end
+ # :ported:
def test_render_file_with_locals
get :render_file_with_locals
assert_equal "The secret is in the sauce\n", @response.body
end
+ # :ported:
def test_render_file_as_string_with_locals
get :render_file_as_string_with_locals
assert_equal "The secret is in the sauce\n", @response.body
end
+ # :assessed:
def test_render_file_from_template
get :render_file_from_template
assert_equal "The secret is in the sauce\n", @response.body
end
- def test_render_json_nil
- get :render_json_nil
- assert_equal 'null', @response.body
- assert_equal 'application/json', @response.content_type
- end
-
- def test_render_json
- get :render_json_hello_world
- assert_equal '{"hello":"world"}', @response.body
- assert_equal 'application/json', @response.content_type
- end
-
- def test_render_json_with_callback
- get :render_json_hello_world_with_callback
- assert_equal 'alert({"hello":"world"})', @response.body
- assert_equal 'application/json', @response.content_type
- end
-
- def test_render_json_with_custom_content_type
- get :render_json_with_custom_content_type
- assert_equal '{"hello":"world"}', @response.body
- assert_equal 'text/javascript', @response.content_type
- end
-
- def test_render_symbol_json
- get :render_symbol_json
- assert_equal '{"hello":"world"}', @response.body
- assert_equal 'application/json', @response.content_type
- end
-
- def test_render_json_with_render_to_string
- get :render_json_with_render_to_string
- assert_equal '{"hello":"partial html"}', @response.body
- assert_equal 'application/json', @response.content_type
- end
-
# :ported:
def test_render_custom_code
get :render_custom_code
@@ -964,12 +800,6 @@ class RenderTest < ActionController::TestCase
assert_equal 'hello world', @response.body
end
- def test_render_custom_code_rjs
- get :render_custom_code_rjs
- assert_response 404
- assert_equal %(Element.replace("foo", "partial html");), @response.body
- end
-
# :ported:
def test_render_text_with_nil
get :render_text_with_nil
@@ -1023,12 +853,6 @@ class RenderTest < ActionController::TestCase
assert_equal "test", @response.body # name is explicitly set to 'test' inside the controller.
end
- def test_render_vanilla_js
- get :render_vanilla_js_hello
- assert_equal "alert('hello')", @response.body
- assert_equal "text/javascript", @response.content_type
- end
-
# :ported:
def test_render_xml
get :render_xml_hello
@@ -1053,20 +877,6 @@ class RenderTest < ActionController::TestCase
assert_equal "\n \n \n", @response.body
end
- def test_enum_rjs_test
- ActiveSupport::SecureRandom.stubs(:base64).returns("asdf")
- get :enum_rjs_test
- body = %{
- $$(".product").each(function(value, index) {
- new Effect.Highlight(element,{});
- new Effect.Highlight(value,{});
- Sortable.create(value, {onUpdate:function(){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value) + '&authenticity_token=' + encodeURIComponent('asdf')})}});
- new Draggable(value, {});
- });
- }.gsub(/^ /, '').strip
- assert_equal body, @response.body
- end
-
def test_layout_rendering
get :layout_test
assert_equal "Hello world!", @response.body
@@ -1114,29 +924,10 @@ class RenderTest < ActionController::TestCase
assert_equal "Goodbye, Local David", @response.body
end
- def test_render_in_an_rjs_template_should_pick_html_templates_when_available
- [:js, "js"].each do |format|
- assert_nothing_raised do
- get :render_implicit_html_template, :format => format
- assert_equal %(document.write("Hello world\\n");), @response.body
- end
- end
- end
-
- def test_explicitly_rendering_an_html_template_with_implicit_html_template_renders_should_be_possible_from_an_rjs_template
- [:js, "js"].each do |format|
- assert_nothing_raised do
- get :render_explicit_html_template, :format => format
- assert_equal %(document.write("Hello world\\n");), @response.body
- end
- end
- end
-
def test_should_implicitly_render_html_template_from_xhr_request
- pending do
- xhr :get, :render_implicit_html_template_from_xhr_request
- assert_equal "XHR!\nHello HTML!", @response.body
- end
+ pending
+ # xhr :get, :render_implicit_html_template_from_xhr_request
+ # assert_equal "XHR!\nHello HTML!", @response.body
end
def test_should_implicitly_render_js_template_without_layout
@@ -1151,11 +942,6 @@ class RenderTest < ActionController::TestCase
assert_equal 'formatted html erb', @response.body
end
- def test_should_render_formatted_xml_erb_template
- get :formatted_xml_erb, :format => :xml
- assert_equal 'passed formatted xml erb ', @response.body
- end
-
def test_should_render_formatted_html_erb_template
get :formatted_xml_erb
assert_equal 'passed formatted html erb ', @response.body
@@ -1167,31 +953,6 @@ class RenderTest < ActionController::TestCase
assert_equal 'passed formatted html erb ', @response.body
end
- def test_should_render_xml_but_keep_custom_content_type
- get :render_xml_with_custom_content_type
- assert_equal "application/atomsvc+xml", @response.content_type
- end
-
- def test_render_with_default_from_accept_header
- xhr :get, :greeting
- assert_equal "$(\"body\").visualEffect(\"highlight\");", @response.body
- end
-
- def test_render_rjs_with_default
- get :delete_with_js
- assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
- end
-
- def test_render_rjs_template_explicitly
- get :render_js_with_explicit_template
- assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
- end
-
- def test_rendering_rjs_action_explicitly
- get :render_js_with_explicit_action_template
- assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
- end
-
def test_layout_test_with_different_layout
get :layout_test_with_different_layout
assert_equal "Hello world!", @response.body
@@ -1299,28 +1060,6 @@ class RenderTest < ActionController::TestCase
assert_equal "The secret is area51\n", @response.body
end
- def test_update_page
- get :update_page
- assert_template nil
- assert_equal 'text/javascript; charset=utf-8', @response.headers['Content-Type']
- assert_equal 2, @response.body.split($/).length
- end
-
- def test_update_page_with_instance_variables
- get :update_page_with_instance_variables
- assert_template nil
- assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"]
- assert_match /balance/, @response.body
- assert_match /\$37/, @response.body
- end
-
- def test_update_page_with_view_method
- get :update_page_with_view_method
- assert_template nil
- assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"]
- assert_match /2 people/, @response.body
- end
-
def test_yield_content_for
assert_not_deprecated { get :yield_content_for }
assert_equal "Putting stuff in the title! \n\nGreat stuff!\n", @response.body
@@ -1391,31 +1130,6 @@ class RenderTest < ActionController::TestCase
assert_response :forbidden
end
- def test_rendering_with_location_should_set_header
- get :render_with_location
- assert_equal "http://example.com", @response.headers["Location"]
- end
-
- def test_rendering_xml_should_call_to_xml_if_possible
- get :render_with_to_xml
- assert_equal " ", @response.body
- end
-
- def test_rendering_with_object_location_should_set_header_with_url_for
- ActionController::Routing::Routes.draw do |map|
- map.resources :customers
- map.connect ':controller/:action/:id'
- end
-
- get :render_with_object_location
- assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"]
- end
-
- def test_should_use_implicit_content_type
- get :implicit_content_type, :format => 'atom'
- assert_equal Mime::ATOM, @response.content_type
- end
-
def test_using_layout_around_block
get :render_using_layout_around_block
assert_equal "Before (David)\nInside from block\nAfter", @response.body
@@ -1446,26 +1160,6 @@ class RenderTest < ActionController::TestCase
assert_equal 'partial html', @response.body
end
- def test_should_render_html_formatted_partial_with_rjs
- xhr :get, :partial_as_rjs
- assert_equal %(Element.replace("foo", "partial html");), @response.body
- end
-
- def test_should_render_html_formatted_partial_with_rjs_and_js_format
- xhr :get, :respond_to_partial_as_rjs
- assert_equal %(Element.replace("foo", "partial html");), @response.body
- end
-
- def test_should_render_js_partial
- xhr :get, :partial, :format => 'js'
- assert_equal 'partial js', @response.body
- end
-
- def test_should_render_with_alternate_default_render
- xhr :get, :render_alternate_default
- assert_equal %(Element.replace("foo", "partial html");), @response.body
- end
-
def test_partial_only_with_layout
get :partial_only_with_layout
assert_equal "only partial", @response.body
diff --git a/actionpack/test/controller/render_xml_test.rb b/actionpack/test/controller/render_xml_test.rb
new file mode 100644
index 0000000000..052b4f0b52
--- /dev/null
+++ b/actionpack/test/controller/render_xml_test.rb
@@ -0,0 +1,81 @@
+require 'abstract_unit'
+require 'controller/fake_models'
+require 'pathname'
+
+class TestController < ActionController::Base
+ protect_from_forgery
+
+ def render_with_location
+ render :xml => " ", :location => "http://example.com", :status => 201
+ end
+
+ def render_with_object_location
+ customer = Customer.new("Some guy", 1)
+ render :xml => " ", :location => customer_url(customer), :status => :created
+ end
+
+ def render_with_to_xml
+ to_xmlable = Class.new do
+ def to_xml
+ " "
+ end
+ end.new
+
+ render :xml => to_xmlable
+ end
+
+ def formatted_xml_erb
+ end
+
+ def render_xml_with_custom_content_type
+ render :xml => " ", :content_type => "application/atomsvc+xml"
+ end
+end
+
+class RenderTest < ActionController::TestCase
+ tests TestController
+
+ def setup
+ # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get
+ # a more accurate simulation of what happens in "real life".
+ super
+ @controller.logger = Logger.new(nil)
+
+ @request.host = "www.nextangle.com"
+ end
+
+ def test_rendering_with_location_should_set_header
+ get :render_with_location
+ assert_equal "http://example.com", @response.headers["Location"]
+ end
+
+ def test_rendering_xml_should_call_to_xml_if_possible
+ get :render_with_to_xml
+ assert_equal " ", @response.body
+ end
+
+ def test_rendering_with_object_location_should_set_header_with_url_for
+ ActionController::Routing::Routes.draw do |map|
+ map.resources :customers
+ map.connect ':controller/:action/:id'
+ end
+
+ get :render_with_object_location
+ assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"]
+ end
+
+ def test_should_render_formatted_xml_erb_template
+ get :formatted_xml_erb, :format => :xml
+ assert_equal 'passed formatted xml erb ', @response.body
+ end
+
+ def test_should_render_xml_but_keep_custom_content_type
+ get :render_xml_with_custom_content_type
+ assert_equal "application/atomsvc+xml", @response.content_type
+ end
+
+ def test_should_use_implicit_content_type
+ get :implicit_content_type, :format => 'atom'
+ assert_equal Mime::ATOM, @response.content_type
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_file_test.rb b/actionpack/test/new_base/render_file_test.rb
new file mode 100644
index 0000000000..769949be0c
--- /dev/null
+++ b/actionpack/test/new_base/render_file_test.rb
@@ -0,0 +1,110 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
+
+module RenderFile
+
+ class BasicController < ActionController::Base
+ self.view_paths = "."
+
+ def index
+ render :file => File.join(File.dirname(__FILE__), *%w[.. fixtures test hello_world])
+ end
+
+ def with_instance_variables
+ @secret = 'in the sauce'
+ render :file => File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb')
+ end
+
+ def without_file_key
+ render File.join(File.dirname(__FILE__), *%w[.. fixtures test hello_world])
+ end
+
+ def without_file_key_with_instance_variable
+ @secret = 'in the sauce'
+ render File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb')
+ end
+
+ def relative_path
+ @secret = 'in the sauce'
+ render :file => '../fixtures/test/render_file_with_ivar'
+ end
+
+ def relative_path_with_dot
+ @secret = 'in the sauce'
+ render :file => '../fixtures/test/dot.directory/render_file_with_ivar'
+ end
+
+ def pathname
+ @secret = 'in the sauce'
+ render :file => Pathname.new(File.dirname(__FILE__)).join(*%w[.. fixtures test dot.directory render_file_with_ivar.erb])
+ end
+
+ def with_locals
+ path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_locals.erb')
+ render :file => path, :locals => {:secret => 'in the sauce'}
+ end
+
+ def without_file_key_with_locals
+ path = File.expand_path('../fixtures/test/render_file_with_locals.erb')
+ render path, :locals => {:secret => 'in the sauce'}
+ end
+ end
+
+ class TestBasic < SimpleRouteCase
+ testing RenderFile::BasicController
+
+ def setup
+ @old_pwd = Dir.pwd
+ Dir.chdir(File.dirname(__FILE__))
+ end
+
+ def teardown
+ Dir.chdir(@old_pwd)
+ end
+
+ test "rendering simple template" do
+ get :index
+ assert_response "Hello world!"
+ end
+
+ test "rendering template with ivar" do
+ get :with_instance_variables
+ assert_response "The secret is in the sauce\n"
+ end
+
+ test "rendering path without specifying the :file key" do
+ get :without_file_key
+ assert_response "Hello world!"
+ end
+
+ test "rendering path without specifying the :file key with ivar" do
+ get :without_file_key_with_instance_variable
+ assert_response "The secret is in the sauce\n"
+ end
+
+ test "rendering a relative path" do
+ get :relative_path
+ assert_response "The secret is in the sauce\n"
+ end
+
+ test "rendering a relative path with dot" do
+ get :relative_path_with_dot
+ assert_response "The secret is in the sauce\n"
+ end
+
+ test "rendering a Pathname" do
+ get :pathname
+ assert_response "The secret is in the sauce\n"
+ end
+
+ test "rendering file with locals" do
+ get :with_locals
+ assert_response "The secret is in the sauce\n"
+ end
+
+ test "rendering path without specifying the :file key with locals" do
+ get :without_file_key_with_locals
+ assert_response "The secret is in the sauce\n"
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_layout_test.rb b/actionpack/test/new_base/render_layout_test.rb
index 5d28926cc6..7f627f86ec 100644
--- a/actionpack/test/new_base/render_layout_test.rb
+++ b/actionpack/test/new_base/render_layout_test.rb
@@ -6,7 +6,8 @@ module ControllerLayouts
self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/application.html.erb" => "OMG <%= yield %> KTHXBAI",
"layouts/override.html.erb" => "Override! <%= yield %>",
- "basic.html.erb" => "Hello world!"
+ "basic.html.erb" => "Hello world!",
+ "controller_layouts/implicit/layout_false.html.erb" => "hai(layout_false.html.erb)"
)]
def index
@@ -17,6 +18,12 @@ module ControllerLayouts
render :template => "basic", :layout => "override"
end
+ def layout_false
+ render :layout => false
+ end
+
+
+
def builder_override
end
@@ -56,4 +63,13 @@ module ControllerLayouts
get "/controller_layouts/implicit/override"
assert_body "Override! Hello world!"
end
+
+ class TestLayoutOptions < SimpleRouteCase
+ testing ControllerLayouts::ImplicitController
+
+ test "rendering with :layout => false leaves out the implicit layout" do
+ get :layout_false
+ assert_response "hai(layout_false.html.erb)"
+ end
+ end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index 78662dc989..a7302af060 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -59,12 +59,28 @@ class Rack::TestCase < ActiveSupport::TestCase
@app ||= ActionController::Dispatcher.new
end
+ def self.testing(klass = nil)
+ if klass
+ @testing = "/#{klass.name.underscore}".sub!(/_controller$/, '')
+ else
+ @testing
+ end
+ end
+
def self.get(url)
setup do |test|
test.get url
end
end
+ def get(thing, *args)
+ if thing.is_a?(Symbol)
+ super("#{self.class.testing}/#{thing}")
+ else
+ super
+ end
+ end
+
def assert_body(body)
assert_equal body, Array.wrap(last_response.body).join
end
@@ -85,6 +101,14 @@ class Rack::TestCase < ActiveSupport::TestCase
end
end
+ def assert_response(body, status = 200, headers = {})
+ assert_body body
+ assert_status status
+ headers.each do |header, value|
+ assert_header header, value
+ end
+ end
+
def assert_content_type(type)
assert_equal type, last_response.headers["Content-Type"]
end
--
cgit v1.2.3
From afcbdfc15f919a470e4cfca97fb0084eebd2ab1f Mon Sep 17 00:00:00 2001
From: Peter Marklund
Date: Thu, 14 May 2009 09:30:16 +0200
Subject: Changed ActiveRecord::Base#exists? to invoke find_initial so that it
is compatible with, and doesn't lose, :include scopes (references to eager
loaded tables)
Signed-off-by: Michael Koziarski
[#2543 state:committed]
---
activerecord/lib/active_record/base.rb | 11 +++--------
activerecord/test/cases/finder_test.rb | 6 ++++++
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index b9ba727a3f..54ec0e841f 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -697,14 +697,9 @@ module ActiveRecord #:nodoc:
# Person.exists?(['name LIKE ?', "%#{query}%"])
# Person.exists?
def exists?(id_or_conditions = {})
- connection.select_all(
- construct_finder_sql(
- :select => "#{quoted_table_name}.#{primary_key}",
- :conditions => expand_id_conditions(id_or_conditions),
- :limit => 1
- ),
- "#{name} Exists"
- ).size > 0
+ find_initial(
+ :select => "#{quoted_table_name}.#{primary_key}",
+ :conditions => expand_id_conditions(id_or_conditions)) ? true : false
end
# Creates an object (or multiple objects) and saves it to the database, if validations pass.
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index ad4588db69..d0d7094e30 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -119,6 +119,12 @@ class FinderTest < ActiveRecord::TestCase
Address.new(existing_address.street + "1", existing_address.city, existing_address.country))
end
+ def test_exists_with_scoped_include
+ Developer.with_scope(:find => { :include => :projects, :order => "projects.name" }) do
+ assert Developer.exists?
+ end
+ end
+
def test_find_by_array_of_one_id
assert_kind_of(Array, Topic.find([ 1 ]))
assert_equal(1, Topic.find([ 1 ]).length)
--
cgit v1.2.3
From 29bd8f7b8975bc0442f0b63e7da077f9a3f22dc6 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 13 May 2009 16:15:18 -0700
Subject: Simple example for require profiling
---
actionpack/examples/simple.rb | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 actionpack/examples/simple.rb
diff --git a/actionpack/examples/simple.rb b/actionpack/examples/simple.rb
new file mode 100644
index 0000000000..4ecb824688
--- /dev/null
+++ b/actionpack/examples/simple.rb
@@ -0,0 +1,17 @@
+$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
+require 'action_controller'
+
+class PeopleController < ActionController::Base
+ def index
+ head :ok
+ end
+end
+
+status, headers, body = PeopleController.action(:index).call({ 'rack.input' => StringIO.new('') })
+
+puts status
+puts headers.to_yaml
+puts '---'
+body.each do |part|
+ puts part
+end
--
cgit v1.2.3
From 5dd29c466c38a1bc395da579fd4b22c5e5a8e9fd Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 13 May 2009 16:15:37 -0700
Subject: Cherry-picking Active Support extensions
---
actionpack/lib/action_dispatch/http/status_codes.rb | 6 ++++--
activesupport/lib/active_support/memoizable.rb | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/actionpack/lib/action_dispatch/http/status_codes.rb b/actionpack/lib/action_dispatch/http/status_codes.rb
index 830de2a6db..5bac842ec1 100644
--- a/actionpack/lib/action_dispatch/http/status_codes.rb
+++ b/actionpack/lib/action_dispatch/http/status_codes.rb
@@ -1,3 +1,5 @@
+require 'active_support/inflector'
+
module ActionDispatch
module StatusCodes #:nodoc:
STATUS_CODES = Rack::Utils::HTTP_STATUS_CODES.merge({
@@ -16,7 +18,7 @@ module ActionDispatch
# :created or :not_implemented) into its corresponding HTTP status
# code (like 200 or 501).
SYMBOL_TO_STATUS_CODE = STATUS_CODES.inject({}) { |hash, (code, message)|
- hash[message.gsub(/ /, "").underscore.to_sym] = code
+ hash[ActiveSupport::Inflector.underscore(message.gsub(/ /, "")).to_sym] = code
hash
}.freeze
@@ -37,4 +39,4 @@ module ActionDispatch
end
end
end
-end
\ No newline at end of file
+end
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb
index edf626802a..fa6db683d4 100644
--- a/activesupport/lib/active_support/memoizable.rb
+++ b/activesupport/lib/active_support/memoizable.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/object/metaclass'
+require 'active_support/core_ext/module/aliasing'
module ActiveSupport
module SafelyMemoizable
--
cgit v1.2.3
From c286952050e8fe16b0f6d64ba0687b52cc8f2ae1 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 14 May 2009 01:56:07 -0700
Subject: Minimal base/new_base comparison
---
actionpack/examples/minimal.rb | 34 ++++++++++++++++++++++
actionpack/examples/simple.rb | 17 -----------
actionpack/lib/action_controller/abstract/base.rb | 6 ++--
.../lib/action_controller/abstract/logger.rb | 4 ++-
actionpack/lib/action_controller/new_base/http.rb | 5 +++-
actionpack/lib/action_controller/routing.rb | 5 ++++
6 files changed, 50 insertions(+), 21 deletions(-)
create mode 100644 actionpack/examples/minimal.rb
delete mode 100644 actionpack/examples/simple.rb
diff --git a/actionpack/examples/minimal.rb b/actionpack/examples/minimal.rb
new file mode 100644
index 0000000000..84a8499daf
--- /dev/null
+++ b/actionpack/examples/minimal.rb
@@ -0,0 +1,34 @@
+$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
+require 'action_controller'
+require 'action_controller/new_base' if ENV['NEW']
+require 'benchmark'
+
+class BaseController < ActionController::Base
+ def index
+ render :text => ''
+ end
+end
+
+n = (ENV['N'] || 10000).to_i
+input = StringIO.new('')
+
+def call_index(controller, input, n)
+ n.times do
+ controller.action(:index).call({ 'rack.input' => input })
+ end
+
+ puts controller.name
+ status, headers, body = controller.action(:index).call({ 'rack.input' => input })
+
+ puts status
+ puts headers.to_yaml
+ puts '---'
+ body.each do |part|
+ puts part
+ end
+ puts '---'
+end
+
+elapsed = Benchmark.realtime { call_index BaseController, input, n }
+
+puts "%dms elapsed, %d requests/sec" % [1000 * elapsed, n / elapsed]
diff --git a/actionpack/examples/simple.rb b/actionpack/examples/simple.rb
deleted file mode 100644
index 4ecb824688..0000000000
--- a/actionpack/examples/simple.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
-require 'action_controller'
-
-class PeopleController < ActionController::Base
- def index
- head :ok
- end
-end
-
-status, headers, body = PeopleController.action(:index).call({ 'rack.input' => StringIO.new('') })
-
-puts status
-puts headers.to_yaml
-puts '---'
-body.each do |part|
- puts part
-end
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index c9e1081b23..4b8d953643 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/module/attr_internal'
+
module AbstractController
class Error < StandardError; end
@@ -89,7 +91,7 @@ module AbstractController
# you must handle it by also overriding process_action and
# handling the case.
def respond_to_action?(action_name)
- action_methods.include?(action_name) || respond_to?(:action_missing, true)
+ action_methods.include?(action_name.to_s) || respond_to?(:action_missing, true)
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb
index 5fb78f1755..b154be754b 100644
--- a/actionpack/lib/action_controller/abstract/logger.rb
+++ b/actionpack/lib/action_controller/abstract/logger.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/class/attribute_accessors'
+
module AbstractController
module Logger
extend ActiveSupport::DependencyModule
@@ -6,4 +8,4 @@ module AbstractController
cattr_accessor :logger
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb
index fb6041a04e..6852eb200a 100644
--- a/actionpack/lib/action_controller/new_base/http.rb
+++ b/actionpack/lib/action_controller/new_base/http.rb
@@ -1,3 +1,6 @@
+require 'action_controller/abstract'
+require 'active_support/core_ext/module/delegation'
+
module ActionController
class Http < AbstractController::Base
abstract!
@@ -57,7 +60,7 @@ module ActionController
def self.action(name)
@actions ||= {}
- @actions[name] ||= proc do |env|
+ @actions[name.to_s] ||= proc do |env|
new.call(name, env)
end
end
diff --git a/actionpack/lib/action_controller/routing.rb b/actionpack/lib/action_controller/routing.rb
index c0eb61340b..7edd379bc0 100644
--- a/actionpack/lib/action_controller/routing.rb
+++ b/actionpack/lib/action_controller/routing.rb
@@ -1,5 +1,10 @@
require 'cgi'
require 'uri'
+require 'set'
+
+require 'active_support/core_ext/module/aliasing'
+require 'active_support/core_ext/module/attribute_accessors'
+
require 'action_controller/routing/optimisations'
require 'action_controller/routing/routing_ext'
require 'action_controller/routing/route'
--
cgit v1.2.3
From 8fac2c88cae0f2fd42fad3c2c2c6c860df14d629 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Thu, 14 May 2009 15:30:35 -0700
Subject: Cleaning up more render tests
---
actionpack/lib/action_controller/abstract.rb | 3 +
actionpack/lib/action_controller/abstract/base.rb | 9 +++
actionpack/lib/action_view.rb | 1 +
actionpack/lib/action_view/helpers/tag_helper.rb | 2 +-
actionpack/test/controller/render_test.rb | 5 ++
actionpack/test/new_base/render_action_test.rb | 17 ++++-
actionpack/test/new_base/render_layout_test.rb | 2 -
actionpack/test/new_base/render_partial_test.rb | 27 ++++++++
actionpack/test/new_base/render_template_test.rb | 76 ++++++++++++++---------
actionpack/test/new_base/render_xml_test.rb | 11 ++++
actionpack/test/new_base/test_helper.rb | 2 +-
11 files changed, 122 insertions(+), 33 deletions(-)
create mode 100644 actionpack/test/new_base/render_partial_test.rb
create mode 100644 actionpack/test/new_base/render_xml_test.rb
diff --git a/actionpack/lib/action_controller/abstract.rb b/actionpack/lib/action_controller/abstract.rb
index 3f5c4a185f..48e33282ec 100644
--- a/actionpack/lib/action_controller/abstract.rb
+++ b/actionpack/lib/action_controller/abstract.rb
@@ -1,3 +1,6 @@
+require "active_support/core_ext/module/attr_internal"
+require "active_support/core_ext/module/delegation"
+
module AbstractController
autoload :Base, "action_controller/abstract/base"
autoload :Callbacks, "action_controller/abstract/callbacks"
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index c9e1081b23..8f2bfb5711 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -23,6 +23,15 @@ module AbstractController
end
alias_method :abstract?, :abstract
+
+ def inherited(klass)
+ ::AbstractController::Base.subclasses << klass.to_s
+ super
+ end
+
+ def subclasses
+ @subclasses ||= []
+ end
def internal_methods
controller = self
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index c3786af439..94138097e3 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -24,6 +24,7 @@
activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
$:.unshift activesupport_path if File.directory?(activesupport_path)
require 'active_support'
+require 'active_support/core_ext/class/attribute_accessors'
require File.join(File.dirname(__FILE__), "action_pack")
diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb
index af8c4d5e21..66d7592874 100644
--- a/actionpack/lib/action_view/helpers/tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/tag_helper.rb
@@ -9,7 +9,7 @@ module ActionView
include ERB::Util
BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked).to_set
- BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map(&:to_sym))
+ BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map {|attr| attr.to_sym })
# Returns an empty HTML tag of type +name+ which by default is XHTML
# compliant. Set +open+ to true to create an open tag compatible
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 469e8601d0..a750f018b8 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -262,6 +262,7 @@ class TestController < ActionController::Base
render :action => "hello_world"
end
+ # :ported:
def builder_layout_test
render :action => "hello", :layout => "layouts/builder"
end
@@ -271,6 +272,7 @@ class TestController < ActionController::Base
render :action => "hello_world_container"
end
+ # :ported:
def partials_list
@test_unchanged = 'hello'
@customers = [ Customer.new("david"), Customer.new("mary") ]
@@ -860,6 +862,7 @@ class RenderTest < ActionController::TestCase
assert_equal "application/xml", @response.content_type
end
+ # :ported:
def test_render_xml_as_string_template
get :render_xml_hello_as_string_template
assert_equal "\n Hello David
\nThis is grand!
\n\n", @response.body
@@ -872,11 +875,13 @@ class RenderTest < ActionController::TestCase
assert_equal "This is grand!
\n", @response.body
end
+ # :move: test in AV
def test_render_xml_with_partial
get :builder_partial_test
assert_equal "\n \n \n", @response.body
end
+ # :ported:
def test_layout_rendering
get :layout_test
assert_equal "Hello world!", @response.body
diff --git a/actionpack/test/new_base/render_action_test.rb b/actionpack/test/new_base/render_action_test.rb
index 348d70381b..f25faee433 100644
--- a/actionpack/test/new_base/render_action_test.rb
+++ b/actionpack/test/new_base/render_action_test.rb
@@ -131,8 +131,10 @@ module RenderActionWithApplicationLayout
# Set the view path to an application view structure with layouts
self.view_paths = self.view_paths = [ActionView::Template::FixturePath.new(
"render_action_with_application_layout/basic/hello_world.html.erb" => "Hello World!",
+ "render_action_with_application_layout/basic/hello.html.builder" => "xml.p 'Omg'",
"layouts/application.html.erb" => "OHAI <%= yield %> KTHXBAI",
- "layouts/greetings.html.erb" => "Greetings <%= yield %> Bai"
+ "layouts/greetings.html.erb" => "Greetings <%= yield %> Bai",
+ "layouts/builder.html.builder" => "xml.html do\n xml << yield\nend"
)]
def hello_world
@@ -154,6 +156,10 @@ module RenderActionWithApplicationLayout
def hello_world_with_custom_layout
render :action => "hello_world", :layout => "greetings"
end
+
+ def with_builder_and_layout
+ render :action => "hello", :layout => "builder"
+ end
end
class TestDefaultLayout < SimpleRouteCase
@@ -199,6 +205,15 @@ module RenderActionWithApplicationLayout
assert_status 200
end
+ class TestLayout < SimpleRouteCase
+ testing BasicController
+
+ test "builder works with layouts" do
+ get :with_builder_and_layout
+ assert_response "\nOmg
\n\n"
+ end
+ end
+
end
module RenderActionWithControllerLayout
diff --git a/actionpack/test/new_base/render_layout_test.rb b/actionpack/test/new_base/render_layout_test.rb
index 7f627f86ec..dc858b4f5c 100644
--- a/actionpack/test/new_base/render_layout_test.rb
+++ b/actionpack/test/new_base/render_layout_test.rb
@@ -22,8 +22,6 @@ module ControllerLayouts
render :layout => false
end
-
-
def builder_override
end
diff --git a/actionpack/test/new_base/render_partial_test.rb b/actionpack/test/new_base/render_partial_test.rb
new file mode 100644
index 0000000000..3a300afe5c
--- /dev/null
+++ b/actionpack/test/new_base/render_partial_test.rb
@@ -0,0 +1,27 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
+
+module RenderPartial
+
+ class BasicController < ActionController::Base
+
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "render_partial/basic/_basic.html.erb" => "OMG!",
+ "render_partial/basic/basic.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'basic' %><%= @test_unchanged %>"
+ )]
+
+ def changing
+ @test_unchanged = 'hello'
+ render :action => "basic"
+ end
+ end
+
+ class TestPartial < SimpleRouteCase
+ testing BasicController
+
+ test "rendering a partial in ActionView doesn't pull the ivars again from the controller" do
+ get :changing
+ assert_response("goodbyeOMG!goodbye")
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_template_test.rb b/actionpack/test/new_base/render_template_test.rb
index c09eeb1926..6c50ae4203 100644
--- a/actionpack/test/new_base/render_template_test.rb
+++ b/actionpack/test/new_base/render_template_test.rb
@@ -4,14 +4,19 @@ module RenderTemplate
class WithoutLayoutController < ActionController::Base
self.view_paths = [ActionView::Template::FixturePath.new(
- "test/basic.html.erb" => "Hello from basic.html.erb",
- "shared.html.erb" => "Elastica",
- "locals.html.erb" => "The secret is <%= secret %>"
+ "test/basic.html.erb" => "Hello from basic.html.erb",
+ "shared.html.erb" => "Elastica",
+ "locals.html.erb" => "The secret is <%= secret %>",
+ "xml_template.xml.builder" => "xml.html do\n xml.p 'Hello'\nend"
)]
def index
render :template => "test/basic"
end
+
+ def index_without_key
+ render "test/basic"
+ end
def in_top_directory
render :template => 'shared'
@@ -21,41 +26,56 @@ module RenderTemplate
render :template => '/shared'
end
+ def in_top_directory_with_slash_without_key
+ render '/shared'
+ end
+
def with_locals
render :template => "locals", :locals => { :secret => 'area51' }
end
+
+ def builder_template
+ render :template => "xml_template"
+ end
end
class TestWithoutLayout < SimpleRouteCase
- describe "rendering a normal template with full path without layout"
+ testing RenderTemplate::WithoutLayoutController
- get "/render_template/without_layout"
- assert_body "Hello from basic.html.erb"
- assert_status 200
- end
-
- class TestTemplateRenderInTopDirectory < SimpleRouteCase
- describe "rendering a template not in a subdirectory"
+ test "rendering a normal template with full path without layout" do
+ get :index
+ assert_response "Hello from basic.html.erb"
+ end
- get "/render_template/without_layout/in_top_directory"
- assert_body "Elastica"
- assert_status 200
- end
-
- class TestTemplateRenderInTopDirectoryWithSlash < SimpleRouteCase
- describe "rendering a template not in a subdirectory with a leading slash"
+ test "rendering a normal template with full path without layout without key" do
+ get :index_without_key
+ assert_response "Hello from basic.html.erb"
+ end
- get "/render_template/without_layout/in_top_directory_with_slash"
- assert_body "Elastica"
- assert_status 200
- end
-
- class TestTemplateRenderWithLocals < SimpleRouteCase
- describe "rendering a template with local variables"
+ test "rendering a template not in a subdirectory" do
+ get :in_top_directory
+ assert_response "Elastica"
+ end
- get "/render_template/without_layout/with_locals"
- assert_body "The secret is area51"
- assert_status 200
+ test "rendering a template not in a subdirectory with a leading slash" do
+ get :in_top_directory_with_slash
+ assert_response "Elastica"
+ end
+
+ test "rendering a template not in a subdirectory with a leading slash without key" do
+ get :in_top_directory_with_slash_without_key
+ assert_response "Elastica"
+ end
+
+ test "rendering a template with local variables" do
+ get :with_locals
+ assert_response "The secret is area51"
+ end
+
+ test "rendering a builder template" do
+ get :builder_template
+ assert_response "\n Hello
\n\n"
+ end
end
class WithLayoutController < ::ApplicationController
diff --git a/actionpack/test/new_base/render_xml_test.rb b/actionpack/test/new_base/render_xml_test.rb
new file mode 100644
index 0000000000..e6c40b1533
--- /dev/null
+++ b/actionpack/test/new_base/render_xml_test.rb
@@ -0,0 +1,11 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
+
+module RenderXml
+
+ # This has no layout and it works
+ class BasicController < ActionController::Base
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "render_xml/basic/with_render_erb" => "Hello world!"
+ )]
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index a7302af060..ec7dbffaae 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -46,7 +46,7 @@ class Rack::TestCase < ActiveSupport::TestCase
ActionController::Routing.use_controllers!(controllers)
# Move into a bootloader
- AbstractController::Base.subclasses.each do |klass|
+ ActionController::Base.subclasses.each do |klass|
klass = klass.constantize
next unless klass < AbstractController::Layouts
klass.class_eval do
--
cgit v1.2.3
From da65320433088548bc4cff33758e5acd71fd137a Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Thu, 14 May 2009 17:25:10 -0700
Subject: Got new base to pass controller/base_test.rb, implemented
method_missing action semantics in compatibility mode, and fixed a few
action_missing bugs.
---
actionpack/lib/action_controller/abstract/base.rb | 10 +++++--
.../lib/action_controller/abstract/logger.rb | 33 ++++++++++++++++++++++
.../action_controller/new_base/compatibility.rb | 15 ++++++++++
.../lib/action_controller/new_base/hide_actions.rb | 4 +--
actionpack/lib/action_controller/new_base/http.rb | 5 ----
actionpack/lib/action_controller/routing.rb | 1 +
actionpack/test/abstract_unit.rb | 2 +-
actionpack/test/controller/base_test.rb | 2 +-
8 files changed, 61 insertions(+), 11 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index 8f2bfb5711..483356a4be 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -67,6 +67,8 @@ module AbstractController
end
def process(action_name)
+ action_name = action_name.to_s
+
unless respond_to_action?(action_name)
raise ActionNotFound, "The action '#{action_name}' could not be found"
end
@@ -82,13 +84,17 @@ module AbstractController
self.class.action_methods
end
+ def action_method?(action)
+ action_methods.include?(action)
+ end
+
# It is possible for respond_to?(action_name) to be false and
# respond_to?(:action_missing) to be false if respond_to_action?
# is overridden in a subclass. For instance, ActionController::Base
# overrides it to include the case where a template matching the
# action_name is found.
def process_action
- if respond_to?(action_name) then send(action_name)
+ if action_method?(action_name) then send(action_name)
elsif respond_to?(:action_missing, true) then action_missing(action_name)
end
end
@@ -98,7 +104,7 @@ module AbstractController
# you must handle it by also overriding process_action and
# handling the case.
def respond_to_action?(action_name)
- action_methods.include?(action_name) || respond_to?(:action_missing, true)
+ action_method?(action_name) || respond_to?(:action_missing, true)
end
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb
index 5fb78f1755..d0603a4ad7 100644
--- a/actionpack/lib/action_controller/abstract/logger.rb
+++ b/actionpack/lib/action_controller/abstract/logger.rb
@@ -2,8 +2,41 @@ module AbstractController
module Logger
extend ActiveSupport::DependencyModule
+ class DelayedLog
+ def initialize(&blk)
+ @blk = blk
+ end
+
+ def to_s
+ @blk.call
+ end
+ alias to_str to_s
+ end
+
included do
cattr_accessor :logger
end
+
+ def process(action)
+ ret = super
+
+ if logger
+ log = DelayedLog.new do
+ "\n\nProcessing #{self.class.name}\##{action_name} " \
+ "to #{request.formats} " \
+ "(for #{request_origin}) [#{request.method.to_s.upcase}]"
+ end
+
+ logger.info(log)
+ end
+
+ ret
+ end
+
+ def request_origin
+ # this *needs* to be cached!
+ # otherwise you'd get different results if calling it more than once
+ @request_origin ||= "#{request.remote_ip} at #{Time.now.to_s(:db)}"
+ end
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index d17f498b60..993e571aba 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -42,6 +42,9 @@ module ActionController
# Controls the resource action separator
cattr_accessor :resource_action_separator
self.resource_action_separator = "/"
+
+ cattr_accessor :use_accept_header
+ self.use_accept_header = true
end
module ClassMethods
@@ -66,6 +69,18 @@ module ActionController
super
end
+
+ def respond_to_action?(action_name)
+ if respond_to?(:method_missing) && !respond_to?(:action_missing)
+ self.class.class_eval do
+ private
+ def action_missing(name, *args)
+ method_missing(name.to_sym, *args)
+ end
+ end
+ end
+ super
+ end
def _layout_for_name(name)
name &&= name.sub(%r{^/?layouts/}, '')
diff --git a/actionpack/lib/action_controller/new_base/hide_actions.rb b/actionpack/lib/action_controller/new_base/hide_actions.rb
index d1857a9169..a29b09a893 100644
--- a/actionpack/lib/action_controller/new_base/hide_actions.rb
+++ b/actionpack/lib/action_controller/new_base/hide_actions.rb
@@ -12,8 +12,8 @@ module ActionController
private
- def respond_to_action?(action_name)
- !hidden_actions.include?(action_name) && (super || respond_to?(:method_missing))
+ def action_method?(action_name)
+ !hidden_actions.include?(action_name) && super
end
module ClassMethods
diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb
index fb6041a04e..f3a60b3bf8 100644
--- a/actionpack/lib/action_controller/new_base/http.rb
+++ b/actionpack/lib/action_controller/new_base/http.rb
@@ -21,11 +21,6 @@ module ActionController
# :api: public
def controller_path() self.class.controller_path end
- # :api: private
- def self.internal_methods
- ActionController::Http.public_instance_methods(true)
- end
-
# :api: private
def self.action_names() action_methods end
diff --git a/actionpack/lib/action_controller/routing.rb b/actionpack/lib/action_controller/routing.rb
index c0eb61340b..06a07a4d0a 100644
--- a/actionpack/lib/action_controller/routing.rb
+++ b/actionpack/lib/action_controller/routing.rb
@@ -1,5 +1,6 @@
require 'cgi'
require 'uri'
+require 'set'
require 'action_controller/routing/optimisations'
require 'action_controller/routing/routing_ext'
require 'action_controller/routing/route'
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 825ac9a46c..7982f06545 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -37,7 +37,7 @@ ActionController::Base.session_store = nil
# Register danish language for testing
I18n.backend.store_translations 'da', {}
I18n.backend.store_translations 'pt-BR', {}
-ORIGINAL_LOCALES = I18n.available_locales.map(&:to_s).sort
+ORIGINAL_LOCALES = I18n.available_locales.map {|locale| locale.to_s }.sort
FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
ActionController::Base.view_paths = FIXTURE_LOAD_PATH
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index a09db95d7d..3a4cdb81d9 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -117,7 +117,7 @@ class PerformActionTest < ActionController::TestCase
end
def method_missing(method, *args)
- @logged << args.first
+ @logged << args.first.to_s
end
end
--
cgit v1.2.3
From 628110d7eeb446fee7f9e043f113c083d24883c1 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 14 May 2009 17:42:20 -0700
Subject: Active Support dependencies
---
actionpack/lib/action_view/helpers/active_record_helper.rb | 1 +
actionpack/test/abstract_controller/layouts_test.rb | 1 +
2 files changed, 2 insertions(+)
diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb
index 7c0dfdab10..b4b9f6e34b 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -1,5 +1,6 @@
require 'cgi'
require 'action_view/helpers/form_helper'
+require 'active_support/core_ext/class/attribute_accessors'
module ActionView
class Base
diff --git a/actionpack/test/abstract_controller/layouts_test.rb b/actionpack/test/abstract_controller/layouts_test.rb
index 6e1c2bf9e8..d3440c3de0 100644
--- a/actionpack/test/abstract_controller/layouts_test.rb
+++ b/actionpack/test/abstract_controller/layouts_test.rb
@@ -1,4 +1,5 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
+require 'active_support/core_ext/class/removal'
module AbstractControllerTests
module Layouts
--
cgit v1.2.3
From eb021707f53be46140b55a48e5ef03ed0577a45c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Valim?=
Date: Wed, 1 Apr 2009 12:44:56 +0200
Subject: Allow strings to be sent as collection to select.
Signed-off-by: Michael Koziarski
---
.../lib/action_view/helpers/form_options_helper.rb | 2 ++
.../test/template/form_options_helper_test.rb | 22 ++++++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index 6b385ef77d..6adbab175f 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -230,6 +230,8 @@ module ActionView
#
# NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.
def options_for_select(container, selected = nil)
+ return container if String === container
+
container = container.to_a if Hash === container
selected, disabled = extract_selected_and_disabled(selected)
diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb
index 78db87971b..73624406be 100644
--- a/actionpack/test/template/form_options_helper_test.rb
+++ b/actionpack/test/template/form_options_helper_test.rb
@@ -80,6 +80,14 @@ class FormOptionsHelperTest < ActionView::TestCase
)
end
+ def test_string_options_for_select
+ options = "Denmark USA Sweden "
+ assert_dom_equal(
+ options,
+ options_for_select(options)
+ )
+ end
+
def test_array_options_for_select
assert_dom_equal(
"<Denmark> \nUSA \nSweden ",
@@ -324,6 +332,20 @@ class FormOptionsHelperTest < ActionView::TestCase
)
end
+ def test_select_under_fields_for_with_string_and_given_prompt
+ @post = Post.new
+ options = "abe mus hest "
+
+ fields_for :post, @post do |f|
+ concat f.select(:category, options, :prompt => 'The prompt')
+ end
+
+ assert_dom_equal(
+ "The prompt \n#{options} ",
+ output_buffer
+ )
+ end
+
def test_select_with_blank
@post = Post.new
@post.category = ""
--
cgit v1.2.3
From 7e10504bdeab14ea70a942110a1b1ef6d8467ed3 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 15 May 2009 15:57:12 -0700
Subject: Refactored AbstractController to provide better hook points for
overriding aspects of action dispatching
---
actionpack/lib/action_controller/abstract/base.rb | 27 ++++++++++++----------
.../lib/action_controller/abstract/callbacks.rb | 4 ++--
actionpack/lib/action_controller/new_base/base.rb | 16 +++++++++----
.../action_controller/new_base/compatibility.rb | 18 ++++++---------
.../abstract_controller_test.rb | 7 +++---
5 files changed, 39 insertions(+), 33 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index f2db201063..1f2f096dae 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -69,14 +69,13 @@ module AbstractController
end
def process(action_name)
- action_name = action_name.to_s
+ @_action_name = action_name = action_name.to_s
- unless respond_to_action?(action_name)
+ unless action_name = method_for_action(action_name)
raise ActionNotFound, "The action '#{action_name}' could not be found"
end
-
- @_action_name = action_name
- process_action
+
+ process_action(action_name)
self
end
@@ -95,18 +94,22 @@ module AbstractController
# is overridden in a subclass. For instance, ActionController::Base
# overrides it to include the case where a template matching the
# action_name is found.
- def process_action
- if action_method?(action_name) then send(action_name)
- elsif respond_to?(:action_missing, true) then action_missing(action_name)
- end
+ def process_action(method_name)
+ send(method_name)
end
-
+
+ def _handle_action_missing
+ action_missing(@_action_name)
+ end
+
# Override this to change the conditions that will raise an
# ActionNotFound error. If you accept a difference case,
# you must handle it by also overriding process_action and
# handling the case.
- def respond_to_action?(action_name)
- action_method?(action_name) || respond_to?(:action_missing, true)
+ def method_for_action(action_name)
+ if action_method?(action_name) then action_name
+ elsif respond_to?(:action_missing, true) then "_handle_action_missing"
+ end
end
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb
index 3aff83a209..51b968c694 100644
--- a/actionpack/lib/action_controller/abstract/callbacks.rb
+++ b/actionpack/lib/action_controller/abstract/callbacks.rb
@@ -8,8 +8,8 @@ module AbstractController
define_callbacks :process_action, "response_body"
end
- def process_action
- _run_process_action_callbacks(action_name) do
+ def process_action(method_name)
+ _run_process_action_callbacks(method_name) do
super
end
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 1adcc9c71f..3ee17769a8 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -114,14 +114,22 @@ module ActionController
super(url, status)
end
- def process_action
+ def process_action(method_name)
ret = super
render if response_body.nil?
ret
end
-
- def respond_to_action?(action_name)
- super || view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
+
+ def _implicit_render
+ render
+ end
+
+ def method_for_action(action_name)
+ super || begin
+ if view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
+ "_implicit_render"
+ end
+ end
end
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index 993e571aba..9884ed12e5 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -69,17 +69,13 @@ module ActionController
super
end
-
- def respond_to_action?(action_name)
- if respond_to?(:method_missing) && !respond_to?(:action_missing)
- self.class.class_eval do
- private
- def action_missing(name, *args)
- method_missing(name.to_sym, *args)
- end
- end
- end
- super
+
+ def _handle_method_missing
+ method_missing(@_action_name.to_sym)
+ end
+
+ def method_for_action(action_name)
+ super || (respond_to?(:method_missing) && "_handle_method_missing")
end
def _layout_for_name(name)
diff --git a/actionpack/test/abstract_controller/abstract_controller_test.rb b/actionpack/test/abstract_controller/abstract_controller_test.rb
index 689aa99fd8..9c028e7d1e 100644
--- a/actionpack/test/abstract_controller/abstract_controller_test.rb
+++ b/actionpack/test/abstract_controller/abstract_controller_test.rb
@@ -201,11 +201,10 @@ module AbstractController
def fail() self.response_body = "fail" end
private
-
- def respond_to_action?(action_name)
- action_name.to_s != "fail"
+
+ def method_for_action(action_name)
+ action_name.to_s != "fail" && action_name
end
-
end
class TestRespondToAction < ActiveSupport::TestCase
--
cgit v1.2.3
From 5a45446cff0daf4ca747257a8779dcd5d9cae1d7 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 15 May 2009 17:49:11 -0700
Subject: Ported Rescuable to new base
---
.../lib/action_controller/base/chained/filters.rb | 2 +-
.../lib/action_controller/dispatch/middlewares.rb | 1 +
actionpack/lib/action_controller/new_base.rb | 1 +
actionpack/lib/action_controller/new_base/base.rb | 50 +++++++++++---------
.../action_controller/new_base/compatibility.rb | 13 ++++++
actionpack/lib/action_controller/new_base/http.rb | 4 +-
.../lib/action_controller/new_base/rescuable.rb | 53 ++++++++++++++++++++++
.../lib/action_controller/new_base/testing.rb | 2 +-
actionpack/test/abstract_unit2.rb | 12 ++++-
9 files changed, 111 insertions(+), 27 deletions(-)
create mode 100644 actionpack/lib/action_controller/new_base/rescuable.rb
diff --git a/actionpack/lib/action_controller/base/chained/filters.rb b/actionpack/lib/action_controller/base/chained/filters.rb
index 9022b8b279..98fe306fd5 100644
--- a/actionpack/lib/action_controller/base/chained/filters.rb
+++ b/actionpack/lib/action_controller/base/chained/filters.rb
@@ -160,7 +160,7 @@ module ActionController #:nodoc:
def convert_only_and_except_options_to_sets_of_strings(opts)
[:only, :except].each do |key|
if values = opts[key]
- opts[key] = Array(values).map(&:to_s).to_set
+ opts[key] = Array(values).map {|val| val.to_s }.to_set
end
end
end
diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb
index f99637b109..0e4ab6fa39 100644
--- a/actionpack/lib/action_controller/dispatch/middlewares.rb
+++ b/actionpack/lib/action_controller/dispatch/middlewares.rb
@@ -6,6 +6,7 @@ use "ActionDispatch::Failsafe"
use "ActionDispatch::ShowExceptions", lambda { ActionController::Base.consider_all_requests_local }
use "ActionDispatch::Rescue", lambda {
controller = (::ApplicationController rescue ActionController::Base)
+ # TODO: Replace with controller.action(:_rescue_action)
controller.method(:rescue_action)
}
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 1f215bb6f1..bc47713529 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -7,6 +7,7 @@ module ActionController
autoload :Rails2Compatibility, "action_controller/new_base/compatibility"
autoload :Redirector, "action_controller/new_base/redirector"
autoload :Renderer, "action_controller/new_base/renderer"
+ autoload :Rescue, "action_controller/new_base/rescuable"
autoload :Testing, "action_controller/new_base/testing"
autoload :UrlFor, "action_controller/new_base/url_for"
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 3ee17769a8..c25ffd5c84 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -12,14 +12,40 @@ module ActionController
include ActionController::Renderer
include ActionController::Layouts
include ActionController::ConditionalGet
-
+
# Legacy modules
include SessionManagement
include ActionDispatch::StatusCodes
-
+
# Rails 2.x compatibility
include ActionController::Rails2Compatibility
-
+
+ # TODO: Extract into its own module
+ # This should be moved together with other normalizing behavior
+ module ImplicitRender
+ def process_action(method_name)
+ ret = super
+ render if response_body.nil?
+ ret
+ end
+
+ def _implicit_render
+ render
+ end
+
+ def method_for_action(action_name)
+ super || begin
+ if view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
+ "_implicit_render"
+ end
+ end
+ end
+ end
+
+ include ImplicitRender
+
+ include ActionController::Rescue
+
def self.inherited(klass)
::ActionController::Base.subclasses << klass.to_s
super
@@ -113,23 +139,5 @@ module ActionController
super(url, status)
end
-
- def process_action(method_name)
- ret = super
- render if response_body.nil?
- ret
- end
-
- def _implicit_render
- render
- end
-
- def method_for_action(action_name)
- super || begin
- if view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
- "_implicit_render"
- end
- end
- end
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index 9884ed12e5..0a283887b6 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -45,6 +45,14 @@ module ActionController
cattr_accessor :use_accept_header
self.use_accept_header = true
+
+ cattr_accessor :page_cache_directory
+ self.page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : ""
+
+ cattr_reader :cache_store
+
+ cattr_accessor :consider_all_requests_local
+ self.consider_all_requests_local = true
end
module ClassMethods
@@ -53,6 +61,11 @@ module ActionController
def rescue_action(env)
raise env["action_dispatch.rescue.exception"]
end
+
+ # Defines the storage option for cached fragments
+ def cache_store=(store_option)
+ @@cache_store = ActiveSupport::Cache.lookup_store(store_option)
+ end
end
def initialize(*)
diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb
index e9a1d5b12f..8891a2a8c3 100644
--- a/actionpack/lib/action_controller/new_base/http.rb
+++ b/actionpack/lib/action_controller/new_base/http.rb
@@ -48,8 +48,6 @@ module ActionController
@_response = ActionDispatch::Response.new
@_response.request = request
process(name)
- @_response.body = response_body
- @_response.prepare!
to_rack
end
@@ -62,6 +60,8 @@ module ActionController
# :api: private
def to_rack
+ @_response.body = response_body
+ @_response.prepare!
@_response.to_a
end
end
diff --git a/actionpack/lib/action_controller/new_base/rescuable.rb b/actionpack/lib/action_controller/new_base/rescuable.rb
new file mode 100644
index 0000000000..29ffe19d5f
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/rescuable.rb
@@ -0,0 +1,53 @@
+module ActionController #:nodoc:
+ # Actions that fail to perform as expected throw exceptions. These
+ # exceptions can either be rescued for the public view (with a nice
+ # user-friendly explanation) or for the developers view (with tons of
+ # debugging information). The developers view is already implemented by
+ # the Action Controller, but the public view should be tailored to your
+ # specific application.
+ #
+ # The default behavior for public exceptions is to render a static html
+ # file with the name of the error code thrown. If no such file exists, an
+ # empty response is sent with the correct status code.
+ #
+ # You can override what constitutes a local request by overriding the
+ # local_request? method in your own controller. Custom rescue
+ # behavior is achieved by overriding the rescue_action_in_public
+ # and rescue_action_locally methods.
+ module Rescue
+ extend ActiveSupport::DependencyModule
+
+ included do
+ include ActiveSupport::Rescuable
+ end
+
+ module ClassMethods
+ # This can be removed once we can move action(:_rescue_action) into middlewares.rb
+ # Currently, it does controller.method(:rescue_action), which is hiding the implementation
+ # difference between the old and new base.
+ def rescue_action(env)
+ action(:_rescue_action).call(env)
+ end
+ end
+
+ attr_internal :rescued_exception
+
+ private
+
+ def method_for_action(action_name)
+ return action_name if self.rescued_exception = request.env.delete("action_dispatch.rescue.exception")
+ super
+ end
+
+ def _rescue_action
+ rescue_with_handler(rescued_exception) || raise(rescued_exception)
+ end
+
+ def process_action(*)
+ super
+ rescue Exception => exception
+ self.rescued_exception = exception
+ _rescue_action
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb
index 106990b9ba..b39d8d539d 100644
--- a/actionpack/lib/action_controller/new_base/testing.rb
+++ b/actionpack/lib/action_controller/new_base/testing.rb
@@ -7,7 +7,7 @@ module ActionController
@_response = response
@_response.request = request
ret = process(request.parameters[:action])
- @_response.body = self.response_body
+ @_response.body = self.response_body || " "
@_response.prepare!
set_test_assigns
ret
diff --git a/actionpack/test/abstract_unit2.rb b/actionpack/test/abstract_unit2.rb
index 932f594ad2..519e6bea36 100644
--- a/actionpack/test/abstract_unit2.rb
+++ b/actionpack/test/abstract_unit2.rb
@@ -11,11 +11,19 @@ require 'action_controller/new_base'
require 'fixture_template'
require 'action_controller/testing/process2'
require 'action_view/test_case'
+require 'action_controller/testing/integration'
+require 'active_support/dependencies'
+
+ActiveSupport::Dependencies.hook!
FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
module ActionController
-
+ Base.session = {
+ :key => '_testing_session',
+ :secret => '8273f16463985e2b3747dc25e30f2528'
+}
+
class ActionControllerError < StandardError #:nodoc:
end
@@ -126,6 +134,6 @@ module ActionController
"Expected no partials to be rendered"
end
end
- end
+ end
end
end
--
cgit v1.2.3
From a6d8ca0f0e65ce509793713cb1efe4ab721b9eb4 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Sat, 16 May 2009 17:02:43 +0200
Subject: Include guides directory in the rails gem
---
railties/Rakefile | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/railties/Rakefile b/railties/Rakefile
index 133a603ed6..69c1ca762a 100644
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -249,7 +249,7 @@ def copy_with_rewritten_ruby_path(src_file, dest_file)
end
desc 'Generate guides (for authors), use ONLY=foo to process just "foo.textile"'
-task :guides do
+task :generate_guides do
ENV["WARN_BROKEN_LINKS"] = "1" # authors can't disable this
ruby "guides/rails_guides.rb"
end
@@ -298,6 +298,7 @@ PKG_FILES = FileList[
'doc/**/*',
'dispatches/**/*',
'environments/**/*',
+ 'guides/**/*',
'helpers/**/*',
'generators/**/*',
'html/**/*',
@@ -324,7 +325,7 @@ spec = Gem::Specification.new do |s|
s.rdoc_options << '--exclude' << '.'
s.has_rdoc = false
- s.files = PKG_FILES.to_a.delete_if {|f| f.include?('.svn')}
+ s.files = PKG_FILES.to_a.delete_if {|f| f =~ %r{\.svn|guides/output}}
s.require_path = 'lib'
s.bindir = "bin" # Use these for applications.
s.executables = ["rails"]
@@ -350,7 +351,7 @@ task :pgem => [:gem] do
end
desc "Publish the guides"
-task :pguides => :guides do
+task :pguides => :generate_guides do
require 'rake/contrib/sshpublisher'
mkdir_p 'pkg'
`tar -czf pkg/guides.gz guides/output`
--
cgit v1.2.3
From 7f318c3ec535afe53733c55cd0ecaccc16a8b944 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp
Date: Sat, 16 May 2009 14:15:26 -0400
Subject: Instead of checking Rails.env.test? in Failsafe middleware, check
env["rails.raise_exceptions"]
---
actionpack/lib/action_dispatch/middleware/failsafe.rb | 5 ++---
actionpack/test/new_base/render_action_test.rb | 6 ++++--
actionpack/test/new_base/render_test.rb | 6 +++---
3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/actionpack/lib/action_dispatch/middleware/failsafe.rb b/actionpack/lib/action_dispatch/middleware/failsafe.rb
index 836098482c..389accbc36 100644
--- a/actionpack/lib/action_dispatch/middleware/failsafe.rb
+++ b/actionpack/lib/action_dispatch/middleware/failsafe.rb
@@ -10,9 +10,8 @@ module ActionDispatch
def call(env)
@app.call(env)
rescue Exception => exception
- # Reraise exception in test environment
- if defined?(Rails) && Rails.env.test?
- raise exception
+ if env["rails.raise_exceptions"]
+ raise
else
failsafe_response(exception)
end
diff --git a/actionpack/test/new_base/render_action_test.rb b/actionpack/test/new_base/render_action_test.rb
index f25faee433..96666077d2 100644
--- a/actionpack/test/new_base/render_action_test.rb
+++ b/actionpack/test/new_base/render_action_test.rb
@@ -92,7 +92,7 @@ module RenderAction
test "raises an exception when requesting a layout and none exist" do
assert_raise(ArgumentError, /no default layout for RenderAction::BasicController in/) do
- get "/render_action/basic/hello_world_with_layout"
+ get "/render_action/basic/hello_world_with_layout", {}, "rails.raise_exceptions" => true
end
end
end
@@ -117,7 +117,9 @@ module RenderAction
describe "rendering a normal template with full path with layout => 'greetings'"
test "raises an exception when requesting a layout that does not exist" do
- assert_raise(ActionView::MissingTemplate) { get "/render_action/basic/hello_world_with_custom_layout" }
+ assert_raise(ActionView::MissingTemplate) do
+ get "/render_action/basic/hello_world_with_custom_layout", {}, "rails.raise_exceptions" => true
+ end
end
end
diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb
index b1867fdcc2..16578fbc82 100644
--- a/actionpack/test/new_base/render_test.rb
+++ b/actionpack/test/new_base/render_test.rb
@@ -48,7 +48,7 @@ module Render
test "raises an exception" do
assert_raises(AbstractController::DoubleRenderError) do
- get "/render/double_render"
+ get "/render/double_render", {}, "rails.raise_exceptions" => true
end
end
end
@@ -58,13 +58,13 @@ module Render
test "raises an exception when a method of Object is called" do
assert_raises(AbstractController::ActionNotFound) do
- get "/render/blank_render/clone"
+ get "/render/blank_render/clone", {}, "rails.raise_exceptions" => true
end
end
test "raises an exception when a private method is called" do
assert_raises(AbstractController::ActionNotFound) do
- get "/render/blank_render/secretz"
+ get "/render/blank_render/secretz", {}, "rails.raise_exceptions" => true
end
end
end
--
cgit v1.2.3
From 59c4d9a5b40dca45b095430d43c04d6c6541992d Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp
Date: Sat, 16 May 2009 14:18:10 -0400
Subject: Changelog
---
actionpack/CHANGELOG | 2 ++
1 file changed, 2 insertions(+)
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 204f5ae272..c1dc6f2ab4 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Instead of checking Rails.env.test? in Failsafe middleware, check env["rails.raise_exceptions"] [Bryan Helmkamp]
+
* Fixed that TestResponse.cookies was returning cookies unescaped #1867 [Doug McInnes]
--
cgit v1.2.3
From 8e6a18d8672f7efe6ef79b49185e4a6a23e4e547 Mon Sep 17 00:00:00 2001
From: Yehuda Katz
Date: Sat, 16 May 2009 12:09:25 -0700
Subject: Get AR CI passing again by requiring the entire core_ext
Note that this includes Time and Date; we should
really figure out what parts of core_ext are really
required for AR and require just those.
---
activerecord/lib/active_record.rb | 3 +++
1 file changed, 3 insertions(+)
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 2d98239052..b5c17cb23b 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -25,6 +25,9 @@ activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
$:.unshift(activesupport_path) if File.directory?(activesupport_path)
require 'active_support'
+# TODO: Figure out what parts of AS are *actually* required and use those
+require 'active_support/core_ext'
+
module ActiveRecord
# TODO: Review explicit loads to see if they will automatically be handled by the initilizer.
def self.load_all!
--
cgit v1.2.3
From db1bf3650d7450811f5dfddc5c5163a70683e37a Mon Sep 17 00:00:00 2001
From: Yehuda Katz
Date: Sat, 16 May 2009 12:13:41 -0700
Subject: Fix ActionMailer Symbol#to_proc instance
---
actionpack/lib/action_view/template/handlers.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb
index 0590372d09..faf54b9fe5 100644
--- a/actionpack/lib/action_view/template/handlers.rb
+++ b/actionpack/lib/action_view/template/handlers.rb
@@ -33,7 +33,7 @@ module ActionView #:nodoc:
end
def template_handler_extensions
- @@template_handlers.keys.map(&:to_s).sort
+ @@template_handlers.keys.map {|key| key.to_s }.sort
end
def registered_template_handler(extension)
--
cgit v1.2.3
From 4fa871654dc6e591c08cbc53e7eac2e008056fee Mon Sep 17 00:00:00 2001
From: Yehuda Katz
Date: Sat, 16 May 2009 12:28:25 -0700
Subject: Get Railties passing again
---
railties/builtin/rails_info/rails/info.rb | 10 +++++++---
railties/lib/initializer.rb | 2 +-
railties/lib/rails/plugin/loader.rb | 12 ++++++------
railties/lib/rails/plugin/locator.rb | 2 +-
.../generators/applications/app/template_runner.rb | 2 +-
.../generators/components/model/templates/model.rb | 2 +-
railties/lib/tasks/gems.rake | 8 ++++----
railties/test/rails_info_test.rb | 2 ++
8 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/railties/builtin/rails_info/rails/info.rb b/railties/builtin/rails_info/rails/info.rb
index 0dd1c090c1..fdacc469f5 100644
--- a/railties/builtin/rails_info/rails/info.rb
+++ b/railties/builtin/rails_info/rails/info.rb
@@ -1,9 +1,13 @@
+require "active_support/core_ext/object/misc"
+require "cgi"
+require "active_support/core_ext/cgi"
+
module Rails
module Info
mattr_accessor :properties
class << (@@properties = [])
def names
- map &:first
+ map {|val| val.first }
end
def value_for(property_name)
@@ -53,7 +57,7 @@ module Rails
alias inspect to_s
def to_html
- returning table = '' do
+ (table = '').tap do
properties.each do |(name, value)|
table << %(#{CGI.escapeHTML(name.to_s)} )
formatted_value = if value.kind_of?(Array)
@@ -108,7 +112,7 @@ module Rails
end
property 'Middleware' do
- ActionController::Dispatcher.middleware.active.map(&:inspect)
+ ActionController::Dispatcher.middleware.active.map {|middle| middle.inspect }
end
# The Rails Git revision, if it's checked out into vendor/rails.
diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index 40000f0dfd..e4d7589aba 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -311,7 +311,7 @@ module Rails
end
def check_for_unbuilt_gems
- unbuilt_gems = @configuration.gems.select(&:frozen?).reject(&:built?)
+ unbuilt_gems = @configuration.gems.select {|gem| gem.frozen? && !gem.built? }
if unbuilt_gems.size > 0
# don't print if the gems:build rake tasks are being run
unless $gems_build_rake_task
diff --git a/railties/lib/rails/plugin/loader.rb b/railties/lib/rails/plugin/loader.rb
index 66e01d70da..bc22dfc591 100644
--- a/railties/lib/rails/plugin/loader.rb
+++ b/railties/lib/rails/plugin/loader.rb
@@ -24,7 +24,7 @@ module Rails
# Returns the plugins that are in engine-form (have an app/ directory)
def engines
- @engines ||= plugins.select(&:engine?)
+ @engines ||= plugins.select {|plugin| plugin.engine? }
end
# Returns all the plugins that could be found by the current locators.
@@ -66,7 +66,7 @@ module Rails
end
def engine_metal_paths
- engines.collect(&:metal_path)
+ engines.collect {|engine| engine.metal_path }
end
protected
@@ -79,18 +79,18 @@ module Rails
end
def add_engine_routing_configurations
- engines.select(&:routed?).collect(&:routing_file).each do |routing_file|
+ engines.select {|engine| engine.routed? }.map {|engine| engine.routing_file }.each do |routing_file|
ActionController::Routing::Routes.add_configuration_file(routing_file)
end
end
def add_engine_controller_paths
- ActionController::Routing.controller_paths += engines.collect(&:controller_path)
+ ActionController::Routing.controller_paths += engines.collect {|engine| engine.controller_path }
end
def add_engine_view_paths
# reverse it such that the last engine can overwrite view paths from the first, like with routes
- paths = ActionView::PathSet.new(engines.collect(&:view_path).reverse)
+ paths = ActionView::PathSet.new(engines.collect {|engine| engine.view_path }.reverse)
ActionController::Base.view_paths.concat(paths)
ActionMailer::Base.view_paths.concat(paths) if configuration.frameworks.include?(:action_mailer)
end
@@ -170,7 +170,7 @@ module Rails
# so we load all in alphabetical order. If it is an empty array, we load no plugins, if it is
# non empty, we load the named plugins in the order specified.
def registered_plugin_names
- configuration.plugins ? configuration.plugins.map(&:to_s) : nil
+ configuration.plugins ? configuration.plugins.map {|plugin| plugin.to_s } : nil
end
def loaded?(plugin_name)
diff --git a/railties/lib/rails/plugin/locator.rb b/railties/lib/rails/plugin/locator.rb
index a6fc388a8e..1057c004e0 100644
--- a/railties/lib/rails/plugin/locator.rb
+++ b/railties/lib/rails/plugin/locator.rb
@@ -25,7 +25,7 @@ module Rails
end
def plugin_names
- plugins.map(&:name)
+ plugins.map {|plugin| plugin.name }
end
end
diff --git a/railties/lib/rails_generator/generators/applications/app/template_runner.rb b/railties/lib/rails_generator/generators/applications/app/template_runner.rb
index 3b49b1fa92..0e24d11950 100644
--- a/railties/lib/rails_generator/generators/applications/app/template_runner.rb
+++ b/railties/lib/rails_generator/generators/applications/app/template_runner.rb
@@ -227,7 +227,7 @@ module Rails
#
def generate(what, *args)
log 'generating', what
- argument = args.map(&:to_s).flatten.join(" ")
+ argument = args.map {|arg| arg.to_s }.flatten.join(" ")
in_root { run_ruby_script("script/generate #{what} #{argument}", false) }
end
diff --git a/railties/lib/rails_generator/generators/components/model/templates/model.rb b/railties/lib/rails_generator/generators/components/model/templates/model.rb
index 6fcf393bdf..0656b06dfe 100644
--- a/railties/lib/rails_generator/generators/components/model/templates/model.rb
+++ b/railties/lib/rails_generator/generators/components/model/templates/model.rb
@@ -1,5 +1,5 @@
class <%= class_name %> < ActiveRecord::Base
-<% attributes.select(&:reference?).each do |attribute| -%>
+<% attributes.select {|attr| attr.reference? }.each do |attribute| -%>
belongs_to :<%= attribute.name %>
<% end -%>
end
diff --git a/railties/lib/tasks/gems.rake b/railties/lib/tasks/gems.rake
index 7cf7061f38..e496e1a04f 100644
--- a/railties/lib/tasks/gems.rake
+++ b/railties/lib/tasks/gems.rake
@@ -20,7 +20,7 @@ namespace :gems do
desc "Build any native extensions for unpacked gems"
task :build do
$gems_build_rake_task = true
- frozen_gems.each &:build
+ frozen_gems.each {|gem| gem.build }
end
namespace :build do
@@ -33,12 +33,12 @@ namespace :gems do
desc "Installs all required gems."
task :install => :base do
- current_gems.each &:install
+ current_gems.each {|gem| gem.install }
end
desc "Unpacks all required gems into vendor/gems."
task :unpack => :install do
- current_gems.each &:unpack
+ current_gems.each {|gem| gem.unpack }
end
namespace :unpack do
@@ -50,7 +50,7 @@ namespace :gems do
desc "Regenerate gem specifications in correct format."
task :refresh_specs => :base do
- current_gems.each &:refresh
+ current_gems.each {|gem| gem.refresh }
end
end
diff --git a/railties/test/rails_info_test.rb b/railties/test/rails_info_test.rb
index 971cba89d0..fdcc7a1ef6 100644
--- a/railties/test/rails_info_test.rb
+++ b/railties/test/rails_info_test.rb
@@ -14,6 +14,8 @@ unless defined?(Rails) && defined?(Rails::Info)
end
end
+require "active_support/core_ext/kernel/reporting"
+
class InfoTest < ActiveSupport::TestCase
def setup
Rails.send :remove_const, :Info
--
cgit v1.2.3
From 842dab0c29bb05b98856aeb333bb0c2d14601a50 Mon Sep 17 00:00:00 2001
From: Jeffrey Chupp
Date: Sat, 4 Apr 2009 09:36:32 -0500
Subject: Ensure WhiteListSanitizer allows dl tag [#2393 state:resolved]
Signed-off-by: Pratik Naik
---
actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
index ae20f9947c..a992f7d912 100644
--- a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
+++ b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
@@ -73,7 +73,7 @@ module HTML
# Specifies the default Set of tags that the #sanitize helper will allow unscathed.
self.allowed_tags = Set.new(%w(strong em b i p code pre tt samp kbd var sub
- sup dfn cite big small address hr br div span h1 h2 h3 h4 h5 h6 ul ol li dt dd abbr
+ sup dfn cite big small address hr br div span h1 h2 h3 h4 h5 h6 ul ol li dl dt dd abbr
acronym a img blockquote del ins))
# Specifies the default Set of html attributes that the #sanitize helper will leave
--
cgit v1.2.3
From a9e8c4b37480564d27883dffe9134a9f95796a15 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Sun, 17 May 2009 14:31:54 +0200
Subject: Ensure rake test does not run new base tests as that requires
rack/test
---
actionpack/Rakefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 6ce8179646..41b190130e 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -22,7 +22,7 @@ task :default => [ :test ]
# Run the unit tests
desc "Run all unit tests"
-task :test => [:test_action_pack, :test_active_record_integration, :test_new_base]
+task :test => [:test_action_pack, :test_active_record_integration]
Rake::TestTask.new(:test_action_pack) do |t|
t.libs << "test"
--
cgit v1.2.3
From 25724eede9b5a62c74b3b78245944638f1cfcef4 Mon Sep 17 00:00:00 2001
From: Daniel Guettler
Date: Sun, 17 May 2009 14:48:20 +0200
Subject: has_one :through should not create a new association when assigned
nil [#698 state:resolved]
Signed-off-by: Pratik Naik
---
.../associations/has_one_through_association.rb | 16 ++++++++--------
.../associations/has_one_through_associations_test.rb | 9 ++++++++-
2 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/activerecord/lib/active_record/associations/has_one_through_association.rb b/activerecord/lib/active_record/associations/has_one_through_association.rb
index 8073ebaf9f..d93c8e7852 100644
--- a/activerecord/lib/active_record/associations/has_one_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_through_association.rb
@@ -1,31 +1,31 @@
module ActiveRecord
module Associations
class HasOneThroughAssociation < HasManyThroughAssociation
-
+
def create_through_record(new_value) #nodoc:
klass = @reflection.through_reflection.klass
current_object = @owner.send(@reflection.through_reflection.name)
-
+
if current_object
- current_object.update_attributes(construct_join_attributes(new_value))
+ new_value ? current_object.update_attributes(construct_join_attributes(new_value)) : current_object.destroy
else
- @owner.send(@reflection.through_reflection.name, klass.send(:create, construct_join_attributes(new_value)))
+ @owner.send(@reflection.through_reflection.name, klass.send(:create, construct_join_attributes(new_value))) if new_value
end
end
-
+
private
def find(*args)
super(args.merge(:limit => 1))
end
-
+
def find_target
super.first
end
def reset_target!
@target = nil
- end
- end
+ end
+ end
end
end
diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb
index 12c598751b..ab6e6d20fc 100644
--- a/activerecord/test/cases/associations/has_one_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb
@@ -43,7 +43,14 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
@member.reload
end
end
-
+
+ def test_set_record_to_nil_should_delete_association
+ @member.club = nil
+ @member.reload
+ assert_equal nil, @member.current_membership
+ assert_nil @member.club
+ end
+
def test_has_one_through_polymorphic
assert_equal clubs(:moustache_club), @member.sponsor_club
end
--
cgit v1.2.3
From d6645a5e52308a3270bf11f8c71cbf7c7f9d48f3 Mon Sep 17 00:00:00 2001
From: Jacob Kjeldahl
Date: Tue, 27 Jan 2009 15:00:18 +0100
Subject: Supply valid ruby-prof parameters [#1804 state:resolved]
Signed-off-by: Pratik Naik
---
railties/lib/commands/performance/profiler.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/railties/lib/commands/performance/profiler.rb b/railties/lib/commands/performance/profiler.rb
index fd111bae87..7df840f197 100644
--- a/railties/lib/commands/performance/profiler.rb
+++ b/railties/lib/commands/performance/profiler.rb
@@ -29,7 +29,7 @@ begin
printer_class = RubyProf::FlatPrinter
end
printer = printer_class.new(results)
- printer.print($stderr, 0)
+ printer.print($stderr)
rescue LoadError
require "prof"
$stderr.puts 'Using the old ruby-prof extension.'
--
cgit v1.2.3
From 34874b3bcdb42a710baecf8c6acfa3a30333d01a Mon Sep 17 00:00:00 2001
From: Paulo Schneider
Date: Mon, 6 Apr 2009 21:38:24 +0100
Subject: Fix typo in the generated routes.rb [#2433 state:resolved]
Signed-off-by: Pratik Naik
---
railties/configs/routes.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/railties/configs/routes.rb b/railties/configs/routes.rb
index 4f3d9d22dd..ea14ce1bfc 100644
--- a/railties/configs/routes.rb
+++ b/railties/configs/routes.rb
@@ -37,7 +37,7 @@ ActionController::Routing::Routes.draw do |map|
# Install the default routes as the lowest priority.
# Note: These default routes make all actions in every controller accessible via GET requests. You should
- # consider removing the them or commenting them out if you're using named routes and resources.
+ # consider removing or commenting them out if you're using named routes and resources.
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
--
cgit v1.2.3
From 344ee681d6a89ea1da71c39e75c29e0cbda44914 Mon Sep 17 00:00:00 2001
From: Mike Gunderloy
Date: Wed, 18 Mar 2009 13:47:53 -0500
Subject: Remove obsolete wiki reference [#2291 state:resolved]
Signed-off-by: Pratik Naik
---
railties/lib/rails_generator/scripts.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/railties/lib/rails_generator/scripts.rb b/railties/lib/rails_generator/scripts.rb
index 9b1a99838a..3763b75dba 100644
--- a/railties/lib/rails_generator/scripts.rb
+++ b/railties/lib/rails_generator/scripts.rb
@@ -57,7 +57,7 @@ module Rails
usage << <
Date: Sun, 17 May 2009 10:37:30 -0500
Subject: Add support for parsing XML and JSON from an IO as well as a string
[#2659 state:resolved]
Signed-off-by: Joshua Peek
---
.../lib/action_dispatch/middleware/params_parser.rb | 8 +++-----
.../lib/active_support/json/backends/jsongem.rb | 5 ++++-
activesupport/lib/active_support/json/backends/yaml.rb | 5 ++++-
activesupport/lib/active_support/xml_mini/jdom.rb | 16 ++++++++++------
activesupport/lib/active_support/xml_mini/libxml.rb | 16 ++++++++++------
activesupport/lib/active_support/xml_mini/nokogiri.rb | 16 ++++++++++------
activesupport/lib/active_support/xml_mini/rexml.rb | 14 +++++++++-----
activesupport/test/xml_mini/nokogiri_engine_test.rb | 13 +++++++++++++
activesupport/test/xml_mini/rexml_engine_test.rb | 14 ++++++++++++++
9 files changed, 77 insertions(+), 30 deletions(-)
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index 58d527a6e7..a42c6598e0 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -32,16 +32,14 @@ module ActionDispatch
when Proc
strategy.call(request.raw_post)
when :xml_simple, :xml_node
- body = request.raw_post
- body.blank? ? {} : Hash.from_xml(body).with_indifferent_access
+ request.body.size == 0 ? {} : Hash.from_xml(request.body).with_indifferent_access
when :yaml
YAML.load(request.raw_post)
when :json
- body = request.raw_post
- if body.blank?
+ if request.body.size == 0
{}
else
- data = ActiveSupport::JSON.decode(body)
+ data = ActiveSupport::JSON.decode(request.body)
data = {:_json => data} unless data.is_a?(Hash)
data.with_indifferent_access
end
diff --git a/activesupport/lib/active_support/json/backends/jsongem.rb b/activesupport/lib/active_support/json/backends/jsongem.rb
index de847e30a3..d1a1cdd7d7 100644
--- a/activesupport/lib/active_support/json/backends/jsongem.rb
+++ b/activesupport/lib/active_support/json/backends/jsongem.rb
@@ -6,8 +6,11 @@ module ActiveSupport
module JSONGem
extend self
- # Converts a JSON string into a Ruby object.
+ # Parses a JSON string or IO and convert it into an object
def decode(json)
+ if json.respond_to?(:read)
+ json = json.read
+ end
data = ::JSON.parse(json)
if ActiveSupport.parse_json_times
convert_dates_from(data)
diff --git a/activesupport/lib/active_support/json/backends/yaml.rb b/activesupport/lib/active_support/json/backends/yaml.rb
index c7db508c23..1c18fc4801 100644
--- a/activesupport/lib/active_support/json/backends/yaml.rb
+++ b/activesupport/lib/active_support/json/backends/yaml.rb
@@ -9,8 +9,11 @@ module ActiveSupport
module Yaml
extend self
- # Converts a JSON string into a Ruby object.
+ # Parses a JSON string or IO and converts it into an object
def decode(json)
+ if json.respond_to?(:read)
+ json = json.read
+ end
YAML.load(convert_json_to_yaml(json))
rescue ArgumentError => e
raise ParseError, "Invalid JSON string"
diff --git a/activesupport/lib/active_support/xml_mini/jdom.rb b/activesupport/lib/active_support/xml_mini/jdom.rb
index d795d55690..1cd714d864 100644
--- a/activesupport/lib/active_support/xml_mini/jdom.rb
+++ b/activesupport/lib/active_support/xml_mini/jdom.rb
@@ -24,15 +24,19 @@ module ActiveSupport
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?
+ # Parse an XML Document string or IO into a simple hash using Java's jdom.
+ # data::
+ # XML Document string or IO to parse
+ def parse(data)
+ if data.respond_to?(:read)
+ data = data.read
+ end
+
+ if data.blank?
{}
else
@dbf = DocumentBuilderFactory.new_instance
- xml_string_reader = StringReader.new(string)
+ xml_string_reader = StringReader.new(data)
xml_input_source = InputSource.new(xml_string_reader)
doc = @dbf.new_document_builder.parse(xml_input_source)
merge_element!({}, doc.document_element)
diff --git a/activesupport/lib/active_support/xml_mini/libxml.rb b/activesupport/lib/active_support/xml_mini/libxml.rb
index 370205409a..d4c4dc7be5 100644
--- a/activesupport/lib/active_support/xml_mini/libxml.rb
+++ b/activesupport/lib/active_support/xml_mini/libxml.rb
@@ -5,16 +5,20 @@ module ActiveSupport
module XmlMini_LibXML #:nodoc:
extend self
- # Parse an XML Document string into a simple hash using libxml.
- # string::
- # XML Document string to parse
- def parse(string)
+ # Parse an XML Document string or IO into a simple hash using libxml.
+ # data::
+ # XML Document string or IO to parse
+ def parse(data)
+ if data.respond_to?(:read)
+ data = data.read
+ end
+
LibXML::XML.default_keep_blanks = false
- if string.blank?
+ if data.blank?
{}
else
- LibXML::XML::Parser.string(string.strip).parse.to_hash
+ LibXML::XML::Parser.string(data.strip).parse.to_hash
end
end
diff --git a/activesupport/lib/active_support/xml_mini/nokogiri.rb b/activesupport/lib/active_support/xml_mini/nokogiri.rb
index 8f9676e4f6..7337c143c9 100644
--- a/activesupport/lib/active_support/xml_mini/nokogiri.rb
+++ b/activesupport/lib/active_support/xml_mini/nokogiri.rb
@@ -5,14 +5,18 @@ module ActiveSupport
module XmlMini_Nokogiri #:nodoc:
extend self
- # Parse an XML Document string into a simple hash using libxml / nokogiri.
- # string::
- # XML Document string to parse
- def parse(string)
- if string.blank?
+ # Parse an XML Document string or IO into a simple hash using libxml / nokogiri.
+ # data::
+ # XML Document string or IO to parse
+ def parse(data)
+ if data.respond_to?(:read)
+ data = data.read
+ end
+
+ if data.blank?
{}
else
- doc = Nokogiri::XML(string)
+ doc = Nokogiri::XML(data)
raise doc.errors.first if doc.errors.length > 0
doc.to_hash
end
diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb
index 5033210aae..1184d2d6c9 100644
--- a/activesupport/lib/active_support/xml_mini/rexml.rb
+++ b/activesupport/lib/active_support/xml_mini/rexml.rb
@@ -7,16 +7,20 @@ module ActiveSupport
CONTENT_KEY = '__content__'.freeze
- # Parse an XML Document string into a simple hash
+ # Parse an XML Document string or IO into a simple hash
#
# Same as XmlSimple::xml_in but doesn't shoot itself in the foot,
# and uses the defaults from ActiveSupport
#
- # string::
- # XML Document string to parse
- def parse(string)
+ # data::
+ # XML Document string or IO to parse
+ def parse(data)
+ if data.respond_to?(:read)
+ data = data.read
+ end
+
require 'rexml/document' unless defined?(REXML::Document)
- doc = REXML::Document.new(string)
+ doc = REXML::Document.new(data)
merge_element!({}, doc.root)
end
diff --git a/activesupport/test/xml_mini/nokogiri_engine_test.rb b/activesupport/test/xml_mini/nokogiri_engine_test.rb
index 886a9d1aba..7c3a591e63 100644
--- a/activesupport/test/xml_mini/nokogiri_engine_test.rb
+++ b/activesupport/test/xml_mini/nokogiri_engine_test.rb
@@ -148,6 +148,19 @@ class NokogiriEngineTest < Test::Unit::TestCase
eoxml
end
+ def test_parse_from_io
+ io = StringIO.new(<<-eoxml)
+
+ good
+
+ hello everyone
+
+ morning
+
+ eoxml
+ XmlMini.parse(io)
+ end
+
private
def assert_equal_rexml(xml)
hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) }
diff --git a/activesupport/test/xml_mini/rexml_engine_test.rb b/activesupport/test/xml_mini/rexml_engine_test.rb
index a412d8ca05..57bb35254a 100644
--- a/activesupport/test/xml_mini/rexml_engine_test.rb
+++ b/activesupport/test/xml_mini/rexml_engine_test.rb
@@ -12,4 +12,18 @@ class REXMLEngineTest < Test::Unit::TestCase
XmlMini.backend = 'REXML'
assert_equal XmlMini_REXML, XmlMini.backend
end
+
+ def test_parse_from_io
+ XmlMini.backend = 'REXML'
+ io = StringIO.new(<<-eoxml)
+
+ good
+
+ hello everyone
+
+ morning
+
+ eoxml
+ XmlMini.parse(io)
+ end
end
--
cgit v1.2.3
From 11bac700784efe232083f94e3d28d171957e667e Mon Sep 17 00:00:00 2001
From: Lance Ivy
Date: Wed, 15 Apr 2009 16:46:30 -0700
Subject: Ensure auto_link does not ignore multiple trailing punctuations
[#2504 state:resolved]
Signed-off-by: Pratik Naik
---
actionpack/lib/action_view/helpers/text_helper.rb | 13 +++++++------
actionpack/test/template/text_helper_test.rb | 7 +++++++
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 573b99b96e..8136a1cb13 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -535,7 +535,7 @@ module ActionView
link_attributes = html_options.stringify_keys
text.gsub(AUTO_LINK_RE) do
href = $&
- punctuation = ''
+ punctuation = []
left, right = $`, $'
# detect already linked URLs and URLs in the middle of a tag
if left =~ /<[^>]+$/ && right =~ /^[^>]*>/
@@ -543,17 +543,18 @@ module ActionView
href
else
# don't include trailing punctuation character as part of the URL
- if href.sub!(/[^\w\/-]$/, '') and punctuation = $& and opening = BRACKETS[punctuation]
- if href.scan(opening).size > href.scan(punctuation).size
- href << punctuation
- punctuation = ''
+ while href.sub!(/[^\w\/-]$/, '')
+ punctuation.push $&
+ if opening = BRACKETS[punctuation.last] and href.scan(opening).size > href.scan(punctuation.last).size
+ href << punctuation.pop
+ break
end
end
link_text = block_given?? yield(href) : href
href = 'http://' + href unless href.index('http') == 0
- content_tag(:a, h(link_text), link_attributes.merge('href' => href)) + punctuation
+ content_tag(:a, h(link_text), link_attributes.merge('href' => href)) + punctuation.reverse.join('')
end
end
end
diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb
index be7163888e..a780bfc606 100644
--- a/actionpack/test/template/text_helper_test.rb
+++ b/actionpack/test/template/text_helper_test.rb
@@ -401,6 +401,13 @@ class TextHelperTest < ActionView::TestCase
auto_link("Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com.",
:link => :all, :html => { :class => "menu", :target => "_blank" })
end
+
+ def test_auto_link_with_multiple_trailing_punctuations
+ url = "http://youtube.com"
+ url_result = generate_result(url)
+ assert_equal url_result, auto_link(url)
+ assert_equal "(link: #{url_result}).", auto_link("(link: #{url}).")
+ end
def test_cycle_class
value = Cycle.new("one", 2, "3")
--
cgit v1.2.3
From 4e8c36a7417e5d447c9b15d5c61df0c014ee6d3b Mon Sep 17 00:00:00 2001
From: Chris Kampmeier
Date: Mon, 16 Mar 2009 05:56:32 -0700
Subject: Implement #many? for NamedScope and AssociationCollection using #size
[#1500 state:resolved]
Signed-off-by: Pratik Naik
---
activerecord/CHANGELOG | 2 ++
.../associations/association_collection.rb | 9 +++++
activerecord/lib/active_record/named_scope.rb | 11 +++++-
.../associations/has_many_associations_test.rb | 39 ++++++++++++++++++++++
activerecord/test/cases/named_scope_test.rb | 34 +++++++++++++++++++
5 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index d58b44144b..411b640c9e 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Implement #many? for NamedScope and AssociationCollection using #size. #1500 [Chris Kampmeier]
+
* Added :touch option to belongs_to associations that will touch the parent record when the current record is saved or destroyed [DHH]
* Added ActiveRecord::Base#touch to update the updated_at/on attributes (or another specified timestamp) with the current time [DHH]
diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb
index 26987dde97..e12f6be35d 100644
--- a/activerecord/lib/active_record/associations/association_collection.rb
+++ b/activerecord/lib/active_record/associations/association_collection.rb
@@ -302,6 +302,15 @@ module ActiveRecord
end
end
+ # Returns true if the collection has more than 1 record. Equivalent to collection.size > 1.
+ def many?
+ if block_given?
+ method_missing(:many?) { |*block_args| yield(*block_args) }
+ else
+ size > 1
+ end
+ end
+
def uniq(collection = self)
seen = Set.new
collection.inject([]) do |kept, record|
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index 07f98dc743..e7151a3d47 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -109,7 +109,7 @@ module ActiveRecord
class Scope
attr_reader :proxy_scope, :proxy_options, :current_scoped_methods_when_defined
- NON_DELEGATE_METHODS = %w(nil? send object_id class extend find size count sum average maximum minimum paginate first last empty? any? respond_to?).to_set
+ NON_DELEGATE_METHODS = %w(nil? send object_id class extend find size count sum average maximum minimum paginate first last empty? any? many? respond_to?).to_set
[].methods.each do |m|
unless m =~ /^__/ || NON_DELEGATE_METHODS.include?(m.to_s)
delegate m, :to => :proxy_found
@@ -168,6 +168,15 @@ module ActiveRecord
end
end
+ # Returns true if the named scope has more than 1 matching record.
+ def many?
+ if block_given?
+ proxy_found.many? { |*block_args| yield(*block_args) }
+ else
+ size > 1
+ end
+ end
+
protected
def proxy_found
@found || load_found
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 5df74fcdcd..d99424f9cd 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1023,6 +1023,45 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert firm.clients.loaded?
end
+ def test_calling_many_should_count_instead_of_loading_association
+ firm = companies(:first_firm)
+ assert_queries(1) do
+ firm.clients.many? # use count query
+ end
+ assert !firm.clients.loaded?
+ end
+
+ def test_calling_many_on_loaded_association_should_not_use_query
+ firm = companies(:first_firm)
+ firm.clients.collect # force load
+ assert_no_queries { assert firm.clients.many? }
+ end
+
+ def test_calling_many_should_defer_to_collection_if_using_a_block
+ firm = companies(:first_firm)
+ assert_queries(1) do
+ firm.clients.expects(:size).never
+ firm.clients.many? { true }
+ end
+ assert firm.clients.loaded?
+ end
+
+ def test_calling_many_should_return_false_if_none_or_one
+ firm = companies(:another_firm)
+ assert !firm.clients_like_ms.many?
+ assert_equal 0, firm.clients_like_ms.size
+
+ firm = companies(:first_firm)
+ assert !firm.limited_clients.many?
+ assert_equal 1, firm.limited_clients.size
+ end
+
+ def test_calling_many_should_return_true_if_more_than_one
+ firm = companies(:first_firm)
+ assert firm.clients.many?
+ assert_equal 2, firm.clients.size
+ end
+
def test_joins_with_namespaced_model_should_use_correct_type
old = ActiveRecord::Base.store_full_sti_class
ActiveRecord::Base.store_full_sti_class = true
diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb
index 7dcea6d42e..69d01d5c2a 100644
--- a/activerecord/test/cases/named_scope_test.rb
+++ b/activerecord/test/cases/named_scope_test.rb
@@ -235,6 +235,40 @@ class NamedScopeTest < ActiveRecord::TestCase
assert_no_queries { assert topics.any? }
end
+ def test_many_should_not_load_results
+ topics = Topic.base
+ assert_queries(2) do
+ topics.many? # use count query
+ topics.collect # force load
+ topics.many? # use loaded (no query)
+ end
+ end
+
+ def test_many_should_call_proxy_found_if_using_a_block
+ topics = Topic.base
+ assert_queries(1) do
+ topics.expects(:size).never
+ topics.many? { true }
+ end
+ end
+
+ def test_many_should_not_fire_query_if_named_scope_loaded
+ topics = Topic.base
+ topics.collect # force load
+ assert_no_queries { assert topics.many? }
+ end
+
+ def test_many_should_return_false_if_none_or_one
+ topics = Topic.base.scoped(:conditions => {:id => 0})
+ assert !topics.many?
+ topics = Topic.base.scoped(:conditions => {:id => 1})
+ assert !topics.many?
+ end
+
+ def test_many_should_return_true_if_more_than_one
+ assert Topic.base.many?
+ end
+
def test_should_build_with_proxy_options
topic = Topic.approved.build({})
assert topic.approved
--
cgit v1.2.3
From e41984c5f7f38b62c05dfcb54940bf51f6961aeb Mon Sep 17 00:00:00 2001
From: "Thomas E. Glasgow"
Date: Sun, 17 May 2009 18:54:34 +0200
Subject: Simplify filter_chain method implementation [#2327 state:resolved]
Signed-off-by: Pratik Naik
---
actionpack/lib/action_controller/base/chained/filters.rb | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/actionpack/lib/action_controller/base/chained/filters.rb b/actionpack/lib/action_controller/base/chained/filters.rb
index 98fe306fd5..e121c0129d 100644
--- a/actionpack/lib/action_controller/base/chained/filters.rb
+++ b/actionpack/lib/action_controller/base/chained/filters.rb
@@ -571,12 +571,7 @@ module ActionController #:nodoc:
# Returns an array of Filter objects for this controller.
def filter_chain
- if chain = read_inheritable_attribute('filter_chain')
- return chain
- else
- write_inheritable_attribute('filter_chain', FilterChain.new)
- return filter_chain
- end
+ read_inheritable_attribute('filter_chain') || write_inheritable_attribute('filter_chain', FilterChain.new)
end
# Returns all the before filters for this class and all its ancestors.
--
cgit v1.2.3
From 98eaa2c6834e418959f2a1a18421e4811167e03b Mon Sep 17 00:00:00 2001
From: Travis Briggs
Date: Wed, 18 Mar 2009 21:51:26 -0400
Subject: Ensure number_to_human_size does not strip zeros from the end [#1763
state:resolved]
Signed-off-by: Pratik Naik
---
actionpack/lib/action_view/helpers/number_helper.rb | 7 ++++++-
actionpack/test/template/number_helper_test.rb | 4 ++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index c02692b09a..999d5b34fc 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -248,6 +248,11 @@ module ActionView
# number_to_human_size(483989, :precision => 0) # => 473 KB
# number_to_human_size(1234567, :precision => 2, :separator => ',') # => 1,18 MB
#
+ # Zeros after the decimal point are always stripped out, regardless of the
+ # specified precision:
+ # helper.number_to_human_size(1234567890123, :precision => 5) # => "1.12283 TB"
+ # helper.number_to_human_size(524288000, :precision=>5) # => "500 MB"
+ #
# You can still use number_to_human_size with the old API that accepts the
# +precision+ as its optional second parameter:
# number_to_human_size(1234567, 2) # => 1.18 MB
@@ -293,7 +298,7 @@ module ActionView
:precision => precision,
:separator => separator,
:delimiter => delimiter
- ).sub(/(\d)(#{escaped_separator}[1-9]*)?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '')
+ ).sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '')
storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit)
rescue
number
diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb
index 29cb60fd73..b6542ef29d 100644
--- a/actionpack/test/template/number_helper_test.rb
+++ b/actionpack/test/template/number_helper_test.rb
@@ -118,6 +118,10 @@ class NumberHelperTest < ActionView::TestCase
assert_equal '1.01 KB', number_to_human_size(1.0123.kilobytes, :precision => 2)
assert_equal '1.01 KB', number_to_human_size(1.0100.kilobytes, :precision => 4)
assert_equal '10 KB', number_to_human_size(10.000.kilobytes, :precision => 4)
+ assert_equal '1 TB', number_to_human_size(1234567890123, :precision => 0)
+ assert_equal '500 MB', number_to_human_size(524288000, :precision=>0)
+ assert_equal '40 KB', number_to_human_size(41010, :precision => 0)
+ assert_equal '40 KB', number_to_human_size(41100, :precision => 0)
end
def test_number_to_human_size_with_custom_delimiter_and_separator
--
cgit v1.2.3
From c3319504f066c9362b4b30e1e15bbd1cadde8e25 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sun, 17 May 2009 11:09:14 -0500
Subject: Rescue hack was supposed to be removed. Some how it crept back in.
---
actionpack/lib/action_controller/base/base.rb | 5 ++---
actionpack/lib/action_controller/testing/process.rb | 3 ---
actionpack/test/controller/filters_test.rb | 1 -
actionpack/test/controller/helper_test.rb | 3 ---
4 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb
index 2813e71d12..c59068c628 100644
--- a/actionpack/lib/action_controller/base/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -368,9 +368,8 @@ module ActionController #:nodoc:
attr_reader :template
def action(name, env)
- # HACK: For global rescue to have access to the original request and response
- request = env["action_controller.rescue.request"] ||= ActionDispatch::Request.new(env)
- response = env["action_controller.rescue.response"] ||= ActionDispatch::Response.new
+ request = ActionDispatch::Request.new(env)
+ response = ActionDispatch::Response.new
self.action_name = name && name.to_s
process(request, response).to_a
end
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 8f4358c33e..8831ff57e2 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -132,9 +132,6 @@ module ActionController #:nodoc:
@request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash
build_request_uri(action, parameters)
- @request.env["action_controller.rescue.request"] = @request
- @request.env["action_controller.rescue.response"] = @response
-
Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
env = @request.env
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index 9ad49e9282..afefc6a77e 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -607,7 +607,6 @@ class FilterTest < Test::Unit::TestCase
def test_dynamic_dispatch
%w(foo bar baz).each do |action|
request = ActionController::TestRequest.new
- request.env["action_controller.rescue.request"] = request
request.query_parameters[:choose] = action
response = DynamicDispatchController.action.call(request.env).last
assert_equal action, response.body
diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb
index 7b8096fccc..3bbda9eb3a 100644
--- a/actionpack/test/controller/helper_test.rb
+++ b/actionpack/test/controller/helper_test.rb
@@ -104,7 +104,6 @@ class HelperTest < Test::Unit::TestCase
def call_controller(klass, action)
request = ActionController::TestRequest.new
- request.env["action_controller.rescue.request"] = request
klass.action(action).call(request.env)
end
@@ -112,7 +111,6 @@ class HelperTest < Test::Unit::TestCase
assert_equal 'hello: Iz guuut!',
call_controller(Fun::GamesController, "render_hello_world").last.body
# request = ActionController::TestRequest.new
- # request.env["action_controller.rescue.request"] = request
#
# resp = Fun::GamesController.action(:render_hello_world).call(request.env)
# assert_equal 'hello: Iz guuut!', resp.last.body
@@ -217,7 +215,6 @@ class IsolatedHelpersTest < Test::Unit::TestCase
def call_controller(klass, action)
request = ActionController::TestRequest.new
- request.env["action_controller.rescue.request"] = request
klass.action(action).call(request.env)
end
--
cgit v1.2.3
From 8118fca9beec675fba19395e7d1027eaa4b5703a Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sun, 17 May 2009 12:24:42 -0500
Subject: Merge Failsafe middleware into ShowExceptions
---
.../lib/action_controller/dispatch/middlewares.rb | 1 -
actionpack/lib/action_dispatch.rb | 1 -
.../lib/action_dispatch/middleware/failsafe.rb | 51 -------------
.../action_dispatch/middleware/show_exceptions.rb | 87 ++++++++++------------
actionpack/test/controller/rescue_test.rb | 14 ++++
actionpack/test/dispatch/show_exceptions_test.rb | 5 ++
actionpack/test/new_base/render_action_test.rb | 4 +-
actionpack/test/new_base/render_test.rb | 6 +-
railties/lib/initializer.rb | 2 +-
9 files changed, 65 insertions(+), 106 deletions(-)
delete mode 100644 actionpack/lib/action_dispatch/middleware/failsafe.rb
diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb
index 0e4ab6fa39..e4e3a704c0 100644
--- a/actionpack/lib/action_controller/dispatch/middlewares.rb
+++ b/actionpack/lib/action_controller/dispatch/middlewares.rb
@@ -2,7 +2,6 @@ use "Rack::Lock", :if => lambda {
!ActionController::Base.allow_concurrency
}
-use "ActionDispatch::Failsafe"
use "ActionDispatch::ShowExceptions", lambda { ActionController::Base.consider_all_requests_local }
use "ActionDispatch::Rescue", lambda {
controller = (::ApplicationController rescue ActionController::Base)
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 27d229835a..f3c91d8624 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -38,7 +38,6 @@ module ActionDispatch
autoload :Response, 'action_dispatch/http/response'
autoload :StatusCodes, 'action_dispatch/http/status_codes'
- autoload :Failsafe, 'action_dispatch/middleware/failsafe'
autoload :ParamsParser, 'action_dispatch/middleware/params_parser'
autoload :Rescue, 'action_dispatch/middleware/rescue'
autoload :ShowExceptions, 'action_dispatch/middleware/show_exceptions'
diff --git a/actionpack/lib/action_dispatch/middleware/failsafe.rb b/actionpack/lib/action_dispatch/middleware/failsafe.rb
deleted file mode 100644
index 389accbc36..0000000000
--- a/actionpack/lib/action_dispatch/middleware/failsafe.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-module ActionDispatch
- class Failsafe
- cattr_accessor :error_file_path
- self.error_file_path = Rails.public_path if defined?(Rails.public_path)
-
- def initialize(app)
- @app = app
- end
-
- def call(env)
- @app.call(env)
- rescue Exception => exception
- if env["rails.raise_exceptions"]
- raise
- else
- failsafe_response(exception)
- end
- end
-
- private
- def failsafe_response(exception)
- log_failsafe_exception(exception)
- [500, {'Content-Type' => 'text/html'}, failsafe_response_body]
- rescue Exception => failsafe_error # Logger or IO errors
- $stderr.puts "Error during failsafe response: #{failsafe_error}"
- end
-
- def failsafe_response_body
- error_path = "#{self.class.error_file_path}/500.html"
- if File.exist?(error_path)
- [File.read(error_path)]
- else
- ["500 Internal Server Error "]
- end
- end
-
- def log_failsafe_exception(exception)
- message = "/!\\ FAILSAFE /!\\ #{Time.now}\n Status: 500 Internal Server Error\n"
- message << " #{exception}\n #{exception.backtrace.join("\n ")}" if exception
- failsafe_logger.fatal(message)
- end
-
- def failsafe_logger
- if defined?(Rails) && Rails.logger
- Rails.logger
- else
- Logger.new($stderr)
- end
- end
- end
-end
diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
index 71c1e1b9a9..108355da63 100644
--- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
@@ -4,8 +4,11 @@ module ActionDispatch
LOCALHOST = '127.0.0.1'.freeze
- DEFAULT_RESCUE_RESPONSE = :internal_server_error
- DEFAULT_RESCUE_RESPONSES = {
+ RESCUES_TEMPLATE_PATH = File.join(File.dirname(__FILE__), 'templates')
+
+ cattr_accessor :rescue_responses
+ @@rescue_responses = Hash.new(:internal_server_error)
+ @@rescue_responses.update({
'ActionController::RoutingError' => :not_found,
'ActionController::UnknownAction' => :not_found,
'ActiveRecord::RecordNotFound' => :not_found,
@@ -15,25 +18,19 @@ module ActionDispatch
'ActionController::MethodNotAllowed' => :method_not_allowed,
'ActionController::NotImplemented' => :not_implemented,
'ActionController::InvalidAuthenticityToken' => :unprocessable_entity
- }
+ })
- DEFAULT_RESCUE_TEMPLATE = 'diagnostics'
- DEFAULT_RESCUE_TEMPLATES = {
+ cattr_accessor :rescue_templates
+ @@rescue_templates = Hash.new('diagnostics')
+ @@rescue_templates.update({
'ActionView::MissingTemplate' => 'missing_template',
'ActionController::RoutingError' => 'routing_error',
'ActionController::UnknownAction' => 'unknown_action',
'ActionView::TemplateError' => 'template_error'
- }
-
- RESCUES_TEMPLATE_PATH = File.join(File.dirname(__FILE__), 'templates')
-
- cattr_accessor :rescue_responses
- @@rescue_responses = Hash.new(DEFAULT_RESCUE_RESPONSE)
- @@rescue_responses.update DEFAULT_RESCUE_RESPONSES
+ })
- cattr_accessor :rescue_templates
- @@rescue_templates = Hash.new(DEFAULT_RESCUE_TEMPLATE)
- @@rescue_templates.update DEFAULT_RESCUE_TEMPLATES
+ FAILSAFE_RESPONSE = [500, {'Content-Type' => 'text/html'},
+ ['500 Internal Server Error ']]
def initialize(app, consider_all_requests_local = false)
@app = app
@@ -43,34 +40,35 @@ module ActionDispatch
def call(env)
@app.call(env)
rescue Exception => exception
- raise exception if env['rack.test']
+ raise exception if env['action_dispatch.show_exceptions'] == false
+ render_exception(env, exception)
+ end
- log_error(exception) if logger
+ private
+ def render_exception(env, exception)
+ log_error(exception)
- request = Request.new(env)
- if @consider_all_requests_local || local_request?(request)
- rescue_action_locally(request, exception)
- else
- rescue_action_in_public(exception)
+ request = Request.new(env)
+ if @consider_all_requests_local || local_request?(request)
+ rescue_action_locally(request, exception)
+ else
+ rescue_action_in_public(exception)
+ end
+ rescue Exception => failsafe_error
+ $stderr.puts "Error during failsafe response: #{failsafe_error}"
+ FAILSAFE_RESPONSE
end
- end
- private
# Render detailed diagnostics for unhandled exceptions rescued from
# a controller action.
def rescue_action_locally(request, exception)
template = ActionView::Base.new([RESCUES_TEMPLATE_PATH],
- :template => template,
:request => request,
:exception => exception
)
file = "rescues/#{@@rescue_templates[exception.class.name]}.erb"
body = template.render(:file => file, :layout => 'rescues/layout.erb')
-
- headers = {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}
- status = status_code(exception)
-
- [status, headers, body]
+ render(status_code(exception), body)
end
# Attempts to render a static error page based on the
@@ -86,11 +84,11 @@ module ActionDispatch
path = "#{public_path}/#{status}.html"
if locale_path && File.exist?(locale_path)
- render_public_file(status, locale_path)
+ render(status, File.read(locale_path))
elsif File.exist?(path)
- render_public_file(status, path)
+ render(status, File.read(path))
else
- [status, {'Content-Type' => 'text/html', 'Content-Length' => '0'}, []]
+ render(status, '')
end
end
@@ -99,24 +97,21 @@ module ActionDispatch
request.remote_addr == LOCALHOST && request.remote_ip == LOCALHOST
end
- def render_public_file(status, path)
- body = File.read(path)
- [status, {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}, body]
- end
-
def status_code(exception)
interpret_status(@@rescue_responses[exception.class.name]).to_i
end
+ def render(status, body)
+ [status, {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}, body]
+ end
+
def public_path
- if defined?(Rails)
- Rails.public_path
- else
- "public"
- end
+ defined?(Rails.public_path) ? Rails.public_path : 'public_path'
end
- def log_error(exception) #:doc:
+ def log_error(exception)
+ return unless logger
+
ActiveSupport::Deprecation.silence do
if ActionView::TemplateError === exception
logger.fatal(exception.to_s)
@@ -136,9 +131,7 @@ module ActionDispatch
end
def logger
- if defined?(Rails.logger)
- Rails.logger
- end
+ defined?(Rails.logger) ? Rails.logger : Logger.new($stderr)
end
end
end
diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb
index f745926b20..490a4ff3b3 100644
--- a/actionpack/test/controller/rescue_test.rb
+++ b/actionpack/test/controller/rescue_test.rb
@@ -1,5 +1,19 @@
require 'abstract_unit'
+module ActionDispatch
+ class ShowExceptions
+ private
+ def public_path
+ "#{FIXTURE_LOAD_PATH}/public"
+ end
+
+ # Silence logger
+ def logger
+ nil
+ end
+ end
+end
+
class RescueController < ActionController::Base
class NotAuthorized < StandardError
end
diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb
index f8f562e7c1..0c0c087340 100644
--- a/actionpack/test/dispatch/show_exceptions_test.rb
+++ b/actionpack/test/dispatch/show_exceptions_test.rb
@@ -6,6 +6,11 @@ module ActionDispatch
def public_path
"#{FIXTURE_LOAD_PATH}/public"
end
+
+ # Silence logger
+ def logger
+ nil
+ end
end
end
diff --git a/actionpack/test/new_base/render_action_test.rb b/actionpack/test/new_base/render_action_test.rb
index 96666077d2..626c7b3540 100644
--- a/actionpack/test/new_base/render_action_test.rb
+++ b/actionpack/test/new_base/render_action_test.rb
@@ -92,7 +92,7 @@ module RenderAction
test "raises an exception when requesting a layout and none exist" do
assert_raise(ArgumentError, /no default layout for RenderAction::BasicController in/) do
- get "/render_action/basic/hello_world_with_layout", {}, "rails.raise_exceptions" => true
+ get "/render_action/basic/hello_world_with_layout", {}, "action_dispatch.show_exceptions" => false
end
end
end
@@ -118,7 +118,7 @@ module RenderAction
test "raises an exception when requesting a layout that does not exist" do
assert_raise(ActionView::MissingTemplate) do
- get "/render_action/basic/hello_world_with_custom_layout", {}, "rails.raise_exceptions" => true
+ get "/render_action/basic/hello_world_with_custom_layout", {}, "action_dispatch.show_exceptions" => false
end
end
end
diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb
index 16578fbc82..ef5e7d89c5 100644
--- a/actionpack/test/new_base/render_test.rb
+++ b/actionpack/test/new_base/render_test.rb
@@ -48,7 +48,7 @@ module Render
test "raises an exception" do
assert_raises(AbstractController::DoubleRenderError) do
- get "/render/double_render", {}, "rails.raise_exceptions" => true
+ get "/render/double_render", {}, "action_dispatch.show_exceptions" => false
end
end
end
@@ -58,13 +58,13 @@ module Render
test "raises an exception when a method of Object is called" do
assert_raises(AbstractController::ActionNotFound) do
- get "/render/blank_render/clone", {}, "rails.raise_exceptions" => true
+ get "/render/blank_render/clone", {}, "action_dispatch.show_exceptions" => false
end
end
test "raises an exception when a private method is called" do
assert_raises(AbstractController::ActionNotFound) do
- get "/render/blank_render/secretz", {}, "rails.raise_exceptions" => true
+ get "/render/blank_render/secretz", {}, "action_dispatch.show_exceptions" => false
end
end
end
diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index e4d7589aba..b16f42b8a0 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -462,7 +462,7 @@ Run `rake gems:install` to install the missing gems.
if RAILS_CACHE.respond_to?(:middleware)
# Insert middleware to setup and teardown local cache for each request
- configuration.middleware.insert_after(:"ActionDispatch::Failsafe", RAILS_CACHE.middleware)
+ configuration.middleware.insert_after(:"Rack::Lock", RAILS_CACHE.middleware)
end
end
end
--
cgit v1.2.3
From edc9c226d11e6104d191ceeb6416c7062ceda54a Mon Sep 17 00:00:00 2001
From: Mike Breen
Date: Sun, 17 May 2009 19:48:15 +0200
Subject: Add tests for assert_template :template
Signed-off-by: Pratik Naik
---
.../test/controller/action_pack_assertions_test.rb | 23 ++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index 484d3c5ce7..c3c769919a 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -12,6 +12,9 @@ class ActionPackAssertionsController < ActionController::Base
# a standard template
def hello_xml_world() render :template => "test/hello_xml_world"; end
+ # a standard partial
+ def partial() render :partial => 'test/partial'; end
+
# a redirect to an internal location
def redirect_internal() redirect_to "/nothing"; end
@@ -331,6 +334,26 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
end
end
+ def test_assert_template_with_partial
+ get :partial
+ assert_template :partial => '_partial'
+ end
+
+ def test_assert_template_with_nil
+ get :nothing
+ assert_template nil
+ end
+
+ def test_assert_template_with_string
+ get :hello_world
+ assert_template 'hello_world'
+ end
+
+ def test_assert_template_with_symbol
+ get :hello_world
+ assert_template :hello_world
+ end
+
# check if we were rendered by a file-based template?
def test_rendered_action
process :nothing
--
cgit v1.2.3
From 092089015b79752c5e9d664b3eeefef9e2223e36 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sun, 17 May 2009 13:39:44 -0500
Subject: Extract generic callbacks middleware from dispatcher
---
.../lib/action_controller/dispatch/dispatcher.rb | 100 ++++++++-------------
.../lib/action_controller/dispatch/middlewares.rb | 1 +
actionpack/lib/action_dispatch.rb | 1 +
.../lib/action_dispatch/middleware/callbacks.rb | 40 +++++++++
actionpack/test/controller/dispatcher_test.rb | 34 ++++---
railties/lib/console_app.rb | 5 +-
railties/lib/initializer.rb | 1 -
7 files changed, 103 insertions(+), 79 deletions(-)
create mode 100644 actionpack/lib/action_dispatch/middleware/callbacks.rb
diff --git a/actionpack/lib/action_controller/dispatch/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb
index 63866caed9..9ad1cadfd3 100644
--- a/actionpack/lib/action_controller/dispatch/dispatcher.rb
+++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb
@@ -1,87 +1,65 @@
+require 'active_support/core_ext/module/delegation'
+
module ActionController
# Dispatches requests to the appropriate controller and takes care of
# reloading the app after each request when Dependencies.load? is true.
class Dispatcher
+ cattr_accessor :prepare_each_request
+ self.prepare_each_request = false
+
+ cattr_accessor :router
+ self.router = Routing::Routes
+
+ cattr_accessor :middleware
+ self.middleware = ActionDispatch::MiddlewareStack.new do |middleware|
+ middlewares = File.join(File.dirname(__FILE__), "middlewares.rb")
+ middleware.instance_eval(File.read(middlewares), middlewares, 1)
+ end
+
class << self
def define_dispatcher_callbacks(cache_classes)
unless cache_classes
+ # Run prepare callbacks before every request in development mode
+ self.prepare_each_request = true
+
# Development mode callbacks
- before_dispatch :reload_application
- after_dispatch :cleanup_application
+ ActionDispatch::Callbacks.before_dispatch do |app|
+ ActionController::Dispatcher.router.reload
+ end
+
+ ActionDispatch::Callbacks.after_dispatch do
+ # Cleanup the application before processing the current request.
+ ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
+ ActiveSupport::Dependencies.clear
+ ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
+ end
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
end
if defined?(ActiveRecord)
- to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers }
+ to_prepare(:activerecord_instantiate_observers) do
+ ActiveRecord::Base.instantiate_observers
+ end
end
- after_dispatch :flush_logger if Base.logger && Base.logger.respond_to?(:flush)
+ if Base.logger && Base.logger.respond_to?(:flush)
+ after_dispatch do
+ Base.logger.flush
+ end
+ end
to_prepare do
I18n.reload!
end
end
- # Add a preparation callback. Preparation callbacks are run before every
- # request in development mode, and before the first request in production
- # mode.
- #
- # An optional identifier may be supplied for the callback. If provided,
- # to_prepare may be called again with the same identifier to replace the
- # existing callback. Passing an identifier is a suggested practice if the
- # code adding a preparation block may be reloaded.
- def to_prepare(identifier = nil, &block)
- @prepare_dispatch_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new
- callback = ActiveSupport::Callbacks::Callback.new(:prepare_dispatch, block, :identifier => identifier)
- @prepare_dispatch_callbacks.replace_or_append!(callback)
- end
+ delegate :to_prepare, :prepare_dispatch, :before_dispatch, :after_dispatch,
+ :to => ActionDispatch::Callbacks
- def run_prepare_callbacks
- new.send :run_callbacks, :prepare_dispatch
+ def new
+ @@middleware.build(@@router)
end
end
-
- cattr_accessor :router
- self.router = Routing::Routes
-
- cattr_accessor :middleware
- self.middleware = ActionDispatch::MiddlewareStack.new do |middleware|
- middlewares = File.join(File.dirname(__FILE__), "middlewares.rb")
- middleware.instance_eval(File.read(middlewares), middlewares, 1)
- end
-
- include ActiveSupport::Callbacks
- define_callbacks :prepare_dispatch, :before_dispatch, :after_dispatch
-
- def initialize
- @app = @@middleware.build(@@router)
- freeze
- end
-
- def call(env)
- run_callbacks :before_dispatch
- @app.call(env)
- ensure
- run_callbacks :after_dispatch, :enumerator => :reverse_each
- end
-
- def reload_application
- # Run prepare callbacks before every request in development mode
- run_callbacks :prepare_dispatch
-
- @@router.reload
- end
-
- def cleanup_application
- # Cleanup the application before processing the current request.
- ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
- ActiveSupport::Dependencies.clear
- ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
- end
-
- def flush_logger
- Base.logger.flush
- end
end
end
diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb
index e4e3a704c0..b25ed3fd3f 100644
--- a/actionpack/lib/action_controller/dispatch/middlewares.rb
+++ b/actionpack/lib/action_controller/dispatch/middlewares.rb
@@ -3,6 +3,7 @@ use "Rack::Lock", :if => lambda {
}
use "ActionDispatch::ShowExceptions", lambda { ActionController::Base.consider_all_requests_local }
+use "ActionDispatch::Callbacks", lambda { ActionController::Dispatcher.prepare_each_request }
use "ActionDispatch::Rescue", lambda {
controller = (::ApplicationController rescue ActionController::Base)
# TODO: Replace with controller.action(:_rescue_action)
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index f3c91d8624..6fc4ad3f21 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -38,6 +38,7 @@ module ActionDispatch
autoload :Response, 'action_dispatch/http/response'
autoload :StatusCodes, 'action_dispatch/http/status_codes'
+ autoload :Callbacks, 'action_dispatch/middleware/callbacks'
autoload :ParamsParser, 'action_dispatch/middleware/params_parser'
autoload :Rescue, 'action_dispatch/middleware/rescue'
autoload :ShowExceptions, 'action_dispatch/middleware/show_exceptions'
diff --git a/actionpack/lib/action_dispatch/middleware/callbacks.rb b/actionpack/lib/action_dispatch/middleware/callbacks.rb
new file mode 100644
index 0000000000..0a2b4cf5f7
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/callbacks.rb
@@ -0,0 +1,40 @@
+module ActionDispatch
+ class Callbacks
+ include ActiveSupport::Callbacks
+ define_callbacks :prepare, :before, :after
+
+ class << self
+ # DEPRECATED
+ alias_method :prepare_dispatch, :prepare
+ alias_method :before_dispatch, :before
+ alias_method :after_dispatch, :after
+ end
+
+ # Add a preparation callback. Preparation callbacks are run before every
+ # request in development mode, and before the first request in production
+ # mode.
+ #
+ # An optional identifier may be supplied for the callback. If provided,
+ # to_prepare may be called again with the same identifier to replace the
+ # existing callback. Passing an identifier is a suggested practice if the
+ # code adding a preparation block may be reloaded.
+ def self.to_prepare(identifier = nil, &block)
+ @prepare_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new
+ callback = ActiveSupport::Callbacks::Callback.new(:prepare, block, :identifier => identifier)
+ @prepare_callbacks.replace_or_append!(callback)
+ end
+
+ def initialize(app, prepare_each_request = false)
+ @app, @prepare_each_request = app, prepare_each_request
+ run_callbacks :prepare
+ end
+
+ def call(env)
+ run_callbacks :before
+ run_callbacks :prepare if @prepare_each_request
+ @app.call(env)
+ ensure
+ run_callbacks :after, :enumerator => :reverse_each
+ end
+ end
+end
diff --git a/actionpack/test/controller/dispatcher_test.rb b/actionpack/test/controller/dispatcher_test.rb
index b315232a7b..9fae1fcf63 100644
--- a/actionpack/test/controller/dispatcher_test.rb
+++ b/actionpack/test/controller/dispatcher_test.rb
@@ -6,20 +6,20 @@ class DispatcherTest < Test::Unit::TestCase
def setup
ENV['REQUEST_METHOD'] = 'GET'
- Dispatcher.middleware = ActionDispatch::MiddlewareStack.new do |middleware|
- middlewares = File.expand_path(File.join(File.dirname(__FILE__), "../../lib/action_controller/dispatch/middlewares.rb"))
- middleware.instance_eval(File.read(middlewares))
- end
-
# Clear callbacks as they are redefined by Dispatcher#define_dispatcher_callbacks
- Dispatcher.instance_variable_set("@prepare_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
- Dispatcher.instance_variable_set("@before_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
- Dispatcher.instance_variable_set("@after_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
+ ActionDispatch::Callbacks.instance_variable_set("@prepare_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
+ ActionDispatch::Callbacks.instance_variable_set("@before_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
+ ActionDispatch::Callbacks.instance_variable_set("@after_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
+ @old_router, Dispatcher.router = Dispatcher.router, mock()
+ Dispatcher.router.stubs(:call).returns([200, {}, 'response'])
+ Dispatcher.router.stubs(:reload)
Dispatcher.stubs(:require_dependency)
end
def teardown
+ Dispatcher.router = @old_router
+ @dispatcher = nil
ENV.delete 'REQUEST_METHOD'
end
@@ -29,12 +29,12 @@ class DispatcherTest < Test::Unit::TestCase
end
def test_reloads_routes_before_dispatch_if_in_loading_mode
- ActionController::Routing::Routes.expects(:reload).once
+ Dispatcher.router.expects(:reload).once
dispatch(false)
end
def test_leaves_dependencies_after_dispatch_if_not_in_loading_mode
- ActionController::Routing::Routes.expects(:reload).never
+ Dispatcher.router.expects(:reload).never
ActiveSupport::Dependencies.expects(:clear).never
dispatch
@@ -55,7 +55,7 @@ class DispatcherTest < Test::Unit::TestCase
assert_nil a || b || c
# Run callbacks
- Dispatcher.run_prepare_callbacks
+ dispatch
assert_equal 1, a
assert_equal 2, b
@@ -72,16 +72,22 @@ class DispatcherTest < Test::Unit::TestCase
Dispatcher.to_prepare(:unique_id) { |*args| a = b = 1 }
Dispatcher.to_prepare(:unique_id) { |*args| a = 2 }
- Dispatcher.run_prepare_callbacks
+ dispatch
assert_equal 2, a
assert_equal nil, b
end
private
def dispatch(cache_classes = true)
- ActionController::Routing::RouteSet.any_instance.stubs(:call).returns([200, {}, 'response'])
+ ActionController::Dispatcher.prepare_each_request = false
Dispatcher.define_dispatcher_callbacks(cache_classes)
- Dispatcher.new.call({'rack.input' => StringIO.new('')})
+ Dispatcher.middleware = ActionDispatch::MiddlewareStack.new do |middleware|
+ middlewares = File.expand_path(File.join(File.dirname(__FILE__), "../../lib/action_controller/dispatch/middlewares.rb"))
+ middleware.instance_eval(File.read(middlewares))
+ end
+
+ @dispatcher ||= Dispatcher.new
+ @dispatcher.call({'rack.input' => StringIO.new(''), 'action_dispatch.show_exceptions' => false})
end
def assert_subclasses(howmany, klass, message = klass.subclasses.inspect)
diff --git a/railties/lib/console_app.rb b/railties/lib/console_app.rb
index c944d49205..42bf50e01e 100644
--- a/railties/lib/console_app.rb
+++ b/railties/lib/console_app.rb
@@ -26,8 +26,7 @@ end
#reloads the environment
def reload!
puts "Reloading..."
- dispatcher = ActionController::Dispatcher.new
- dispatcher.cleanup_application
- dispatcher.reload_application
+ ActionController::Dispatcher.new
+ ActionController::Dispatcher.router.reload
true
end
diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index b16f42b8a0..4c6de48a65 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -632,7 +632,6 @@ Run `rake gems:install` to install the missing gems.
return unless configuration.frameworks.include?(:action_controller)
require 'dispatcher' unless defined?(::Dispatcher)
Dispatcher.define_dispatcher_callbacks(configuration.cache_classes)
- Dispatcher.run_prepare_callbacks
end
def disable_dependency_loading
--
cgit v1.2.3
From b33c0d98329b97f8f540ba455d419d5046e6bb39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mislav=20Marohni=C4=87?=
Date: Sun, 17 May 2009 13:51:35 -0500
Subject: replace the aaa_create_tables_test hack with loading test database
schema in the test helper [#2663 state:resolved]
Signed-off-by: Joshua Peek
---
activerecord/test/cases/aaa_create_tables_test.rb | 24 -----------------------
activerecord/test/cases/helper.rb | 18 +++++++++++++++++
activerecord/test/schema/schema.rb | 5 ++++-
activerecord/test/schema/schema2.rb | 6 ------
4 files changed, 22 insertions(+), 31 deletions(-)
delete mode 100644 activerecord/test/cases/aaa_create_tables_test.rb
delete mode 100644 activerecord/test/schema/schema2.rb
diff --git a/activerecord/test/cases/aaa_create_tables_test.rb b/activerecord/test/cases/aaa_create_tables_test.rb
deleted file mode 100644
index 3911afac49..0000000000
--- a/activerecord/test/cases/aaa_create_tables_test.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# The filename begins with "aaa" to ensure this is the first test.
-require "cases/helper"
-
-class AAACreateTablesTest < ActiveRecord::TestCase
- self.use_transactional_fixtures = false
-
- def test_load_schema
- eval(File.read(SCHEMA_ROOT + "/schema.rb"))
- if File.exists?(adapter_specific_schema_file)
- eval(File.read(adapter_specific_schema_file))
- end
- assert true
- end
-
- def test_drop_and_create_courses_table
- eval(File.read(SCHEMA_ROOT + "/schema2.rb"))
- assert true
- end
-
- private
- def adapter_specific_schema_file
- SCHEMA_ROOT + '/' + ActiveRecord::Base.connection.adapter_name.downcase + '_specific_schema.rb'
- end
-end
diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb
index 05e92433cd..f82784836e 100644
--- a/activerecord/test/cases/helper.rb
+++ b/activerecord/test/cases/helper.rb
@@ -5,6 +5,7 @@ require 'config'
require 'rubygems'
require 'test/unit'
+require 'stringio'
gem 'mocha', '>= 0.9.5'
require 'mocha'
@@ -72,3 +73,20 @@ class ActiveSupport::TestCase
Fixtures.create_fixtures(ActiveSupport::TestCase.fixture_path, table_names, {}, &block)
end
end
+
+# silence verbose schema loading
+original_stdout = $stdout
+$stdout = StringIO.new
+
+begin
+ adapter_name = ActiveRecord::Base.connection.adapter_name.downcase
+ adapter_specific_schema_file = SCHEMA_ROOT + "/#{adapter_name}_specific_schema.rb"
+
+ load SCHEMA_ROOT + "/schema.rb"
+
+ if File.exists?(adapter_specific_schema_file)
+ load adapter_specific_schema_file
+ end
+ensure
+ $stdout = original_stdout
+end
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index a776cd974b..4ee0ffe132 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -1,4 +1,3 @@
-
ActiveRecord::Schema.define do
def except(adapter_names_to_exclude)
unless [adapter_names_to_exclude].flatten.include?(adapter_name)
@@ -500,3 +499,7 @@ ActiveRecord::Schema.define do
execute "ALTER TABLE fk_test_has_fk ADD CONSTRAINT fk_name FOREIGN KEY (#{quote_column_name 'fk_id'}) REFERENCES #{quote_table_name 'fk_test_has_pk'} (#{quote_column_name 'id'})"
end
end
+
+Course.connection.create_table :courses, :force => true do |t|
+ t.column :name, :string, :null => false
+end
diff --git a/activerecord/test/schema/schema2.rb b/activerecord/test/schema/schema2.rb
deleted file mode 100644
index 8527f7ba8f..0000000000
--- a/activerecord/test/schema/schema2.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-ActiveRecord::Schema.define do
-
- Course.connection.create_table :courses, :force => true do |t|
- t.column :name, :string, :null => false
- end
-end
--
cgit v1.2.3
From 01d7acd11d631d980497870aad1af42a0c66115c Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sun, 17 May 2009 14:42:36 -0500
Subject: Fix reset_session with ActiveRecord store [#2200 state:resolved]
---
actionpack/test/activerecord/active_record_store_test.rb | 6 +++---
activerecord/lib/active_record/session_store.rb | 10 +++++++++-
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/actionpack/test/activerecord/active_record_store_test.rb b/actionpack/test/activerecord/active_record_store_test.rb
index 663cd259c8..47f8496181 100644
--- a/actionpack/test/activerecord/active_record_store_test.rb
+++ b/actionpack/test/activerecord/active_record_store_test.rb
@@ -28,9 +28,9 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest
end
def call_reset_session
- session[:bar]
+ session[:foo]
reset_session
- session[:bar] = "baz"
+ session[:foo] = "baz"
head :ok
end
@@ -91,7 +91,7 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest
get '/get_session_value'
assert_response :success
- assert_equal 'foo: nil', response.body
+ assert_equal 'foo: "baz"', response.body
get '/get_session_id'
assert_response :success
diff --git a/activerecord/lib/active_record/session_store.rb b/activerecord/lib/active_record/session_store.rb
index 21471da419..9dda3361d8 100644
--- a/activerecord/lib/active_record/session_store.rb
+++ b/activerecord/lib/active_record/session_store.rb
@@ -295,7 +295,7 @@ module ActiveRecord
def set_session(env, sid, session_data)
Base.silence do
- record = env[SESSION_RECORD_KEY] ||= find_session(sid)
+ record = get_session_model(env, sid)
record.data = session_data
return false unless record.save
@@ -309,6 +309,14 @@ module ActiveRecord
return true
end
+
+ def get_session_model(env, sid)
+ if env[ENV_SESSION_OPTIONS_KEY][:id].nil?
+ env[SESSION_RECORD_KEY] = find_session(sid)
+ else
+ env[SESSION_RECORD_KEY] ||= find_session(sid)
+ end
+ end
def find_session(id)
@@session_class.find_by_session_id(id) ||
--
cgit v1.2.3
From b0de061e7b8d3c291a328f6b0b9bfc5f48b2f907 Mon Sep 17 00:00:00 2001
From: Brian Lopez
Date: Sun, 17 May 2009 16:09:28 -0500
Subject: Allow ParamsParser to parse YAML from the request body IO directly
Signed-off-by: Joshua Peek
---
actionpack/lib/action_dispatch/middleware/params_parser.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index a42c6598e0..e83cf9236b 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -34,7 +34,7 @@ module ActionDispatch
when :xml_simple, :xml_node
request.body.size == 0 ? {} : Hash.from_xml(request.body).with_indifferent_access
when :yaml
- YAML.load(request.raw_post)
+ YAML.load(request.body)
when :json
if request.body.size == 0
{}
--
cgit v1.2.3
From e89241c92fbcf68b59d9efb50c21c5040e9f3156 Mon Sep 17 00:00:00 2001
From: rick
Date: Sun, 17 May 2009 19:16:11 -0700
Subject: load the JSON Backend lazily. If the JSON gem is already loaded, use
the JSONGem backend by default.
---
activesupport/lib/active_support/json.rb | 11 ++++++++---
activesupport/lib/active_support/json/backends/jsongem.rb | 4 +++-
activesupport/lib/active_support/json/backends/yaml.rb | 4 +++-
activesupport/test/json/decoding_test.rb | 3 +++
4 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/activesupport/lib/active_support/json.rb b/activesupport/lib/active_support/json.rb
index 5072992cdf..1e8ded12da 100644
--- a/activesupport/lib/active_support/json.rb
+++ b/activesupport/lib/active_support/json.rb
@@ -40,9 +40,15 @@ module ActiveSupport
end
class << self
- attr_reader :backend
delegate :decode, :to => :backend
-
+
+ def backend
+ @backend || begin
+ self.backend = defined?(::JSON) ? "JSONGem" : "Yaml"
+ @backend
+ end
+ end
+
def backend=(name)
if name.is_a?(Module)
@backend = name
@@ -77,6 +83,5 @@ module ActiveSupport
end
ActiveSupport.escape_html_entities_in_json = true
-ActiveSupport::JSON.backend = 'Yaml'
require 'active_support/json/encoding'
diff --git a/activesupport/lib/active_support/json/backends/jsongem.rb b/activesupport/lib/active_support/json/backends/jsongem.rb
index d1a1cdd7d7..649e6301d1 100644
--- a/activesupport/lib/active_support/json/backends/jsongem.rb
+++ b/activesupport/lib/active_support/json/backends/jsongem.rb
@@ -1,6 +1,8 @@
+require 'json' unless defined?(JSON)
+
module ActiveSupport
module JSON
- ParseError = ::JSON::ParserError
+ ParseError = ::JSON::ParserError unless const_defined?(:ParseError)
module Backends
module JSONGem
diff --git a/activesupport/lib/active_support/json/backends/yaml.rb b/activesupport/lib/active_support/json/backends/yaml.rb
index 1c18fc4801..667016f45d 100644
--- a/activesupport/lib/active_support/json/backends/yaml.rb
+++ b/activesupport/lib/active_support/json/backends/yaml.rb
@@ -2,7 +2,9 @@ require 'active_support/core_ext/string/starts_ends_with'
module ActiveSupport
module JSON
- class ParseError < StandardError
+ unless const_defined?(:ParseError)
+ class ParseError < StandardError
+ end
end
module Backends
diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb
index 7e1bfcca84..09fd0d09ba 100644
--- a/activesupport/test/json/decoding_test.rb
+++ b/activesupport/test/json/decoding_test.rb
@@ -36,6 +36,9 @@ class TestJSONDecoding < ActiveSupport::TestCase
%q({"b":["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => {'b' => ["","",""]}
}
+ # load the default JSON backend
+ ActiveSupport::JSON.backend
+
backends = %w(Yaml)
begin
gem 'json', '>= 1.1'
--
cgit v1.2.3
From 49afe81a13a98d1878f2400bef11a7b89468dff0 Mon Sep 17 00:00:00 2001
From: Kerry Buckley
Date: Mon, 18 May 2009 11:13:51 +0200
Subject: Report errors in 'all project' rake tasks [#2224 state:resolved]
Signed-off-by: Pratik Naik
---
Rakefile | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Rakefile b/Rakefile
index 58e1247600..fbb7f2213c 100644
--- a/Rakefile
+++ b/Rakefile
@@ -15,9 +15,11 @@ task :default => :test
%w(test isolated_test rdoc pgem package release).each do |task_name|
desc "Run #{task_name} task for all projects"
task task_name do
+ errors = []
PROJECTS.each do |project|
- system %(cd #{project} && #{env} #{$0} #{task_name})
+ system(%(cd #{project} && #{env} #{$0} #{task_name})) || errors << project
end
+ fail("Errors in #{errors.join(', ')}") unless errors.empty?
end
end
--
cgit v1.2.3
From 27de7f150b57a18d4ccdd274f6f8b621b58108c6 Mon Sep 17 00:00:00 2001
From: Benjamin Floering
Date: Sun, 17 May 2009 23:35:47 -0700
Subject: Fixed limited eager loading associations with numbers in the name
[#2668 state:resolved]
Signed-off-by: Pratik Naik
---
activerecord/lib/active_record/associations.rb | 2 +-
activerecord/test/cases/associations/eager_test.rb | 4 ++++
activerecord/test/fixtures/people.yml | 5 ++++-
activerecord/test/models/person.rb | 1 +
activerecord/test/schema/schema.rb | 1 +
5 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index c5e4df4950..76726b7845 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1668,7 +1668,7 @@ module ActiveRecord
def tables_in_string(string)
return [] if string.blank?
- string.scan(/([\.a-zA-Z_]+).?\./).flatten
+ string.scan(/([a-zA-Z_][\.\w]+).?\./).flatten
end
def tables_in_hash(hash)
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index d23f86b700..65049c4f87 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -589,6 +589,10 @@ class EagerAssociationTest < ActiveRecord::TestCase
assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title) DESC, posts.id', :limit => 2, :offset => 1)
end
+ def test_limited_eager_with_numeric_in_association
+ assert_equal people(:david, :susan), Person.find(:all, :include => [:readers, :primary_contact, :number1_fan], :conditions => "number1_fans_people.first_name like 'M%'", :order => 'readers.id', :limit => 2, :offset => 0)
+ end
+
def test_preload_with_interpolation
assert_equal [comments(:greetings)], Post.find(posts(:welcome).id, :include => :comments_with_interpolated_conditions).comments_with_interpolated_conditions
end
diff --git a/activerecord/test/fixtures/people.yml b/activerecord/test/fixtures/people.yml
index 3babb1fe59..123673a2af 100644
--- a/activerecord/test/fixtures/people.yml
+++ b/activerecord/test/fixtures/people.yml
@@ -2,14 +2,17 @@ michael:
id: 1
first_name: Michael
primary_contact_id: 2
+ number1_fan_id: 3
gender: M
david:
id: 2
first_name: David
primary_contact_id: 3
+ number1_fan_id: 1
gender: M
susan:
id: 3
first_name: Susan
primary_contact_id: 2
- gender: F
\ No newline at end of file
+ number1_fan_id: 1
+ gender: F
diff --git a/activerecord/test/models/person.rb b/activerecord/test/models/person.rb
index ec2f684a6e..57fa6418f1 100644
--- a/activerecord/test/models/person.rb
+++ b/activerecord/test/models/person.rb
@@ -10,6 +10,7 @@ class Person < ActiveRecord::Base
belongs_to :primary_contact, :class_name => 'Person'
has_many :agents, :class_name => 'Person', :foreign_key => 'primary_contact_id'
+ belongs_to :number1_fan, :class_name => 'Person'
named_scope :males, :conditions => { :gender => 'M' }
named_scope :females, :conditions => { :gender => 'F' }
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 4ee0ffe132..6e8813d8ab 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -324,6 +324,7 @@ ActiveRecord::Schema.define do
t.string :first_name, :null => false
t.references :primary_contact
t.string :gender, :limit => 1
+ t.references :number1_fan
t.integer :lock_version, :null => false, :default => 0
end
--
cgit v1.2.3
From 28f5cfe066dfa901d71c02987e390937a74517c8 Mon Sep 17 00:00:00 2001
From: Emilio Tagua
Date: Mon, 18 May 2009 10:43:18 -0300
Subject: Add missing model and fixtures to finder_test [#2671 state:resolved]
Signed-off-by: Pratik Naik
---
activerecord/test/cases/finder_test.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index d0d7094e30..037b67ec84 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -7,10 +7,10 @@ require 'models/company'
require 'models/topic'
require 'models/reply'
require 'models/entrant'
+require 'models/project'
require 'models/developer'
require 'models/customer'
require 'models/job'
-require 'models/categorization'
class DynamicFinderMatchTest < ActiveRecord::TestCase
def test_find_no_match
@@ -64,7 +64,7 @@ class DynamicFinderMatchTest < ActiveRecord::TestCase
end
class FinderTest < ActiveRecord::TestCase
- fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers
+ fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers, :categories, :categorizations
def test_find
assert_equal(topics(:first).title, Topic.find(1).title)
--
cgit v1.2.3
From 195fadbfd31294d43634afb7bbf4f0ffc86b470a Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Mon, 18 May 2009 16:59:37 +0200
Subject: Ensure HTTP Digest auth uses appropriate HTTP method [#2490
state:resolved] [Steve Madsen]
---
.../action_controller/base/http_authentication.rb | 3 ++-
.../controller/http_digest_authentication_test.rb | 23 +++++++++++++++++++---
2 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/actionpack/lib/action_controller/base/http_authentication.rb b/actionpack/lib/action_controller/base/http_authentication.rb
index fa8ecea408..2893290efb 100644
--- a/actionpack/lib/action_controller/base/http_authentication.rb
+++ b/actionpack/lib/action_controller/base/http_authentication.rb
@@ -194,9 +194,10 @@ module ActionController
if valid_nonce && realm == credentials[:realm] && opaque == credentials[:opaque]
password = password_procedure.call(credentials[:username])
+ method = request.env['rack.methodoverride.original_method'] || request.env['REQUEST_METHOD']
[true, false].any? do |password_is_ha1|
- expected = expected_response(request.env['REQUEST_METHOD'], request.env['REQUEST_URI'], credentials, password, password_is_ha1)
+ expected = expected_response(method, request.env['REQUEST_URI'], credentials, password, password_is_ha1)
expected == credentials[:response]
end
end
diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb
index 7bebc8cd2a..b8a2205ce6 100644
--- a/actionpack/test/controller/http_digest_authentication_test.rb
+++ b/actionpack/test/controller/http_digest_authentication_test.rb
@@ -149,6 +149,16 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
assert_equal 'Definitely Maybe', @response.body
end
+ test "authentication request with _method" do
+ @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please', :method => :post)
+ @request.env['rack.methodoverride.original_method'] = 'POST'
+ put :display
+
+ assert_response :success
+ assert assigns(:logged_in)
+ assert_equal 'Definitely Maybe', @response.body
+ end
+
private
def encode_credentials(options)
@@ -159,15 +169,22 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
# to prevent tampering of timestamp
ActionController::Base.session_options[:secret] = "session_options_secret"
- # Perform unauthenticated GET to retrieve digest parameters to use on subsequent request
- get :index
+ # Perform unauthenticated request to retrieve digest parameters to use on subsequent request
+ method = options.delete(:method) || 'GET'
+
+ case method.to_s.upcase
+ when 'GET'
+ get :index
+ when 'POST'
+ post :index
+ end
assert_response :unauthorized
credentials = decode_credentials(@response.headers['WWW-Authenticate'])
credentials.merge!(options)
credentials.reverse_merge!(:uri => "#{@request.env['REQUEST_URI']}")
- ActionController::HttpAuthentication::Digest.encode_credentials("GET", credentials, password, options[:password_is_ha1])
+ ActionController::HttpAuthentication::Digest.encode_credentials(method, credentials, password, options[:password_is_ha1])
end
def decode_credentials(header)
--
cgit v1.2.3
From 5e190ef138a034bf86419ce4f4c343ae16bfc77b Mon Sep 17 00:00:00 2001
From: Andy Stewart
Date: Wed, 28 Jan 2009 16:45:28 +0000
Subject: Truncate helper accepts a :separator for a more legible result [#1807
state:resolved]
Signed-off-by: Pratik Naik
---
actionpack/lib/action_view/helpers/text_helper.rb | 7 ++++++-
actionpack/test/template/text_helper_test.rb | 3 +++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 8136a1cb13..ad0733a7e1 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -34,12 +34,16 @@ module ActionView
# Truncates a given +text+ after a given :length if +text+ is longer than :length
# (defaults to 30). The last characters will be replaced with the :omission (defaults to "...").
+ # Pass a :separator to truncate +text+ at a natural break.
#
# ==== Examples
#
# truncate("Once upon a time in a world far far away")
# # => Once upon a time in a world f...
#
+ # truncate("Once upon a time in a world far far away", :separator => ' ')
+ # # => Once upon a time in a world...
+ #
# truncate("Once upon a time in a world far far away", :length => 14)
# # => Once upon a...
#
@@ -71,7 +75,8 @@ module ActionView
if text
l = options[:length] - options[:omission].mb_chars.length
chars = text.mb_chars
- (chars.length > options[:length] ? chars[0...l] + options[:omission] : text).to_s
+ stop = options[:separator] ? (chars.rindex(options[:separator].mb_chars, l) || l) : l
+ (chars.length > options[:length] ? chars[0...stop] + options[:omission] : text).to_s
end
end
diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb
index a780bfc606..706b5085f4 100644
--- a/actionpack/test/template/text_helper_test.rb
+++ b/actionpack/test/template/text_helper_test.rb
@@ -49,6 +49,9 @@ class TextHelperTest < ActionView::TestCase
assert_equal "This is a string that wil[...]", truncate("This is a string that will go longer then the default truncate length of 30", :omission => "[...]")
assert_equal "Hello W...", truncate("Hello World!", :length => 10)
assert_equal "Hello[...]", truncate("Hello World!", :omission => "[...]", :length => 10)
+ assert_equal "Hello[...]", truncate("Hello Big World!", :omission => "[...]", :length => 13, :separator => ' ')
+ assert_equal "Hello Big[...]", truncate("Hello Big World!", :omission => "[...]", :length => 14, :separator => ' ')
+ assert_equal "Hello Big[...]", truncate("Hello Big World!", :omission => "[...]", :length => 15, :separator => ' ')
end
if RUBY_VERSION < '1.9.0'
--
cgit v1.2.3
From 37453e11e9c071f9bdec47b073939fd34402127d Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Mon, 18 May 2009 11:55:06 -0700
Subject: Revert "Get AR CI passing again by requiring the entire core_ext"
This reverts commit 8e6a18d8672f7efe6ef79b49185e4a6a23e4e547.
---
activerecord/lib/active_record.rb | 3 ---
1 file changed, 3 deletions(-)
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index b5c17cb23b..2d98239052 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -25,9 +25,6 @@ activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
$:.unshift(activesupport_path) if File.directory?(activesupport_path)
require 'active_support'
-# TODO: Figure out what parts of AS are *actually* required and use those
-require 'active_support/core_ext'
-
module ActiveRecord
# TODO: Review explicit loads to see if they will automatically be handled by the initilizer.
def self.load_all!
--
cgit v1.2.3
From c5e109bbe766b0407a909361f18d2b87e9bfc75c Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Mon, 18 May 2009 21:27:42 +0200
Subject: Make sure default_scope#create checks for options[:conditions] [#2181
state:resolved] [James Le Cuirot]
---
activerecord/lib/active_record/base.rb | 2 +-
activerecord/test/cases/method_scoping_test.rb | 10 ++++++++++
activerecord/test/models/developer.rb | 10 ++++++++++
3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index ca4f4fa6b6..968b9bde5a 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -2176,7 +2176,7 @@ module ActiveRecord #:nodoc:
# default_scope :order => 'last_name, first_name'
# end
def default_scope(options = {})
- self.default_scoping << { :find => options, :create => (options.is_a?(Hash) && options.has_key?(:conditions)) ? options[:conditions] : {} }
+ self.default_scoping << { :find => options, :create => options[:conditions].is_a?(Hash) ? options[:conditions] : {} }
end
# Test whether the given method and optional key are scoped.
diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb
index c479859ee0..d8246f49b8 100644
--- a/activerecord/test/cases/method_scoping_test.rb
+++ b/activerecord/test/cases/method_scoping_test.rb
@@ -591,6 +591,16 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal expected, received
end
+ def test_default_scope_with_conditions_string
+ assert_equal Developer.find_all_by_name('David').map(&:id).sort, DeveloperCalledDavid.all.map(&:id).sort
+ assert_equal nil, DeveloperCalledDavid.create!.name
+ end
+
+ def test_default_scope_with_conditions_hash
+ assert_equal Developer.find_all_by_name('Jamis').map(&:id).sort, DeveloperCalledJamis.all.map(&:id).sort
+ assert_equal 'Jamis', DeveloperCalledJamis.create!.name
+ end
+
def test_default_scoping_with_threads
scope = [{ :create => {}, :find => { :order => 'salary DESC' } }]
diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb
index 92039a4f54..058970336b 100644
--- a/activerecord/test/models/developer.rb
+++ b/activerecord/test/models/developer.rb
@@ -89,3 +89,13 @@ class DeveloperOrderedBySalary < ActiveRecord::Base
end
end
end
+
+class DeveloperCalledDavid < ActiveRecord::Base
+ self.table_name = 'developers'
+ default_scope :conditions => "name = 'David'"
+end
+
+class DeveloperCalledJamis < ActiveRecord::Base
+ self.table_name = 'developers'
+ default_scope :conditions => { :name => 'Jamis' }
+end
--
cgit v1.2.3
From a69b28a8b10fdcbb6801051e3086228b56891dbb Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Mon, 18 May 2009 13:20:04 -0700
Subject: Missing 1.8.7 backport extensions
---
activerecord/lib/active_record/base.rb | 1 +
activerecord/lib/active_record/validations.rb | 2 ++
2 files changed, 3 insertions(+)
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index ca4f4fa6b6..e8e1746b4b 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -9,6 +9,7 @@ require 'active_support/core_ext/hash/deep_merge'
require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/string/behavior'
+require 'active_support/core_ext/symbol'
require 'active_support/core/time'
module ActiveRecord #:nodoc:
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index b6e848fa79..a18fb3f426 100644
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/integer/even_odd'
+
module ActiveRecord
# Raised by save! and create! when the record is invalid. Use the
# +record+ method to retrieve the record which did not validate.
--
cgit v1.2.3
From cef76c8af4705dc60f85a721e3a14adb99418d33 Mon Sep 17 00:00:00 2001
From: Luca Guidi
Date: Mon, 16 Mar 2009 13:30:30 +0100
Subject: Ensure HasManyThroughAssociation#destroy delete orphan records [#2251
state:resolved]
Signed-off-by: Pratik Naik
---
.../active_record/associations/has_many_through_association.rb | 7 +++++++
.../cases/associations/has_many_through_associations_test.rb | 10 ++++++++--
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb
index 2dca84b911..e8dbae9011 100644
--- a/activerecord/lib/active_record/associations/has_many_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_through_association.rb
@@ -17,6 +17,13 @@ module ActiveRecord
end
end
+ def destroy(*records)
+ transaction do
+ delete_records(flatten_deeper(records))
+ super
+ end
+ end
+
# Returns the size of the collection by executing a SELECT COUNT(*) query if the collection hasn't been loaded and
# calling collection.size if it has. If it's more likely than not that the collection does have a size larger than zero,
# and you need to fetch that collection afterwards, it'll take one fewer SELECT query if you use #length.
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index 97efca7891..51c70b9819 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -93,7 +93,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
end
def test_destroy_association
- assert_difference "Person.count", -1 do
+ assert_difference ["Person.count", "Reader.count"], -1 do
posts(:welcome).people.destroy(people(:michael))
end
@@ -102,7 +102,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
end
def test_destroy_all
- assert_difference "Person.count", -1 do
+ assert_difference ["Person.count", "Reader.count"], -1 do
posts(:welcome).people.destroy_all
end
@@ -110,6 +110,12 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
assert posts(:welcome).people(true).empty?
end
+ def test_should_raise_exception_for_destroying_mismatching_records
+ assert_no_difference ["Person.count", "Reader.count"] do
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:welcome).people.destroy(posts(:thinking)) }
+ end
+ end
+
def test_replace_association
assert_queries(4){posts(:welcome);people(:david);people(:michael); posts(:welcome).people(true)}
--
cgit v1.2.3
From 87adecfef59577be17a9731245cb201ecb1b477f Mon Sep 17 00:00:00 2001
From: Ken Collins
Date: Mon, 11 May 2009 23:22:20 -0400
Subject: Reimplement Fixtures.identify so that it consistently generates
identities across ruby versions.
[#2633 state:committed]
Signed-off-by: Jeremy Kemper
---
activerecord/lib/active_record/fixtures.rb | 9 +++++----
activerecord/test/cases/fixtures_test.rb | 5 +++++
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index e30fcf9a4f..721114d9d0 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -1,6 +1,7 @@
require 'erb'
require 'yaml'
require 'csv'
+require 'zlib'
require 'active_support/dependencies'
require 'active_support/test_case'
require 'active_support/core_ext/logger'
@@ -434,6 +435,7 @@ end
# Any fixture labeled "DEFAULTS" is safely ignored.
class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
+ MAX_ID = 2 ** 31 - 1
DEFAULT_FILTER_RE = /\.ya?ml$/
@@all_cached_fixtures = {}
@@ -525,11 +527,10 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
cached_fixtures(connection, table_names)
end
- # Returns a consistent identifier for +label+. This will always
- # be a positive integer, and will always be the same for a given
- # label, assuming the same OS, platform, and version of Ruby.
+ # Returns a consistent, platform-independent identifier for +label+.
+ # Identifiers are positive integers less than 2^32.
def self.identify(label)
- label.to_s.hash.abs
+ Zlib.crc32(label.to_s) % MAX_ID
end
attr_reader :table_name, :name
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index 252bf4ff61..b07d4f3521 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -518,6 +518,11 @@ class FoxyFixturesTest < ActiveRecord::TestCase
assert_equal(Fixtures.identify(:foo), Fixtures.identify(:foo))
end
+ def test_identifies_consistently
+ assert_equal 1281023246, Fixtures.identify(:ruby)
+ assert_equal 2140105598, Fixtures.identify(:sapphire_2)
+ end
+
TIMESTAMP_COLUMNS = %w(created_at created_on updated_at updated_on)
def test_populates_timestamp_columns
--
cgit v1.2.3
From 29550cc91f8dcbfe3e4020986d719c77ddd2f14d Mon Sep 17 00:00:00 2001
From: Joe Van Dyk
Date: Mon, 2 Feb 2009 16:43:14 -0800
Subject: Add ability to get multiple memcached keys at the same time (via
MemCacheStore#read_multi).
Signed-off-by: Jeremy Kemper
---
activesupport/lib/active_support/cache/mem_cache_store.rb | 5 +++++
activesupport/memcached_get_multi.diff | 0
activesupport/test/caching_test.rb | 9 +++++++++
3 files changed, 14 insertions(+)
create mode 100644 activesupport/memcached_get_multi.diff
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index 4d8e1fdd67..90b7526fe1 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -43,6 +43,11 @@ module ActiveSupport
extend Strategy::LocalCache
end
+ # Reads multiple keys from the cache.
+ def read_multi(*keys)
+ @data.get_multi keys
+ end
+
def read(key, options = nil) # :nodoc:
super
@data.get(key, raw?(options))
diff --git a/activesupport/memcached_get_multi.diff b/activesupport/memcached_get_multi.diff
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index 8bb0c155cf..b845796fe5 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -251,6 +251,15 @@ uses_memcached 'memcached backed store' do
end
end
+ def test_multi_get
+ @cache.with_local_cache do
+ @cache.write('foo', 1)
+ @cache.write('goo', 2)
+ result = @cache.read_multi('foo', 'goo')
+ assert_equal({'foo' => 1, 'goo' => 2}, result)
+ end
+ end
+
def test_middleware
app = lambda { |env|
result = @cache.write('foo', 'bar')
--
cgit v1.2.3
From 5463823df38310d392a3f87d633dce9b4150259a Mon Sep 17 00:00:00 2001
From: Emilio Tagua
Date: Sat, 2 May 2009 13:56:10 -0300
Subject: Remove unnecessary condition and local variable [#2602
state:resolved]
Signed-off-by: Pratik Naik
---
activerecord/lib/active_record/base.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 968b9bde5a..af800261e5 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1541,12 +1541,12 @@ module ActiveRecord #:nodoc:
end
def reverse_sql_order(order_query)
- reversed_query = order_query.to_s.split(/,/).each { |s|
+ order_query.to_s.split(/,/).each { |s|
if s.match(/\s(asc|ASC)$/)
s.gsub!(/\s(asc|ASC)$/, ' DESC')
elsif s.match(/\s(desc|DESC)$/)
s.gsub!(/\s(desc|DESC)$/, ' ASC')
- elsif !s.match(/\s(asc|ASC|desc|DESC)$/)
+ else
s.concat(' DESC')
end
}.join(',')
--
cgit v1.2.3
From 41e9414b60e8d042bacf2f8d61d7efc07111417a Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Mon, 18 May 2009 15:01:13 -0700
Subject: Include acts_as_string?
---
activesupport/lib/active_support/multibyte/chars.rb | 1 +
1 file changed, 1 insertion(+)
diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb
index 60f082bcc1..96ed35f0e0 100644
--- a/activesupport/lib/active_support/multibyte/chars.rb
+++ b/activesupport/lib/active_support/multibyte/chars.rb
@@ -1,4 +1,5 @@
# encoding: utf-8
+require 'active_support/core_ext/string/behavior'
module ActiveSupport #:nodoc:
module Multibyte #:nodoc:
--
cgit v1.2.3
From 07f733c6315980bde120c98c6b8a25e2773ee6bf Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Mon, 18 May 2009 16:15:43 -0700
Subject: Ported simple benchmarking in new base
---
actionpack/Rakefile | 4 ++--
actionpack/lib/action_controller/abstract.rb | 1 +
.../lib/action_controller/abstract/benchmarker.rb | 28 ++++++++++++++++++++++
.../lib/action_controller/abstract/logger.rb | 1 +
.../action_controller/base/chained/benchmarking.rb | 2 +-
actionpack/lib/action_controller/new_base/base.rb | 1 +
actionpack/test/controller/logging_test.rb | 5 ++++
7 files changed, 39 insertions(+), 3 deletions(-)
create mode 100644 actionpack/lib/action_controller/abstract/benchmarker.rb
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 41b190130e..57c3276cb9 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -21,8 +21,8 @@ task :default => [ :test ]
# Run the unit tests
-desc "Run all unit tests"
-task :test => [:test_action_pack, :test_active_record_integration]
+desc "Run all unit tests" # Do not remove :test_new_base
+task :test => [:test_action_pack, :test_active_record_integration, :test_new_base]
Rake::TestTask.new(:test_action_pack) do |t|
t.libs << "test"
diff --git a/actionpack/lib/action_controller/abstract.rb b/actionpack/lib/action_controller/abstract.rb
index 48e33282ec..d6b7a44f5f 100644
--- a/actionpack/lib/action_controller/abstract.rb
+++ b/actionpack/lib/action_controller/abstract.rb
@@ -3,6 +3,7 @@ require "active_support/core_ext/module/delegation"
module AbstractController
autoload :Base, "action_controller/abstract/base"
+ autoload :Benchmarker, "action_controller/abstract/benchmarker"
autoload :Callbacks, "action_controller/abstract/callbacks"
autoload :Helpers, "action_controller/abstract/helpers"
autoload :Layouts, "action_controller/abstract/layouts"
diff --git a/actionpack/lib/action_controller/abstract/benchmarker.rb b/actionpack/lib/action_controller/abstract/benchmarker.rb
new file mode 100644
index 0000000000..9f5889c704
--- /dev/null
+++ b/actionpack/lib/action_controller/abstract/benchmarker.rb
@@ -0,0 +1,28 @@
+module AbstractController
+ module Benchmarker
+ extend ActiveSupport::DependencyModule
+
+ depends_on Logger
+
+ module ClassMethods
+ def benchmark(title, log_level = ::Logger::DEBUG, use_silence = true)
+ if logger && logger.level >= log_level
+ result = nil
+ ms = Benchmark.ms { result = use_silence ? silence { yield } : yield }
+ logger.add(log_level, "#{title} (#{('%.1f' % ms)}ms)")
+ result
+ else
+ yield
+ end
+ end
+
+ # Silences the logger for the duration of the block.
+ def silence
+ old_logger_level, logger.level = logger.level, ::Logger::ERROR if logger
+ yield
+ ensure
+ logger.level = old_logger_level if logger
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb
index 750a5c9fb6..980ede0bed 100644
--- a/actionpack/lib/action_controller/abstract/logger.rb
+++ b/actionpack/lib/action_controller/abstract/logger.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/class/attribute_accessors'
+require 'active_support/core_ext/logger'
module AbstractController
module Logger
diff --git a/actionpack/lib/action_controller/base/chained/benchmarking.rb b/actionpack/lib/action_controller/base/chained/benchmarking.rb
index 66e9e9c31d..57a1ac8314 100644
--- a/actionpack/lib/action_controller/base/chained/benchmarking.rb
+++ b/actionpack/lib/action_controller/base/chained/benchmarking.rb
@@ -21,7 +21,7 @@ module ActionController #:nodoc:
# easy to include benchmarking statements in production software that will remain inexpensive because the benchmark
# will only be conducted if the log level is low enough.
def benchmark(title, log_level = Logger::DEBUG, use_silence = true)
- if logger && logger.level == log_level
+ if logger && logger.level >= log_level
result = nil
ms = Benchmark.ms { result = use_silence ? silence { yield } : yield }
logger.add(log_level, "#{title} (#{('%.1f' % ms)}ms)")
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index c25ffd5c84..756a0799fe 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -2,6 +2,7 @@ module ActionController
class Base < Http
abstract!
+ include AbstractController::Benchmarker
include AbstractController::Callbacks
include AbstractController::Helpers
include AbstractController::Logger
diff --git a/actionpack/test/controller/logging_test.rb b/actionpack/test/controller/logging_test.rb
index 1f3ff4ef52..75afa2d133 100644
--- a/actionpack/test/controller/logging_test.rb
+++ b/actionpack/test/controller/logging_test.rb
@@ -11,6 +11,11 @@ class LoggingTest < ActionController::TestCase
class MockLogger
attr_reader :logged
+ attr_accessor :level
+
+ def initialize
+ @level = Logger::DEBUG
+ end
def method_missing(method, *args)
@logged ||= []
--
cgit v1.2.3
From 20deb677a23d2a57f0a946dc98debe0fcdb70c40 Mon Sep 17 00:00:00 2001
From: Emilio Tagua
Date: Mon, 18 May 2009 20:17:35 -0300
Subject: Add missing models and fixtures [#2673 state:resolved]
Signed-off-by: Pratik Naik
---
.../has_many_through_associations_test.rb | 46 +++++++++++-----------
.../test/cases/autosave_association_test.rb | 7 +++-
activerecord/test/cases/named_scope_test.rb | 4 +-
3 files changed, 32 insertions(+), 25 deletions(-)
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index 51c70b9819..4254badef2 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -13,7 +13,7 @@ require 'models/pet'
require 'models/toy'
class HasManyThroughAssociationsTest < ActiveRecord::TestCase
- fixtures :posts, :readers, :people, :comments, :authors, :owners, :pets, :toys
+ fixtures :posts, :readers, :people, :comments, :authors, :owners, :pets, :toys, :jobs, :references
def test_associate_existing
assert_queries(2) { posts(:thinking);people(:david) }
@@ -23,49 +23,49 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
assert_queries(1) do
posts(:thinking).people << people(:david)
end
-
+
assert_queries(1) do
assert posts(:thinking).people.include?(people(:david))
end
-
+
assert posts(:thinking).reload.people(true).include?(people(:david))
end
def test_associating_new
assert_queries(1) { posts(:thinking) }
new_person = nil # so block binding catches it
-
+
assert_queries(0) do
new_person = Person.new :first_name => 'bob'
end
-
+
# Associating new records always saves them
# Thus, 1 query for the new person record, 1 query for the new join table record
assert_queries(2) do
posts(:thinking).people << new_person
end
-
+
assert_queries(1) do
assert posts(:thinking).people.include?(new_person)
end
-
+
assert posts(:thinking).reload.people(true).include?(new_person)
end
def test_associate_new_by_building
assert_queries(1) { posts(:thinking) }
-
+
assert_queries(0) do
posts(:thinking).people.build(:first_name=>"Bob")
posts(:thinking).people.new(:first_name=>"Ted")
end
-
+
# Should only need to load the association once
assert_queries(1) do
assert posts(:thinking).people.collect(&:first_name).include?("Bob")
assert posts(:thinking).people.collect(&:first_name).include?("Ted")
end
-
+
# 2 queries for each new record (1 to save the record itself, 1 for the join model)
# * 2 new records = 4
# + 1 query to save the actual post = 5
@@ -73,22 +73,22 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
posts(:thinking).body += '-changed'
posts(:thinking).save
end
-
+
assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Bob")
assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Ted")
end
def test_delete_association
assert_queries(2){posts(:welcome);people(:michael); }
-
+
assert_queries(1) do
posts(:welcome).people.delete(people(:michael))
end
-
+
assert_queries(1) do
assert posts(:welcome).people.empty?
end
-
+
assert posts(:welcome).reload.people(true).empty?
end
@@ -118,36 +118,36 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
def test_replace_association
assert_queries(4){posts(:welcome);people(:david);people(:michael); posts(:welcome).people(true)}
-
+
# 1 query to delete the existing reader (michael)
# 1 query to associate the new reader (david)
assert_queries(2) do
posts(:welcome).people = [people(:david)]
end
-
+
assert_queries(0){
assert posts(:welcome).people.include?(people(:david))
assert !posts(:welcome).people.include?(people(:michael))
}
-
+
assert posts(:welcome).reload.people(true).include?(people(:david))
assert !posts(:welcome).reload.people(true).include?(people(:michael))
end
def test_associate_with_create
assert_queries(1) { posts(:thinking) }
-
+
# 1 query for the new record, 1 for the join table record
# No need to update the actual collection yet!
assert_queries(2) do
posts(:thinking).people.create(:first_name=>"Jeb")
end
-
+
# *Now* we actually need the collection so it's loaded
assert_queries(1) do
assert posts(:thinking).people.collect(&:first_name).include?("Jeb")
end
-
+
assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Jeb")
end
@@ -165,15 +165,15 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
def test_clear_associations
assert_queries(2) { posts(:welcome);posts(:welcome).people(true) }
-
+
assert_queries(1) do
posts(:welcome).people.clear
end
-
+
assert_queries(0) do
assert posts(:welcome).people.empty?
end
-
+
assert posts(:welcome).reload.people(true).empty?
end
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index 919b6f857c..f95b2c0079 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -12,6 +12,7 @@ require 'models/reader'
require 'models/ship'
require 'models/ship_part'
require 'models/treasure'
+require 'models/company'
class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
def test_autosave_should_be_a_valid_option_for_has_one
@@ -38,6 +39,8 @@ class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
end
class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
+ fixtures :companies, :accounts
+
def test_should_save_parent_but_not_invalid_child
firm = Firm.new(:name => 'GlobalMegaCorp')
assert firm.valid?
@@ -137,6 +140,8 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas
end
class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase
+ fixtures :companies
+
def test_should_save_parent_but_not_invalid_child
client = Client.new(:name => 'Joe (the Plumber)')
assert client.valid?
@@ -920,4 +925,4 @@ class TestAutosaveAssociationOnAHasAndBelongsToManyAssociation < ActiveRecord::T
end
include AutosaveAssociationOnACollectionAssociationTests
-end
\ No newline at end of file
+end
diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb
index 69d01d5c2a..92fe48cb5a 100644
--- a/activerecord/test/cases/named_scope_test.rb
+++ b/activerecord/test/cases/named_scope_test.rb
@@ -373,7 +373,7 @@ class NamedScopeTest < ActiveRecord::TestCase
end
end
-class DynamicScopeMatchTest < ActiveRecord::TestCase
+class DynamicScopeMatchTest < ActiveRecord::TestCase
def test_scoped_by_no_match
assert_nil ActiveRecord::DynamicScopeMatch.match("not_scoped_at_all")
end
@@ -387,6 +387,8 @@ class DynamicScopeMatchTest < ActiveRecord::TestCase
end
class DynamicScopeTest < ActiveRecord::TestCase
+ fixtures :posts
+
def test_dynamic_scope
assert_equal Post.scoped_by_author_id(1).find(1), Post.find(1)
assert_equal Post.scoped_by_author_id_and_title(1, "Welcome to the weblog").first, Post.find(:first, :conditions => { :author_id => 1, :title => "Welcome to the weblog"})
--
cgit v1.2.3
From 6dc3a6a954b742ac7160593f94962b9b93a2ce25 Mon Sep 17 00:00:00 2001
From: Chad Woolley
Date: Tue, 19 May 2009 12:50:26 +0200
Subject: Upgrade CI server to latest RubyGems [#2665 state:resolved]
Signed-off-by: Pratik Naik
---
ci/ci_setup_notes.txt | 2 +-
ci/cruise_config.rb | 2 +-
ci/geminstaller.yml | 2 ++
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/ci/ci_setup_notes.txt b/ci/ci_setup_notes.txt
index 63f1851b19..780277c939 100644
--- a/ci/ci_setup_notes.txt
+++ b/ci/ci_setup_notes.txt
@@ -47,7 +47,7 @@ $ sudo aptitude update
* If you did not configure no-root-gem installation via ~/.gemrc as shown above, then allow no-password sudo for gem installation:
$ sudo visudo
# add this line to bottom:
-ci ALL=NOPASSWD: /usr/local/bin/geminstaller, /usr/local/bin/ruby, /usr/local/bin/gem
+ci ALL=(ALL) NOPASSWD: ALL
* Start ccrb via init script and check for default homepage at port 3333
diff --git a/ci/cruise_config.rb b/ci/cruise_config.rb
index 7985e3c8df..2247a1b6ea 100644
--- a/ci/cruise_config.rb
+++ b/ci/cruise_config.rb
@@ -1,5 +1,5 @@
Project.configure do |project|
- project.build_command = 'ruby ci/ci_build.rb'
+ project.build_command = 'sudo update_rubygems && ruby ci/ci_build.rb'
project.email_notifier.emails = ['thewoolleyman@gmail.com']
# project.email_notifier.emails = ['thewoolleyman@gmail.com','michael@koziarski.com', 'david@loudthinking.com', 'jeremy@bitsweat.net', 'josh@joshpeek.com', 'pratiknaik@gmail.com', 'wycats@gmail.com']
project.email_notifier.from = 'thewoolleyman+railsci@gmail.com'
diff --git a/ci/geminstaller.yml b/ci/geminstaller.yml
index 387e370a6f..f1ef9b59a0 100644
--- a/ci/geminstaller.yml
+++ b/ci/geminstaller.yml
@@ -21,3 +21,5 @@ gems:
version: >= 2.2.3
- name: sqlite3-ruby
version: >= 1.2.2
+- name: rubygems-update
+ version: >= 1.3.3
--
cgit v1.2.3
From e2ed1a1ca4f2dbfb9eb2c31fd1ddd45562afef25 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp
Date: Tue, 19 May 2009 10:24:26 -0400
Subject: Allow MemCacheStore to be initialized with a MemCache object instead
of addresses and options
---
activesupport/CHANGELOG | 2 ++
.../lib/active_support/cache/mem_cache_store.rb | 17 +++++++++++------
activesupport/test/caching_test.rb | 14 ++++++++++----
3 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 032f0fb9c1..6551be01f9 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Allow MemCacheStore to be initialized with a MemCache object instead of addresses and options [Bryan Helmkamp]
+
* Change spelling of Kyev timezone to Kyiv #2613 [Alexander Dymo]
* Add ActiveSupport.parse_json_times to disable time parsing in JSON backends that don't support it or don't need it. [rick]
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index 90b7526fe1..ab8eb72096 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -23,7 +23,12 @@ module ActiveSupport
DELETED = "DELETED\r\n"
end
- attr_reader :addresses
+ def self.build_mem_cache(*addresses)
+ addresses = addresses.flatten
+ options = addresses.extract_options!
+ addresses = ["localhost"] if addresses.empty?
+ MemCache.new(addresses, options)
+ end
# Creates a new MemCacheStore object, with the given memcached server
# addresses. Each address is either a host name, or a host-with-port string
@@ -34,11 +39,11 @@ module ActiveSupport
# If no addresses are specified, then MemCacheStore will connect to
# localhost port 11211 (the default memcached port).
def initialize(*addresses)
- addresses = addresses.flatten
- options = addresses.extract_options!
- addresses = ["localhost"] if addresses.empty?
- @addresses = addresses
- @data = MemCache.new(addresses, options)
+ if addresses.first.is_a?(MemCache)
+ @data = addresses.first
+ else
+ @data = self.class.build_mem_cache(*addresses)
+ end
extend Strategy::LocalCache
end
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index b845796fe5..ad19dcfd09 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -15,22 +15,28 @@ class CacheStoreSettingTest < ActiveSupport::TestCase
end
def test_mem_cache_fragment_cache_store
+ MemCache.expects(:new).with(%w[localhost], {})
store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost"
assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
- assert_equal %w(localhost), store.addresses
+ end
+
+ def test_mem_cache_fragment_cache_store_with_given_mem_cache
+ mem_cache = MemCache.new
+ MemCache.expects(:new).never
+ store = ActiveSupport::Cache.lookup_store :mem_cache_store, mem_cache
+ assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
end
def test_mem_cache_fragment_cache_store_with_multiple_servers
+ MemCache.expects(:new).with(%w[localhost 192.168.1.1], {})
store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1'
assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
- assert_equal %w(localhost 192.168.1.1), store.addresses
end
def test_mem_cache_fragment_cache_store_with_options
+ MemCache.expects(:new).with(%w[localhost 192.168.1.1], { :namespace => "foo" })
store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1', :namespace => 'foo'
assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
- assert_equal %w(localhost 192.168.1.1), store.addresses
- assert_equal 'foo', store.instance_variable_get('@data').instance_variable_get('@namespace')
end
def test_object_assigned_fragment_cache_store
--
cgit v1.2.3
From 0bdef30f35501953ffdcb34f1c8d3a1e23f9434d Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Tue, 19 May 2009 12:19:58 -0700
Subject: Lazy-require Kernel#silence_warnings
---
railties/lib/rails/plugin.rb | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb
index e66166306a..49ec5c7fba 100644
--- a/railties/lib/rails/plugin.rb
+++ b/railties/lib/rails/plugin.rb
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/kernel/reporting'
-
module Rails
# The Plugin class should be an object which provides the following methods:
#
@@ -141,6 +139,7 @@ module Rails
def evaluate_init_rb(initializer)
if has_init_file?
+ require 'active_support/core_ext/kernel/reporting'
silence_warnings do
# Allow plugins to reference the current configuration object
config = initializer.configuration
--
cgit v1.2.3
From 4a6f4b92ad2f48dc7906d223fe4708d36624bd50 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Tue, 19 May 2009 23:48:05 +0200
Subject: Change integration test helpers to accept Rack environment instead of
just HTTP Headers.
Before : get '/path', {}, 'Accept' => 'text/javascript'
After : get '/path', {}, 'HTTP_ACCEPT' => 'text/javascript'
---
.../lib/action_controller/testing/integration.rb | 10 ++++-----
actionpack/test/controller/integration_test.rb | 24 +++++++++++-----------
2 files changed, 16 insertions(+), 18 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb
index d6991ab4f5..a8e8f16d6c 100644
--- a/actionpack/lib/action_controller/testing/integration.rb
+++ b/actionpack/lib/action_controller/testing/integration.rb
@@ -62,8 +62,8 @@ module ActionController
# with 'HTTP_' if not already.
def xml_http_request(request_method, path, parameters = nil, headers = nil)
headers ||= {}
- headers['X-Requested-With'] = 'XMLHttpRequest'
- headers['Accept'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
+ headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
+ headers['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
process(request_method, path, parameters, headers)
end
alias xhr :xml_http_request
@@ -228,7 +228,7 @@ module ActionController
private
# Performs the actual request.
- def process(method, path, parameters = nil, headers = nil)
+ def process(method, path, parameters = nil, rack_environment = nil)
if path =~ %r{://}
location = URI.parse(path)
https! URI::HTTPS === location if location.scheme
@@ -265,9 +265,7 @@ module ActionController
}
env = Rack::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_/
+ (rack_environment || {}).each do |key, value|
env[key] = value
end
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index c616107324..a2b3ad2106 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -123,8 +123,8 @@ class SessionTest < Test::Unit::TestCase
def test_xml_http_request_get
path = "/index"; params = "blah"; headers = {:location => 'blah'}
headers_after_xhr = headers.merge(
- "X-Requested-With" => "XMLHttpRequest",
- "Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
+ "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
+ "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*"
)
@session.expects(:process).with(:get,path,params,headers_after_xhr)
@session.xml_http_request(:get,path,params,headers)
@@ -133,8 +133,8 @@ class SessionTest < Test::Unit::TestCase
def test_xml_http_request_post
path = "/index"; params = "blah"; headers = {:location => 'blah'}
headers_after_xhr = headers.merge(
- "X-Requested-With" => "XMLHttpRequest",
- "Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
+ "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
+ "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*"
)
@session.expects(:process).with(:post,path,params,headers_after_xhr)
@session.xml_http_request(:post,path,params,headers)
@@ -143,8 +143,8 @@ class SessionTest < Test::Unit::TestCase
def test_xml_http_request_put
path = "/index"; params = "blah"; headers = {:location => 'blah'}
headers_after_xhr = headers.merge(
- "X-Requested-With" => "XMLHttpRequest",
- "Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
+ "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
+ "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*"
)
@session.expects(:process).with(:put,path,params,headers_after_xhr)
@session.xml_http_request(:put,path,params,headers)
@@ -153,8 +153,8 @@ class SessionTest < Test::Unit::TestCase
def test_xml_http_request_delete
path = "/index"; params = "blah"; headers = {:location => 'blah'}
headers_after_xhr = headers.merge(
- "X-Requested-With" => "XMLHttpRequest",
- "Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
+ "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
+ "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*"
)
@session.expects(:process).with(:delete,path,params,headers_after_xhr)
@session.xml_http_request(:delete,path,params,headers)
@@ -163,17 +163,17 @@ class SessionTest < Test::Unit::TestCase
def test_xml_http_request_head
path = "/index"; params = "blah"; headers = {:location => 'blah'}
headers_after_xhr = headers.merge(
- "X-Requested-With" => "XMLHttpRequest",
- "Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
+ "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
+ "HTTP_ACCEPT" => "text/javascript, text/html, application/xml, text/xml, */*"
)
@session.expects(:process).with(:head,path,params,headers_after_xhr)
@session.xml_http_request(:head,path,params,headers)
end
def test_xml_http_request_override_accept
- path = "/index"; params = "blah"; headers = {:location => 'blah', "Accept" => "application/xml"}
+ path = "/index"; params = "blah"; headers = {:location => 'blah', "HTTP_ACCEPT" => "application/xml"}
headers_after_xhr = headers.merge(
- "X-Requested-With" => "XMLHttpRequest"
+ "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"
)
@session.expects(:process).with(:post,path,params,headers_after_xhr)
@session.xml_http_request(:post,path,params,headers)
--
cgit v1.2.3
From f503a5dc97d18794cc0eda5ffe77e2cd7d762d47 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Tue, 19 May 2009 23:57:49 +0200
Subject: Missing CHANGELOG entry for 4a6f4b92ad2f
---
actionpack/CHANGELOG | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index c1dc6f2ab4..e3ad19558e 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,10 @@
*Edge*
+* Change integration test helpers to accept Rack environment instead of just HTTP Headers [Pratik Naik]
+
+ Before : get '/path', {}, 'Accept' => 'text/javascript'
+ After : get '/path', {}, 'HTTP_ACCEPT' => 'text/javascript'
+
* Instead of checking Rails.env.test? in Failsafe middleware, check env["rails.raise_exceptions"] [Bryan Helmkamp]
* Fixed that TestResponse.cookies was returning cookies unescaped #1867 [Doug McInnes]
--
cgit v1.2.3
From d8fffe7b23acce42bc3941d7bba47e07a66aed67 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Wed, 20 May 2009 00:06:14 +0200
Subject: Replace ad hoc Rack::Test with ActionController::IntegrationTest
---
actionpack/Rakefile | 2 +-
actionpack/test/new_base/test_helper.rb | 16 +++++++---------
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 57c3276cb9..6ce8179646 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -21,7 +21,7 @@ task :default => [ :test ]
# Run the unit tests
-desc "Run all unit tests" # Do not remove :test_new_base
+desc "Run all unit tests"
task :test => [:test_action_pack, :test_active_record_integration, :test_new_base]
Rake::TestTask.new(:test_action_pack) do |t|
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index ec7dbffaae..9401e692f1 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -20,8 +20,8 @@ require 'action_controller/abstract'
require 'action_controller/new_base'
require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late
-require 'rubygems'
-require 'rack/test'
+require 'action_controller/testing/process'
+require 'action_controller/testing/integration'
module Rails
def self.env
@@ -32,9 +32,7 @@ module Rails
end
# Temporary base class
-class Rack::TestCase < ActiveSupport::TestCase
- include Rack::Test::Methods
-
+class Rack::TestCase < ActionController::IntegrationTest
setup do
ActionController::Base.session_options[:key] = "abc"
ActionController::Base.session_options[:secret] = ("*" * 30)
@@ -82,7 +80,7 @@ class Rack::TestCase < ActiveSupport::TestCase
end
def assert_body(body)
- assert_equal body, Array.wrap(last_response.body).join
+ assert_equal body, Array.wrap(response.body).join
end
def self.assert_body(body)
@@ -92,7 +90,7 @@ class Rack::TestCase < ActiveSupport::TestCase
end
def assert_status(code)
- assert_equal code, last_response.status
+ assert_equal code, response.status
end
def self.assert_status(code)
@@ -110,7 +108,7 @@ class Rack::TestCase < ActiveSupport::TestCase
end
def assert_content_type(type)
- assert_equal type, last_response.headers["Content-Type"]
+ assert_equal type, response.headers["Content-Type"]
end
def self.assert_content_type(type)
@@ -120,7 +118,7 @@ class Rack::TestCase < ActiveSupport::TestCase
end
def assert_header(name, value)
- assert_equal value, last_response.headers[name]
+ assert_equal value, response.headers[name]
end
def self.assert_header(name, value)
--
cgit v1.2.3
From 36058f45040b5559fd8f6a44a17ead27a6b3d2f7 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp
Date: Tue, 19 May 2009 19:51:38 -0400
Subject: Use duck typing to also allow MemCache-like object when initializing
a MemCacheStore
Signed-off-by: Jeremy Kemper
---
activesupport/CHANGELOG | 2 +-
activesupport/lib/active_support/cache/mem_cache_store.rb | 2 +-
activesupport/test/caching_test.rb | 6 ++++++
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 6551be01f9..27d26b2ba5 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,6 +1,6 @@
*Edge*
-* Allow MemCacheStore to be initialized with a MemCache object instead of addresses and options [Bryan Helmkamp]
+* Allow MemCacheStore to be initialized with a MemCache-like object instead of addresses and options [Bryan Helmkamp]
* Change spelling of Kyev timezone to Kyiv #2613 [Alexander Dymo]
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index ab8eb72096..38b3409ca6 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -39,7 +39,7 @@ module ActiveSupport
# If no addresses are specified, then MemCacheStore will connect to
# localhost port 11211 (the default memcached port).
def initialize(*addresses)
- if addresses.first.is_a?(MemCache)
+ if addresses.first.respond_to?(:get)
@data = addresses.first
else
@data = self.class.build_mem_cache(*addresses)
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index ad19dcfd09..bd237a5c8e 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -27,6 +27,12 @@ class CacheStoreSettingTest < ActiveSupport::TestCase
assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
end
+ def test_mem_cache_fragment_cache_store_with_given_mem_cache_like_object
+ MemCache.expects(:new).never
+ store = ActiveSupport::Cache.lookup_store :mem_cache_store, stub("memcache", :get => true)
+ assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
+ end
+
def test_mem_cache_fragment_cache_store_with_multiple_servers
MemCache.expects(:new).with(%w[localhost 192.168.1.1], {})
store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1'
--
cgit v1.2.3
From 67247ca8ee850223193a5fe77f5460aefc0336c0 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Tue, 19 May 2009 17:41:17 -0700
Subject: Corrected new callbacks semantics with regards to using objects for
around filters.
---
activesupport/lib/active_support/new_callbacks.rb | 10 ++--
activesupport/test/new_callbacks_test.rb | 62 +++++++++++++++++++++++
2 files changed, 69 insertions(+), 3 deletions(-)
diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb
index 9316d6d2b6..f8108780f1 100644
--- a/activesupport/lib/active_support/new_callbacks.rb
+++ b/activesupport/lib/active_support/new_callbacks.rb
@@ -296,9 +296,13 @@ module ActiveSupport
method_name
else
kind, name = @kind, @name
- @klass.send(:define_method, method_name) do
- filter.send("#{kind}_#{name}", self)
- end
+ @klass.send(:define_method, "#{method_name}_object") { filter }
+
+ @klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
+ def #{method_name}(&blk)
+ #{method_name}_object.send("#{kind}_#{name}", self, &blk)
+ end
+ RUBY_EVAL
method_name
end
end
diff --git a/activesupport/test/new_callbacks_test.rb b/activesupport/test/new_callbacks_test.rb
index dec6106ac1..7bec47224d 100644
--- a/activesupport/test/new_callbacks_test.rb
+++ b/activesupport/test/new_callbacks_test.rb
@@ -396,6 +396,68 @@ module NewCallbacksTest
end
end
+ class CallbackObject
+ def before_save(caller)
+ caller.record << "before"
+ end
+
+ def around_save(caller)
+ caller.record << "around before"
+ yield
+ caller.record << "around after"
+ end
+ end
+
+ class UsingObjectBefore
+ include ActiveSupport::NewCallbacks
+
+ define_callbacks :save
+ save_callback :before, CallbackObject.new
+
+ attr_accessor :record
+ def initialize
+ @record = []
+ end
+
+ def save
+ _run_save_callbacks do
+ @record << "yielded"
+ end
+ end
+ end
+
+ class UsingObjectAround
+ include ActiveSupport::NewCallbacks
+
+ define_callbacks :save
+ save_callback :around, CallbackObject.new
+
+ attr_accessor :record
+ def initialize
+ @record = []
+ end
+
+ def save
+ _run_save_callbacks do
+ @record << "yielded"
+ end
+ end
+ end
+
+ class UsingObjectTest < Test::Unit::TestCase
+ def test_before_object
+ u = UsingObjectBefore.new
+ u.save
+ assert_equal ["before", "yielded"], u.record
+ end
+
+ def test_around_object
+ u = UsingObjectAround.new
+ u.save
+ assert_equal ["around before", "yielded", "around after"], u.record
+ end
+ end
+
class CallbackTerminatorTest < Test::Unit::TestCase
def test_termination
terminator = CallbackTerminator.new
--
cgit v1.2.3
From 26f2be01c2d537aac6d484c8a1ed2df92aa52f00 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Tue, 19 May 2009 18:02:03 -0700
Subject: Modify caching to use new included helper
---
actionpack/lib/action_controller/caching.rb | 30 ++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb
index ffd8081edc..2f2eec10f6 100644
--- a/actionpack/lib/action_controller/caching.rb
+++ b/actionpack/lib/action_controller/caching.rb
@@ -24,31 +24,31 @@ module ActionController #:nodoc:
# ActionController::Base.cache_store = :mem_cache_store, "localhost"
# ActionController::Base.cache_store = MyOwnStore.new("parameter")
module Caching
+ extend ActiveSupport::DependencyModule
+
autoload :Actions, 'action_controller/caching/actions'
autoload :Fragments, 'action_controller/caching/fragments'
autoload :Pages, 'action_controller/caching/pages'
autoload :Sweeper, 'action_controller/caching/sweeping'
autoload :Sweeping, 'action_controller/caching/sweeping'
- def self.included(base) #:nodoc:
- base.class_eval do
- @@cache_store = nil
- cattr_reader :cache_store
+ included do
+ @@cache_store = nil
+ cattr_reader :cache_store
- # Defines the storage option for cached fragments
- def self.cache_store=(store_option)
- @@cache_store = ActiveSupport::Cache.lookup_store(store_option)
- end
+ # Defines the storage option for cached fragments
+ def self.cache_store=(store_option)
+ @@cache_store = ActiveSupport::Cache.lookup_store(store_option)
+ end
- include Pages, Actions, Fragments
- include Sweeping if defined?(ActiveRecord)
+ include Pages, Actions, Fragments
+ include Sweeping if defined?(ActiveRecord)
- @@perform_caching = true
- cattr_accessor :perform_caching
+ @@perform_caching = true
+ cattr_accessor :perform_caching
- def self.cache_configured?
- perform_caching && cache_store
- end
+ def self.cache_configured?
+ perform_caching && cache_store
end
end
--
cgit v1.2.3
From 0e7da0e4a06f78ab39b0e90daadfc223b8f1738a Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Tue, 19 May 2009 18:04:17 -0700
Subject: Include caching module into new base
---
actionpack/lib/action_controller/new_base.rb | 1 +
actionpack/lib/action_controller/new_base/base.rb | 1 +
2 files changed, 2 insertions(+)
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index bc47713529..078f66ced1 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -13,6 +13,7 @@ module ActionController
# Ported modules
# require 'action_controller/routing'
+ autoload :Caching, 'action_controller/caching'
autoload :Dispatcher, 'action_controller/dispatch/dispatcher'
autoload :PolymorphicRoutes, 'action_controller/routing/generation/polymorphic_routes'
autoload :RecordIdentifier, 'action_controller/record_identifier'
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 756a0799fe..7f830307b6 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -17,6 +17,7 @@ module ActionController
# Legacy modules
include SessionManagement
include ActionDispatch::StatusCodes
+ include ActionController::Caching
# Rails 2.x compatibility
include ActionController::Rails2Compatibility
--
cgit v1.2.3
From 67cc021d019515c94d4bcc4c3c7060c9a2594c87 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Tue, 19 May 2009 18:05:16 -0700
Subject: Modified caching implementation to work with NewBase
---
.../lib/action_controller/caching/actions.rb | 22 +++++++++++++++++++---
.../lib/action_controller/new_base/renderer.rb | 5 +++++
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb
index 2b822b52c8..430db3932f 100644
--- a/actionpack/lib/action_controller/caching/actions.rb
+++ b/actionpack/lib/action_controller/caching/actions.rb
@@ -61,8 +61,14 @@ module ActionController #:nodoc:
filter_options = { :only => actions, :if => options.delete(:if), :unless => options.delete(:unless) }
cache_filter = ActionCacheFilter.new(:layout => options.delete(:layout), :cache_path => options.delete(:cache_path), :store_options => options)
- around_filter(filter_options) do |controller, action|
- cache_filter.filter(controller, action)
+
+ # TODO: Remove this once new base is swapped in.
+ if defined?(Http)
+ around_filter cache_filter, filter_options
+ else
+ around_filter(filter_options) do |controller, action|
+ cache_filter.filter(controller, action)
+ end
end
end
end
@@ -85,14 +91,22 @@ module ActionController #:nodoc:
@options = options
end
+ # TODO: Remove once New Base is merged
def filter(controller, action)
should_continue = before(controller)
action.call if should_continue
after(controller)
end
+ def around_process_action(controller)
+ should_continue = before(controller)
+ yield if should_continue
+ after(controller)
+ end
+
def before(controller)
cache_path = ActionCachePath.new(controller, path_options_for(controller, @options.slice(:cache_path)))
+
if cache = controller.read_fragment(cache_path.path, @options[:store_options])
controller.rendered_action_cache = true
set_content_type!(controller, cache_path.extension)
@@ -129,7 +143,9 @@ module ActionController #:nodoc:
end
def content_for_layout(controller)
- controller.template.layout && controller.template.instance_variable_get('@cached_content_for_layout')
+ # TODO: Remove this when new base is merged in
+ template = controller.respond_to?(:template) ? controller.template : controller._action_view
+ template.layout && template.instance_variable_get('@cached_content_for_layout')
end
end
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 8a9f230603..9253df53a1 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -9,6 +9,11 @@ module ActionController
super
end
+ def response_body=(body)
+ response.body = body if response
+ super
+ end
+
def render_to_body(options)
_process_options(options)
--
cgit v1.2.3
From 321168b17bce2e73ab7ba22309491ad5c245dcf8 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Tue, 19 May 2009 18:08:04 -0700
Subject: Make old caching tests pass on new base.
---
actionpack/lib/action_controller/new_base/compatibility.rb | 4 ++++
actionpack/lib/action_controller/new_base/http.rb | 1 -
actionpack/lib/action_controller/new_base/url_for.rb | 5 +++++
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index 0a283887b6..0098c0747e 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -55,6 +55,10 @@ module ActionController
self.consider_all_requests_local = true
end
+ # For old tests
+ def initialize_template_class(*) end
+ def assign_shortcuts(*) end
+
module ClassMethods
def protect_from_forgery() end
def consider_all_requests_local() end
diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb
index 8891a2a8c3..17466a2d52 100644
--- a/actionpack/lib/action_controller/new_base/http.rb
+++ b/actionpack/lib/action_controller/new_base/http.rb
@@ -60,7 +60,6 @@ module ActionController
# :api: private
def to_rack
- @_response.body = response_body
@_response.prepare!
@_response.to_a
end
diff --git a/actionpack/lib/action_controller/new_base/url_for.rb b/actionpack/lib/action_controller/new_base/url_for.rb
index af5b21012b..94de9fab50 100644
--- a/actionpack/lib/action_controller/new_base/url_for.rb
+++ b/actionpack/lib/action_controller/new_base/url_for.rb
@@ -1,5 +1,10 @@
module ActionController
module UrlFor
+ def process_action(*)
+ initialize_current_url
+ super
+ end
+
def initialize_current_url
@url = UrlRewriter.new(request, params.clone)
end
--
cgit v1.2.3
From 0029d5e5943dd20d38485ac7127cc150659da9e5 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp
Date: Mon, 11 May 2009 23:04:39 -0400
Subject: Integrating Rack::MockSession (from Rack::Test)
---
.../lib/action_controller/testing/integration.rb | 25 +++++++++++-----------
actionpack/test/controller/integration_test.rb | 6 +++---
2 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb
index a8e8f16d6c..31afd54258 100644
--- a/actionpack/lib/action_controller/testing/integration.rb
+++ b/actionpack/lib/action_controller/testing/integration.rb
@@ -1,6 +1,8 @@
require 'stringio'
require 'uri'
require 'active_support/test_case'
+require 'rack/test'
+require 'rack/mock_session'
module ActionController
module Integration #:nodoc:
@@ -121,6 +123,8 @@ module ActionController
# IntegrationTest#open_session, rather than instantiating
# Integration::Session directly.
class Session
+ DEFAULT_HOST = "www.example.com"
+
include Test::Unit::Assertions
include ActionDispatch::Assertions
include ActionController::TestProcess
@@ -145,7 +149,9 @@ module ActionController
# A map of the cookies returned by the last response, and which will be
# sent with the next request.
- attr_reader :cookies
+ def cookies
+ @mock_session.cookie_jar
+ end
# A reference to the controller instance used by the last request.
attr_reader :controller
@@ -172,11 +178,11 @@ module ActionController
# session.reset!
def reset!
@https = false
- @cookies = {}
+ @mock_session = Rack::MockSession.new(@app, DEFAULT_HOST)
@controller = @request = @response = nil
@request_count = 0
- self.host = "www.example.com"
+ self.host = DEFAULT_HOST
self.remote_addr = "127.0.0.1"
self.accept = "text/xml,application/xml,application/xhtml+xml," +
"text/html;q=0.9,text/plain;q=0.8,image/png," +
@@ -227,6 +233,7 @@ module ActionController
end
private
+
# Performs the actual request.
def process(method, path, parameters = nil, rack_environment = nil)
if path =~ %r{://}
@@ -258,10 +265,7 @@ module ActionController
"HTTP_HOST" => host,
"REMOTE_ADDR" => remote_addr,
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
- "HTTP_ACCEPT" => accept,
- "HTTP_COOKIE" => cookies.inject("") { |string, (name, value)|
- string << "#{name}=#{value}; "
- }
+ "HTTP_ACCEPT" => accept
}
env = Rack::MockRequest.env_for(path, opts)
@@ -269,15 +273,12 @@ module ActionController
env[key] = value
end
- app = Rack::Lint.new(@app)
- status, headers, body = app.call(env)
- mock_response = ::Rack::MockResponse.new(status, headers, body)
+ @mock_session.request(URI.parse(path), env)
@request_count += 1
@request = ActionDispatch::Request.new(env)
- @response = ActionDispatch::TestResponse.from_response(mock_response)
+ @response = ActionDispatch::TestResponse.from_response(@mock_session.last_response)
- @cookies.merge!(@response.cookies)
@html_document = nil
if @controller = ActionController::Base.last_instantiation
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index a2b3ad2106..eae6835714 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -253,7 +253,7 @@ class IntegrationProcessTest < ActionController::IntegrationTest
assert_response 200
assert_response :success
assert_response :ok
- assert_equal({}, cookies)
+ assert_equal({}, cookies.to_hash)
assert_equal "OK", body
assert_equal "OK", response.body
assert_kind_of HTML::Document, html_document
@@ -269,7 +269,7 @@ class IntegrationProcessTest < ActionController::IntegrationTest
assert_response 201
assert_response :success
assert_response :created
- assert_equal({}, cookies)
+ assert_equal({}, cookies.to_hash)
assert_equal "Created", body
assert_equal "Created", response.body
assert_kind_of HTML::Document, html_document
@@ -287,7 +287,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"=>nil, "cookie_2"=>"oatmeal", "cookie_3"=>"chocolate"}, cookies)
+ assert_equal({"cookie_1"=>"", "cookie_2"=>"oatmeal", "cookie_3"=>"chocolate"}, cookies.to_hash)
assert_equal "Gone", response.body
end
end
--
cgit v1.2.3
From df0faea378034b031f49995f06c8bf108a0b5530 Mon Sep 17 00:00:00 2001
From: Bryan Helmkamp
Date: Tue, 12 May 2009 01:37:19 -0400
Subject: Refactor ActionController instantiation capture
---
.../lib/action_controller/testing/integration.rb | 24 +++++++++-------------
1 file changed, 10 insertions(+), 14 deletions(-)
diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb
index 31afd54258..717b77674c 100644
--- a/actionpack/lib/action_controller/testing/integration.rb
+++ b/actionpack/lib/action_controller/testing/integration.rb
@@ -249,8 +249,6 @@ module ActionController
end
end
- ActionController::Base.clear_last_instantiation!
-
opts = {
:method => method,
:params => parameters,
@@ -273,18 +271,15 @@ module ActionController
env[key] = value
end
- @mock_session.request(URI.parse(path), env)
+ @controller = ActionController::Base.capture_instantiation do
+ @mock_session.request(URI.parse(path), env)
+ end
@request_count += 1
@request = ActionDispatch::Request.new(env)
@response = ActionDispatch::TestResponse.from_response(@mock_session.last_response)
-
@html_document = nil
- if @controller = ActionController::Base.last_instantiation
- @controller.send(:set_test_assigns)
- end
-
return response.status
end
@@ -305,11 +300,10 @@ module ActionController
# A module used to extend ActionController::Base, so that integration tests
# can capture the controller used to satisfy a request.
module ControllerCapture #:nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- base.class_eval do
- alias_method_chain :initialize, :capture
- end
+ extend ActiveSupport::DependencyModule
+
+ included do
+ alias_method_chain :initialize, :capture
end
def initialize_with_capture(*args)
@@ -320,8 +314,10 @@ module ActionController
module ClassMethods #:nodoc:
mattr_accessor :last_instantiation
- def clear_last_instantiation!
+ def capture_instantiation
self.last_instantiation = nil
+ yield
+ return last_instantiation
end
end
end
--
cgit v1.2.3
From 6761759a90c08b9db8d5720a8ee4c4329a547caf Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Tue, 19 May 2009 22:42:59 -0500
Subject: Temporarily bundle rack-test while MockSession is baking
---
.../lib/action_controller/testing/integration.rb | 3 +-
actionpack/lib/action_dispatch.rb | 2 +
.../vendor/rack-test/rack/mock_session.rb | 50 +++++
.../action_dispatch/vendor/rack-test/rack/test.rb | 239 +++++++++++++++++++++
.../vendor/rack-test/rack/test/cookie_jar.rb | 169 +++++++++++++++
.../vendor/rack-test/rack/test/methods.rb | 45 ++++
.../rack-test/rack/test/mock_digest_request.rb | 27 +++
.../vendor/rack-test/rack/test/uploaded_file.rb | 36 ++++
.../vendor/rack-test/rack/test/utils.rb | 75 +++++++
9 files changed, 645 insertions(+), 1 deletion(-)
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-test/rack/mock_session.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-test/rack/test.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-test/rack/test/cookie_jar.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-test/rack/test/methods.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-test/rack/test/mock_digest_request.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-test/rack/test/uploaded_file.rb
create mode 100644 actionpack/lib/action_dispatch/vendor/rack-test/rack/test/utils.rb
diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb
index 717b77674c..cc157816e2 100644
--- a/actionpack/lib/action_controller/testing/integration.rb
+++ b/actionpack/lib/action_controller/testing/integration.rb
@@ -1,8 +1,9 @@
require 'stringio'
require 'uri'
require 'active_support/test_case'
-require 'rack/test'
+
require 'rack/mock_session'
+require 'rack/test/cookie_jar'
module ActionController
module Integration #:nodoc:
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 6fc4ad3f21..f9003c51ea 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -33,6 +33,8 @@ end
require 'rack'
+$:.unshift "#{File.dirname(__FILE__)}/action_dispatch/vendor/rack-test"
+
module ActionDispatch
autoload :Request, 'action_dispatch/http/request'
autoload :Response, 'action_dispatch/http/response'
diff --git a/actionpack/lib/action_dispatch/vendor/rack-test/rack/mock_session.rb b/actionpack/lib/action_dispatch/vendor/rack-test/rack/mock_session.rb
new file mode 100644
index 0000000000..eba6226538
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-test/rack/mock_session.rb
@@ -0,0 +1,50 @@
+module Rack
+
+ class MockSession
+ attr_writer :cookie_jar
+ attr_reader :last_response
+
+ def initialize(app, default_host = Rack::Test::DEFAULT_HOST)
+ @app = app
+ @default_host = default_host
+ end
+
+ def clear_cookies
+ @cookie_jar = Rack::Test::CookieJar.new([], @default_host)
+ end
+
+ def set_cookie(cookie, uri = nil)
+ cookie_jar.merge(cookie, uri)
+ end
+
+ def request(uri, env)
+ env["HTTP_COOKIE"] ||= cookie_jar.for(uri)
+ @last_request = Rack::Request.new(env)
+ status, headers, body = @app.call(@last_request.env)
+ @last_response = MockResponse.new(status, headers, body, env["rack.errors"].flush)
+ cookie_jar.merge(last_response.headers["Set-Cookie"], uri)
+
+ @last_response
+ end
+
+ # Return the last request issued in the session. Raises an error if no
+ # requests have been sent yet.
+ def last_request
+ raise Rack::Test::Error.new("No request yet. Request a page first.") unless @last_request
+ @last_request
+ end
+
+ # Return the last response received in the session. Raises an error if
+ # no requests have been sent yet.
+ def last_response
+ raise Rack::Test::Error.new("No response yet. Request a page first.") unless @last_response
+ @last_response
+ end
+
+ def cookie_jar
+ @cookie_jar ||= Rack::Test::CookieJar.new([], @default_host)
+ end
+
+ end
+
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack-test/rack/test.rb b/actionpack/lib/action_dispatch/vendor/rack-test/rack/test.rb
new file mode 100644
index 0000000000..70384b1d76
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-test/rack/test.rb
@@ -0,0 +1,239 @@
+unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__) + "/.."))
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/.."))
+end
+
+require "uri"
+require "rack"
+require "rack/mock_session"
+require "rack/test/cookie_jar"
+require "rack/test/mock_digest_request"
+require "rack/test/utils"
+require "rack/test/methods"
+require "rack/test/uploaded_file"
+
+module Rack
+ module Test
+
+ VERSION = "0.3.0"
+
+ DEFAULT_HOST = "example.org"
+ MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
+
+ # The common base class for exceptions raised by Rack::Test
+ class Error < StandardError; end
+
+ class Session
+ extend Forwardable
+ include Rack::Test::Utils
+
+ def_delegators :@rack_mock_session, :clear_cookies, :set_cookie, :last_response, :last_request
+
+ # Initialize a new session for the given Rack app
+ def initialize(app, default_host = DEFAULT_HOST)
+ @headers = {}
+ @default_host = default_host
+ @rack_mock_session = Rack::MockSession.new(app, default_host)
+ end
+
+ # Issue a GET request for the given URI with the given params and Rack
+ # environment. Stores the issues request object in #last_request and
+ # the app's response in #last_response. Yield #last_response to a block
+ # if given.
+ #
+ # Example:
+ # get "/"
+ def get(uri, params = {}, env = {}, &block)
+ env = env_for(uri, env.merge(:method => "GET", :params => params))
+ process_request(uri, env, &block)
+ end
+
+ # Issue a POST request for the given URI. See #get
+ #
+ # Example:
+ # post "/signup", "name" => "Bryan"
+ def post(uri, params = {}, env = {}, &block)
+ env = env_for(uri, env.merge(:method => "POST", :params => params))
+ process_request(uri, env, &block)
+ end
+
+ # Issue a PUT request for the given URI. See #get
+ #
+ # Example:
+ # put "/"
+ def put(uri, params = {}, env = {}, &block)
+ env = env_for(uri, env.merge(:method => "PUT", :params => params))
+ process_request(uri, env, &block)
+ end
+
+ # Issue a DELETE request for the given URI. See #get
+ #
+ # Example:
+ # delete "/"
+ def delete(uri, params = {}, env = {}, &block)
+ env = env_for(uri, env.merge(:method => "DELETE", :params => params))
+ process_request(uri, env, &block)
+ end
+
+ # Issue a HEAD request for the given URI. See #get
+ #
+ # Example:
+ # head "/"
+ def head(uri, params = {}, env = {}, &block)
+ env = env_for(uri, env.merge(:method => "HEAD", :params => params))
+ process_request(uri, env, &block)
+ end
+
+ # Issue a request to the Rack app for the given URI and optional Rack
+ # environment. Stores the issues request object in #last_request and
+ # the app's response in #last_response. Yield #last_response to a block
+ # if given.
+ #
+ # Example:
+ # request "/"
+ def request(uri, env = {}, &block)
+ env = env_for(uri, env)
+ process_request(uri, env, &block)
+ end
+
+ # Set a header to be included on all subsequent requests through the
+ # session. Use a value of nil to remove a previously configured header.
+ #
+ # Example:
+ # header "User-Agent", "Firefox"
+ def header(name, value)
+ if value.nil?
+ @headers.delete(name)
+ else
+ @headers[name] = value
+ end
+ end
+
+ # Set the username and password for HTTP Basic authorization, to be
+ # included in subsequent requests in the HTTP_AUTHORIZATION header.
+ #
+ # Example:
+ # basic_authorize "bryan", "secret"
+ def basic_authorize(username, password)
+ encoded_login = ["#{username}:#{password}"].pack("m*")
+ header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
+ end
+
+ alias_method :authorize, :basic_authorize
+
+ def digest_authorize(username, password)
+ @digest_username = username
+ @digest_password = password
+ end
+
+ # Rack::Test will not follow any redirects automatically. This method
+ # will follow the redirect returned in the last response. If the last
+ # response was not a redirect, an error will be raised.
+ def follow_redirect!
+ unless last_response.redirect?
+ raise Error.new("Last response was not a redirect. Cannot follow_redirect!")
+ end
+
+ get(last_response["Location"])
+ end
+
+ private
+
+ def env_for(path, env)
+ uri = URI.parse(path)
+ uri.host ||= @default_host
+
+ env = default_env.merge(env)
+
+ env.update("HTTPS" => "on") if URI::HTTPS === uri
+ env["X-Requested-With"] = "XMLHttpRequest" if env[:xhr]
+
+ if (env[:method] == "POST" || env["REQUEST_METHOD"] == "POST") && !env.has_key?(:input)
+ env["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
+
+ multipart = (Hash === env[:params]) &&
+ env[:params].any? { |_, v| UploadedFile === v }
+
+ if multipart
+ env[:input] = multipart_body(env.delete(:params))
+ env["CONTENT_LENGTH"] ||= env[:input].length.to_s
+ env["CONTENT_TYPE"] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}"
+ else
+ env[:input] = params_to_string(env.delete(:params))
+ end
+ end
+
+ params = env[:params] || {}
+ params.update(parse_query(uri.query))
+
+ uri.query = requestify(params)
+
+ if env.has_key?(:cookie)
+ set_cookie(env.delete(:cookie), uri)
+ end
+
+ Rack::MockRequest.env_for(uri.to_s, env)
+ end
+
+ def process_request(uri, env)
+ uri = URI.parse(uri)
+ uri.host ||= @default_host
+
+ @rack_mock_session.request(uri, env)
+
+ if retry_with_digest_auth?(env)
+ auth_env = env.merge({
+ "HTTP_AUTHORIZATION" => digest_auth_header,
+ "rack-test.digest_auth_retry" => true
+ })
+ auth_env.delete('rack.request')
+ process_request(uri.path, auth_env)
+ else
+ yield last_response if block_given?
+
+ last_response
+ end
+ end
+
+ def digest_auth_header
+ challenge = last_response["WWW-Authenticate"].split(" ", 2).last
+ params = Rack::Auth::Digest::Params.parse(challenge)
+
+ params.merge!({
+ "username" => @digest_username,
+ "nc" => "00000001",
+ "cnonce" => "nonsensenonce",
+ "uri" => last_request.path_info,
+ "method" => last_request.env["REQUEST_METHOD"],
+ })
+
+ params["response"] = MockDigestRequest.new(params).response(@digest_password)
+
+ "Digest #{params}"
+ end
+
+ def retry_with_digest_auth?(env)
+ last_response.status == 401 &&
+ digest_auth_configured? &&
+ !env["rack-test.digest_auth_retry"]
+ end
+
+ def digest_auth_configured?
+ @digest_username
+ end
+
+ def default_env
+ { "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(@headers)
+ end
+
+ def params_to_string(params)
+ case params
+ when Hash then requestify(params)
+ when nil then ""
+ else params
+ end
+ end
+
+ end
+
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/cookie_jar.rb b/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/cookie_jar.rb
new file mode 100644
index 0000000000..d58c914c9b
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/cookie_jar.rb
@@ -0,0 +1,169 @@
+require "uri"
+module Rack
+ module Test
+
+ class Cookie
+ include Rack::Utils
+
+ # :api: private
+ attr_reader :name, :value
+
+ # :api: private
+ def initialize(raw, uri = nil, default_host = DEFAULT_HOST)
+ @default_host = default_host
+ uri ||= default_uri
+
+ # separate the name / value pair from the cookie options
+ @name_value_raw, options = raw.split(/[;,] */n, 2)
+
+ @name, @value = parse_query(@name_value_raw, ';').to_a.first
+ @options = parse_query(options, ';')
+
+ @options["domain"] ||= (uri.host || default_host)
+ @options["path"] ||= uri.path.sub(/\/[^\/]*\Z/, "")
+ end
+
+ def replaces?(other)
+ [name.downcase, domain, path] == [other.name.downcase, other.domain, other.path]
+ end
+
+ # :api: private
+ def raw
+ @name_value_raw
+ end
+
+ # :api: private
+ def empty?
+ @value.nil? || @value.empty?
+ end
+
+ # :api: private
+ def domain
+ @options["domain"]
+ end
+
+ def secure?
+ @options.has_key?("secure")
+ end
+
+ # :api: private
+ def path
+ @options["path"].strip || "/"
+ end
+
+ # :api: private
+ def expires
+ Time.parse(@options["expires"]) if @options["expires"]
+ end
+
+ # :api: private
+ def expired?
+ expires && expires < Time.now
+ end
+
+ # :api: private
+ def valid?(uri)
+ uri ||= default_uri
+
+ if uri.host.nil?
+ uri.host = @default_host
+ end
+
+ (!secure? || (secure? && uri.scheme == "https")) &&
+ uri.host =~ Regexp.new("#{Regexp.escape(domain)}$", Regexp::IGNORECASE) &&
+ uri.path =~ Regexp.new("^#{Regexp.escape(path)}")
+ end
+
+ # :api: private
+ def matches?(uri)
+ ! expired? && valid?(uri)
+ end
+
+ # :api: private
+ def <=>(other)
+ # Orders the cookies from least specific to most
+ [name, path, domain.reverse] <=> [other.name, other.path, other.domain.reverse]
+ end
+
+ protected
+
+ def default_uri
+ URI.parse("//" + @default_host + "/")
+ end
+
+ end
+
+ class CookieJar
+
+ # :api: private
+ def initialize(cookies = [], default_host = DEFAULT_HOST)
+ @default_host = default_host
+ @cookies = cookies
+ @cookies.sort!
+ end
+
+ def [](name)
+ cookies = hash_for(nil)
+ # TODO: Should be case insensitive
+ cookies[name] && cookies[name].value
+ end
+
+ def []=(name, value)
+ # TODO: needs proper escaping
+ merge("#{name}=#{value}")
+ end
+
+ def merge(raw_cookies, uri = nil)
+ return unless raw_cookies
+
+ raw_cookies.each_line do |raw_cookie|
+ cookie = Cookie.new(raw_cookie, uri, @default_host)
+ self << cookie if cookie.valid?(uri)
+ end
+ end
+
+ def <<(new_cookie)
+ @cookies.reject! do |existing_cookie|
+ new_cookie.replaces?(existing_cookie)
+ end
+
+ @cookies << new_cookie
+ @cookies.sort!
+ end
+
+ # :api: private
+ def for(uri)
+ hash_for(uri).values.map { |c| c.raw }.join(';')
+ end
+
+ def to_hash
+ cookies = {}
+
+ hash_for(nil).each do |name, cookie|
+ cookies[name] = cookie.value
+ end
+
+ return cookies
+ end
+
+ protected
+
+ def hash_for(uri = nil)
+ cookies = {}
+
+ # The cookies are sorted by most specific first. So, we loop through
+ # all the cookies in order and add it to a hash by cookie name if
+ # the cookie can be sent to the current URI. It's added to the hash
+ # so that when we are done, the cookies will be unique by name and
+ # we'll have grabbed the most specific to the URI.
+ @cookies.each do |cookie|
+ cookies[cookie.name] = cookie if cookie.matches?(uri)
+ end
+
+ return cookies
+ end
+
+ end
+
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/methods.rb b/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/methods.rb
new file mode 100644
index 0000000000..a191fa23d8
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/methods.rb
@@ -0,0 +1,45 @@
+require "forwardable"
+
+module Rack
+ module Test
+ module Methods
+ extend Forwardable
+
+ def rack_test_session
+ @_rack_test_session ||= Rack::Test::Session.new(app)
+ end
+
+ def rack_mock_session
+ @_rack_mock_session ||= Rack::MockSession.new(app)
+ end
+
+ METHODS = [
+ :request,
+
+ # HTTP verbs
+ :get,
+ :post,
+ :put,
+ :delete,
+ :head,
+
+ # Redirects
+ :follow_redirect!,
+
+ # Header-related features
+ :header,
+ :set_cookie,
+ :clear_cookies,
+ :authorize,
+ :basic_authorize,
+ :digest_authorize,
+
+ # Expose the last request and response
+ :last_response,
+ :last_request
+ ]
+
+ def_delegators :rack_test_session, *METHODS
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/mock_digest_request.rb b/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/mock_digest_request.rb
new file mode 100644
index 0000000000..81c398ba51
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/mock_digest_request.rb
@@ -0,0 +1,27 @@
+module Rack
+ module Test
+
+ class MockDigestRequest
+ def initialize(params)
+ @params = params
+ end
+
+ def method_missing(sym)
+ if @params.has_key? k = sym.to_s
+ return @params[k]
+ end
+
+ super
+ end
+
+ def method
+ @params['method']
+ end
+
+ def response(password)
+ Rack::Auth::Digest::MD5.new(nil).send :digest, self, password
+ end
+ end
+
+ end
+end
diff --git a/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/uploaded_file.rb b/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/uploaded_file.rb
new file mode 100644
index 0000000000..239302fbe4
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/uploaded_file.rb
@@ -0,0 +1,36 @@
+require "tempfile"
+
+module Rack
+ 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/lib/action_dispatch/vendor/rack-test/rack/test/utils.rb b/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/utils.rb
new file mode 100644
index 0000000000..d25b849709
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-test/rack/test/utils.rb
@@ -0,0 +1,75 @@
+module Rack
+ module Test
+
+ module Utils
+ include Rack::Utils
+
+ 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}[#{escape(k)}]" : escape(k))
+ end.join("&")
+ else
+ "#{prefix}=#{escape(value)}"
+ end
+ end
+
+ module_function :requestify
+
+ 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
+
+ module_function :multipart_requestify
+
+ 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="#{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
+
+ module_function :multipart_body
+
+ end
+
+ end
+end
--
cgit v1.2.3
From c03b0ca7eb7e73587005e1440bf90cd01ed10aa5 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Wed, 20 May 2009 21:15:06 +0200
Subject: Replace the class level Rack::Test DSL with the regular integration
tests DSL
---
actionpack/test/new_base/base_test.rb | 80 ++---
actionpack/test/new_base/content_type_test.rb | 120 +++----
actionpack/test/new_base/etag_test.rb | 23 +-
actionpack/test/new_base/render_action_test.rb | 388 ++++++++++-----------
.../test/new_base/render_implicit_action_test.rb | 28 +-
actionpack/test/new_base/render_layout_test.rb | 64 ++--
actionpack/test/new_base/render_template_test.rb | 87 +++--
actionpack/test/new_base/render_test.rb | 45 ++-
actionpack/test/new_base/render_text_test.rb | 151 ++++----
actionpack/test/new_base/test_helper.rb | 55 +--
10 files changed, 477 insertions(+), 564 deletions(-)
diff --git a/actionpack/test/new_base/base_test.rb b/actionpack/test/new_base/base_test.rb
index a32653f128..d9d552f9e5 100644
--- a/actionpack/test/new_base/base_test.rb
+++ b/actionpack/test/new_base/base_test.rb
@@ -10,78 +10,60 @@ module Dispatching
def modify_response_body
self.response_body = "success"
end
-
+
def modify_response_body_twice
ret = (self.response_body = "success")
self.response_body = "#{ret}!"
end
-
+
def modify_response_headers
-
end
end
-
- class TestSimpleDispatch < SimpleRouteCase
-
- get "/dispatching/simple/index"
-
- test "sets the body" do
+
+ class EmptyController < ActionController::Base ; end
+
+ module Submodule
+ class ContainedEmptyController < ActionController::Base ; end
+ end
+
+ class BaseTest < SimpleRouteCase
+ # :api: plugin
+ test "simple dispatching" do
+ get "/dispatching/simple/index"
+
assert_body "success"
- end
-
- test "sets the status code" do
assert_status 200
- end
-
- test "sets the content type" do
assert_content_type "text/html; charset=utf-8"
- end
-
- test "sets the content length" do
assert_header "Content-Length", "7"
end
-
- end
-
- # :api: plugin
- class TestDirectResponseMod < SimpleRouteCase
- get "/dispatching/simple/modify_response_body"
-
- test "sets the body" do
+
+ # :api: plugin
+ test "directly modifying response body" do
+ get "/dispatching/simple/modify_response_body"
+
assert_body "success"
+ assert_header "Content-Length", "7" # setting the body manually sets the content length
end
-
- test "setting the body manually sets the content length" do
- assert_header "Content-Length", "7"
- end
- end
-
- # :api: plugin
- class TestDirectResponseModTwice < SimpleRouteCase
- get "/dispatching/simple/modify_response_body_twice"
-
- test "self.response_body= returns the body being set" do
+
+ # :api: plugin
+ test "directly modifying response body twice" do
+ get "/dispatching/simple/modify_response_body_twice"
+
assert_body "success!"
- end
-
- test "updating the response body updates the content length" do
assert_header "Content-Length", "8"
end
- end
-
- class EmptyController < ActionController::Base ; end
- module Submodule
- class ContainedEmptyController < ActionController::Base ; end
- end
- class ControllerClassTests < Test::Unit::TestCase
- def test_controller_path
+ test "controller path" do
assert_equal 'dispatching/empty', EmptyController.controller_path
assert_equal EmptyController.controller_path, EmptyController.new.controller_path
+ end
+
+ test "namespaced controller path" do
assert_equal 'dispatching/submodule/contained_empty', Submodule::ContainedEmptyController.controller_path
assert_equal Submodule::ContainedEmptyController.controller_path, Submodule::ContainedEmptyController.new.controller_path
end
- def test_controller_name
+
+ test "controller name" do
assert_equal 'empty', EmptyController.controller_name
assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name
end
diff --git a/actionpack/test/new_base/content_type_test.rb b/actionpack/test/new_base/content_type_test.rb
index a5c04e9cb6..82b817a5a3 100644
--- a/actionpack/test/new_base/content_type_test.rb
+++ b/actionpack/test/new_base/content_type_test.rb
@@ -5,107 +5,107 @@ module ContentType
def index
render :text => "Hello world!"
end
-
+
def set_on_response_obj
response.content_type = Mime::RSS
render :text => "Hello world!"
end
-
+
def set_on_render
render :text => "Hello world!", :content_type => Mime::RSS
end
end
-
- class TestDefault < SimpleRouteCase
- describe "a default response is HTML and UTF8"
-
- get "/content_type/base"
- assert_body "Hello world!"
- assert_header "Content-Type", "text/html; charset=utf-8"
- end
-
- class TestSetOnResponseObj < SimpleRouteCase
- describe "setting the content type of the response directly on the response object"
-
- get "/content_type/base/set_on_response_obj"
- assert_body "Hello world!"
- assert_header "Content-Type", "application/rss+xml; charset=utf-8"
- end
-
- class TestSetOnRender < SimpleRouteCase
- describe "setting the content type of the response as an option to render"
-
- get "/content_type/base/set_on_render"
- assert_body "Hello world!"
- assert_header "Content-Type", "application/rss+xml; charset=utf-8"
- end
-
+
class ImpliedController < ActionController::Base
+ # Template's mime type is used if no content_type is specified
+
self.view_paths = [ActionView::Template::FixturePath.new(
"content_type/implied/i_am_html_erb.html.erb" => "Hello world!",
"content_type/implied/i_am_xml_erb.xml.erb" => "Hello world! ",
"content_type/implied/i_am_html_builder.html.builder" => "xml.p 'Hello'",
"content_type/implied/i_am_xml_builder.xml.builder" => "xml.awesome 'Hello'"
)]
-
+
def i_am_html_erb() end
def i_am_xml_erb() end
def i_am_html_builder() end
def i_am_xml_builder() end
end
-
- class TestImpliedController < SimpleRouteCase
- describe "the template's mime type is used if no content_type is specified"
-
+
+ class CharsetController < ActionController::Base
+ def set_on_response_obj
+ response.charset = "utf-16"
+ render :text => "Hello world!"
+ end
+
+ def set_as_nil_on_response_obj
+ response.charset = nil
+ render :text => "Hello world!"
+ end
+ end
+
+ class ExplicitContentTypeTest < SimpleRouteCase
+ test "default response is HTML and UTF8" do
+ get "/content_type/base"
+
+ assert_body "Hello world!"
+ assert_header "Content-Type", "text/html; charset=utf-8"
+ end
+
+ test "setting the content type of the response directly on the response object" do
+ get "/content_type/base/set_on_response_obj"
+
+ assert_body "Hello world!"
+ assert_header "Content-Type", "application/rss+xml; charset=utf-8"
+ end
+
+ test "setting the content type of the response as an option to render" do
+ get "/content_type/base/set_on_render"
+
+ assert_body "Hello world!"
+ assert_header "Content-Type", "application/rss+xml; charset=utf-8"
+ end
+ end
+
+ class ImpliedContentTypeTest < SimpleRouteCase
test "sets Content-Type as text/html when rendering *.html.erb" do
get "/content_type/implied/i_am_html_erb"
+
assert_header "Content-Type", "text/html; charset=utf-8"
end
test "sets Content-Type as application/xml when rendering *.xml.erb" do
get "/content_type/implied/i_am_xml_erb"
+
assert_header "Content-Type", "application/xml; charset=utf-8"
end
test "sets Content-Type as text/html when rendering *.html.builder" do
get "/content_type/implied/i_am_html_builder"
+
assert_header "Content-Type", "text/html; charset=utf-8"
end
test "sets Content-Type as application/xml when rendering *.xml.builder" do
get "/content_type/implied/i_am_xml_builder"
+
assert_header "Content-Type", "application/xml; charset=utf-8"
end
-
end
-end
-module Charset
- class BaseController < ActionController::Base
- def set_on_response_obj
- response.charset = "utf-16"
- render :text => "Hello world!"
+ class ExplicitCharsetTest < SimpleRouteCase
+ test "setting the charset of the response directly on the response object" do
+ get "/content_type/charset/set_on_response_obj"
+
+ assert_body "Hello world!"
+ assert_header "Content-Type", "text/html; charset=utf-16"
end
-
- def set_as_nil_on_response_obj
- response.charset = nil
- render :text => "Hello world!"
+
+ test "setting the charset of the response as nil directly on the response object" do
+ get "/content_type/charset/set_as_nil_on_response_obj"
+
+ assert_body "Hello world!"
+ assert_header "Content-Type", "text/html; charset=utf-8"
end
end
-
- class TestSetOnResponseObj < SimpleRouteCase
- describe "setting the charset of the response directly on the response object"
-
- get "/charset/base/set_on_response_obj"
- assert_body "Hello world!"
- assert_header "Content-Type", "text/html; charset=utf-16"
- end
-
- class TestSetAsNilOnResponseObj < SimpleRouteCase
- describe "setting the charset of the response as nil directly on the response object"
-
- get "/charset/base/set_as_nil_on_response_obj"
- assert_body "Hello world!"
- assert_header "Content-Type", "text/html; charset=utf-8"
- end
-end
\ No newline at end of file
+end
diff --git a/actionpack/test/new_base/etag_test.rb b/actionpack/test/new_base/etag_test.rb
index 7af5febfb3..c77636bb64 100644
--- a/actionpack/test/new_base/etag_test.rb
+++ b/actionpack/test/new_base/etag_test.rb
@@ -1,47 +1,46 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
module Etags
-
class BasicController < ActionController::Base
-
self.view_paths = [ActionView::Template::FixturePath.new(
"etags/basic/base.html.erb" => "Hello from without_layout.html.erb",
"layouts/etags.html.erb" => "teh <%= yield %> tagz"
)]
-
+
def without_layout
render :action => "base"
end
-
+
def with_layout
render :action => "base", :layout => "etag"
end
-
end
-
- class TestBasic < SimpleRouteCase
+
+ class EtagTest < SimpleRouteCase
describe "Rendering without any special etag options returns an etag that is an MD5 hash of its text"
-
+
test "an action without a layout" do
get "/etags/basic/without_layout"
+
body = "Hello from without_layout.html.erb"
assert_body body
assert_header "Etag", etag_for(body)
assert_status 200
end
-
+
test "an action with a layout" do
get "/etags/basic/with_layout"
+
body = "teh Hello from without_layout.html.erb tagz"
assert_body body
assert_header "Etag", etag_for(body)
assert_status 200
end
-
+
+ private
+
def etag_for(text)
%("#{Digest::MD5.hexdigest(text)}")
end
end
-
-
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_action_test.rb b/actionpack/test/new_base/render_action_test.rb
index 626c7b3540..4402eadf42 100644
--- a/actionpack/test/new_base/render_action_test.rb
+++ b/actionpack/test/new_base/render_action_test.rb
@@ -1,26 +1,24 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
module RenderAction
-
# This has no layout and it works
class BasicController < ActionController::Base
-
self.view_paths = [ActionView::Template::FixturePath.new(
"render_action/basic/hello_world.html.erb" => "Hello world!"
)]
-
+
def hello_world
render :action => "hello_world"
end
-
+
def hello_world_as_string
render "hello_world"
end
-
+
def hello_world_as_string_with_options
render "hello_world", :status => 404
end
-
+
def hello_world_as_symbol
render :hello_world
end
@@ -28,107 +26,95 @@ module RenderAction
def hello_world_with_symbol
render :action => :hello_world
end
-
+
def hello_world_with_layout
render :action => "hello_world", :layout => true
end
-
+
def hello_world_with_layout_false
render :action => "hello_world", :layout => false
end
-
+
def hello_world_with_layout_nil
render :action => "hello_world", :layout => nil
end
-
+
def hello_world_with_custom_layout
render :action => "hello_world", :layout => "greetings"
end
-
- end
-
- class TestBasic < SimpleRouteCase
- describe "Rendering an action using :action => "
-
- get "/render_action/basic/hello_world"
- assert_body "Hello world!"
- assert_status 200
- end
-
- class TestWithString < SimpleRouteCase
- describe "Render an action using 'hello_world'"
-
- get "/render_action/basic/hello_world_as_string"
- assert_body "Hello world!"
- assert_status 200
- end
-
- class TestWithStringAndOptions < SimpleRouteCase
- describe "Render an action using 'hello_world'"
-
- get "/render_action/basic/hello_world_as_string_with_options"
- assert_body "Hello world!"
- assert_status 404
- end
-
- class TestAsSymbol < SimpleRouteCase
- describe "Render an action using :hello_world"
-
- get "/render_action/basic/hello_world_as_symbol"
- assert_body "Hello world!"
- assert_status 200
+
end
-
- class TestWithSymbol < SimpleRouteCase
- describe "Render an action using :action => :hello_world"
-
- get "/render_action/basic/hello_world_with_symbol"
- assert_body "Hello world!"
- assert_status 200
+
+ class RenderActionTest < SimpleRouteCase
+ test "rendering an action using :action => " do
+ get "/render_action/basic/hello_world"
+
+ assert_body "Hello world!"
+ assert_status 200
+ end
+
+ test "rendering an action using ''" do
+ get "/render_action/basic/hello_world_as_string"
+
+ assert_body "Hello world!"
+ assert_status 200
+ end
+
+ test "rendering an action using '' and options" do
+ get "/render_action/basic/hello_world_as_string_with_options"
+
+ assert_body "Hello world!"
+ assert_status 404
+ end
+
+ test "rendering an action using :action" do
+ get "/render_action/basic/hello_world_as_symbol"
+
+ assert_body "Hello world!"
+ assert_status 200
+ end
+
+ test "rendering an action using :action => :hello_world" do
+ get "/render_action/basic/hello_world_with_symbol"
+
+ assert_body "Hello world!"
+ assert_status 200
+ end
end
-
- class TestLayoutTrue < SimpleRouteCase
- describe "rendering a normal template with full path with layout => true"
-
- test "raises an exception when requesting a layout and none exist" do
- assert_raise(ArgumentError, /no default layout for RenderAction::BasicController in/) do
+
+ class RenderLayoutTest < SimpleRouteCase
+ describe "Both .html.erb and application.html.erb are missing"
+
+ test "rendering with layout => true" do
+ assert_raise(ArgumentError, /no default layout for RenderAction::BasicController in/) do
get "/render_action/basic/hello_world_with_layout", {}, "action_dispatch.show_exceptions" => false
end
end
- end
-
- class TestLayoutFalse < SimpleRouteCase
- describe "rendering a normal template with full path with layout => false"
-
- get "/render_action/basic/hello_world_with_layout_false"
- assert_body "Hello world!"
- assert_status 200
- end
-
- class TestLayoutNil < SimpleRouteCase
- describe "rendering a normal template with full path with layout => :nil"
-
- get "/render_action/basic/hello_world_with_layout_nil"
- assert_body "Hello world!"
- assert_status 200
- end
-
- class TestCustomLayout < SimpleRouteCase
- describe "rendering a normal template with full path with layout => 'greetings'"
-
- test "raises an exception when requesting a layout that does not exist" do
+
+ test "rendering with layout => false" do
+ get "/render_action/basic/hello_world_with_layout_false"
+
+ assert_body "Hello world!"
+ assert_status 200
+ end
+
+ test "rendering with layout => :nil" do
+ get "/render_action/basic/hello_world_with_layout_nil"
+
+ assert_body "Hello world!"
+ assert_status 200
+ end
+
+ test "rendering with layout => 'greetings'" do
assert_raise(ActionView::MissingTemplate) do
get "/render_action/basic/hello_world_with_custom_layout", {}, "action_dispatch.show_exceptions" => false
end
end
end
-
end
module RenderActionWithApplicationLayout
-
# # ==== Render actions with layouts ====
-
class BasicController < ::ApplicationController
# Set the view path to an application view structure with layouts
self.view_paths = self.view_paths = [ActionView::Template::FixturePath.new(
@@ -138,205 +124,197 @@ module RenderActionWithApplicationLayout
"layouts/greetings.html.erb" => "Greetings <%= yield %> Bai",
"layouts/builder.html.builder" => "xml.html do\n xml << yield\nend"
)]
-
+
def hello_world
render :action => "hello_world"
end
-
+
def hello_world_with_layout
render :action => "hello_world", :layout => true
end
-
+
def hello_world_with_layout_false
render :action => "hello_world", :layout => false
end
-
+
def hello_world_with_layout_nil
render :action => "hello_world", :layout => nil
end
-
+
def hello_world_with_custom_layout
render :action => "hello_world", :layout => "greetings"
end
-
+
def with_builder_and_layout
render :action => "hello", :layout => "builder"
end
end
-
- class TestDefaultLayout < SimpleRouteCase
- describe %(
- Render hello_world and implicitly use application.html.erb as a layout if
- no layout is specified and no controller layout is present
- )
-
- get "/render_action_with_application_layout/basic/hello_world"
- assert_body "OHAI Hello World! KTHXBAI"
- assert_status 200
- end
-
- class TestLayoutTrue < SimpleRouteCase
- describe "rendering a normal template with full path with layout => true"
-
- get "/render_action_with_application_layout/basic/hello_world_with_layout"
- assert_body "OHAI Hello World! KTHXBAI"
- assert_status 200
- end
-
- class TestLayoutFalse < SimpleRouteCase
- describe "rendering a normal template with full path with layout => false"
-
- get "/render_action_with_application_layout/basic/hello_world_with_layout_false"
- assert_body "Hello World!"
- assert_status 200
- end
-
- class TestLayoutNil < SimpleRouteCase
- describe "rendering a normal template with full path with layout => :nil"
-
- get "/render_action_with_application_layout/basic/hello_world_with_layout_nil"
- assert_body "Hello World!"
- assert_status 200
- end
-
- class TestCustomLayout < SimpleRouteCase
- describe "rendering a normal template with full path with layout => 'greetings'"
-
- get "/render_action_with_application_layout/basic/hello_world_with_custom_layout"
- assert_body "Greetings Hello World! Bai"
- assert_status 200
+
+ class LayoutTest < SimpleRouteCase
+ describe "Only application.html.erb is present and .html.erb is missing"
+
+ test "rendering implicit application.html.erb as layout" do
+ get "/render_action_with_application_layout/basic/hello_world"
+
+ assert_body "OHAI Hello World! KTHXBAI"
+ assert_status 200
+ end
+
+ test "rendering with layout => true" do
+ get "/render_action_with_application_layout/basic/hello_world_with_layout"
+
+ assert_body "OHAI Hello World! KTHXBAI"
+ assert_status 200
+ end
+
+ test "rendering with layout => false" do
+ get "/render_action_with_application_layout/basic/hello_world_with_layout_false"
+
+ assert_body "Hello World!"
+ assert_status 200
+ end
+
+ test "rendering with layout => :nil" do
+ get "/render_action_with_application_layout/basic/hello_world_with_layout_nil"
+
+ assert_body "Hello World!"
+ assert_status 200
+ end
+
+ test "rendering with layout => 'greetings'" do
+ get "/render_action_with_application_layout/basic/hello_world_with_custom_layout"
+
+ assert_body "Greetings Hello World! Bai"
+ assert_status 200
+ end
end
-
+
class TestLayout < SimpleRouteCase
testing BasicController
-
+
test "builder works with layouts" do
get :with_builder_and_layout
assert_response "\nOmg
\n\n"
end
end
-
+
end
module RenderActionWithControllerLayout
-
class BasicController < ActionController::Base
self.view_paths = self.view_paths = [ActionView::Template::FixturePath.new(
"render_action_with_controller_layout/basic/hello_world.html.erb" => "Hello World!",
"layouts/render_action_with_controller_layout/basic.html.erb" => "With Controller Layout! <%= yield %> KTHXBAI"
)]
-
+
def hello_world
render :action => "hello_world"
end
-
+
def hello_world_with_layout
render :action => "hello_world", :layout => true
end
-
+
def hello_world_with_layout_false
render :action => "hello_world", :layout => false
end
-
+
def hello_world_with_layout_nil
render :action => "hello_world", :layout => nil
end
-
+
def hello_world_with_custom_layout
render :action => "hello_world", :layout => "greetings"
end
end
-
- class TestControllerLayout < SimpleRouteCase
- describe "Render hello_world and implicitly use .html.erb as a layout."
- get "/render_action_with_controller_layout/basic/hello_world"
- assert_body "With Controller Layout! Hello World! KTHXBAI"
- assert_status 200
- end
-
- class TestLayoutTrue < SimpleRouteCase
- describe "rendering a normal template with full path with layout => true"
-
- get "/render_action_with_controller_layout/basic/hello_world_with_layout"
- assert_body "With Controller Layout! Hello World! KTHXBAI"
- assert_status 200
- end
-
- class TestLayoutFalse < SimpleRouteCase
- describe "rendering a normal template with full path with layout => false"
-
- get "/render_action_with_controller_layout/basic/hello_world_with_layout_false"
- assert_body "Hello World!"
- assert_status 200
- end
-
- class TestLayoutNil < SimpleRouteCase
- describe "rendering a normal template with full path with layout => :nil"
-
- get "/render_action_with_controller_layout/basic/hello_world_with_layout_nil"
- assert_body "Hello World!"
- assert_status 200
+ class ControllerLayoutTest < SimpleRouteCase
+ describe "Only .html.erb is present and application.html.erb is missing"
+
+ test "render hello_world and implicitly use .html.erb as a layout." do
+ get "/render_action_with_controller_layout/basic/hello_world"
+
+ assert_body "With Controller Layout! Hello World! KTHXBAI"
+ assert_status 200
+ end
+
+ test "rendering with layout => true" do
+ get "/render_action_with_controller_layout/basic/hello_world_with_layout"
+
+ assert_body "With Controller Layout! Hello World! KTHXBAI"
+ assert_status 200
+ end
+
+ test "rendering with layout => false" do
+ get "/render_action_with_controller_layout/basic/hello_world_with_layout_false"
+
+ assert_body "Hello World!"
+ assert_status 200
+ end
+
+ test "rendering with layout => :nil" do
+ get "/render_action_with_controller_layout/basic/hello_world_with_layout_nil"
+
+ assert_body "Hello World!"
+ assert_status 200
+ end
end
-
end
module RenderActionWithBothLayouts
-
class BasicController < ActionController::Base
self.view_paths = [ActionView::Template::FixturePath.new({
"render_action_with_both_layouts/basic/hello_world.html.erb" => "Hello World!",
"layouts/application.html.erb" => "OHAI <%= yield %> KTHXBAI",
"layouts/render_action_with_both_layouts/basic.html.erb" => "With Controller Layout! <%= yield %> KTHXBAI"
})]
-
+
def hello_world
render :action => "hello_world"
end
-
+
def hello_world_with_layout
render :action => "hello_world", :layout => true
end
-
+
def hello_world_with_layout_false
render :action => "hello_world", :layout => false
end
-
+
def hello_world_with_layout_nil
render :action => "hello_world", :layout => nil
end
end
-
- class TestControllerLayoutFirst < SimpleRouteCase
- describe "Render hello_world and implicitly use .html.erb over application.html.erb as a layout"
- get "/render_action_with_both_layouts/basic/hello_world"
- assert_body "With Controller Layout! Hello World! KTHXBAI"
- assert_status 200
- end
-
- class TestLayoutTrue < SimpleRouteCase
- describe "rendering a normal template with full path with layout => true"
-
- get "/render_action_with_both_layouts/basic/hello_world_with_layout"
- assert_body "With Controller Layout! Hello World! KTHXBAI"
- assert_status 200
- end
-
- class TestLayoutFalse < SimpleRouteCase
- describe "rendering a normal template with full path with layout => false"
-
- get "/render_action_with_both_layouts/basic/hello_world_with_layout_false"
- assert_body "Hello World!"
- assert_status 200
- end
-
- class TestLayoutNil < SimpleRouteCase
- describe "rendering a normal template with full path with layout => :nil"
-
- get "/render_action_with_both_layouts/basic/hello_world_with_layout_nil"
- assert_body "Hello World!"
- assert_status 200
+ class ControllerLayoutTest < SimpleRouteCase
+ describe "Both .html.erb and application.html.erb are present"
+
+ test "rendering implicitly use .html.erb over application.html.erb as a layout" do
+ get "/render_action_with_both_layouts/basic/hello_world"
+
+ assert_body "With Controller Layout! Hello World! KTHXBAI"
+ assert_status 200
+ end
+
+ test "rendering with layout => true" do
+ get "/render_action_with_both_layouts/basic/hello_world_with_layout"
+
+ assert_body "With Controller Layout! Hello World! KTHXBAI"
+ assert_status 200
+ end
+
+ test "rendering with layout => false" do
+ get "/render_action_with_both_layouts/basic/hello_world_with_layout_false"
+
+ assert_body "Hello World!"
+ assert_status 200
+ end
+
+ test "rendering with layout => :nil" do
+ get "/render_action_with_both_layouts/basic/hello_world_with_layout_nil"
+
+ assert_body "Hello World!"
+ assert_status 200
+ end
end
-
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_implicit_action_test.rb b/actionpack/test/new_base/render_implicit_action_test.rb
index 58f5cec181..2846df48da 100644
--- a/actionpack/test/new_base/render_implicit_action_test.rb
+++ b/actionpack/test/new_base/render_implicit_action_test.rb
@@ -10,19 +10,19 @@ module RenderImplicitAction
def hello_world() end
end
- class TestImplicitRender < SimpleRouteCase
- describe "render a simple action with new explicit call to render"
-
- get "/render_implicit_action/simple/hello_world"
- assert_body "Hello world!"
- assert_status 200
- end
-
- class TestImplicitWithSpecialCharactersRender < SimpleRouteCase
- describe "render an action with a missing method and has special characters"
-
- get "/render_implicit_action/simple/hyphen-ated"
- assert_body "Hello hyphen-ated!"
- assert_status 200
+ class RenderImplicitActionTest < SimpleRouteCase
+ test "render a simple action with new explicit call to render" do
+ get "/render_implicit_action/simple/hello_world"
+
+ assert_body "Hello world!"
+ assert_status 200
+ end
+
+ test "render an action with a missing method and has special characters" do
+ get "/render_implicit_action/simple/hyphen-ated"
+
+ assert_body "Hello hyphen-ated!"
+ assert_status 200
+ end
end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_layout_test.rb b/actionpack/test/new_base/render_layout_test.rb
index dc858b4f5c..76bd5175a3 100644
--- a/actionpack/test/new_base/render_layout_test.rb
+++ b/actionpack/test/new_base/render_layout_test.rb
@@ -2,69 +2,65 @@ require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
module ControllerLayouts
class ImplicitController < ::ApplicationController
-
self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/application.html.erb" => "OMG <%= yield %> KTHXBAI",
"layouts/override.html.erb" => "Override! <%= yield %>",
"basic.html.erb" => "Hello world!",
"controller_layouts/implicit/layout_false.html.erb" => "hai(layout_false.html.erb)"
)]
-
+
def index
render :template => "basic"
end
-
+
def override
render :template => "basic", :layout => "override"
end
-
+
def layout_false
render :layout => false
end
-
+
def builder_override
-
end
end
-
- class TestImplicitLayout < SimpleRouteCase
- describe "rendering a normal template, but using the implicit layout"
-
- get "/controller_layouts/implicit/index"
- assert_body "OMG Hello world! KTHXBAI"
- assert_status 200
- end
-
+
class ImplicitNameController < ::ApplicationController
-
self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/controller_layouts/implicit_name.html.erb" => "OMGIMPLICIT <%= yield %> KTHXBAI",
"basic.html.erb" => "Hello world!"
)]
-
+
def index
render :template => "basic"
end
end
-
- class TestImplicitNamedLayout < SimpleRouteCase
- describe "rendering a normal template, but using an implicit NAMED layout"
-
- get "/controller_layouts/implicit_name/index"
- assert_body "OMGIMPLICIT Hello world! KTHXBAI"
- assert_status 200
- end
-
- class TestOverridingImplicitLayout < SimpleRouteCase
- describe "overriding an implicit layout with render :layout option"
-
- get "/controller_layouts/implicit/override"
- assert_body "Override! Hello world!"
+
+ class RenderLayoutTest < SimpleRouteCase
+ test "rendering a normal template, but using the implicit layout" do
+ get "/controller_layouts/implicit/index"
+
+ assert_body "OMG Hello world! KTHXBAI"
+ assert_status 200
+ end
+
+ test "rendering a normal template, but using an implicit NAMED layout" do
+ get "/controller_layouts/implicit_name/index"
+
+ assert_body "OMGIMPLICIT Hello world! KTHXBAI"
+ assert_status 200
+ end
+
+ test "overriding an implicit layout with render :layout option" do
+ get "/controller_layouts/implicit/override"
+ assert_body "Override! Hello world!"
+ end
+
end
-
- class TestLayoutOptions < SimpleRouteCase
+
+ class LayoutOptionsTest < SimpleRouteCase
testing ControllerLayouts::ImplicitController
-
+
test "rendering with :layout => false leaves out the implicit layout" do
get :layout_false
assert_response "hai(layout_false.html.erb)"
diff --git a/actionpack/test/new_base/render_template_test.rb b/actionpack/test/new_base/render_template_test.rb
index 6c50ae4203..face5b7571 100644
--- a/actionpack/test/new_base/render_template_test.rb
+++ b/actionpack/test/new_base/render_template_test.rb
@@ -79,7 +79,6 @@ module RenderTemplate
end
class WithLayoutController < ::ApplicationController
-
self.view_paths = [ActionView::Template::FixturePath.new(
"test/basic.html.erb" => "Hello from basic.html.erb",
"shared.html.erb" => "Elastica",
@@ -108,46 +107,45 @@ module RenderTemplate
end
end
- class TestTemplateRenderWithLayout < SimpleRouteCase
- describe "rendering a normal template with full path with layout"
-
- get "/render_template/with_layout"
- assert_body "Hello from basic.html.erb, I'm here!"
- assert_status 200
- end
-
- class TestTemplateRenderWithLayoutTrue < SimpleRouteCase
- describe "rendering a normal template with full path with layout => :true"
-
- get "/render_template/with_layout/with_layout"
- assert_body "Hello from basic.html.erb, I'm here!"
- assert_status 200
- end
-
- class TestTemplateRenderWithLayoutFalse < SimpleRouteCase
- describe "rendering a normal template with full path with layout => :false"
-
- get "/render_template/with_layout/with_layout_false"
- assert_body "Hello from basic.html.erb"
- assert_status 200
- end
-
- class TestTemplateRenderWithLayoutNil < SimpleRouteCase
- describe "rendering a normal template with full path with layout => :nil"
-
- get "/render_template/with_layout/with_layout_nil"
- assert_body "Hello from basic.html.erb"
- assert_status 200
- end
-
- class TestTemplateRenderWithCustomLayout < SimpleRouteCase
- describe "rendering a normal template with full path with layout => 'greetings'"
-
- get "/render_template/with_layout/with_custom_layout"
- assert_body "Hello from basic.html.erb, I wish thee well."
- assert_status 200
+ class TestWithLayout < SimpleRouteCase
+ describe "Rendering with :template using implicit or explicit layout"
+
+ test "rendering with implicit layout" do
+ get "/render_template/with_layout"
+
+ assert_body "Hello from basic.html.erb, I'm here!"
+ assert_status 200
+ end
+
+ test "rendering with layout => :true" do
+ get "/render_template/with_layout/with_layout"
+
+ assert_body "Hello from basic.html.erb, I'm here!"
+ assert_status 200
+ end
+
+ test "rendering with layout => :false" do
+ get "/render_template/with_layout/with_layout_false"
+
+ assert_body "Hello from basic.html.erb"
+ assert_status 200
+ end
+
+ test "rendering with layout => :nil" do
+ get "/render_template/with_layout/with_layout_nil"
+
+ assert_body "Hello from basic.html.erb"
+ assert_status 200
+ end
+
+ test "rendering layout => 'greetings'" do
+ get "/render_template/with_layout/with_custom_layout"
+
+ assert_body "Hello from basic.html.erb, I wish thee well."
+ assert_status 200
+ end
end
-
+
module Compatibility
class WithoutLayoutController < ActionController::Base
self.view_paths = [ActionView::Template::FixturePath.new(
@@ -161,11 +159,12 @@ module RenderTemplate
end
class TestTemplateRenderWithForwardSlash < SimpleRouteCase
- describe "rendering a normal template with full path starting with a leading slash"
+ test "rendering a normal template with full path starting with a leading slash" do
+ get "/render_template/compatibility/without_layout/with_forward_slash"
- get "/render_template/compatibility/without_layout/with_forward_slash"
- assert_body "Hello from basic.html.erb"
- assert_status 200
+ assert_body "Hello from basic.html.erb"
+ assert_status 200
+ end
end
end
end
\ No newline at end of file
diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb
index ef5e7d89c5..ed3d50fa0b 100644
--- a/actionpack/test/new_base/render_test.rb
+++ b/actionpack/test/new_base/render_test.rb
@@ -8,60 +8,57 @@ module Render
"render/blank_render/access_action_name.html.erb" => "Action Name: <%= action_name %>",
"render/blank_render/access_controller_name.html.erb" => "Controller Name: <%= controller_name %>"
)]
-
+
def index
render
end
-
+
def access_request
render :action => "access_request"
end
-
+
def render_action_name
render :action => "access_action_name"
end
-
- private
-
+
+ private
+
def secretz
render :text => "FAIL WHALE!"
end
end
-
- class TestBlankRender < SimpleRouteCase
- describe "Render with blank"
- get "/render/blank_render"
- assert_body "Hello world!"
- assert_status 200
- end
-
class DoubleRenderController < ActionController::Base
def index
render :text => "hello"
render :text => "world"
end
end
-
- class TestBasic < SimpleRouteCase
- describe "Rendering more than once"
-
- test "raises an exception" do
+
+ class RenderTest < SimpleRouteCase
+ test "render with blank" do
+ get "/render/blank_render"
+
+ assert_body "Hello world!"
+ assert_status 200
+ end
+
+ test "rendering more than once raises an exception" do
assert_raises(AbstractController::DoubleRenderError) do
get "/render/double_render", {}, "action_dispatch.show_exceptions" => false
end
end
end
-
+
class TestOnlyRenderPublicActions < SimpleRouteCase
describe "Only public methods on actual controllers are callable actions"
-
+
test "raises an exception when a method of Object is called" do
assert_raises(AbstractController::ActionNotFound) do
get "/render/blank_render/clone", {}, "action_dispatch.show_exceptions" => false
end
end
-
+
test "raises an exception when a private method is called" do
assert_raises(AbstractController::ActionNotFound) do
get "/render/blank_render/secretz", {}, "action_dispatch.show_exceptions" => false
@@ -74,12 +71,12 @@ module Render
get "/render/blank_render/access_request"
assert_body "The request: GET"
end
-
+
test "The action_name is accessible in the view" do
get "/render/blank_render/render_action_name"
assert_body "Action Name: render_action_name"
end
-
+
test "The controller_name is accessible in the view" do
get "/render/blank_render/access_controller_name"
assert_body "Controller Name: blank_render"
diff --git a/actionpack/test/new_base/render_text_test.rb b/actionpack/test/new_base/render_text_test.rb
index 39f2f7abbf..69594e4b64 100644
--- a/actionpack/test/new_base/render_text_test.rb
+++ b/actionpack/test/new_base/render_text_test.rb
@@ -11,15 +11,7 @@ module RenderText
render :text => "hello david"
end
end
-
- class TestSimpleTextRenderWithNoLayout < SimpleRouteCase
- describe "Rendering text from a action with default options renders the text with the layout"
-
- get "/render_text/simple"
- assert_body "hello david"
- assert_status 200
- end
-
+
class WithLayoutController < ::ApplicationController
self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/application.html.erb" => "<%= yield %>, I'm here!",
@@ -73,76 +65,77 @@ module RenderText
end
end
- class TestSimpleTextRenderWithLayout < SimpleRouteCase
- describe "Rendering text from a action with default options renders the text without the layout"
-
- get "/render_text/with_layout"
- assert_body "hello david"
- assert_status 200
- end
-
- class TestTextRenderWithStatus < SimpleRouteCase
- describe "Rendering text, while also providing a custom status code"
-
- get "/render_text/with_layout/custom_code"
- assert_body "hello world"
- assert_status 404
- end
-
- class TestTextRenderWithNil < SimpleRouteCase
- describe "Rendering text with nil returns a single space character"
-
- get "/render_text/with_layout/with_nil"
- assert_body " "
- assert_status 200
- end
-
- class TestTextRenderWithNilAndStatus < SimpleRouteCase
- describe "Rendering text with nil and custom status code returns a single space character with the status"
-
- get "/render_text/with_layout/with_nil_and_status"
- assert_body " "
- assert_status 403
- end
-
- class TestTextRenderWithFalse < SimpleRouteCase
- describe "Rendering text with false returns the string 'false'"
-
- get "/render_text/with_layout/with_false"
- assert_body "false"
- assert_status 200
- end
-
- class TestTextRenderWithLayoutTrue < SimpleRouteCase
- describe "Rendering text with :layout => true"
-
- get "/render_text/with_layout/with_layout_true"
- assert_body "hello world, I'm here!"
- assert_status 200
- end
-
- class TestTextRenderWithCustomLayout < SimpleRouteCase
- describe "Rendering text with :layout => 'greetings'"
-
- get "/render_text/with_layout/with_custom_layout"
- assert_body "hello world, I wish thee well."
- assert_status 200
- end
-
- class TestTextRenderWithLayoutFalse < SimpleRouteCase
- describe "Rendering text with :layout => false"
-
- get "/render_text/with_layout/with_layout_false"
- assert_body "hello world"
- assert_status 200
- end
-
- class TestTextRenderWithLayoutNil < SimpleRouteCase
- describe "Rendering text with :layout => nil"
-
- get "/render_text/with_layout/with_layout_nil"
- assert_body "hello world"
- assert_status 200
+ class RenderTextTest < SimpleRouteCase
+ describe "Rendering text using render :text"
+
+ test "rendering text from a action with default options renders the text with the layout" do
+ get "/render_text/simple"
+ assert_body "hello david"
+ assert_status 200
+ end
+
+ test "rendering text from a action with default options renders the text without the layout" do
+ get "/render_text/with_layout"
+
+ assert_body "hello david"
+ assert_status 200
+ end
+
+ test "rendering text, while also providing a custom status code" do
+ get "/render_text/with_layout/custom_code"
+
+ assert_body "hello world"
+ assert_status 404
+ end
+
+ test "rendering text with nil returns a single space character" do
+ get "/render_text/with_layout/with_nil"
+
+ assert_body " "
+ assert_status 200
+ end
+
+ test "Rendering text with nil and custom status code returns a single space character with the status" do
+ get "/render_text/with_layout/with_nil_and_status"
+
+ assert_body " "
+ assert_status 403
+ end
+
+ test "rendering text with false returns the string 'false'" do
+ get "/render_text/with_layout/with_false"
+
+ assert_body "false"
+ assert_status 200
+ end
+
+ test "rendering text with :layout => true" do
+ get "/render_text/with_layout/with_layout_true"
+
+ assert_body "hello world, I'm here!"
+ assert_status 200
+ end
+
+ test "rendering text with :layout => 'greetings'" do
+ get "/render_text/with_layout/with_custom_layout"
+
+ assert_body "hello world, I wish thee well."
+ assert_status 200
+ end
+
+ test "rendering text with :layout => false" do
+ get "/render_text/with_layout/with_layout_false"
+
+ assert_body "hello world"
+ assert_status 200
+ end
+
+ test "rendering text with :layout => nil" do
+ get "/render_text/with_layout/with_layout_nil"
+
+ assert_body "hello world"
+ assert_status 200
+ end
end
end
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index 9401e692f1..89c1290063 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -36,13 +36,13 @@ class Rack::TestCase < ActionController::IntegrationTest
setup do
ActionController::Base.session_options[:key] = "abc"
ActionController::Base.session_options[:secret] = ("*" * 30)
-
+
controllers = ActionController::Base.subclasses.map do |k|
k.underscore.sub(/_controller$/, '')
end
-
+
ActionController::Routing.use_controllers!(controllers)
-
+
# Move into a bootloader
ActionController::Base.subclasses.each do |klass|
klass = klass.constantize
@@ -50,13 +50,13 @@ class Rack::TestCase < ActionController::IntegrationTest
klass.class_eval do
_write_layout_method
end
- end
+ end
end
-
+
def app
@app ||= ActionController::Dispatcher.new
end
-
+
def self.testing(klass = nil)
if klass
@testing = "/#{klass.name.underscore}".sub!(/_controller$/, '')
@@ -64,13 +64,7 @@ class Rack::TestCase < ActionController::IntegrationTest
@testing
end
end
-
- def self.get(url)
- setup do |test|
- test.get url
- end
- end
-
+
def get(thing, *args)
if thing.is_a?(Symbol)
super("#{self.class.testing}/#{thing}")
@@ -78,27 +72,15 @@ class Rack::TestCase < ActionController::IntegrationTest
super
end
end
-
+
def assert_body(body)
assert_equal body, Array.wrap(response.body).join
end
-
- def self.assert_body(body)
- test "body is set to '#{body}'" do
- assert_body body
- end
- end
-
+
def assert_status(code)
assert_equal code, response.status
end
-
- def self.assert_status(code)
- test "status code is set to #{code}" do
- assert_status code
- end
- end
-
+
def assert_response(body, status = 200, headers = {})
assert_body body
assert_status status
@@ -106,27 +88,14 @@ class Rack::TestCase < ActionController::IntegrationTest
assert_header header, value
end
end
-
+
def assert_content_type(type)
assert_equal type, response.headers["Content-Type"]
end
-
- def self.assert_content_type(type)
- test "content type is set to #{type}" do
- assert_content_type(type)
- end
- end
-
+
def assert_header(name, value)
assert_equal value, response.headers[name]
end
-
- def self.assert_header(name, value)
- test "'#{name}' header is set to #{value.inspect}" do
- assert_header(name, value)
- end
- end
-
end
class ::ApplicationController < ActionController::Base
--
cgit v1.2.3
From 01f032f256f96f65e154061b582fbb4b32e4a692 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 20 May 2009 15:33:08 -0700
Subject: Added responds_to to new base.
---
.../lib/action_controller/abstract/layouts.rb | 7 +-
.../lib/action_controller/base/mime_responds.rb | 215 ++++++++++-----------
actionpack/lib/action_controller/new_base.rb | 1 +
actionpack/lib/action_controller/new_base/base.rb | 1 +
.../action_controller/new_base/compatibility.rb | 11 +-
.../lib/action_controller/new_base/renderer.rb | 2 +-
.../lib/action_controller/new_base/testing.rb | 2 +-
.../lib/action_controller/testing/process.rb | 1 +
actionpack/lib/action_view/template/text.rb | 7 +-
actionpack/test/controller/caching_test.rb | 2 +
actionpack/test/controller/mime_responds_test.rb | 24 ++-
11 files changed, 148 insertions(+), 125 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 35d5e85ed9..96cb05972f 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -66,7 +66,12 @@ module AbstractController
raise ArgumentError, "String, false, or nil expected; you passed #{name.inspect}"
end
- name && view_paths.find_by_parts(name, {:formats => formats}, "layouts")
+ name && view_paths.find_by_parts(name, {:formats => formats}, _layout_prefix(name))
+ end
+
+ # TODO: Decide if this is the best hook point for the feature
+ def _layout_prefix(name)
+ "layouts"
end
def _default_layout(require_layout = false)
diff --git a/actionpack/lib/action_controller/base/mime_responds.rb b/actionpack/lib/action_controller/base/mime_responds.rb
index 1003e61a0b..e560376e0d 100644
--- a/actionpack/lib/action_controller/base/mime_responds.rb
+++ b/actionpack/lib/action_controller/base/mime_responds.rb
@@ -1,111 +1,103 @@
module ActionController #:nodoc:
module MimeResponds #:nodoc:
- def self.included(base)
- base.module_eval do
- include ActionController::MimeResponds::InstanceMethods
- end
- end
-
- module InstanceMethods
- # Without web-service support, an action which collects the data for displaying a list of people
- # might look something like this:
- #
- # def index
- # @people = Person.find(:all)
- # end
- #
- # Here's the same action, with web-service support baked in:
- #
- # def index
- # @people = Person.find(:all)
- #
- # respond_to do |format|
- # format.html
- # format.xml { render :xml => @people.to_xml }
- # end
- # end
- #
- # What that says is, "if the client wants HTML in response to this action, just respond as we
- # would have before, but if the client wants XML, return them the list of people in XML format."
- # (Rails determines the desired response format from the HTTP Accept header submitted by the client.)
- #
- # Supposing you have an action that adds a new person, optionally creating their company
- # (by name) if it does not already exist, without web-services, it might look like this:
- #
- # def create
- # @company = Company.find_or_create_by_name(params[:company][:name])
- # @person = @company.people.create(params[:person])
- #
- # redirect_to(person_list_url)
- # end
- #
- # Here's the same action, with web-service support baked in:
- #
- # def create
- # company = params[:person].delete(:company)
- # @company = Company.find_or_create_by_name(company[:name])
- # @person = @company.people.create(params[:person])
- #
- # respond_to do |format|
- # format.html { redirect_to(person_list_url) }
- # format.js
- # format.xml { render :xml => @person.to_xml(:include => @company) }
- # end
- # end
- #
- # If the client wants HTML, we just redirect them back to the person list. If they want Javascript
- # (format.js), then it is an RJS request and we render the RJS template associated with this action.
- # Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also
- # include the person's company in the rendered XML, so you get something like this:
- #
- #
- # ...
- # ...
- #
- # ...
- # ...
- # ...
- #
- #
- #
- # Note, however, the extra bit at the top of that action:
- #
- # company = params[:person].delete(:company)
- # @company = Company.find_or_create_by_name(company[:name])
- #
- # This is because the incoming XML document (if a web-service request is in process) can only contain a
- # single root-node. So, we have to rearrange things so that the request looks like this (url-encoded):
- #
- # person[name]=...&person[company][name]=...&...
- #
- # And, like this (xml-encoded):
- #
- #
- # ...
- #
- # ...
- #
- #
- #
- # In other words, we make the request so that it operates on a single entity's person. Then, in the action,
- # we extract the company data from the request, find or create the company, and then create the new person
- # with the remaining data.
- #
- # Note that you can define your own XML parameter parser which would allow you to describe multiple entities
- # in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow
- # and accept Rails' defaults, life will be much easier.
- #
- # If you need to use a MIME type which isn't supported by default, you can register your own handlers in
- # environment.rb as follows.
- #
- # Mime::Type.register "image/jpg", :jpg
- def respond_to(*types, &block)
- raise ArgumentError, "respond_to takes either types or a block, never both" unless types.any? ^ block
- block ||= lambda { |responder| types.each { |type| responder.send(type) } }
- responder = Responder.new(self)
- block.call(responder)
- responder.respond
- end
+ # Without web-service support, an action which collects the data for displaying a list of people
+ # might look something like this:
+ #
+ # def index
+ # @people = Person.find(:all)
+ # end
+ #
+ # Here's the same action, with web-service support baked in:
+ #
+ # def index
+ # @people = Person.find(:all)
+ #
+ # respond_to do |format|
+ # format.html
+ # format.xml { render :xml => @people.to_xml }
+ # end
+ # end
+ #
+ # What that says is, "if the client wants HTML in response to this action, just respond as we
+ # would have before, but if the client wants XML, return them the list of people in XML format."
+ # (Rails determines the desired response format from the HTTP Accept header submitted by the client.)
+ #
+ # Supposing you have an action that adds a new person, optionally creating their company
+ # (by name) if it does not already exist, without web-services, it might look like this:
+ #
+ # def create
+ # @company = Company.find_or_create_by_name(params[:company][:name])
+ # @person = @company.people.create(params[:person])
+ #
+ # redirect_to(person_list_url)
+ # end
+ #
+ # Here's the same action, with web-service support baked in:
+ #
+ # def create
+ # company = params[:person].delete(:company)
+ # @company = Company.find_or_create_by_name(company[:name])
+ # @person = @company.people.create(params[:person])
+ #
+ # respond_to do |format|
+ # format.html { redirect_to(person_list_url) }
+ # format.js
+ # format.xml { render :xml => @person.to_xml(:include => @company) }
+ # end
+ # end
+ #
+ # If the client wants HTML, we just redirect them back to the person list. If they want Javascript
+ # (format.js), then it is an RJS request and we render the RJS template associated with this action.
+ # Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also
+ # include the person's company in the rendered XML, so you get something like this:
+ #
+ #
+ # ...
+ # ...
+ #
+ # ...
+ # ...
+ # ...
+ #
+ #
+ #
+ # Note, however, the extra bit at the top of that action:
+ #
+ # company = params[:person].delete(:company)
+ # @company = Company.find_or_create_by_name(company[:name])
+ #
+ # This is because the incoming XML document (if a web-service request is in process) can only contain a
+ # single root-node. So, we have to rearrange things so that the request looks like this (url-encoded):
+ #
+ # person[name]=...&person[company][name]=...&...
+ #
+ # And, like this (xml-encoded):
+ #
+ #
+ # ...
+ #
+ # ...
+ #
+ #
+ #
+ # In other words, we make the request so that it operates on a single entity's person. Then, in the action,
+ # we extract the company data from the request, find or create the company, and then create the new person
+ # with the remaining data.
+ #
+ # Note that you can define your own XML parameter parser which would allow you to describe multiple entities
+ # in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow
+ # and accept Rails' defaults, life will be much easier.
+ #
+ # If you need to use a MIME type which isn't supported by default, you can register your own handlers in
+ # environment.rb as follows.
+ #
+ # Mime::Type.register "image/jpg", :jpg
+ def respond_to(*types, &block)
+ raise ArgumentError, "respond_to takes either types or a block, never both" unless types.any? ^ block
+ block ||= lambda { |responder| types.each { |type| responder.send(type) } }
+ responder = Responder.new(self)
+ block.call(responder)
+ responder.respond
end
class Responder #:nodoc:
@@ -127,8 +119,15 @@ module ActionController #:nodoc:
@order << mime_type
@responses[mime_type] ||= Proc.new do
- @controller.template.formats = [mime_type.to_sym]
- @response.content_type = mime_type.to_s
+ # TODO: Remove this when new base is merged in
+ if defined?(Http)
+ @controller.formats = [mime_type.to_sym]
+ @controller.template.formats = [mime_type.to_sym]
+ else
+ @controller.template.formats = [mime_type.to_sym]
+ @response.content_type = mime_type.to_s
+ end
+
block_given? ? block.call : @controller.send(:render, :action => @controller.action_name)
end
end
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 078f66ced1..3fc5d82d01 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -15,6 +15,7 @@ module ActionController
# require 'action_controller/routing'
autoload :Caching, 'action_controller/caching'
autoload :Dispatcher, 'action_controller/dispatch/dispatcher'
+ autoload :MimeResponds, 'action_controller/base/mime_responds'
autoload :PolymorphicRoutes, 'action_controller/routing/generation/polymorphic_routes'
autoload :RecordIdentifier, 'action_controller/record_identifier'
autoload :Resources, 'action_controller/routing/resources'
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 7f830307b6..3d8d46c9c2 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -18,6 +18,7 @@ module ActionController
include SessionManagement
include ActionDispatch::StatusCodes
include ActionController::Caching
+ include ActionController::MimeResponds
# Rails 2.x compatibility
include ActionController::Rails2Compatibility
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index 0098c0747e..c861af2fa2 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -59,6 +59,11 @@ module ActionController
def initialize_template_class(*) end
def assign_shortcuts(*) end
+ # TODO: Remove this after we flip
+ def template
+ _action_view
+ end
+
module ClassMethods
def protect_from_forgery() end
def consider_all_requests_local() end
@@ -95,10 +100,8 @@ module ActionController
super || (respond_to?(:method_missing) && "_handle_method_missing")
end
- def _layout_for_name(name)
- name &&= name.sub(%r{^/?layouts/}, '')
- super
+ def _layout_prefix(name)
+ super unless name =~ /\blayouts/
end
-
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 9253df53a1..276816a6f5 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -18,7 +18,7 @@ module ActionController
_process_options(options)
if options.key?(:text)
- options[:_template] = ActionView::TextTemplate.new(_text(options))
+ options[:_template] = ActionView::TextTemplate.new(_text(options), formats.first)
template = nil
elsif options.key?(:inline)
handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb")
diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb
index b39d8d539d..0659d81710 100644
--- a/actionpack/lib/action_controller/new_base/testing.rb
+++ b/actionpack/lib/action_controller/new_base/testing.rb
@@ -7,7 +7,7 @@ module ActionController
@_response = response
@_response.request = request
ret = process(request.parameters[:action])
- @_response.body = self.response_body || " "
+ @_response.body ||= self.response_body || " "
@_response.prepare!
set_test_assigns
ret
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 8831ff57e2..9647f8ce45 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -41,6 +41,7 @@ module ActionController #:nodoc:
end
def recycle!
+ @formats = nil
@env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
@env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
@env['action_dispatch.request.query_parameters'] = {}
diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb
index a777021a12..927a0d7a72 100644
--- a/actionpack/lib/action_view/template/text.rb
+++ b/actionpack/lib/action_view/template/text.rb
@@ -1,11 +1,16 @@
module ActionView #:nodoc:
class TextTemplate < String #:nodoc:
+ def initialize(string, content_type = Mime[:html])
+ super(string)
+ @content_type = Mime[content_type]
+ end
+
def identifier() self end
def render(*) self end
- def mime_type() Mime::HTML end
+ def mime_type() @content_type end
def partial?() false end
end
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index 560c09509b..c286976315 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -48,6 +48,8 @@ class PageCachingTest < ActionController::TestCase
super
ActionController::Base.perform_caching = true
+ ActionController::Routing::Routes.clear!
+
ActionController::Routing::Routes.draw do |map|
map.main '', :controller => 'posts'
map.formatted_posts 'posts.:format', :controller => 'posts'
diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb
index 7cd5145a2f..3b8babb84c 100644
--- a/actionpack/test/controller/mime_responds_test.rb
+++ b/actionpack/test/controller/mime_responds_test.rb
@@ -437,7 +437,7 @@ class MimeControllerTest < ActionController::TestCase
@controller.instance_eval do
def render(*args)
unless args.empty?
- @action = args.first[:action]
+ @action = args.first[:action] || action_name
end
response.body = "#{@action} - #{@template.formats}"
end
@@ -490,14 +490,15 @@ class PostController < AbstractPostController
end
end
- protected
- def with_iphone
- Mime::Type.register_alias("text/html", :iphone)
- request.format = "iphone" if request.env["HTTP_ACCEPT"] == "text/iphone"
- yield
- ensure
- Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) }
- end
+protected
+
+ def with_iphone
+ Mime::Type.register_alias("text/html", :iphone)
+ request.format = "iphone" if request.env["HTTP_ACCEPT"] == "text/iphone"
+ yield
+ ensure
+ Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) }
+ end
end
class SuperPostController < PostController
@@ -509,6 +510,11 @@ class SuperPostController < PostController
end
end
+if ENV["new_base"]
+ PostController._write_layout_method
+ SuperPostController._write_layout_method
+end
+
class MimeControllerLayoutsTest < ActionController::TestCase
tests PostController
--
cgit v1.2.3
From 77d955c51740216131fc0b130d5cb37fcd18d071 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 20 May 2009 15:54:29 -0700
Subject: Added passing old tests on new base to the main test runner
---
actionpack/Rakefile | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 6ce8179646..f1f407c008 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -22,7 +22,7 @@ task :default => [ :test ]
# Run the unit tests
desc "Run all unit tests"
-task :test => [:test_action_pack, :test_active_record_integration, :test_new_base]
+task :test => [:test_action_pack, :test_active_record_integration, :test_new_base, :test_new_base_on_old_tests]
Rake::TestTask.new(:test_action_pack) do |t|
t.libs << "test"
@@ -55,6 +55,17 @@ Rake::TestTask.new(:test_new_base) do |t|
t.verbose = true
end
+desc 'Old Controller Tests on New Base'
+Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
+ ENV['new_base'] = "true"
+ t.libs << "test"
+ # content_type mime_responds layout
+ t.test_files = %w(
+ addresses_render base benchmark caching capture dispatcher record_identifier
+ redirect render rescue url_rewriter webservice
+ ).map { |name| "test/controller/#{name}_test.rb" }
+end
+
# Genereate the RDoc documentation
--
cgit v1.2.3
From b46c9071c382b48c5ff349fbe61854683663a866 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 20 May 2009 16:00:16 -0700
Subject: Ruby 1.9 stdlib gems don't recognize .pre yet
---
actionpack/lib/action_dispatch.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index f9003c51ea..ee162765cb 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -27,7 +27,7 @@ require 'active_support'
begin
gem 'rack', '~> 1.1.pre'
-rescue Gem::LoadError
+rescue Gem::LoadError, ArgumentError
$:.unshift "#{File.dirname(__FILE__)}/action_dispatch/vendor/rack-1.1.pre"
end
--
cgit v1.2.3
From c86ec82cf63938f691c9ae4f5a4d72bea9e8a9c7 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 20 May 2009 16:00:50 -0700
Subject: Wrap string body in an array
---
actionpack/lib/action_dispatch/middleware/show_exceptions.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
index 108355da63..4d598669c7 100644
--- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
@@ -102,7 +102,7 @@ module ActionDispatch
end
def render(status, body)
- [status, {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}, body]
+ [status, {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}, [body]]
end
def public_path
--
cgit v1.2.3
From 205cfe2163d9eb6ee801a23f550e960136b5680e Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 20 May 2009 16:23:55 -0700
Subject: Massage setup for old tests on new base
---
actionpack/Rakefile | 3 +-
actionpack/test/abstract_unit.rb | 4 -
actionpack/test/abstract_unit2.rb | 139 -----------------------------
actionpack/test/new_base/abstract_unit.rb | 141 ++++++++++++++++++++++++++++++
4 files changed, 142 insertions(+), 145 deletions(-)
delete mode 100644 actionpack/test/abstract_unit2.rb
create mode 100644 actionpack/test/new_base/abstract_unit.rb
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index f1f407c008..af14e592c0 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -57,8 +57,7 @@ end
desc 'Old Controller Tests on New Base'
Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
- ENV['new_base'] = "true"
- t.libs << "test"
+ t.libs << "test/new_base" << "test"
# content_type mime_responds layout
t.test_files = %w(
addresses_render base benchmark caching capture dispatcher record_identifier
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 7982f06545..f6f62bcf83 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -1,6 +1,3 @@
-if ENV["new_base"]
- require "abstract_unit2"
-else
$:.unshift(File.dirname(__FILE__) + '/../lib')
$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
$:.unshift(File.dirname(__FILE__) + '/fixtures/helpers')
@@ -41,4 +38,3 @@ ORIGINAL_LOCALES = I18n.available_locales.map {|locale| locale.to_s }.sort
FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
ActionController::Base.view_paths = FIXTURE_LOAD_PATH
-end
\ No newline at end of file
diff --git a/actionpack/test/abstract_unit2.rb b/actionpack/test/abstract_unit2.rb
deleted file mode 100644
index 519e6bea36..0000000000
--- a/actionpack/test/abstract_unit2.rb
+++ /dev/null
@@ -1,139 +0,0 @@
-$:.unshift(File.dirname(__FILE__) + '/../lib')
-$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
-$:.unshift(File.dirname(__FILE__) + '/lib')
-
-
-require 'test/unit'
-require 'active_support'
-require 'active_support/test_case'
-require 'action_controller/abstract'
-require 'action_controller/new_base'
-require 'fixture_template'
-require 'action_controller/testing/process2'
-require 'action_view/test_case'
-require 'action_controller/testing/integration'
-require 'active_support/dependencies'
-
-ActiveSupport::Dependencies.hook!
-
-FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
-
-module ActionController
- Base.session = {
- :key => '_testing_session',
- :secret => '8273f16463985e2b3747dc25e30f2528'
-}
-
- class ActionControllerError < StandardError #:nodoc:
- end
-
- class SessionRestoreError < ActionControllerError #:nodoc:
- end
-
- class RenderError < ActionControllerError #:nodoc:
- end
-
- class RoutingError < ActionControllerError #:nodoc:
- attr_reader :failures
- def initialize(message, failures=[])
- super(message)
- @failures = failures
- end
- end
-
- class MethodNotAllowed < ActionControllerError #:nodoc:
- attr_reader :allowed_methods
-
- def initialize(*allowed_methods)
- super("Only #{allowed_methods.to_sentence(:locale => :en)} requests are allowed.")
- @allowed_methods = allowed_methods
- end
-
- def allowed_methods_header
- allowed_methods.map { |method_symbol| method_symbol.to_s.upcase } * ', '
- end
-
- def handle_response!(response)
- response.headers['Allow'] ||= allowed_methods_header
- end
- end
-
- class NotImplemented < MethodNotAllowed #:nodoc:
- end
-
- class UnknownController < ActionControllerError #:nodoc:
- end
-
- class MissingFile < ActionControllerError #:nodoc:
- end
-
- class RenderError < ActionControllerError #:nodoc:
- end
-
- class SessionOverflowError < ActionControllerError #:nodoc:
- DEFAULT_MESSAGE = 'Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.'
-
- def initialize(message = nil)
- super(message || DEFAULT_MESSAGE)
- end
- end
-
- class UnknownHttpMethod < ActionControllerError #:nodoc:
- end
-
- class Base
- include ActionController::Testing
- end
-
- Base.view_paths = FIXTURE_LOAD_PATH
-
- class TestCase
- include TestProcess
- setup do
- ActionController::Routing::Routes.draw do |map|
- map.connect ':controller/:action/:id'
- end
- end
-
- def assert_template(options = {}, message = nil)
- validate_request!
-
- hax = @controller._action_view.instance_variable_get(:@_rendered)
-
- case options
- when NilClass, String
- rendered = (hax[:template] || []).map { |t| t.identifier }
- msg = build_message(message,
- "expecting > but rendering with >",
- options, rendered.join(', '))
- assert_block(msg) do
- if options.nil?
- hax[:template].blank?
- else
- rendered.any? { |t| t.match(options) }
- end
- end
- when Hash
- if expected_partial = options[:partial]
- partials = hax[:partials]
- if expected_count = options[:count]
- 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)",
- expected_partial, expected_count, actual_count)
- assert(actual_count == expected_count.to_i, msg)
- else
- msg = build_message(message,
- "expecting partial > but action rendered >",
- options[:partial], partials.keys)
- assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg)
- end
- else
- assert hax[:partials].empty?,
- "Expected no partials to be rendered"
- end
- end
- end
- end
-end
diff --git a/actionpack/test/new_base/abstract_unit.rb b/actionpack/test/new_base/abstract_unit.rb
new file mode 100644
index 0000000000..e72165ee67
--- /dev/null
+++ b/actionpack/test/new_base/abstract_unit.rb
@@ -0,0 +1,141 @@
+$:.unshift(File.dirname(__FILE__) + '/../../lib')
+$:.unshift(File.dirname(__FILE__) + '/../../../activesupport/lib')
+$:.unshift(File.dirname(__FILE__) + '/../lib')
+
+ENV['new_base'] = "true"
+$stderr.puts "Running old tests on new_base"
+
+require 'test/unit'
+require 'active_support'
+require 'active_support/test_case'
+require 'action_controller/abstract'
+require 'action_controller/new_base'
+require 'fixture_template'
+require 'action_controller/testing/process2'
+require 'action_view/test_case'
+require 'action_controller/testing/integration'
+require 'active_support/dependencies'
+
+ActiveSupport::Dependencies.hook!
+
+FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), '../fixtures')
+
+module ActionController
+ Base.session = {
+ :key => '_testing_session',
+ :secret => '8273f16463985e2b3747dc25e30f2528'
+}
+
+ class ActionControllerError < StandardError #:nodoc:
+ end
+
+ class SessionRestoreError < ActionControllerError #:nodoc:
+ end
+
+ class RenderError < ActionControllerError #:nodoc:
+ end
+
+ class RoutingError < ActionControllerError #:nodoc:
+ attr_reader :failures
+ def initialize(message, failures=[])
+ super(message)
+ @failures = failures
+ end
+ end
+
+ class MethodNotAllowed < ActionControllerError #:nodoc:
+ attr_reader :allowed_methods
+
+ def initialize(*allowed_methods)
+ super("Only #{allowed_methods.to_sentence(:locale => :en)} requests are allowed.")
+ @allowed_methods = allowed_methods
+ end
+
+ def allowed_methods_header
+ allowed_methods.map { |method_symbol| method_symbol.to_s.upcase } * ', '
+ end
+
+ def handle_response!(response)
+ response.headers['Allow'] ||= allowed_methods_header
+ end
+ end
+
+ class NotImplemented < MethodNotAllowed #:nodoc:
+ end
+
+ class UnknownController < ActionControllerError #:nodoc:
+ end
+
+ class MissingFile < ActionControllerError #:nodoc:
+ end
+
+ class RenderError < ActionControllerError #:nodoc:
+ end
+
+ class SessionOverflowError < ActionControllerError #:nodoc:
+ DEFAULT_MESSAGE = 'Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.'
+
+ def initialize(message = nil)
+ super(message || DEFAULT_MESSAGE)
+ end
+ end
+
+ class UnknownHttpMethod < ActionControllerError #:nodoc:
+ end
+
+ class Base
+ include ActionController::Testing
+ end
+
+ Base.view_paths = FIXTURE_LOAD_PATH
+
+ class TestCase
+ include TestProcess
+ setup do
+ ActionController::Routing::Routes.draw do |map|
+ map.connect ':controller/:action/:id'
+ end
+ end
+
+ def assert_template(options = {}, message = nil)
+ validate_request!
+
+ hax = @controller._action_view.instance_variable_get(:@_rendered)
+
+ case options
+ when NilClass, String
+ rendered = (hax[:template] || []).map { |t| t.identifier }
+ msg = build_message(message,
+ "expecting > but rendering with >",
+ options, rendered.join(', '))
+ assert_block(msg) do
+ if options.nil?
+ hax[:template].blank?
+ else
+ rendered.any? { |t| t.match(options) }
+ end
+ end
+ when Hash
+ if expected_partial = options[:partial]
+ partials = hax[:partials]
+ if expected_count = options[:count]
+ 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)",
+ expected_partial, expected_count, actual_count)
+ assert(actual_count == expected_count.to_i, msg)
+ else
+ msg = build_message(message,
+ "expecting partial > but action rendered >",
+ options[:partial], partials.keys)
+ assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg)
+ end
+ else
+ assert hax[:partials].empty?,
+ "Expected no partials to be rendered"
+ end
+ end
+ end
+ end
+end
--
cgit v1.2.3
From 8e7a87d299483fce6af3be89e50deae43055a96f Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Thu, 21 May 2009 01:38:48 +0200
Subject: Make ActionController::Flash work with new_base
---
actionpack/Rakefile | 2 +-
.../lib/action_controller/base/chained/flash.rb | 74 +++++++++++++++-------
actionpack/lib/action_controller/new_base.rb | 5 +-
actionpack/lib/action_controller/new_base/base.rb | 3 +
actionpack/lib/action_controller/new_base/http.rb | 2 +-
.../lib/action_controller/new_base/session.rb | 11 ++++
actionpack/test/controller/flash_test.rb | 49 +++++++-------
7 files changed, 97 insertions(+), 49 deletions(-)
create mode 100644 actionpack/lib/action_controller/new_base/session.rb
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index af14e592c0..2a456ebb05 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -61,7 +61,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
# content_type mime_responds layout
t.test_files = %w(
addresses_render base benchmark caching capture dispatcher record_identifier
- redirect render rescue url_rewriter webservice
+ redirect render rescue url_rewriter webservice flash
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/lib/action_controller/base/chained/flash.rb b/actionpack/lib/action_controller/base/chained/flash.rb
index 56ee9c67e2..6bd482d85a 100644
--- a/actionpack/lib/action_controller/base/chained/flash.rb
+++ b/actionpack/lib/action_controller/base/chained/flash.rb
@@ -26,9 +26,18 @@ module ActionController #:nodoc:
#
# See docs on the FlashHash class for more details about the flash.
module Flash
- def self.included(base)
- base.class_eval do
- include InstanceMethods
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ depends_on Session if defined?(ActionController::Http)
+
+ included do
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ include InstanceMethodsForNewBase
+ else
+ include InstanceMethodsForBase
+
alias_method_chain :perform_action, :flash
alias_method_chain :reset_session, :flash
end
@@ -135,29 +144,50 @@ module ActionController #:nodoc:
end
end
- module InstanceMethods #:nodoc:
+ module InstanceMethodsForBase #:nodoc:
protected
- def perform_action_with_flash
- perform_action_without_flash
- remove_instance_variable(:@_flash) if defined? @_flash
- end
- def reset_session_with_flash
- reset_session_without_flash
- remove_instance_variable(:@_flash) if defined? @_flash
- end
+ def perform_action_with_flash
+ perform_action_without_flash
+ remove_instance_variable(:@_flash) if defined?(@_flash)
+ end
- # Access the contents of the flash. Use flash["notice"] to
- # read a notice you put there or flash["notice"] = "hello"
- # to put a new one.
- def flash #:doc:
- unless defined? @_flash
- @_flash = session["flash"] ||= FlashHash.new
- @_flash.sweep
- end
+ def reset_session_with_flash
+ reset_session_without_flash
+ remove_instance_variable(:@_flash) if defined?(@_flash)
+ end
+ end
- @_flash
- end
+ module InstanceMethodsForNewBase #:nodoc:
+ protected
+
+ def reset_session
+ super
+ remove_flash_instance_variable
+ end
+
+ def process_action(method_name)
+ super
+ remove_flash_instance_variable
+ end
+
+ def remove_flash_instance_variable
+ remove_instance_variable(:@_flash) if defined?(@_flash)
+ end
+ end
+
+ protected
+
+ # Access the contents of the flash. Use flash["notice"] to
+ # read a notice you put there or flash["notice"] = "hello"
+ # to put a new one.
+ def flash #:doc:
+ unless defined?(@_flash)
+ @_flash = session["flash"] ||= FlashHash.new
+ @_flash.sweep
+ end
+
+ @_flash
end
end
end
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 3fc5d82d01..d2f6514ff9 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -10,7 +10,8 @@ module ActionController
autoload :Rescue, "action_controller/new_base/rescuable"
autoload :Testing, "action_controller/new_base/testing"
autoload :UrlFor, "action_controller/new_base/url_for"
-
+ autoload :Session, "action_controller/new_base/session"
+
# Ported modules
# require 'action_controller/routing'
autoload :Caching, 'action_controller/caching'
@@ -23,6 +24,8 @@ module ActionController
autoload :TestCase, 'action_controller/testing/test_case'
autoload :UrlRewriter, 'action_controller/routing/generation/url_rewriter'
autoload :UrlWriter, 'action_controller/routing/generation/url_rewriter'
+
+ autoload :Flash, 'action_controller/base/chained/flash'
require 'action_controller/routing'
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 3d8d46c9c2..eff7297973 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -14,6 +14,9 @@ module ActionController
include ActionController::Layouts
include ActionController::ConditionalGet
+ include ActionController::Session
+ include ActionController::Flash
+
# Legacy modules
include SessionManagement
include ActionDispatch::StatusCodes
diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb
index 17466a2d52..2525e221a6 100644
--- a/actionpack/lib/action_controller/new_base/http.rb
+++ b/actionpack/lib/action_controller/new_base/http.rb
@@ -37,7 +37,7 @@ module ActionController
end
delegate :headers, :to => "@_response"
-
+
def params
@_params ||= @_request.parameters
end
diff --git a/actionpack/lib/action_controller/new_base/session.rb b/actionpack/lib/action_controller/new_base/session.rb
new file mode 100644
index 0000000000..a8715555fb
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/session.rb
@@ -0,0 +1,11 @@
+module ActionController
+ module Session
+ def session
+ @_request.session
+ end
+
+ def reset_session
+ @_request.reset_session
+ end
+ end
+end
diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb
index ef60cae0ff..84e27d7779 100644
--- a/actionpack/test/controller/flash_test.rb
+++ b/actionpack/test/controller/flash_test.rb
@@ -60,6 +60,7 @@ class FlashTest < ActionController::TestCase
def std_action
@flash_copy = {}.update(flash)
+ render :nothing => true
end
def filter_halting_action
@@ -79,64 +80,64 @@ class FlashTest < ActionController::TestCase
get :set_flash
get :use_flash
- assert_equal "hello", @controller.template.assigns["flash_copy"]["that"]
- assert_equal "hello", @controller.template.assigns["flashy"]
+ assert_equal "hello", assigns["flash_copy"]["that"]
+ assert_equal "hello", assigns["flashy"]
get :use_flash
- assert_nil @controller.template.assigns["flash_copy"]["that"], "On second flash"
+ assert_nil assigns["flash_copy"]["that"], "On second flash"
end
def test_keep_flash
get :set_flash
get :use_flash_and_keep_it
- assert_equal "hello", @controller.template.assigns["flash_copy"]["that"]
- assert_equal "hello", @controller.template.assigns["flashy"]
+ assert_equal "hello", assigns["flash_copy"]["that"]
+ assert_equal "hello", assigns["flashy"]
get :use_flash
- assert_equal "hello", @controller.template.assigns["flash_copy"]["that"], "On second flash"
+ assert_equal "hello", assigns["flash_copy"]["that"], "On second flash"
get :use_flash
- assert_nil @controller.template.assigns["flash_copy"]["that"], "On third flash"
+ assert_nil assigns["flash_copy"]["that"], "On third flash"
end
def test_flash_now
get :set_flash_now
- 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"]
+ assert_equal "hello", assigns["flash_copy"]["that"]
+ assert_equal "bar" , assigns["flash_copy"]["foo"]
+ assert_equal "hello", assigns["flashy"]
get :attempt_to_use_flash_now
- assert_nil @controller.template.assigns["flash_copy"]["that"]
- assert_nil @controller.template.assigns["flash_copy"]["foo"]
- assert_nil @controller.template.assigns["flashy"]
+ assert_nil assigns["flash_copy"]["that"]
+ assert_nil assigns["flash_copy"]["foo"]
+ assert_nil assigns["flashy"]
end
def test_update_flash
get :set_flash
get :use_flash_and_update_it
- assert_equal "hello", @controller.template.assigns["flash_copy"]["that"]
- assert_equal "hello again", @controller.template.assigns["flash_copy"]["this"]
+ assert_equal "hello", assigns["flash_copy"]["that"]
+ assert_equal "hello again", assigns["flash_copy"]["this"]
get :use_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"
+ assert_nil assigns["flash_copy"]["that"], "On second flash"
+ assert_equal "hello again", assigns["flash_copy"]["this"], "On second flash"
end
def test_flash_after_reset_session
get :use_flash_after_reset_session
- 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"]
+ assert_equal "hello", assigns["flashy_that"]
+ assert_equal "good-bye", assigns["flashy_this"]
+ assert_nil assigns["flashy_that_reset"]
end
def test_sweep_after_halted_filter_chain
get :std_action
- assert_nil @controller.template.assigns["flash_copy"]["foo"]
+ assert_nil assigns["flash_copy"]["foo"]
get :filter_halting_action
- assert_equal "bar", @controller.template.assigns["flash_copy"]["foo"]
+ assert_equal "bar", assigns["flash_copy"]["foo"]
get :std_action # follow redirection
- assert_equal "bar", @controller.template.assigns["flash_copy"]["foo"]
+ assert_equal "bar", assigns["flash_copy"]["foo"]
get :std_action
- assert_nil @controller.template.assigns["flash_copy"]["foo"]
+ assert_nil assigns["flash_copy"]["foo"]
end
end
--
cgit v1.2.3
From c4a6109286909c394e8c5bfc471a1eb9de245d2b Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 20 May 2009 16:52:56 -0700
Subject: Got controller/mime_responds_test.rb running on the new base
---
actionpack/Rakefile | 7 +++---
actionpack/test/abstract_unit.rb | 2 ++
actionpack/test/controller/mime_responds_test.rb | 26 +++++++++++++---------
actionpack/test/new_base/abstract_unit.rb | 3 +++
activesupport/lib/active_support/test_case.rb | 5 +++++
.../lib/active_support/testing/pending.rb | 5 +++++
6 files changed, 34 insertions(+), 14 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 2a456ebb05..86f7adaee3 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -58,10 +58,11 @@ end
desc 'Old Controller Tests on New Base'
Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
t.libs << "test/new_base" << "test"
- # content_type mime_responds layout
+ # content_type layout
+ # Dir.glob( "test/{dispatch,template}/**/*_test.rb" ).sort +
t.test_files = %w(
- addresses_render base benchmark caching capture dispatcher record_identifier
- redirect render rescue url_rewriter webservice flash
+ addresses_render base benchmark caching capture dispatcher flash mime_responds
+ record_identifier redirect render rescue url_rewriter webservice
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index f6f62bcf83..5ae54d097a 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -23,6 +23,8 @@ require 'action_controller'
require 'action_controller/testing/process'
require 'action_view/test_case'
+$tags[:old_base] = true
+
# Show backtraces for deprecated behavior for quicker cleanup.
ActiveSupport::Deprecation.debug = true
diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb
index 3b8babb84c..56b49251c6 100644
--- a/actionpack/test/controller/mime_responds_test.rb
+++ b/actionpack/test/controller/mime_responds_test.rb
@@ -375,9 +375,11 @@ class MimeControllerTest < ActionController::TestCase
end
def test_rjs_type_skips_layout
- @request.accept = "text/javascript"
- get :all_types_with_layout
- assert_equal 'RJS for all_types_with_layout', @response.body
+ pending(:new_base) do
+ @request.accept = "text/javascript"
+ get :all_types_with_layout
+ assert_equal 'RJS for all_types_with_layout', @response.body
+ end
end
def test_html_type_with_layout
@@ -510,7 +512,7 @@ class SuperPostController < PostController
end
end
-if ENV["new_base"]
+if defined?(ActionController::Http)
PostController._write_layout_method
SuperPostController._write_layout_method
end
@@ -532,14 +534,16 @@ class MimeControllerLayoutsTest < ActionController::TestCase
assert_equal 'Hello iPhone', @response.body
end
- def test_format_with_inherited_layouts
- @controller = SuperPostController.new
+ for_tag(:old_base) do
+ def test_format_with_inherited_layouts
+ @controller = SuperPostController.new
- get :index
- assert_equal 'Super Firefox', @response.body
+ get :index
+ assert_equal 'Super Firefox', @response.body
- @request.accept = "text/iphone"
- get :index
- assert_equal 'Super iPhone
', @response.body
+ @request.accept = "text/iphone"
+ get :index
+ assert_equal 'Super iPhone
', @response.body
+ end
end
end
diff --git a/actionpack/test/new_base/abstract_unit.rb b/actionpack/test/new_base/abstract_unit.rb
index e72165ee67..c045247702 100644
--- a/actionpack/test/new_base/abstract_unit.rb
+++ b/actionpack/test/new_base/abstract_unit.rb
@@ -16,6 +16,9 @@ require 'action_view/test_case'
require 'action_controller/testing/integration'
require 'active_support/dependencies'
+$tags[:new_base] = true
+
+
ActiveSupport::Dependencies.hook!
FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), '../fixtures')
diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb
index 50e25ef740..bab2a401eb 100644
--- a/activesupport/lib/active_support/test_case.rb
+++ b/activesupport/lib/active_support/test_case.rb
@@ -32,6 +32,11 @@ module ActiveSupport
include ActiveSupport::Testing::Default
end
+ $tags = {}
+ def self.for_tag(tag)
+ yield if $tags[tag]
+ end
+
include ActiveSupport::Testing::SetupAndTeardown
include ActiveSupport::Testing::Assertions
include ActiveSupport::Testing::Deprecation
diff --git a/activesupport/lib/active_support/testing/pending.rb b/activesupport/lib/active_support/testing/pending.rb
index d945c7e476..21134ff9e2 100644
--- a/activesupport/lib/active_support/testing/pending.rb
+++ b/activesupport/lib/active_support/testing/pending.rb
@@ -11,6 +11,11 @@ module ActiveSupport
@@at_exit = false
def pending(description = "", &block)
+ if description.is_a?(Symbol)
+ is_pending = $tags[description]
+ return block.call unless is_pending
+ end
+
if block_given?
failed = false
--
cgit v1.2.3
From c8eda9ade49700abce104de1ce7e8e1a754fc97e Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 20 May 2009 17:22:29 -0700
Subject: Fixed new_base tests on ruby 1.9
---
actionpack/lib/action_controller/new_base/renderer.rb | 4 ++--
actionpack/lib/action_dispatch/http/mime_types.rb | 2 +-
actionpack/test/lib/fixture_template.rb | 2 +-
actionpack/test/new_base/etag_test.rb | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 276816a6f5..6176212970 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -4,8 +4,8 @@ module ActionController
depends_on AbstractController::Renderer
- def initialize(*)
- self.formats = [:html]
+ def process_action(*)
+ self.formats = request.formats.map {|x| x.to_sym}
super
end
diff --git a/actionpack/lib/action_dispatch/http/mime_types.rb b/actionpack/lib/action_dispatch/http/mime_types.rb
index 2d7fba1173..7c28cac419 100644
--- a/actionpack/lib/action_dispatch/http/mime_types.rb
+++ b/actionpack/lib/action_dispatch/http/mime_types.rb
@@ -1,9 +1,9 @@
# Build list of Mime types for HTTP responses
# http://www.iana.org/assignments/media-types/
+Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml )
Mime::Type.register "*/*", :all
Mime::Type.register "text/plain", :text, [], %w(txt)
-Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml )
Mime::Type.register "text/javascript", :js, %w( application/javascript application/x-javascript )
Mime::Type.register "text/css", :css
Mime::Type.register "text/calendar", :ics
diff --git a/actionpack/test/lib/fixture_template.rb b/actionpack/test/lib/fixture_template.rb
index e43e329a9e..59fb6819ed 100644
--- a/actionpack/test/lib/fixture_template.rb
+++ b/actionpack/test/lib/fixture_template.rb
@@ -46,7 +46,7 @@ class Template
end
end
- %r'#{Regexp.escape(path)}#{extensions}#{handler_regexp}'
+ %r'^#{Regexp.escape(path)}#{extensions}#{handler_regexp}$'
end
# TODO: fix me
diff --git a/actionpack/test/new_base/etag_test.rb b/actionpack/test/new_base/etag_test.rb
index c77636bb64..a40d3c936a 100644
--- a/actionpack/test/new_base/etag_test.rb
+++ b/actionpack/test/new_base/etag_test.rb
@@ -12,7 +12,7 @@ module Etags
end
def with_layout
- render :action => "base", :layout => "etag"
+ render :action => "base", :layout => "etags"
end
end
--
cgit v1.2.3
From 7f7fdc407a90c9ce75ce0a77bc0f631115514d2f Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Wed, 20 May 2009 17:42:04 -0700
Subject: Make controller/content_type_test.rb pass on new base
---
actionpack/Rakefile | 7 ++++---
actionpack/lib/action_controller/new_base/renderer.rb | 6 +++++-
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 86f7adaee3..684b828254 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -58,11 +58,12 @@ end
desc 'Old Controller Tests on New Base'
Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
t.libs << "test/new_base" << "test"
- # content_type layout
+ # layout
# Dir.glob( "test/{dispatch,template}/**/*_test.rb" ).sort +
t.test_files = %w(
- addresses_render base benchmark caching capture dispatcher flash mime_responds
- record_identifier redirect render rescue url_rewriter webservice
+ addresses_render base benchmark caching capture content_type dispatcher
+ flash mime_responds record_identifier redirect render rescue url_rewriter
+ webservice
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 6176212970..81685ca9d6 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -38,7 +38,11 @@ module ActionController
ret = super(options)
options[:_template] ||= _action_view._partial
- response.content_type ||= options[:_template].mime_type
+ response.content_type ||= begin
+ mime = options[:_template].mime_type
+ mime &&= mime.to_sym
+ formats.include?(mime) ? mime : formats.first
+ end
ret
end
--
cgit v1.2.3
From e21d1614bb9006e69bf4bb2467b823aa12e64485 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Thu, 21 May 2009 02:55:25 +0200
Subject: Made ActionController::Verification work with new_base
---
actionpack/Rakefile | 2 +-
actionpack/lib/action_controller/base/verification.rb | 12 +++++++++---
actionpack/lib/action_controller/new_base.rb | 5 +++--
actionpack/lib/action_controller/new_base/base.rb | 1 +
actionpack/lib/action_controller/new_base/compatibility.rb | 4 ++++
actionpack/lib/action_controller/new_base/testing.rb | 2 +-
actionpack/lib/action_controller/testing/process2.rb | 2 +-
actionpack/test/controller/verification_test.rb | 14 ++++++--------
8 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 684b828254..3a6a54768e 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -63,7 +63,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
t.test_files = %w(
addresses_render base benchmark caching capture content_type dispatcher
flash mime_responds record_identifier redirect render rescue url_rewriter
- webservice
+ webservice verification
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/lib/action_controller/base/verification.rb b/actionpack/lib/action_controller/base/verification.rb
index c62b81b666..a513e9f40c 100644
--- a/actionpack/lib/action_controller/base/verification.rb
+++ b/actionpack/lib/action_controller/base/verification.rb
@@ -1,7 +1,13 @@
module ActionController #:nodoc:
module Verification #:nodoc:
- def self.included(base) #:nodoc:
- base.extend(ClassMethods)
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ depends_on AbstractController::Callbacks
+ depends_on Session
+ depends_on Flash
+ depends_on Renderer
end
# This module provides a class-level method for specifying that certain
@@ -102,7 +108,7 @@ module ActionController #:nodoc:
end
def verify_presence_of_keys_in_hash_flash_or_params(options) # :nodoc:
- [*options[:params] ].find { |v| params[v].nil? } ||
+ [*options[:params] ].find { |v| v && params[v.to_sym].nil? } ||
[*options[:session]].find { |v| session[v].nil? } ||
[*options[:flash] ].find { |v| flash[v].nil? }
end
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index d2f6514ff9..8bc15d2450 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -25,8 +25,9 @@ module ActionController
autoload :UrlRewriter, 'action_controller/routing/generation/url_rewriter'
autoload :UrlWriter, 'action_controller/routing/generation/url_rewriter'
- autoload :Flash, 'action_controller/base/chained/flash'
-
+ autoload :Verification, 'action_controller/base/verification'
+ autoload :Flash, 'action_controller/base/chained/flash'
+
require 'action_controller/routing'
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index eff7297973..a419a80b6a 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -16,6 +16,7 @@ module ActionController
include ActionController::Session
include ActionController::Flash
+ include ActionController::Verification
# Legacy modules
include SessionManagement
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index c861af2fa2..9b85b39052 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -103,5 +103,9 @@ module ActionController
def _layout_prefix(name)
super unless name =~ /\blayouts/
end
+
+ def performed?
+ response_body
+ end
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb
index 0659d81710..bc3bc70404 100644
--- a/actionpack/lib/action_controller/new_base/testing.rb
+++ b/actionpack/lib/action_controller/new_base/testing.rb
@@ -2,7 +2,7 @@ module ActionController
module Testing
# OMG MEGA HAX
- def process_with_test(request, response)
+ def process_with_new_base_test(request, response)
@_request = request
@_response = response
@_response.request = request
diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb
index e9a79369b9..2dafcaa5a9 100644
--- a/actionpack/lib/action_controller/testing/process2.rb
+++ b/actionpack/lib/action_controller/testing/process2.rb
@@ -53,7 +53,7 @@ module ActionController
@controller.request = @request
@controller.params.merge!(parameters)
# Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
- @controller.process_with_test(@request, @response)
+ @controller.process_with_new_base_test(@request, @response)
end
def build_request_uri(action, parameters)
diff --git a/actionpack/test/controller/verification_test.rb b/actionpack/test/controller/verification_test.rb
index 418a81baa8..85134a8264 100644
--- a/actionpack/test/controller/verification_test.rb
+++ b/actionpack/test/controller/verification_test.rb
@@ -103,17 +103,15 @@ class VerificationTest < ActionController::TestCase
end
protected
- def rescue_action(e) raise end
- def unconditional_redirect
- redirect_to :action => "unguarded"
- end
+ def unconditional_redirect
+ redirect_to :action => "unguarded"
+ end
end
- def setup
- @controller = TestController.new
- @request = ActionController::TestRequest.new
- @response = ActionController::TestResponse.new
+ tests TestController
+
+ setup do
ActionController::Routing::Routes.add_named_route :foo, '/foo', :controller => 'test', :action => 'foo'
end
--
cgit v1.2.3
From 5a036457620b7fb22027dc4f0c399871db6ed0c3 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Thu, 21 May 2009 03:04:17 +0200
Subject: Allow Module#depends_on to accept multiple modules
---
actionpack/lib/action_controller/base/verification.rb | 5 +----
activesupport/lib/active_support/dependency_module.rb | 10 ++++++----
activesupport/test/dependency_module_test.rb | 11 +++++++++++
3 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/actionpack/lib/action_controller/base/verification.rb b/actionpack/lib/action_controller/base/verification.rb
index a513e9f40c..3fa5a105b1 100644
--- a/actionpack/lib/action_controller/base/verification.rb
+++ b/actionpack/lib/action_controller/base/verification.rb
@@ -4,10 +4,7 @@ module ActionController #:nodoc:
# TODO : Remove the defined? check when new base is the main base
if defined?(ActionController::Http)
- depends_on AbstractController::Callbacks
- depends_on Session
- depends_on Flash
- depends_on Renderer
+ depends_on AbstractController::Callbacks, Session, Flash, Renderer
end
# This module provides a class-level method for specifying that certain
diff --git a/activesupport/lib/active_support/dependency_module.rb b/activesupport/lib/active_support/dependency_module.rb
index 8c202acc8f..9872b9654b 100644
--- a/activesupport/lib/active_support/dependency_module.rb
+++ b/activesupport/lib/active_support/dependency_module.rb
@@ -16,10 +16,12 @@ module ActiveSupport
end
end
- def depends_on(mod)
- return if self < mod
- @_dependencies ||= []
- @_dependencies << mod
+ def depends_on(*mods)
+ mods.each do |mod|
+ next if self < mod
+ @_dependencies ||= []
+ @_dependencies << mod
+ end
end
end
end
diff --git a/activesupport/test/dependency_module_test.rb b/activesupport/test/dependency_module_test.rb
index 07090d15a1..be7db0fa7b 100644
--- a/activesupport/test/dependency_module_test.rb
+++ b/activesupport/test/dependency_module_test.rb
@@ -42,6 +42,12 @@ class DependencyModuleTest < Test::Unit::TestCase
end
end
+ module Foo
+ extend ActiveSupport::DependencyModule
+
+ depends_on Bar, Baz
+ end
+
def setup
@klass = Class.new
end
@@ -74,4 +80,9 @@ class DependencyModuleTest < Test::Unit::TestCase
assert_equal "baz", @klass.baz
assert_equal [DependencyModuleTest::Bar, DependencyModuleTest::Baz], @klass.included_modules[0..1]
end
+
+ def test_depends_on_with_multiple_modules
+ @klass.send(:include, Foo)
+ assert_equal [DependencyModuleTest::Foo, DependencyModuleTest::Bar, DependencyModuleTest::Baz], @klass.included_modules[0..2]
+ end
end
--
cgit v1.2.3
From 429a00f225b24b938575ed40d11fa07987e12a6f Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 20 May 2009 16:41:20 -0700
Subject: Remove bad add
---
activesupport/memcached_get_multi.diff | 0
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 activesupport/memcached_get_multi.diff
diff --git a/activesupport/memcached_get_multi.diff b/activesupport/memcached_get_multi.diff
deleted file mode 100644
index e69de29bb2..0000000000
--
cgit v1.2.3
From 68398838544a778244e6028f2c30deb7313ea0b2 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 20 May 2009 16:49:21 -0700
Subject: Break up misc Object extensions
---
.../lib/active_support/core_ext/object/misc.rb | 83 +---------------------
.../active_support/core_ext/object/returning.rb | 42 +++++++++++
.../lib/active_support/core_ext/object/tap.rb | 16 +++++
.../active_support/core_ext/object/with_options.rb | 24 +++++++
4 files changed, 85 insertions(+), 80 deletions(-)
create mode 100644 activesupport/lib/active_support/core_ext/object/returning.rb
create mode 100644 activesupport/lib/active_support/core_ext/object/tap.rb
create mode 100644 activesupport/lib/active_support/core_ext/object/with_options.rb
diff --git a/activesupport/lib/active_support/core_ext/object/misc.rb b/activesupport/lib/active_support/core_ext/object/misc.rb
index fb1bcdb98f..80011dfbed 100644
--- a/activesupport/lib/active_support/core_ext/object/misc.rb
+++ b/activesupport/lib/active_support/core_ext/object/misc.rb
@@ -1,80 +1,3 @@
-class Object
- # Returns +value+ after yielding +value+ to the block. This simplifies the
- # process of constructing an object, performing work on the object, and then
- # returning the object from a method. It is a Ruby-ized realization of the K
- # combinator, courtesy of Mikael Brockman.
- #
- # ==== Examples
- #
- # # Without returning
- # def foo
- # values = []
- # values << "bar"
- # values << "baz"
- # return values
- # end
- #
- # foo # => ['bar', 'baz']
- #
- # # returning with a local variable
- # def foo
- # returning values = [] do
- # values << 'bar'
- # values << 'baz'
- # end
- # end
- #
- # foo # => ['bar', 'baz']
- #
- # # returning with a block argument
- # def foo
- # returning [] do |values|
- # values << 'bar'
- # values << 'baz'
- # end
- # end
- #
- # foo # => ['bar', 'baz']
- def returning(value)
- yield(value)
- value
- end
-
- # Yields x
to the block, and then returns x
.
- # The primary purpose of this method is to "tap into" a method chain,
- # in order to perform operations on intermediate results within the chain.
- #
- # (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a.
- # tap { |x| puts "array: #{x.inspect}" }.
- # select { |x| x%2 == 0 }.
- # tap { |x| puts "evens: #{x.inspect}" }.
- # map { |x| x*x }.
- # tap { |x| puts "squares: #{x.inspect}" }
- def tap
- yield self
- self
- end unless Object.respond_to?(:tap)
-
- # An elegant way to factor duplication out of options passed to a series of
- # method calls. Each method called in the block, with the block variable as
- # the receiver, will have its options merged with the default +options+ hash
- # provided. Each method called on the block variable must take an options
- # hash as its final argument.
- #
- # with_options :order => 'created_at', :class_name => 'Comment' do |post|
- # post.has_many :comments, :conditions => ['approved = ?', true], :dependent => :delete_all
- # post.has_many :unapproved_comments, :conditions => ['approved = ?', false]
- # post.has_many :all_comments
- # end
- #
- # Can also be used with an explicit receiver:
- #
- # map.with_options :controller => "people" do |people|
- # people.connect "/people", :action => "index"
- # people.connect "/people/:id", :action => "show"
- # end
- #
- def with_options(options)
- yield ActiveSupport::OptionMerger.new(self, options)
- end
-end
+require 'active_support/core_ext/object/returning'
+require 'active_support/core_ext/object/tap'
+require 'active_support/core_ext/object/with_options'
diff --git a/activesupport/lib/active_support/core_ext/object/returning.rb b/activesupport/lib/active_support/core_ext/object/returning.rb
new file mode 100644
index 0000000000..0dc2e1266a
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/object/returning.rb
@@ -0,0 +1,42 @@
+class Object
+ # Returns +value+ after yielding +value+ to the block. This simplifies the
+ # process of constructing an object, performing work on the object, and then
+ # returning the object from a method. It is a Ruby-ized realization of the K
+ # combinator, courtesy of Mikael Brockman.
+ #
+ # ==== Examples
+ #
+ # # Without returning
+ # def foo
+ # values = []
+ # values << "bar"
+ # values << "baz"
+ # return values
+ # end
+ #
+ # foo # => ['bar', 'baz']
+ #
+ # # returning with a local variable
+ # def foo
+ # returning values = [] do
+ # values << 'bar'
+ # values << 'baz'
+ # end
+ # end
+ #
+ # foo # => ['bar', 'baz']
+ #
+ # # returning with a block argument
+ # def foo
+ # returning [] do |values|
+ # values << 'bar'
+ # values << 'baz'
+ # end
+ # end
+ #
+ # foo # => ['bar', 'baz']
+ def returning(value)
+ yield(value)
+ value
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/object/tap.rb b/activesupport/lib/active_support/core_ext/object/tap.rb
new file mode 100644
index 0000000000..db7e715e2d
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/object/tap.rb
@@ -0,0 +1,16 @@
+class Object
+ # Yields x
to the block, and then returns x
.
+ # The primary purpose of this method is to "tap into" a method chain,
+ # in order to perform operations on intermediate results within the chain.
+ #
+ # (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a.
+ # tap { |x| puts "array: #{x.inspect}" }.
+ # select { |x| x%2 == 0 }.
+ # tap { |x| puts "evens: #{x.inspect}" }.
+ # map { |x| x*x }.
+ # tap { |x| puts "squares: #{x.inspect}" }
+ def tap
+ yield self
+ self
+ end unless Object.respond_to?(:tap)
+end
diff --git a/activesupport/lib/active_support/core_ext/object/with_options.rb b/activesupport/lib/active_support/core_ext/object/with_options.rb
new file mode 100644
index 0000000000..dd38b7d261
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/object/with_options.rb
@@ -0,0 +1,24 @@
+class Object
+ # An elegant way to factor duplication out of options passed to a series of
+ # method calls. Each method called in the block, with the block variable as
+ # the receiver, will have its options merged with the default +options+ hash
+ # provided. Each method called on the block variable must take an options
+ # hash as its final argument.
+ #
+ # with_options :order => 'created_at', :class_name => 'Comment' do |post|
+ # post.has_many :comments, :conditions => ['approved = ?', true], :dependent => :delete_all
+ # post.has_many :unapproved_comments, :conditions => ['approved = ?', false]
+ # post.has_many :all_comments
+ # end
+ #
+ # Can also be used with an explicit receiver:
+ #
+ # map.with_options :controller => "people" do |people|
+ # people.connect "/people", :action => "index"
+ # people.connect "/people/:id", :action => "show"
+ # end
+ #
+ def with_options(options)
+ yield ActiveSupport::OptionMerger.new(self, options)
+ end
+end
--
cgit v1.2.3
From 3694227f24d0f220c0ce7ef6c7f51598e2715d2d Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 20 May 2009 17:10:10 -0700
Subject: Break out Symbol#to_proc as a future-ruby extension
---
activesupport/lib/active_support/core_ext/symbol.rb | 15 +--------------
.../lib/active_support/core_ext/symbol/to_proc.rb | 14 ++++++++++++++
2 files changed, 15 insertions(+), 14 deletions(-)
create mode 100644 activesupport/lib/active_support/core_ext/symbol/to_proc.rb
diff --git a/activesupport/lib/active_support/core_ext/symbol.rb b/activesupport/lib/active_support/core_ext/symbol.rb
index 520369452b..c103cd9dcf 100644
--- a/activesupport/lib/active_support/core_ext/symbol.rb
+++ b/activesupport/lib/active_support/core_ext/symbol.rb
@@ -1,14 +1 @@
-class Symbol
- # Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
- #
- # # The same as people.collect { |p| p.name }
- # people.collect(&:name)
- #
- # # The same as people.select { |p| p.manager? }.collect { |p| p.salary }
- # people.select(&:manager?).collect(&:salary)
- #
- # This is a builtin method in Ruby 1.8.7 and later.
- def to_proc
- Proc.new { |*args| args.shift.__send__(self, *args) }
- end unless :to_proc.respond_to?(:to_proc)
-end
+require 'active_support/core_ext/symbol/to_proc'
diff --git a/activesupport/lib/active_support/core_ext/symbol/to_proc.rb b/activesupport/lib/active_support/core_ext/symbol/to_proc.rb
new file mode 100644
index 0000000000..520369452b
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/symbol/to_proc.rb
@@ -0,0 +1,14 @@
+class Symbol
+ # Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
+ #
+ # # The same as people.collect { |p| p.name }
+ # people.collect(&:name)
+ #
+ # # The same as people.select { |p| p.manager? }.collect { |p| p.salary }
+ # people.select(&:manager?).collect(&:salary)
+ #
+ # This is a builtin method in Ruby 1.8.7 and later.
+ def to_proc
+ Proc.new { |*args| args.shift.__send__(self, *args) }
+ end unless :to_proc.respond_to?(:to_proc)
+end
--
cgit v1.2.3
From 5f222c524ed00b2ac805e267f70a916cf8f9bc77 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 20 May 2009 17:11:41 -0700
Subject: Remove 'core' fluff. Hookable ActiveSupport.load_all!
---
activerecord/lib/active_record/base.rb | 2 +-
activesupport/lib/active_support.rb | 11 +++++++++--
activesupport/lib/active_support/all.rb | 3 +++
activesupport/lib/active_support/core.rb | 7 -------
activesupport/lib/active_support/core/all.rb | 5 -----
activesupport/lib/active_support/core/time.rb | 4 ----
activesupport/lib/active_support/core/time/autoload.rb | 5 -----
.../lib/active_support/core_ext/hash/conversions.rb | 3 +--
activesupport/lib/active_support/time.rb | 14 ++++++++++++++
activesupport/lib/active_support/time/autoload.rb | 5 +++++
activesupport/test/core_ext/duration_test.rb | 2 +-
activesupport/test/core_ext/numeric_ext_test.rb | 2 +-
activesupport/test/core_ext/object_and_class_ext_test.rb | 2 +-
activesupport/test/core_ext/time_ext_test.rb | 2 +-
activesupport/test/i18n_test.rb | 2 +-
activesupport/test/time_zone_test.rb | 2 +-
railties/lib/console_app.rb | 3 +--
railties/lib/initializer.rb | 3 +--
railties/lib/rails_generator.rb | 13 +++----------
railties/lib/tasks/misc.rake | 4 ++--
20 files changed, 46 insertions(+), 48 deletions(-)
create mode 100644 activesupport/lib/active_support/all.rb
delete mode 100644 activesupport/lib/active_support/core.rb
delete mode 100644 activesupport/lib/active_support/core/all.rb
delete mode 100644 activesupport/lib/active_support/core/time.rb
delete mode 100644 activesupport/lib/active_support/core/time/autoload.rb
create mode 100644 activesupport/lib/active_support/time.rb
create mode 100644 activesupport/lib/active_support/time/autoload.rb
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 8a65945e61..ec49d40a12 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1,6 +1,7 @@
require 'yaml'
require 'set'
require 'active_support/dependencies'
+require 'active_support/time'
require 'active_support/core_ext/class/attribute_accessors'
require 'active_support/core_ext/class/delegating_attributes'
require 'active_support/core_ext/class/inheritable_attributes'
@@ -10,7 +11,6 @@ require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/string/behavior'
require 'active_support/core_ext/symbol'
-require 'active_support/core/time'
module ActiveRecord #:nodoc:
# Generic Active Record exception class.
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index dab017770d..a1a140bc33 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -22,8 +22,15 @@
#++
module ActiveSupport
- def self.load_all!
- [Dependencies, Deprecation, Gzip, MessageVerifier, Multibyte, SecureRandom] + Core.load_all!
+ class << self
+ attr_accessor :load_all_hooks
+ def on_load_all(&hook) load_all_hooks << hook end
+ def load_all!; load_all_hooks.each { |hook| hook.call } end
+ end
+ self.load_all_hooks = []
+
+ on_load_all do
+ [Dependencies, Deprecation, Gzip, MessageVerifier, Multibyte, SecureRandom]
end
autoload :BacktraceCleaner, 'active_support/backtrace_cleaner'
diff --git a/activesupport/lib/active_support/all.rb b/activesupport/lib/active_support/all.rb
new file mode 100644
index 0000000000..f537818300
--- /dev/null
+++ b/activesupport/lib/active_support/all.rb
@@ -0,0 +1,3 @@
+require 'active_support'
+require 'active_support/time'
+require 'active_support/core_ext'
diff --git a/activesupport/lib/active_support/core.rb b/activesupport/lib/active_support/core.rb
deleted file mode 100644
index ad8db94941..0000000000
--- a/activesupport/lib/active_support/core.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module ActiveSupport
- module Core
- def self.load_all!
- [TimeWithZone]
- end
- end
-end
diff --git a/activesupport/lib/active_support/core/all.rb b/activesupport/lib/active_support/core/all.rb
deleted file mode 100644
index 55e8b4cfac..0000000000
--- a/activesupport/lib/active_support/core/all.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'active_support/core_ext'
-require 'active_support/core'
-Dir["#{File.dirname(__FILE__)}/*.rb"].sort.each do |path|
- require "active_support/core/#{File.basename(path, '.rb')}"
-end
diff --git a/activesupport/lib/active_support/core/time.rb b/activesupport/lib/active_support/core/time.rb
deleted file mode 100644
index 43e13b5e58..0000000000
--- a/activesupport/lib/active_support/core/time.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'active_support/core/time/autoload'
-require 'active_support/core_ext/time'
-require 'active_support/core_ext/date'
-require 'active_support/core_ext/date_time'
diff --git a/activesupport/lib/active_support/core/time/autoload.rb b/activesupport/lib/active_support/core/time/autoload.rb
deleted file mode 100644
index c9a7731b39..0000000000
--- a/activesupport/lib/active_support/core/time/autoload.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-module ActiveSupport
- autoload :Duration, 'active_support/duration'
- autoload :TimeWithZone, 'active_support/time_with_zone'
- autoload :TimeZone, 'active_support/values/time_zone'
-end
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index fe1f79050c..2a34874d08 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -1,8 +1,7 @@
-require 'date'
+require 'active_support/time'
require 'active_support/core_ext/object/conversions'
require 'active_support/core_ext/array/conversions'
require 'active_support/core_ext/hash/reverse_merge'
-require 'active_support/core/time'
class Hash
# This module exists to decorate files deserialized using Hash.from_xml with
diff --git a/activesupport/lib/active_support/time.rb b/activesupport/lib/active_support/time.rb
new file mode 100644
index 0000000000..d36a683601
--- /dev/null
+++ b/activesupport/lib/active_support/time.rb
@@ -0,0 +1,14 @@
+require 'active_support'
+require 'active_support/core_ext/time'
+require 'active_support/core_ext/date'
+require 'active_support/core_ext/date_time'
+
+module ActiveSupport
+ autoload :Duration, 'active_support/duration'
+ autoload :TimeWithZone, 'active_support/time_with_zone'
+ autoload :TimeZone, 'active_support/values/time_zone'
+
+ on_load_all do
+ [Duration, TimeWithZone, TimeZone]
+ end
+end
diff --git a/activesupport/lib/active_support/time/autoload.rb b/activesupport/lib/active_support/time/autoload.rb
new file mode 100644
index 0000000000..c9a7731b39
--- /dev/null
+++ b/activesupport/lib/active_support/time/autoload.rb
@@ -0,0 +1,5 @@
+module ActiveSupport
+ autoload :Duration, 'active_support/duration'
+ autoload :TimeWithZone, 'active_support/time_with_zone'
+ autoload :TimeZone, 'active_support/values/time_zone'
+end
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index 30d4152729..6f16621ae5 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -1,5 +1,5 @@
require 'abstract_unit'
-require 'active_support/core/time'
+require 'active_support/time'
class DurationTest < ActiveSupport::TestCase
def test_inspect
diff --git a/activesupport/test/core_ext/numeric_ext_test.rb b/activesupport/test/core_ext/numeric_ext_test.rb
index 74b086fa9c..992ec60302 100644
--- a/activesupport/test/core_ext/numeric_ext_test.rb
+++ b/activesupport/test/core_ext/numeric_ext_test.rb
@@ -1,7 +1,7 @@
require 'abstract_unit'
+require 'active_support/time'
require 'active_support/core_ext/numeric'
require 'active_support/core_ext/integer'
-require 'active_support/core/time'
class NumericExtTimeAndDateTimeTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/test/core_ext/object_and_class_ext_test.rb b/activesupport/test/core_ext/object_and_class_ext_test.rb
index 8869b053e6..f0121b862d 100644
--- a/activesupport/test/core_ext/object_and_class_ext_test.rb
+++ b/activesupport/test/core_ext/object_and_class_ext_test.rb
@@ -1,7 +1,7 @@
require 'abstract_unit'
+require 'active_support/time'
require 'active_support/core_ext/object'
require 'active_support/core_ext/class/removal'
-require 'active_support/core/time'
class ClassA; end
class ClassB < ClassA; end
diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb
index e265423f06..1c2d0fbce4 100644
--- a/activesupport/test/core_ext/time_ext_test.rb
+++ b/activesupport/test/core_ext/time_ext_test.rb
@@ -1,5 +1,5 @@
require 'abstract_unit'
-require 'active_support/core/time'
+require 'active_support/time'
class TimeExtCalculationsTest < Test::Unit::TestCase
def test_seconds_since_midnight
diff --git a/activesupport/test/i18n_test.rb b/activesupport/test/i18n_test.rb
index 2a08abfb3e..9868f1e87d 100644
--- a/activesupport/test/i18n_test.rb
+++ b/activesupport/test/i18n_test.rb
@@ -1,5 +1,5 @@
require 'abstract_unit'
-require 'active_support/core/time'
+require 'active_support/time'
require 'active_support/core_ext/array/conversions'
class I18nTest < Test::Unit::TestCase
diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb
index 87d6ccc30d..99c4310854 100644
--- a/activesupport/test/time_zone_test.rb
+++ b/activesupport/test/time_zone_test.rb
@@ -1,5 +1,5 @@
require 'abstract_unit'
-require 'active_support/core/time'
+require 'active_support/time'
class TimeZoneTest < Test::Unit::TestCase
def test_utc_to_local
diff --git a/railties/lib/console_app.rb b/railties/lib/console_app.rb
index 42bf50e01e..75e6f11ea3 100644
--- a/railties/lib/console_app.rb
+++ b/railties/lib/console_app.rb
@@ -1,5 +1,4 @@
-require 'active_support'
-require 'active_support/core/all'
+require 'active_support/all'
require 'active_support/test_case'
require 'action_controller'
diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index 4c6de48a65..3c0d5940ea 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -263,9 +263,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/all'
configuration.frameworks.each { |framework| require(framework.to_s) }
- require 'active_support/core/all'
rescue LoadError => e
# Re-raise as RuntimeError because Mongrel would swallow LoadError.
raise e.to_s
diff --git a/railties/lib/rails_generator.rb b/railties/lib/rails_generator.rb
index 201a9e0f91..85400932dd 100644
--- a/railties/lib/rails_generator.rb
+++ b/railties/lib/rails_generator.rb
@@ -21,16 +21,9 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
-begin
- require 'active_support'
-rescue LoadError
- activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
- if File.directory?(activesupport_path)
- $:.unshift activesupport_path
- require 'active_support'
- end
-end
-require 'active_support/core/all'
+activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
+$:.unshift(activesupport_path) if File.directory?(activesupport_path)
+require 'active_support/all'
$:.unshift(File.dirname(__FILE__))
require 'rails_generator/base'
diff --git a/railties/lib/tasks/misc.rake b/railties/lib/tasks/misc.rake
index a2c338aa5b..fb2fc31dc1 100644
--- a/railties/lib/tasks/misc.rake
+++ b/railties/lib/tasks/misc.rake
@@ -31,7 +31,7 @@ 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'
+ require 'active_support/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
@@ -41,7 +41,7 @@ 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'
+ require 'active_support/time'
if offset
offset = if offset.to_s.match(/(\+|-)?(\d+):(\d+)/)
sign = $1 == '-' ? -1 : 1
--
cgit v1.2.3
From 886aa2f0e1a1a95a5b518d918fefaa526755ad34 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 20 May 2009 17:58:35 -0700
Subject: Extract autoloads
---
activesupport/lib/active_support.rb | 25 +------------------------
activesupport/lib/active_support/autoload.rb | 25 +++++++++++++++++++++++++
2 files changed, 26 insertions(+), 24 deletions(-)
create mode 100644 activesupport/lib/active_support/autoload.rb
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index a1a140bc33..a20635ba62 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -32,32 +32,9 @@ module ActiveSupport
on_load_all do
[Dependencies, Deprecation, Gzip, MessageVerifier, Multibyte, SecureRandom]
end
-
- autoload :BacktraceCleaner, 'active_support/backtrace_cleaner'
- autoload :Base64, 'active_support/base64'
- autoload :BasicObject, 'active_support/basic_object'
- autoload :BufferedLogger, 'active_support/buffered_logger'
- autoload :Cache, 'active_support/cache'
- autoload :Callbacks, 'active_support/callbacks'
- autoload :NewCallbacks, 'active_support/new_callbacks'
- autoload :ConcurrentHash, 'active_support/concurrent_hash'
- autoload :DependencyModule, 'active_support/dependency_module'
- autoload :Deprecation, 'active_support/deprecation'
- autoload :Gzip, 'active_support/gzip'
- autoload :Inflector, 'active_support/inflector'
- autoload :Memoizable, 'active_support/memoizable'
- autoload :MessageEncryptor, 'active_support/message_encryptor'
- autoload :MessageVerifier, 'active_support/message_verifier'
- autoload :Multibyte, 'active_support/multibyte'
- autoload :OptionMerger, 'active_support/option_merger'
- autoload :OrderedHash, 'active_support/ordered_hash'
- autoload :OrderedOptions, 'active_support/ordered_options'
- autoload :Rescuable, 'active_support/rescuable'
- autoload :SecureRandom, 'active_support/secure_random'
- autoload :StringInquirer, 'active_support/string_inquirer'
- autoload :XmlMini, 'active_support/xml_mini'
end
+require 'active_support/autoload'
require 'active_support/vendor'
I18n.load_path << "#{File.dirname(__FILE__)}/active_support/locale/en.yml"
diff --git a/activesupport/lib/active_support/autoload.rb b/activesupport/lib/active_support/autoload.rb
new file mode 100644
index 0000000000..ed229d1c5f
--- /dev/null
+++ b/activesupport/lib/active_support/autoload.rb
@@ -0,0 +1,25 @@
+module ActiveSupport
+ autoload :BacktraceCleaner, 'active_support/backtrace_cleaner'
+ autoload :Base64, 'active_support/base64'
+ autoload :BasicObject, 'active_support/basic_object'
+ autoload :BufferedLogger, 'active_support/buffered_logger'
+ autoload :Cache, 'active_support/cache'
+ autoload :Callbacks, 'active_support/callbacks'
+ autoload :NewCallbacks, 'active_support/new_callbacks'
+ autoload :ConcurrentHash, 'active_support/concurrent_hash'
+ autoload :DependencyModule, 'active_support/dependency_module'
+ autoload :Deprecation, 'active_support/deprecation'
+ autoload :Gzip, 'active_support/gzip'
+ autoload :Inflector, 'active_support/inflector'
+ autoload :Memoizable, 'active_support/memoizable'
+ autoload :MessageEncryptor, 'active_support/message_encryptor'
+ autoload :MessageVerifier, 'active_support/message_verifier'
+ autoload :Multibyte, 'active_support/multibyte'
+ autoload :OptionMerger, 'active_support/option_merger'
+ autoload :OrderedHash, 'active_support/ordered_hash'
+ autoload :OrderedOptions, 'active_support/ordered_options'
+ autoload :Rescuable, 'active_support/rescuable'
+ autoload :SecureRandom, 'active_support/secure_random'
+ autoload :StringInquirer, 'active_support/string_inquirer'
+ autoload :XmlMini, 'active_support/xml_mini'
+end
--
cgit v1.2.3
From 428829fc38d06be63082e261d59f478a4b7dd354 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 20 May 2009 17:59:34 -0700
Subject: Single-require forward compatibility with new Ruby features like
Object#tap, Enumerable#group_by, and Process.daemon. Code with the latest but
run anywhere.
---
activesupport/lib/active_support/ruby/shim.rb | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 activesupport/lib/active_support/ruby/shim.rb
diff --git a/activesupport/lib/active_support/ruby/shim.rb b/activesupport/lib/active_support/ruby/shim.rb
new file mode 100644
index 0000000000..37c57c485a
--- /dev/null
+++ b/activesupport/lib/active_support/ruby/shim.rb
@@ -0,0 +1,24 @@
+# Backported Ruby builtins so you can code with the latest & greatest
+# but still run on any Ruby 1.8.x.
+#
+# Date next_year, next_month
+# DateTime to_date, to_datetime, xmlschema
+# Enumerable group_by, each_with_object, none?
+# Integer even?, odd?
+# Object tap
+# Process Process.daemon
+# REXML security fix
+# String ord
+# Symbol to_proc
+# Time to_date, to_time, to_datetime
+require 'active_support'
+require 'active_support/core_ext/date/calculations'
+require 'active_support/core_ext/date_time/conversions'
+require 'active_support/core_ext/enumerable'
+require 'active_support/core_ext/integer/even_odd'
+require 'active_support/core_ext/object/tap'
+require 'active_support/core_ext/process/daemon'
+require 'active_support/core_ext/string/conversions'
+require 'active_support/core_ext/rexml'
+require 'active_support/core_ext/symbol/to_proc'
+require 'active_support/core_ext/time/conversions'
--
cgit v1.2.3
From e9a75451236119e1db3e5d7cc7703637d048c7f8 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 20 May 2009 18:11:06 -0700
Subject: Avoid uninitialized instance variable warning
---
activesupport/lib/active_support/json.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/activesupport/lib/active_support/json.rb b/activesupport/lib/active_support/json.rb
index 1e8ded12da..6d845182fb 100644
--- a/activesupport/lib/active_support/json.rb
+++ b/activesupport/lib/active_support/json.rb
@@ -43,10 +43,10 @@ module ActiveSupport
delegate :decode, :to => :backend
def backend
- @backend || begin
+ unless defined? @backend
self.backend = defined?(::JSON) ? "JSONGem" : "Yaml"
- @backend
end
+ @backend
end
def backend=(name)
--
cgit v1.2.3
From 0f1b283e03633410729aa006f6abf070c713095d Mon Sep 17 00:00:00 2001
From: Chad Woolley
Date: Thu, 21 May 2009 00:41:19 -0700
Subject: Fix eager association test related to different ordering on sqlite
[#2686 state:committed]
Signed-off-by: Jeremy Kemper
---
activerecord/test/cases/associations/eager_test.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index 65049c4f87..4cf49be668 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -590,7 +590,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
end
def test_limited_eager_with_numeric_in_association
- assert_equal people(:david, :susan), Person.find(:all, :include => [:readers, :primary_contact, :number1_fan], :conditions => "number1_fans_people.first_name like 'M%'", :order => 'readers.id', :limit => 2, :offset => 0)
+ assert_equal people(:david, :susan), Person.find(:all, :include => [:readers, :primary_contact, :number1_fan], :conditions => "number1_fans_people.first_name like 'M%'", :order => 'people.id', :limit => 2, :offset => 0)
end
def test_preload_with_interpolation
--
cgit v1.2.3
From 886eeed52e17184747b43f57282d8635614f1be3 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 21 May 2009 10:03:32 -0700
Subject: Clean up tools/profile_requires a bit
---
tools/profile_requires | 60 +++++++++++++++++++++++---------------------------
1 file changed, 27 insertions(+), 33 deletions(-)
diff --git a/tools/profile_requires b/tools/profile_requires
index 0fd11c7d41..927467bc4e 100755
--- a/tools/profile_requires
+++ b/tools/profile_requires
@@ -4,58 +4,52 @@
# tools/profile_requires activeresource/examples/simple.rb
abort 'Use REE so you can profile memory and object allocation' unless GC.respond_to?(:enable_stats)
+ENV['NO_RELOAD'] ||= '1'
+ENV['RAILS_ENV'] ||= 'development'
+
GC.enable_stats
require 'rubygems'
Gem.source_index
require 'benchmark'
-module TrackHeapGrowth
+module RequireProfiler
+ def require(file, *args) RequireProfiler.profile(file) { super } end
+ def load(file, *args) RequireProfiler.profile(file) { super } end
+
+ @depth, @stats = 0, []
class << self
- attr_accessor :indent
+ attr_accessor :depth
attr_accessor :stats
- end
- self.indent = 0
- self.stats = []
-
- def track_growth(file)
- TrackHeapGrowth.stats << [file, TrackHeapGrowth.indent]
- TrackHeapGrowth.indent += 1
- heap_before, objects_before = GC.allocated_size, ObjectSpace.allocated_objects
- result = nil
- elapsed = Benchmark.realtime { result = yield }
- heap_after, objects_after = GC.allocated_size, ObjectSpace.allocated_objects
- TrackHeapGrowth.indent -= 1
- TrackHeapGrowth.stats.pop if TrackHeapGrowth.stats.last.first == file
- TrackHeapGrowth.stats << [file, TrackHeapGrowth.indent, elapsed, heap_after - heap_before, objects_after - objects_before] if result
- result
- end
- def require(file, *args)
- track_growth(file) { super }
- end
-
- def load(file, *args)
- track_growth(file) { super }
+ def profile(file)
+ stats << [file, depth]
+ self.depth += 1
+ heap_before, objects_before = GC.allocated_size, ObjectSpace.allocated_objects
+ result = nil
+ elapsed = Benchmark.realtime { result = yield }
+ heap_after, objects_after = GC.allocated_size, ObjectSpace.allocated_objects
+ self.depth -= 1
+ stats.pop if stats.last.first == file
+ stats << [file, depth, elapsed, heap_after - heap_before, objects_after - objects_before] if result
+ result
+ end
end
end
-Object.instance_eval { include TrackHeapGrowth }
-
GC.start
before = GC.allocated_size
before_rss = `ps -o rss= -p #{Process.pid}`.to_i
before_live_objects = ObjectSpace.live_objects
path = ARGV.shift
-
if mode = ARGV.shift
require 'ruby-prof'
RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
RubyProf.start
+else
+ Object.instance_eval { include RequireProfiler }
end
-ENV['NO_RELOAD'] ||= '1'
-ENV['RAILS_ENV'] ||= 'development'
elapsed = Benchmark.realtime { require path }
results = RubyProf.stop if mode
@@ -66,16 +60,16 @@ after = GC.allocated_size
usage = (after - before) / 1024.0
if mode
- File.open("profile_startup.#{mode}.tree", 'w') do |out|
+ File.open("#{File.basename(path, '.rb')}.#{mode}.callgrind", 'w') do |out|
RubyProf::CallTreePrinter.new(results).print(out)
end
end
-TrackHeapGrowth.stats.each do |file, indent, sec, bytes, objects|
+RequireProfiler.stats.each do |file, depth, sec, bytes, objects|
if sec
- puts "%10.2f KB %10d obj %8.1f ms %s%s" % [bytes / 1024.0, objects, sec * 1000, ' ' * indent, file]
+ puts "%10.2f KB %10d obj %8.1f ms %s%s" % [bytes / 1024.0, objects, sec * 1000, ' ' * depth, file]
else
- puts "#{' ' * (42 + indent)}#{file}"
+ puts "#{' ' * (42 + depth)}#{file}"
end
end
puts "%10.2f KB %10d obj %8.1f ms %d KB RSS" % [usage, after_live_objects - before_live_objects, elapsed * 1000, after_rss - before_rss]
--
cgit v1.2.3
From 59b32f2883b58a1e7bf2c246801a605b673e3fb6 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Thu, 21 May 2009 11:50:34 +0200
Subject: RequestForgeryProtection now works with the new base
---
actionpack/Rakefile | 2 +-
.../base/request_forgery_protection.rb | 24 +++++++++++++++++-----
actionpack/lib/action_controller/new_base.rb | 5 +++--
actionpack/lib/action_controller/new_base/base.rb | 9 ++++----
.../action_controller/new_base/compatibility.rb | 6 ++++--
actionpack/lib/action_dispatch.rb | 1 +
6 files changed, 33 insertions(+), 14 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 3a6a54768e..84b42b4eb3 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -63,7 +63,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
t.test_files = %w(
addresses_render base benchmark caching capture content_type dispatcher
flash mime_responds record_identifier redirect render rescue url_rewriter
- webservice verification
+ webservice verification request_forgery_protection
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/lib/action_controller/base/request_forgery_protection.rb b/actionpack/lib/action_controller/base/request_forgery_protection.rb
index 3067122ceb..0a0e20e1f1 100644
--- a/actionpack/lib/action_controller/base/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/base/request_forgery_protection.rb
@@ -3,12 +3,26 @@ module ActionController #:nodoc:
end
module RequestForgeryProtection
- def self.included(base)
- base.class_eval do
- helper_method :form_authenticity_token
- helper_method :protect_against_forgery?
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ depends_on AbstractController::Helpers, Session
+ end
+
+ included do
+ if defined?(ActionController::Http)
+ # Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+
+ # sets it to :authenticity_token by default.
+ cattr_accessor :request_forgery_protection_token
+
+ # Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode.
+ class_inheritable_accessor :allow_forgery_protection
+ self.allow_forgery_protection = true
end
- base.extend(ClassMethods)
+
+ helper_method :form_authenticity_token
+ helper_method :protect_against_forgery?
end
# Protecting controller actions from CSRF attacks by ensuring that all forms are coming from the current web application, not a
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 8bc15d2450..93c54174b7 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -25,8 +25,9 @@ module ActionController
autoload :UrlRewriter, 'action_controller/routing/generation/url_rewriter'
autoload :UrlWriter, 'action_controller/routing/generation/url_rewriter'
- autoload :Verification, 'action_controller/base/verification'
- autoload :Flash, 'action_controller/base/chained/flash'
+ autoload :Verification, 'action_controller/base/verification'
+ autoload :Flash, 'action_controller/base/chained/flash'
+ autoload :RequestForgeryProtection, 'action_controller/base/request_forgery_protection'
require 'action_controller/routing'
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index a419a80b6a..3d8f785280 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -14,10 +14,6 @@ module ActionController
include ActionController::Layouts
include ActionController::ConditionalGet
- include ActionController::Session
- include ActionController::Flash
- include ActionController::Verification
-
# Legacy modules
include SessionManagement
include ActionDispatch::StatusCodes
@@ -27,6 +23,11 @@ module ActionController
# Rails 2.x compatibility
include ActionController::Rails2Compatibility
+ include ActionController::Session
+ include ActionController::Flash
+ include ActionController::Verification
+ include ActionController::RequestForgeryProtection
+
# TODO: Extract into its own module
# This should be moved together with other normalizing behavior
module ImplicitRender
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index 9b85b39052..522a9fe23b 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -1,7 +1,10 @@
module ActionController
module Rails2Compatibility
extend ActiveSupport::DependencyModule
-
+
+ class ::ActionController::ActionControllerError < StandardError #:nodoc:
+ end
+
# Temporary hax
included do
::ActionController::UnknownAction = ::AbstractController::ActionNotFound
@@ -65,7 +68,6 @@ module ActionController
end
module ClassMethods
- def protect_from_forgery() end
def consider_all_requests_local() end
def rescue_action(env)
raise env["action_dispatch.rescue.exception"]
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index ee162765cb..884828a01a 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -46,6 +46,7 @@ module ActionDispatch
autoload :ShowExceptions, 'action_dispatch/middleware/show_exceptions'
autoload :MiddlewareStack, 'action_dispatch/middleware/stack'
+ autoload :HTML, 'action_controller/vendor/html-scanner'
autoload :Assertions, 'action_dispatch/testing/assertions'
autoload :TestRequest, 'action_dispatch/testing/test_request'
autoload :TestResponse, 'action_dispatch/testing/test_response'
--
cgit v1.2.3
From 386ff66e5ed4fbe1e060610d4226a4eb22dca766 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Thu, 21 May 2009 21:48:26 +0200
Subject: Add Streaming to new base
---
actionpack/Rakefile | 2 +-
actionpack/lib/action_controller/base/streaming.rb | 1 +
actionpack/lib/action_controller/new_base.rb | 2 +-
actionpack/lib/action_controller/new_base/base.rb | 1 +
.../lib/action_controller/new_base/testing.rb | 9 ++++++--
.../lib/action_controller/testing/process2.rb | 1 +
actionpack/test/controller/send_file_test.rb | 24 ++++++++++++----------
7 files changed, 25 insertions(+), 15 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 84b42b4eb3..5968317c60 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -63,7 +63,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
t.test_files = %w(
addresses_render base benchmark caching capture content_type dispatcher
flash mime_responds record_identifier redirect render rescue url_rewriter
- webservice verification request_forgery_protection
+ webservice verification request_forgery_protection send_file
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/lib/action_controller/base/streaming.rb b/actionpack/lib/action_controller/base/streaming.rb
index 9f80f48c3d..b69b13eea8 100644
--- a/actionpack/lib/action_controller/base/streaming.rb
+++ b/actionpack/lib/action_controller/base/streaming.rb
@@ -88,6 +88,7 @@ module ActionController #:nodoc:
head options[:status], X_SENDFILE_HEADER => path
else
if options[:stream]
+ # TODO : Make render :text => proc {} work with the new base
render :status => options[:status], :text => Proc.new { |response, output|
logger.info "Streaming file #{path}" unless logger.nil?
len = options[:buffer_size] || 4096
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 93c54174b7..58c7382661 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -28,7 +28,7 @@ module ActionController
autoload :Verification, 'action_controller/base/verification'
autoload :Flash, 'action_controller/base/chained/flash'
autoload :RequestForgeryProtection, 'action_controller/base/request_forgery_protection'
-
+ autoload :Streaming, 'action_controller/base/streaming'
require 'action_controller/routing'
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 3d8f785280..142699326e 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -27,6 +27,7 @@ module ActionController
include ActionController::Flash
include ActionController::Verification
include ActionController::RequestForgeryProtection
+ include ActionController::Streaming
# TODO: Extract into its own module
# This should be moved together with other normalizing behavior
diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb
index bc3bc70404..6a92c292bd 100644
--- a/actionpack/lib/action_controller/new_base/testing.rb
+++ b/actionpack/lib/action_controller/new_base/testing.rb
@@ -1,6 +1,6 @@
module ActionController
module Testing
-
+
# OMG MEGA HAX
def process_with_new_base_test(request, response)
@_request = request
@@ -20,6 +20,11 @@ module ActionController
@assigns[name] = value
end
end
-
+
+ # TODO : Rewrite tests using controller.headers= to use Rack env
+ def headers=(new_headers)
+ @_response ||= ActionDispatch::Response.new
+ @_response.headers.replace(new_headers)
+ end
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb
index 2dafcaa5a9..6a95e638cd 100644
--- a/actionpack/lib/action_controller/testing/process2.rb
+++ b/actionpack/lib/action_controller/testing/process2.rb
@@ -54,6 +54,7 @@ module ActionController
@controller.params.merge!(parameters)
# Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
@controller.process_with_new_base_test(@request, @response)
+ @response
end
def build_request_uri(action, parameters)
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index 6007ebef7a..3a99774ae0 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -40,17 +40,19 @@ class SendFileTest < ActionController::TestCase
assert_equal file_data, response.body
end
- def test_file_stream
- response = nil
- assert_nothing_raised { response = process('file') }
- assert_not_nil response
- assert_kind_of Array, response.body_parts
-
- require 'stringio'
- output = StringIO.new
- output.binmode
- assert_nothing_raised { response.body_parts.each { |part| output << part.to_s } }
- assert_equal file_data, output.string
+ for_tag(:old_base) do
+ def test_file_stream
+ response = nil
+ assert_nothing_raised { response = process('file') }
+ assert_not_nil response
+ assert_kind_of Array, response.body_parts
+
+ require 'stringio'
+ output = StringIO.new
+ output.binmode
+ assert_nothing_raised { response.body_parts.each { |part| output << part.to_s } }
+ assert_equal file_data, output.string
+ end
end
def test_file_url_based_filename
--
cgit v1.2.3
From e693f45e155a81b6c337b8766870b56716a05105 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Thu, 21 May 2009 14:22:07 -0700
Subject: Remove some response content type concepts from ActionView
---
.../lib/action_controller/base/mime_responds.rb | 7 +++----
actionpack/lib/action_controller/new_base/base.rb | 20 ++++++++++++++++----
.../lib/action_controller/new_base/renderer.rb | 20 +++++++++++---------
actionpack/lib/action_controller/testing/process2.rb | 1 +
actionpack/lib/action_dispatch/http/mime_type.rb | 2 +-
actionpack/lib/action_dispatch/http/request.rb | 2 +-
actionpack/lib/action_view/base.rb | 7 +++++--
actionpack/lib/action_view/template/handler.rb | 5 +++++
.../lib/action_view/template/handlers/builder.rb | 2 ++
actionpack/lib/action_view/template/handlers/erb.rb | 2 ++
actionpack/lib/action_view/template/handlers/rjs.rb | 6 ++++++
actionpack/lib/action_view/template/template.rb | 15 ++++++++-------
actionpack/test/controller/content_type_test.rb | 3 ++-
13 files changed, 63 insertions(+), 29 deletions(-)
diff --git a/actionpack/lib/action_controller/base/mime_responds.rb b/actionpack/lib/action_controller/base/mime_responds.rb
index e560376e0d..3c17dda1a1 100644
--- a/actionpack/lib/action_controller/base/mime_responds.rb
+++ b/actionpack/lib/action_controller/base/mime_responds.rb
@@ -122,12 +122,11 @@ module ActionController #:nodoc:
# TODO: Remove this when new base is merged in
if defined?(Http)
@controller.formats = [mime_type.to_sym]
- @controller.template.formats = [mime_type.to_sym]
- else
- @controller.template.formats = [mime_type.to_sym]
- @response.content_type = mime_type.to_s
end
+ @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
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 142699326e..b8674d5099 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -70,7 +70,7 @@ module ActionController
end
end
- def render_to_body(action = nil, options = {})
+ def _normalize_options(action = nil, options = {})
if action.is_a?(Hash)
options, action = action, nil
elsif action.is_a?(String) || action.is_a?(Symbol)
@@ -87,9 +87,21 @@ module ActionController
if options.key?(:action) && options[:action].to_s.index("/")
options[:template] = options.delete(:action)
end
-
- # options = {:template => options.to_s} if options.is_a?(String) || options.is_a?(Symbol)
- super(options) || " "
+ options
+ end
+
+ def render(action = nil, options = {})
+ options = _normalize_options(action, options)
+ super(options)
+ end
+
+ def render_to_string(action = nil, options = {})
+ options = _normalize_options(action, options)
+ super(options)
+ end
+
+ def render_to_body(options)
+ super || [" "]
end
# Redirects the browser to the target specified in +options+. This parameter can take one of three forms:
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 81685ca9d6..840168397d 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -14,6 +14,16 @@ module ActionController
super
end
+ def render(options)
+ super
+ options[:_template] ||= _action_view._partial
+ response.content_type ||= begin
+ mime = options[:_template].mime_type
+ formats.include?(mime && mime.to_sym) || formats.include?(:all) ? mime : Mime::Type.lookup_by_extension(formats.first)
+ end
+ response_body
+ end
+
def render_to_body(options)
_process_options(options)
@@ -35,15 +45,7 @@ module ActionController
options[:_prefix] = _prefix
end
- ret = super(options)
-
- options[:_template] ||= _action_view._partial
- response.content_type ||= begin
- mime = options[:_template].mime_type
- mime &&= mime.to_sym
- formats.include?(mime) ? mime : formats.first
- end
- ret
+ super
end
private
diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb
index 6a95e638cd..bee82c280e 100644
--- a/actionpack/lib/action_controller/testing/process2.rb
+++ b/actionpack/lib/action_controller/testing/process2.rb
@@ -40,6 +40,7 @@ module ActionController
@request.recycle!
@response.recycle!
@controller.response_body = nil
+ @controller.formats = nil
@html_document = nil
@request.env['REQUEST_METHOD'] = http_method
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index dfcf3a558f..25156a4c75 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -3,7 +3,7 @@ require 'active_support/core_ext/class/attribute_accessors'
module Mime
SET = []
- EXTENSION_LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) unless k.blank? }
+ EXTENSION_LOOKUP = {}
LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) unless k.blank? }
def self.[](type)
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 13ff049a97..4831b89bde 100755
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -175,7 +175,7 @@ module ActionDispatch
if ActionController::Base.use_accept_header
Array(Mime[parameters[:format]] || accepts)
else
- [format]
+ [format, Mime[:all]]
end
end
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 56f0b5ef4f..6b72d406af 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -288,8 +288,11 @@ module ActionView #:nodoc:
end
def _set_controller_content_type(content_type) #:nodoc:
- if controller.respond_to?(:response)
- controller.response.content_type ||= content_type
+ # TODO: Remove this method when new base is switched
+ unless defined?(ActionController::Http)
+ if controller.respond_to?(:response)
+ controller.response.content_type ||= content_type
+ end
end
end
end
diff --git a/actionpack/lib/action_view/template/handler.rb b/actionpack/lib/action_view/template/handler.rb
index 672da0ed2b..3481a4a4e7 100644
--- a/actionpack/lib/action_view/template/handler.rb
+++ b/actionpack/lib/action_view/template/handler.rb
@@ -1,3 +1,5 @@
+require "active_support/core_ext/class/inheritable_attributes"
+
# Legacy TemplateHandler stub
module ActionView
module TemplateHandlers #:nodoc:
@@ -19,6 +21,9 @@ module ActionView
end
class TemplateHandler
+ extlib_inheritable_accessor :default_format
+ self.default_format = Mime::HTML
+
def self.call(template)
"#{name}.new(self).render(template, local_assigns)"
end
diff --git a/actionpack/lib/action_view/template/handlers/builder.rb b/actionpack/lib/action_view/template/handlers/builder.rb
index 788dc93326..f412228752 100644
--- a/actionpack/lib/action_view/template/handlers/builder.rb
+++ b/actionpack/lib/action_view/template/handlers/builder.rb
@@ -5,6 +5,8 @@ module ActionView
class Builder < TemplateHandler
include Compilable
+ self.default_format = Mime::XML
+
def compile(template)
"_set_controller_content_type(Mime::XML);" +
"xml = ::Builder::XmlMarkup.new(:indent => 2);" +
diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb
index fdcb108ffc..95f11d6490 100644
--- a/actionpack/lib/action_view/template/handlers/erb.rb
+++ b/actionpack/lib/action_view/template/handlers/erb.rb
@@ -13,6 +13,8 @@ module ActionView
cattr_accessor :erb_trim_mode
self.erb_trim_mode = '-'
+ self.default_format = Mime::HTML
+
def compile(template)
src = ::ERB.new("<% __in_erb_template=true %>#{template.source}", nil, erb_trim_mode, '@output_buffer').src
diff --git a/actionpack/lib/action_view/template/handlers/rjs.rb b/actionpack/lib/action_view/template/handlers/rjs.rb
index 802a79b3fc..a36744c2b7 100644
--- a/actionpack/lib/action_view/template/handlers/rjs.rb
+++ b/actionpack/lib/action_view/template/handlers/rjs.rb
@@ -3,11 +3,17 @@ module ActionView
class RJS < TemplateHandler
include Compilable
+ self.default_format = Mime::JS
+
def compile(template)
"@formats = [:html];" +
"controller.response.content_type ||= Mime::JS;" +
"update_page do |page|;#{template.source}\nend"
end
+
+ def default_format
+ Mime::JS
+ end
end
end
end
diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb
index dcc5006103..0eedc596d2 100644
--- a/actionpack/lib/action_view/template/template.rb
+++ b/actionpack/lib/action_view/template/template.rb
@@ -7,13 +7,19 @@ require "action_view/template/path"
module ActionView
class Template
extend TemplateHandlers
- attr_reader :source, :identifier, :handler
+ attr_reader :source, :identifier, :handler, :mime_type
def initialize(source, identifier, handler, details)
@source = source
@identifier = identifier
@handler = handler
@details = details
+
+ format = details[:format] || begin
+ # TODO: Clean this up
+ handler.respond_to?(:default_format) ? handler.default_format.to_sym.to_s : "html"
+ end
+ @mime_type = Mime::Type.lookup_by_extension(format.to_s)
end
def render(view, locals, &blk)
@@ -35,12 +41,7 @@ module ActionView
def partial?
@details[:partial]
end
-
- # TODO: Move out of Template
- def mime_type
- Mime::Type.lookup_by_extension(@details[:format].to_s) if @details[:format]
- end
-
+
private
def compile(locals, view)
diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb
index 64b8b10d5b..d622ac1e85 100644
--- a/actionpack/test/controller/content_type_test.rb
+++ b/actionpack/test/controller/content_type_test.rb
@@ -148,12 +148,13 @@ class AcceptBasedContentTypeTest < ActionController::TestCase
def setup
super
+ @_old_accept_header = ActionController::Base.use_accept_header
ActionController::Base.use_accept_header = true
end
def teardown
super
- ActionController::Base.use_accept_header = false
+ ActionController::Base.use_accept_header = @_old_accept_header
end
--
cgit v1.2.3
From 2daac47d585c5b8f37e4749d6a9a3aea4b989bd0 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Thu, 21 May 2009 14:34:42 -0700
Subject: Added the ability to register methods to handle specific render
option keys and render :json
---
actionpack/Rakefile | 5 +--
actionpack/lib/action_controller/new_base.rb | 2 ++
actionpack/lib/action_controller/new_base/base.rb | 2 ++
.../action_controller/new_base/render_options.rb | 39 ++++++++++++++++++++++
4 files changed, 46 insertions(+), 2 deletions(-)
create mode 100644 actionpack/lib/action_controller/new_base/render_options.rb
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 5968317c60..2041f5a844 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -62,8 +62,9 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
# Dir.glob( "test/{dispatch,template}/**/*_test.rb" ).sort +
t.test_files = %w(
addresses_render base benchmark caching capture content_type dispatcher
- flash mime_responds record_identifier redirect render rescue url_rewriter
- webservice verification request_forgery_protection send_file
+ flash mime_responds record_identifier redirect
+ render render_json
+ send_file request_forgery_protection rescue url_rewriter verification webservice
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 58c7382661..95808decd5 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -7,6 +7,8 @@ module ActionController
autoload :Rails2Compatibility, "action_controller/new_base/compatibility"
autoload :Redirector, "action_controller/new_base/redirector"
autoload :Renderer, "action_controller/new_base/renderer"
+ autoload :RenderOptions, "action_controller/new_base/render_options"
+ autoload :Renderers, "action_controller/new_base/render_options"
autoload :Rescue, "action_controller/new_base/rescuable"
autoload :Testing, "action_controller/new_base/testing"
autoload :UrlFor, "action_controller/new_base/url_for"
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index b8674d5099..6e1f92c45d 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -11,6 +11,8 @@ module ActionController
include ActionController::UrlFor
include ActionController::Redirector
include ActionController::Renderer
+ include ActionController::RenderOptions
+ include ActionController::Renderers::Json
include ActionController::Layouts
include ActionController::ConditionalGet
diff --git a/actionpack/lib/action_controller/new_base/render_options.rb b/actionpack/lib/action_controller/new_base/render_options.rb
new file mode 100644
index 0000000000..e7ed2bd278
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/render_options.rb
@@ -0,0 +1,39 @@
+module ActionController
+ module RenderOptions
+ extend ActiveSupport::DependencyModule
+
+ included do
+ extlib_inheritable_accessor :_renderers
+ self._renderers = []
+ end
+
+ def render_to_body(options)
+ _renderers.each do |renderer|
+ if options.key?(renderer)
+ _process_options(options)
+ return send("_render_#{renderer}", options[renderer], options)
+ end
+ end
+ super
+ end
+ end
+
+ module Renderers
+ module Json
+ extend ActiveSupport::DependencyModule
+
+ depends_on RenderOptions
+
+ included do
+ _renderers << :json
+ end
+
+ def _render_json(json, options)
+ json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str)
+ json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
+ response.content_type ||= Mime::JSON
+ self.response_body = json
+ end
+ end
+ end
+end
\ No newline at end of file
--
cgit v1.2.3
From ad1c90de3a766d12a0906c7cf3772f3bc0e1b445 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Thu, 21 May 2009 14:51:29 -0700
Subject: Added the :xml render option
---
actionpack/Rakefile | 2 +-
actionpack/lib/action_controller/new_base/base.rb | 2 +-
.../action_controller/new_base/render_options.rb | 30 +++++++++++++++++-----
.../lib/action_controller/new_base/renderer.rb | 3 ++-
4 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 2041f5a844..d192a2e3bf 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -63,7 +63,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
t.test_files = %w(
addresses_render base benchmark caching capture content_type dispatcher
flash mime_responds record_identifier redirect
- render render_json
+ render render_json render_xml
send_file request_forgery_protection rescue url_rewriter verification webservice
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 6e1f92c45d..08ffafb27e 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -11,8 +11,8 @@ module ActionController
include ActionController::UrlFor
include ActionController::Redirector
include ActionController::Renderer
- include ActionController::RenderOptions
include ActionController::Renderers::Json
+ include ActionController::Renderers::Xml
include ActionController::Layouts
include ActionController::ConditionalGet
diff --git a/actionpack/lib/action_controller/new_base/render_options.rb b/actionpack/lib/action_controller/new_base/render_options.rb
index e7ed2bd278..a9ac0e0a41 100644
--- a/actionpack/lib/action_controller/new_base/render_options.rb
+++ b/actionpack/lib/action_controller/new_base/render_options.rb
@@ -18,15 +18,23 @@ module ActionController
end
end
- module Renderers
- module Json
+ module RenderOption
+ extend ActiveSupport::DependencyModule
+
+ included do
extend ActiveSupport::DependencyModule
-
depends_on RenderOptions
-
- included do
- _renderers << :json
+
+ def self.register_renderer(name)
+ included { _renderers << name }
end
+ end
+ end
+
+ module Renderers
+ module Json
+ include RenderOption
+ register_renderer :json
def _render_json(json, options)
json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str)
@@ -35,5 +43,15 @@ module ActionController
self.response_body = json
end
end
+
+ module Xml
+ include RenderOption
+ register_renderer :xml
+
+ def _render_xml(xml, options)
+ response.content_type ||= Mime::XML
+ self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml
+ end
+ end
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 840168397d..2a52eedb59 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -79,9 +79,10 @@ module ActionController
end
def _process_options(options)
- status, content_type = options.values_at(:status, :content_type)
+ status, content_type, location = options.values_at(:status, :content_type, :location)
response.status = status.to_i if status
response.content_type = content_type if content_type
+ response.headers["Location"] = url_for(location) if location
end
end
end
--
cgit v1.2.3
From 9d3d7746702b65ddc09364c260ee4ace4b178281 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Thu, 21 May 2009 15:23:52 -0700
Subject: Update render options to remove performance implications of many
render options types
---
.../action_controller/new_base/render_options.rb | 32 +++++++++++++++++-----
1 file changed, 25 insertions(+), 7 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base/render_options.rb b/actionpack/lib/action_controller/new_base/render_options.rb
index a9ac0e0a41..aa6593b957 100644
--- a/actionpack/lib/action_controller/new_base/render_options.rb
+++ b/actionpack/lib/action_controller/new_base/render_options.rb
@@ -7,14 +7,32 @@ module ActionController
self._renderers = []
end
- def render_to_body(options)
- _renderers.each do |renderer|
- if options.key?(renderer)
- _process_options(options)
- return send("_render_#{renderer}", options[renderer], options)
+ module ClassMethods
+ def _write_render_options
+ renderers = _renderers.map do |r|
+ <<-RUBY_EVAL
+ if options.key?(:#{r})
+ _process_options(options)
+ return _render_#{r}(options[:#{r}], options)
+ end
+ RUBY_EVAL
end
+
+ class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
+ def _handle_render_options(options)
+ #{renderers.join}
+ end
+ RUBY_EVAL
+ end
+
+ def _add_render_option(name)
+ _renderers << name
+ _write_render_options
end
- super
+ end
+
+ def render_to_body(options)
+ _handle_render_options(options) || super
end
end
@@ -26,7 +44,7 @@ module ActionController
depends_on RenderOptions
def self.register_renderer(name)
- included { _renderers << name }
+ included { _add_render_option(name) }
end
end
end
--
cgit v1.2.3
From d2cac9dd0e28b99bd45fd9eaa1d5a6b3dee8fa8f Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Thu, 21 May 2009 22:03:52 +0200
Subject: Add missing dependency in Streaming
---
actionpack/lib/action_controller/base/streaming.rb | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/actionpack/lib/action_controller/base/streaming.rb b/actionpack/lib/action_controller/base/streaming.rb
index b69b13eea8..5872ba99a2 100644
--- a/actionpack/lib/action_controller/base/streaming.rb
+++ b/actionpack/lib/action_controller/base/streaming.rb
@@ -2,6 +2,13 @@ module ActionController #:nodoc:
# Methods for sending arbitrary data and for streaming files to the browser,
# instead of rendering.
module Streaming
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ depends_on ActionController::Renderer
+ end
+
DEFAULT_SEND_FILE_OPTIONS = {
:type => 'application/octet-stream'.freeze,
:disposition => 'attachment'.freeze,
--
cgit v1.2.3
From 1a52b246eb245d159a1c331417a4b14923e9bc4e Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Fri, 22 May 2009 00:26:58 +0200
Subject: Add HTTP Authentication to the new base
---
actionpack/Rakefile | 1 +
actionpack/lib/action_controller/new_base.rb | 2 ++
actionpack/lib/action_controller/new_base/base.rb | 7 +++++++
.../lib/action_controller/new_base/conditional_get.rb | 2 +-
actionpack/lib/action_controller/new_base/renderer.rb | 2 +-
.../test/controller/http_digest_authentication_test.rb | 13 +++++++++----
actionpack/test/controller/send_file_test.rb | 13 +++++++++----
7 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index d192a2e3bf..012f5384e2 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -65,6 +65,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
flash mime_responds record_identifier redirect
render render_json render_xml
send_file request_forgery_protection rescue url_rewriter verification webservice
+ http_basic_authentication http_digest_authentication
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 95808decd5..14f73e1edd 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -31,6 +31,8 @@ module ActionController
autoload :Flash, 'action_controller/base/chained/flash'
autoload :RequestForgeryProtection, 'action_controller/base/request_forgery_protection'
autoload :Streaming, 'action_controller/base/streaming'
+ autoload :HttpAuthentication, 'action_controller/base/http_authentication'
+
require 'action_controller/routing'
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 08ffafb27e..b432060bc1 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -30,6 +30,8 @@ module ActionController
include ActionController::Verification
include ActionController::RequestForgeryProtection
include ActionController::Streaming
+ include ActionController::HttpAuthentication::Basic::ControllerMethods
+ include ActionController::HttpAuthentication::Digest::ControllerMethods
# TODO: Extract into its own module
# This should be moved together with other normalizing behavior
@@ -89,6 +91,11 @@ module ActionController
if options.key?(:action) && options[:action].to_s.index("/")
options[:template] = options.delete(:action)
end
+
+ if options[:status]
+ options[:status] = interpret_status(options.delete(:status)).to_i
+ end
+
options
end
diff --git a/actionpack/lib/action_controller/new_base/conditional_get.rb b/actionpack/lib/action_controller/new_base/conditional_get.rb
index e1407e671a..116ce34494 100644
--- a/actionpack/lib/action_controller/new_base/conditional_get.rb
+++ b/actionpack/lib/action_controller/new_base/conditional_get.rb
@@ -57,7 +57,7 @@ module ActionController
raise ArgumentError, "too few arguments to head"
end
options = args.extract_options!
- status = interpret_status(args.shift || options.delete(:status) || :ok)
+ status = args.shift || options.delete(:status) || :ok
options.each do |key, value|
headers[key.to_s.dasherize.split(/-/).map { |v| v.capitalize }.join("-")] = value.to_s
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 2a52eedb59..878859f3e6 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -80,7 +80,7 @@ module ActionController
def _process_options(options)
status, content_type, location = options.values_at(:status, :content_type, :location)
- response.status = status.to_i if status
+ response.status = status if status
response.content_type = content_type if content_type
response.headers["Location"] = url_for(location) if location
end
diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb
index b8a2205ce6..15a11395bb 100644
--- a/actionpack/test/controller/http_digest_authentication_test.rb
+++ b/actionpack/test/controller/http_digest_authentication_test.rb
@@ -38,6 +38,15 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
tests DummyDigestController
+ setup do
+ # Used as secret in generating nonce to prevent tampering of timestamp
+ @old_secret, ActionController::Base.session_options[:secret] = ActionController::Base.session_options[:secret], "session_options_secret"
+ end
+
+ teardown do
+ ActionController::Base.session_options[:secret] = @old_secret
+ end
+
AUTH_HEADERS.each do |header|
test "successful authentication with #{header.downcase}" do
@request.env[header] = encode_credentials(:username => 'lifo', :password => 'world')
@@ -165,10 +174,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
options.reverse_merge!(:nc => "00000001", :cnonce => "0a4f113b", :password_is_ha1 => false)
password = options.delete(:password)
- # Set in /initializers/session_store.rb. Used as secret in generating nonce
- # to prevent tampering of timestamp
- ActionController::Base.session_options[:secret] = "session_options_secret"
-
# Perform unauthenticated request to retrieve digest parameters to use on subsequent request
method = options.delete(:method) || 'GET'
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index 3a99774ae0..0bc0eb2df6 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -11,12 +11,17 @@ class SendFileController < ActionController::Base
layout "layouts/standard" # to make sure layouts don't interfere
attr_writer :options
- def options() @options ||= {} end
+ def options
+ @options ||= {}
+ end
- def file() send_file(file_path, options) end
- def data() send_data(file_data, options) end
+ def file
+ send_file(file_path, options)
+ end
- def rescue_action(e) raise end
+ def data
+ send_data(file_data, options)
+ end
end
class SendFileTest < ActionController::TestCase
--
cgit v1.2.3
From e773d0e68ac64bd26d86860a9a8e0048e2b6bb48 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Thu, 21 May 2009 16:31:05 -0700
Subject: Renamed #implicit_render to #default_render in new base to support
the default_render API
---
actionpack/lib/action_controller/new_base/base.rb | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index b432060bc1..034e614d6e 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -38,18 +38,18 @@ module ActionController
module ImplicitRender
def process_action(method_name)
ret = super
- render if response_body.nil?
+ default_render if response_body.nil?
ret
end
- def _implicit_render
+ def default_render
render
end
def method_for_action(action_name)
super || begin
if view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
- "_implicit_render"
+ "default_render"
end
end
end
--
cgit v1.2.3
From 6923b392b740f2346326634532b40cf24a0f26ef Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Thu, 21 May 2009 16:35:40 -0700
Subject: Added the :rjs render option
---
actionpack/lib/action_controller/new_base/base.rb | 14 ++++++++------
.../lib/action_controller/new_base/render_options.rb | 11 +++++++++++
actionpack/lib/action_view/base.rb | 17 +++++++++--------
actionpack/lib/action_view/helpers/prototype_helper.rb | 2 ++
actionpack/lib/action_view/template/handler.rb | 1 +
actionpack/test/controller/render_other_test.rb | 8 ++++++++
actionpack/test/template/javascript_helper_test.rb | 4 ++++
actionpack/test/template/prototype_helper_test.rb | 4 ++++
8 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 034e614d6e..fae08c58b2 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -13,6 +13,7 @@ module ActionController
include ActionController::Renderer
include ActionController::Renderers::Json
include ActionController::Renderers::Xml
+ include ActionController::Renderers::Rjs
include ActionController::Layouts
include ActionController::ConditionalGet
@@ -74,7 +75,7 @@ module ActionController
end
end
- def _normalize_options(action = nil, options = {})
+ def _normalize_options(action = nil, options = {}, &blk)
if action.is_a?(Hash)
options, action = action, nil
elsif action.is_a?(String) || action.is_a?(Symbol)
@@ -93,19 +94,20 @@ module ActionController
end
if options[:status]
- options[:status] = interpret_status(options.delete(:status)).to_i
+ options[:status] = interpret_status(options[:status]).to_i
end
+ options[:update] = blk if block_given?
options
end
- def render(action = nil, options = {})
- options = _normalize_options(action, options)
+ def render(action = nil, options = {}, &blk)
+ options = _normalize_options(action, options, &blk)
super(options)
end
- def render_to_string(action = nil, options = {})
- options = _normalize_options(action, options)
+ def render_to_string(action = nil, options = {}, &blk)
+ options = _normalize_options(action, options, &blk)
super(options)
end
diff --git a/actionpack/lib/action_controller/new_base/render_options.rb b/actionpack/lib/action_controller/new_base/render_options.rb
index aa6593b957..1df23deee7 100644
--- a/actionpack/lib/action_controller/new_base/render_options.rb
+++ b/actionpack/lib/action_controller/new_base/render_options.rb
@@ -71,5 +71,16 @@ module ActionController
self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml
end
end
+
+ module Rjs
+ include RenderOption
+ register_renderer :update
+
+ def _render_update(proc, options)
+ generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(_action_view, &proc)
+ response.content_type = Mime::JS
+ self.response_body = generator.to_s
+ end
+ end
end
end
\ No newline at end of file
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 6b72d406af..4ab568b44c 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -269,15 +269,16 @@ module ActionView #:nodoc:
nil
end
- private
- # Evaluates the local assigns and controller ivars, pushes them to the view.
- def _evaluate_assigns_and_ivars #:nodoc:
- unless @assigns_added
- @assigns.each { |key, value| instance_variable_set("@#{key}", value) }
- _copy_ivars_from_controller
- @assigns_added = true
- end
+ # Evaluates the local assigns and controller ivars, pushes them to the view.
+ def _evaluate_assigns_and_ivars #:nodoc:
+ unless @assigns_added
+ @assigns.each { |key, value| instance_variable_set("@#{key}", value) }
+ _copy_ivars_from_controller
+ @assigns_added = true
end
+ end
+
+ private
def _copy_ivars_from_controller #:nodoc:
if @controller
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index 1fbe012a95..c0f5df3468 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -1,5 +1,6 @@
require 'set'
require 'active_support/json'
+require 'active_support/core_ext/object/extending'
module ActionView
module Helpers
@@ -572,6 +573,7 @@ module ActionView
# #include_helpers_from_context has nothing to overwrite.
class JavaScriptGenerator #:nodoc:
def initialize(context, &block) #:nodoc:
+ context._evaluate_assigns_and_ivars
@context, @lines = context, []
include_helpers_from_context
@context.with_output_buffer(@lines) do
diff --git a/actionpack/lib/action_view/template/handler.rb b/actionpack/lib/action_view/template/handler.rb
index 3481a4a4e7..3071c78174 100644
--- a/actionpack/lib/action_view/template/handler.rb
+++ b/actionpack/lib/action_view/template/handler.rb
@@ -1,4 +1,5 @@
require "active_support/core_ext/class/inheritable_attributes"
+require "action_dispatch/http/mime_type"
# Legacy TemplateHandler stub
module ActionView
diff --git a/actionpack/test/controller/render_other_test.rb b/actionpack/test/controller/render_other_test.rb
index ddbdd2d213..3c52b7036d 100644
--- a/actionpack/test/controller/render_other_test.rb
+++ b/actionpack/test/controller/render_other_test.rb
@@ -103,6 +103,14 @@ class TestController < ActionController::Base
end
private
+ def default_render
+ if @alternate_default_render
+ @alternate_default_render.call
+ else
+ super
+ end
+ end
+
def determine_layout
case action_name
when "render_js_with_explicit_template",
diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb
index f9bc92c7c9..8caabfc3e1 100644
--- a/actionpack/test/template/javascript_helper_test.rb
+++ b/actionpack/test/template/javascript_helper_test.rb
@@ -3,6 +3,8 @@ require 'abstract_unit'
class JavaScriptHelperTest < ActionView::TestCase
tests ActionView::Helpers::JavaScriptHelper
+ def _evaluate_assigns_and_ivars() end
+
attr_accessor :formats, :output_buffer
def setup
@@ -10,6 +12,8 @@ class JavaScriptHelperTest < ActionView::TestCase
@template = self
end
+ def _evaluate_assigns_and_ivars() end
+
def test_escape_javascript
assert_equal '', escape_javascript(nil)
assert_equal %(This \\"thing\\" is really\\n netos\\'), escape_javascript(%(This "thing" is really\n netos'))
diff --git a/actionpack/test/template/prototype_helper_test.rb b/actionpack/test/template/prototype_helper_test.rb
index 28851f113f..f9f418aec9 100644
--- a/actionpack/test/template/prototype_helper_test.rb
+++ b/actionpack/test/template/prototype_helper_test.rb
@@ -61,6 +61,8 @@ class PrototypeHelperBaseTest < ActionView::TestCase
end
class PrototypeHelperTest < PrototypeHelperBaseTest
+ def _evaluate_assigns_and_ivars() end
+
def setup
@record = @author = Author.new
@article = Article.new
@@ -304,6 +306,8 @@ class JavaScriptGeneratorTest < PrototypeHelperBaseTest
@generator = create_generator
end
+ def _evaluate_assigns_and_ivars() end
+
def test_insert_html_with_string
assert_equal 'Element.insert("element", { top: "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E" });',
@generator.insert_html(:top, 'element', 'This is a test
')
--
cgit v1.2.3
From 68a207ccf6dffa58c9a9a3e221b99af72859ce27 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Thu, 21 May 2009 18:14:20 -0700
Subject: Implemented layout conditions in new base
---
.../lib/action_controller/abstract/layouts.rb | 25 ++++++++++++++++++---
actionpack/test/controller/layout_test.rb | 26 ++++++++++++++--------
.../layouts/third_party_template_library.mab | 2 +-
3 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 96cb05972f..557d68d866 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -4,11 +4,19 @@ module AbstractController
depends_on Renderer
+ included do
+ extlib_inheritable_accessor :_layout_conditions
+ self._layout_conditions = {}
+ end
+
module ClassMethods
- def layout(layout)
+ def layout(layout, conditions = {})
unless [String, Symbol, FalseClass, NilClass].include?(layout.class)
raise ArgumentError, "Layouts must be specified as a String, Symbol, false, or nil"
end
+
+ conditions.each {|k, v| conditions[k] = Array(v).map {|a| a.to_s} }
+ self._layout_conditions = conditions
@_layout = layout || false # Converts nil to false
_write_layout_method
@@ -75,17 +83,28 @@ module AbstractController
end
def _default_layout(require_layout = false)
- if require_layout && !_layout
+ if require_layout && _action_has_layout? && !_layout
raise ArgumentError,
"There was no default layout for #{self.class} in #{view_paths.inspect}"
end
begin
- layout = _layout_for_name(_layout)
+ _layout_for_name(_layout) if _action_has_layout?
rescue NameError => e
raise NoMethodError,
"You specified #{@_layout.inspect} as the layout, but no such method was found"
end
end
+
+ def _action_has_layout?
+ conditions = _layout_conditions
+ if only = conditions[:only]
+ only.include?(action_name)
+ elsif except = conditions[:except]
+ !except.include?(action_name)
+ else
+ true
+ end
+ end
end
end
\ No newline at end of file
diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb
index 5b7d40d16d..1cd448d5e8 100644
--- a/actionpack/test/controller/layout_test.rb
+++ b/actionpack/test/controller/layout_test.rb
@@ -9,8 +9,11 @@ ActionView::Template::register_template_handler :mab,
ActionController::Base.view_paths = [ File.dirname(__FILE__) + '/../fixtures/layout_tests/' ]
+require "lib/fixture_template"
+
class LayoutTest < ActionController::Base
def self.controller_path; 'views' end
+ def self._implied_layout_name; to_s.underscore.gsub(/_controller$/, '') ; end
self.view_paths = ActionController::Base.view_paths.dup
end
@@ -35,6 +38,15 @@ end
class MultipleExtensions < LayoutTest
end
+if defined?(ActionController::Http)
+ LayoutTest._write_layout_method
+ ProductController._write_layout_method
+ ItemController._write_layout_method
+ ThirdPartyTemplateLibraryController._write_layout_method
+ MultipleExtensions._write_layout_method
+ ControllerNameSpace::NestedController._write_layout_method
+end
+
class LayoutAutoDiscoveryTest < ActionController::TestCase
def setup
super
@@ -56,23 +68,19 @@ class LayoutAutoDiscoveryTest < ActionController::TestCase
def test_third_party_template_library_auto_discovers_layout
@controller = ThirdPartyTemplateLibraryController.new
get :hello
- assert @controller.active_layout(true).identifier.include?('layouts/third_party_template_library.mab')
- assert @controller.template.layout.include?('layouts/third_party_template_library')
assert_response :success
- assert_equal 'Mab', @response.body
+ assert_equal 'layouts/third_party_template_library.mab', @response.body
end
- def test_namespaced_controllers_auto_detect_layouts
+ def test_namespaced_controllers_auto_detect_layouts1
@controller = ControllerNameSpace::NestedController.new
get :hello
- assert_equal 'layouts/controller_name_space/nested', @controller.active_layout(true).to_s
assert_equal 'controller_name_space/nested.rhtml hello.rhtml', @response.body
end
- def test_namespaced_controllers_auto_detect_layouts
+ def test_namespaced_controllers_auto_detect_layouts2
@controller = MultipleExtensions.new
get :hello
- 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
@@ -139,7 +147,7 @@ class LayoutSetInResponseTest < ActionController::TestCase
def test_layout_only_exception_when_excepted
@controller = OnlyLayoutController.new
get :goodbye
- assert_equal nil, @controller.template.layout
+ assert !@response.body.include?("item.rhtml"), "#{@response.body.inspect} included 'item.rhtml'"
end
def test_layout_except_exception_when_included
@@ -151,7 +159,7 @@ class LayoutSetInResponseTest < ActionController::TestCase
def test_layout_except_exception_when_excepted
@controller = ExceptLayoutController.new
get :goodbye
- assert_equal nil, @controller.template.layout
+ assert !@response.body.include?("item.rhtml"), "#{@response.body.inspect} included 'item.rhtml'"
end
def test_layout_set_when_using_render
diff --git a/actionpack/test/fixtures/layout_tests/layouts/third_party_template_library.mab b/actionpack/test/fixtures/layout_tests/layouts/third_party_template_library.mab
index 018abfb0ac..fcee620d82 100644
--- a/actionpack/test/fixtures/layout_tests/layouts/third_party_template_library.mab
+++ b/actionpack/test/fixtures/layout_tests/layouts/third_party_template_library.mab
@@ -1 +1 @@
-Mab
\ No newline at end of file
+layouts/third_party_template_library.mab
\ No newline at end of file
--
cgit v1.2.3
From e0e124757a98a22a3a1ff7cfbceb1d0e4c4c7533 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 21 May 2009 19:44:02 -0700
Subject: Fewer runs by default
---
actionpack/examples/minimal.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/examples/minimal.rb b/actionpack/examples/minimal.rb
index 84a8499daf..76668b375d 100644
--- a/actionpack/examples/minimal.rb
+++ b/actionpack/examples/minimal.rb
@@ -9,7 +9,7 @@ class BaseController < ActionController::Base
end
end
-n = (ENV['N'] || 10000).to_i
+n = (ENV['N'] || 1000).to_i
input = StringIO.new('')
def call_index(controller, input, n)
--
cgit v1.2.3
From 8f3cbb477375071cfa2ca9b3b01d8a4e3034ccf5 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 21 May 2009 19:45:15 -0700
Subject: Dead local
---
actionpack/lib/action_controller/new_base/renderer.rb | 1 -
1 file changed, 1 deletion(-)
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 878859f3e6..71b79fbc42 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -29,7 +29,6 @@ module ActionController
if options.key?(:text)
options[:_template] = ActionView::TextTemplate.new(_text(options), formats.first)
- template = nil
elsif options.key?(:inline)
handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb")
template = ActionView::Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {})
--
cgit v1.2.3
From 4c52ba278b8e349bc18cb89086af765d0828f0af Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 21 May 2009 20:22:18 -0700
Subject: Move Safari response-padding fix to Rails2Compatibility. Should be a
Rack concern.
---
actionpack/lib/action_controller/new_base/base.rb | 8 ++------
actionpack/lib/action_controller/new_base/compatibility.rb | 6 ++++--
actionpack/lib/action_controller/new_base/renderer.rb | 13 ++-----------
actionpack/lib/action_controller/new_base/testing.rb | 4 ++--
actionpack/lib/action_view/template/text.rb | 2 +-
actionpack/test/controller/verification_test.rb | 2 +-
actionpack/test/controller/webservice_test.rb | 4 ++--
actionpack/test/new_base/render_text_test.rb | 6 +++---
8 files changed, 17 insertions(+), 28 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index fae08c58b2..88686d29d0 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -110,11 +110,7 @@ module ActionController
options = _normalize_options(action, options, &blk)
super(options)
end
-
- def render_to_body(options)
- super || [" "]
- end
-
+
# Redirects the browser to the target specified in +options+. This parameter can take one of three forms:
#
# * Hash - The URL will be generated by calling url_for with the +options+.
@@ -172,4 +168,4 @@ module ActionController
super(url, status)
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index 522a9fe23b..250e7f0dff 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -91,7 +91,9 @@ module ActionController
options[:text] = nil if options[:nothing] == true
- super
+ body = super
+ body = [' '] if body.blank?
+ body
end
def _handle_method_missing
@@ -110,4 +112,4 @@ module ActionController
response_body
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 71b79fbc42..59df3c51da 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -28,7 +28,7 @@ module ActionController
_process_options(options)
if options.key?(:text)
- options[:_template] = ActionView::TextTemplate.new(_text(options), formats.first)
+ options[:_template] = ActionView::TextTemplate.new(options[:text], formats.first)
elsif options.key?(:inline)
handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb")
template = ActionView::Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {})
@@ -51,17 +51,8 @@ module ActionController
def _prefix
controller_path
- end
-
- def _text(options)
- text = options[:text]
-
- case text
- when nil then " "
- else text.to_s
- end
end
-
+
def _render_partial(partial, options)
case partial
when true
diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb
index 6a92c292bd..d8c3421587 100644
--- a/actionpack/lib/action_controller/new_base/testing.rb
+++ b/actionpack/lib/action_controller/new_base/testing.rb
@@ -7,7 +7,7 @@ module ActionController
@_response = response
@_response.request = request
ret = process(request.parameters[:action])
- @_response.body ||= self.response_body || " "
+ @_response.body ||= self.response_body
@_response.prepare!
set_test_assigns
ret
@@ -27,4 +27,4 @@ module ActionController
@_response.headers.replace(new_headers)
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb
index 927a0d7a72..a86c3915c2 100644
--- a/actionpack/lib/action_view/template/text.rb
+++ b/actionpack/lib/action_view/template/text.rb
@@ -2,7 +2,7 @@ module ActionView #:nodoc:
class TextTemplate < String #:nodoc:
def initialize(string, content_type = Mime[:html])
- super(string)
+ super(string.to_s)
@content_type = Mime[content_type]
end
diff --git a/actionpack/test/controller/verification_test.rb b/actionpack/test/controller/verification_test.rb
index 85134a8264..d568030e41 100644
--- a/actionpack/test/controller/verification_test.rb
+++ b/actionpack/test/controller/verification_test.rb
@@ -182,7 +182,7 @@ class VerificationTest < ActionController::TestCase
def test_unguarded_without_params
get :unguarded
- assert_equal "", @response.body
+ assert @response.body.blank?
end
def test_guarded_in_session_with_prereqs
diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb
index e89d6bb960..9bf8da7276 100644
--- a/actionpack/test/controller/webservice_test.rb
+++ b/actionpack/test/controller/webservice_test.rb
@@ -34,7 +34,7 @@ class WebServiceTest < ActionController::IntegrationTest
def test_check_parameters
with_test_route_set do
get "/"
- assert_equal '', @controller.response.body
+ assert @controller.response.body.blank?
end
end
@@ -163,7 +163,7 @@ class WebServiceTest < ActionController::IntegrationTest
with_test_route_set do
ActionController::Base.param_parsers[Mime::XML] = :xml_simple
assert_nothing_raised { post "/", "", {'CONTENT_TYPE' => 'application/xml'} }
- assert_equal "", @controller.response.body
+ assert @controller.response.body.blank?
end
end
diff --git a/actionpack/test/new_base/render_text_test.rb b/actionpack/test/new_base/render_text_test.rb
index 69594e4b64..aed903ee8a 100644
--- a/actionpack/test/new_base/render_text_test.rb
+++ b/actionpack/test/new_base/render_text_test.rb
@@ -88,14 +88,14 @@ module RenderText
assert_status 404
end
- test "rendering text with nil returns a single space character" do
+ test "rendering text with nil returns an empty body padded for Safari" do
get "/render_text/with_layout/with_nil"
assert_body " "
assert_status 200
end
- test "Rendering text with nil and custom status code returns a single space character with the status" do
+ test "Rendering text with nil and custom status code returns an empty body padded for Safari and the status" do
get "/render_text/with_layout/with_nil_and_status"
assert_body " "
@@ -139,4 +139,4 @@ module RenderText
end
end
-ActionController::Base.app_loaded!
\ No newline at end of file
+ActionController::Base.app_loaded!
--
cgit v1.2.3
From 1fa7e3322dc8ceac0da3b2b516ca338ee36c89a9 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 21 May 2009 20:54:28 -0700
Subject: Ruby 1.9 compat: don't rely on lexical scoping since the included
block is called from dependency_module
---
actionpack/lib/action_controller/new_base/render_options.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base/render_options.rb b/actionpack/lib/action_controller/new_base/render_options.rb
index 1df23deee7..2ce9d0c7ae 100644
--- a/actionpack/lib/action_controller/new_base/render_options.rb
+++ b/actionpack/lib/action_controller/new_base/render_options.rb
@@ -41,7 +41,7 @@ module ActionController
included do
extend ActiveSupport::DependencyModule
- depends_on RenderOptions
+ depends_on ::ActionController::RenderOptions
def self.register_renderer(name)
included { _add_render_option(name) }
@@ -83,4 +83,4 @@ module ActionController
end
end
end
-end
\ No newline at end of file
+end
--
cgit v1.2.3
From d1d9a6c26113cf4a0decb504c46e4e7fe4351ce6 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Fri, 22 May 2009 18:15:43 +0200
Subject: Require ruby-debug from new_base/abstract_unit
---
actionpack/test/new_base/abstract_unit.rb | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/actionpack/test/new_base/abstract_unit.rb b/actionpack/test/new_base/abstract_unit.rb
index c045247702..1d4bcbd91d 100644
--- a/actionpack/test/new_base/abstract_unit.rb
+++ b/actionpack/test/new_base/abstract_unit.rb
@@ -18,6 +18,13 @@ require 'active_support/dependencies'
$tags[:new_base] = true
+begin
+ require 'ruby-debug'
+ Debugger.settings[:autoeval] = true
+ Debugger.start
+rescue LoadError
+ # Debugging disabled. `gem install ruby-debug` to enable.
+end
ActiveSupport::Dependencies.hook!
--
cgit v1.2.3
From 9d08f86cd45ed939ecf2e24e81655371910c8045 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Fri, 22 May 2009 18:40:26 +0200
Subject: Make assertion tests pass with the new base
---
actionpack/Rakefile | 1 +
actionpack/lib/action_controller/testing/process2.rb | 1 +
actionpack/lib/action_view/test_case.rb | 2 +-
actionpack/test/controller/action_pack_assertions_test.rb | 6 +++---
actionpack/test/new_base/abstract_unit.rb | 2 +-
5 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 012f5384e2..494286fa4c 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -66,6 +66,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
render render_json render_xml
send_file request_forgery_protection rescue url_rewriter verification webservice
http_basic_authentication http_digest_authentication
+ action_pack_assertions
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb
index bee82c280e..677dd41781 100644
--- a/actionpack/lib/action_controller/testing/process2.rb
+++ b/actionpack/lib/action_controller/testing/process2.rb
@@ -41,6 +41,7 @@ module ActionController
@response.recycle!
@controller.response_body = nil
@controller.formats = nil
+ @controller.params = nil
@html_document = nil
@request.env['REQUEST_METHOD'] = http_method
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index 22adf97304..7355af4192 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -11,7 +11,7 @@ module ActionView
attr_internal :rendered
alias_method :_render_template_without_template_tracking, :_render_template
def _render_template(template, local_assigns = {})
- if template.respond_to?(:identifier)
+ if template.respond_to?(:identifier) && template.present?
@_rendered[:partials][template] += 1 if template.partial?
@_rendered[:template] ||= []
@_rendered[:template] << template
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index c3c769919a..24686ab4b6 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'action_controller/vendor/html-scanner'
# a controller class to facilitate the tests
class ActionPackAssertionsController < ActionController::Base
@@ -295,8 +296,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
# make sure that the template objects exist
def test_template_objects_alive
process :assign_this
- assert !@controller.template.assigns['hi']
- assert @controller.template.assigns['howdy']
+ assert !@controller.template.instance_variable_get(:"@hi")
+ assert @controller.template.instance_variable_get(:"@howdy")
end
# make sure we don't have template objects when we shouldn't
@@ -444,7 +445,6 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
assert_equal "Mr. David", @response.body
end
-
def test_assert_redirection_fails_with_incorrect_controller
process :redirect_to_controller
assert_raise(ActiveSupport::TestCase::Assertion) do
diff --git a/actionpack/test/new_base/abstract_unit.rb b/actionpack/test/new_base/abstract_unit.rb
index 1d4bcbd91d..5df3467ff5 100644
--- a/actionpack/test/new_base/abstract_unit.rb
+++ b/actionpack/test/new_base/abstract_unit.rb
@@ -113,7 +113,7 @@ module ActionController
hax = @controller._action_view.instance_variable_get(:@_rendered)
case options
- when NilClass, String
+ when NilClass, String
rendered = (hax[:template] || []).map { |t| t.identifier }
msg = build_message(message,
"expecting > but rendering with >",
--
cgit v1.2.3
From faaff383e6f52e1c077684bfa49619139db728fb Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Fri, 22 May 2009 19:03:27 +0200
Subject: Add assert_select tests to the new base
---
actionpack/Rakefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 494286fa4c..bc30fc7308 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -66,7 +66,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
render render_json render_xml
send_file request_forgery_protection rescue url_rewriter verification webservice
http_basic_authentication http_digest_authentication
- action_pack_assertions
+ action_pack_assertions assert_select
).map { |name| "test/controller/#{name}_test.rb" }
end
--
cgit v1.2.3
From 1d168afcb146872cb7e49b6d513629fbb19e39b0 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Fri, 22 May 2009 19:51:11 +0200
Subject: Move FilterParameterLogging to a stand alone module and make it work
on new base
---
actionpack/Rakefile | 2 +-
actionpack/lib/action_controller.rb | 1 +
actionpack/lib/action_controller/base/base.rb | 58 +------------
.../base/filter_parameter_logging.rb | 97 ++++++++++++++++++++++
actionpack/lib/action_controller/new_base.rb | 1 +
actionpack/lib/action_controller/new_base/base.rb | 1 +
actionpack/test/controller/filter_params_test.rb | 45 +++++++++-
7 files changed, 144 insertions(+), 61 deletions(-)
create mode 100644 actionpack/lib/action_controller/base/filter_parameter_logging.rb
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index bc30fc7308..c9ed9ac532 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -66,7 +66,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
render render_json render_xml
send_file request_forgery_protection rescue url_rewriter verification webservice
http_basic_authentication http_digest_authentication
- action_pack_assertions assert_select
+ action_pack_assertions assert_select filter_params
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index 39083a84e9..dd22bfd617 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -66,6 +66,7 @@ module ActionController
autoload :UrlRewriter, 'action_controller/routing/generation/url_rewriter'
autoload :UrlWriter, 'action_controller/routing/generation/url_rewriter'
autoload :Verification, 'action_controller/base/verification'
+ autoload :FilterParameterLogging, 'action_controller/base/filter_parameter_logging'
module Assertions
autoload :DomAssertions, 'action_controller/testing/assertions/dom'
diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb
index c59068c628..2586037965 100644
--- a/actionpack/lib/action_controller/base/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -448,55 +448,6 @@ module ActionController #:nodoc:
@view_paths = superclass.view_paths.dup if @view_paths.nil?
@view_paths.push(*path)
end
-
- # Replace sensitive parameter data from the request log.
- # Filters parameters that have any of the arguments as a substring.
- # Looks in all subhashes of the param hash for keys to filter.
- # If a block is given, each key and value of the parameter hash and all
- # subhashes is passed to it, the value or key
- # can be replaced using String#replace or similar method.
- #
- # Examples:
- # filter_parameter_logging
- # => Does nothing, just slows the logging process down
- #
- # filter_parameter_logging :password
- # => replaces the value to all keys matching /password/i with "[FILTERED]"
- #
- # filter_parameter_logging :foo, "bar"
- # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
- #
- # filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i }
- # => reverses the value to all keys matching /secret/i
- #
- # filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i }
- # => reverses the value to all keys matching /secret/i, and
- # replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
- def filter_parameter_logging(*filter_words, &block)
- parameter_filter = Regexp.new(filter_words.collect{ |s| s.to_s }.join('|'), true) if filter_words.length > 0
-
- define_method(:filter_parameters) do |unfiltered_parameters|
- filtered_parameters = {}
-
- unfiltered_parameters.each do |key, value|
- if key =~ parameter_filter
- filtered_parameters[key] = '[FILTERED]'
- elsif value.is_a?(Hash)
- filtered_parameters[key] = filter_parameters(value)
- elsif block_given?
- key = key.dup
- value = value.dup if value
- yield key, value
- filtered_parameters[key] = value
- else
- filtered_parameters[key] = value
- end
- end
-
- filtered_parameters
- end
- protected :filter_parameters
- end
@@exempt_from_layout = [ActionView::TemplateHandlers::RJS]
@@ -853,13 +804,6 @@ module ActionController #:nodoc:
logger.info(request_id)
end
- def log_processing_for_parameters
- parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
- parameters = parameters.except!(:controller, :action, :format, :_method)
-
- logger.info " Parameters: #{parameters.inspect}" unless parameters.empty?
- end
-
def default_render #:nodoc:
render
end
@@ -933,7 +877,7 @@ module ActionController #:nodoc:
[ Filters, Layout, Renderer, Redirector, Responder, Benchmarking, Rescue, Flash, MimeResponds, Helpers,
Cookies, Caching, Verification, Streaming, SessionManagement,
HttpAuthentication::Basic::ControllerMethods, HttpAuthentication::Digest::ControllerMethods, RecordIdentifier,
- RequestForgeryProtection, Translation
+ RequestForgeryProtection, Translation, FilterParameterLogging
].each do |mod|
include mod
end
diff --git a/actionpack/lib/action_controller/base/filter_parameter_logging.rb b/actionpack/lib/action_controller/base/filter_parameter_logging.rb
new file mode 100644
index 0000000000..8e012b2a25
--- /dev/null
+++ b/actionpack/lib/action_controller/base/filter_parameter_logging.rb
@@ -0,0 +1,97 @@
+module ActionController
+ module FilterParameterLogging
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ depends_on AbstractController::Logger
+ end
+
+ included do
+ if defined?(ActionController::Http)
+ include InstanceMethodsForNewBase
+ end
+ end
+
+ module ClassMethods
+ # Replace sensitive parameter data from the request log.
+ # Filters parameters that have any of the arguments as a substring.
+ # Looks in all subhashes of the param hash for keys to filter.
+ # If a block is given, each key and value of the parameter hash and all
+ # subhashes is passed to it, the value or key
+ # can be replaced using String#replace or similar method.
+ #
+ # Examples:
+ # filter_parameter_logging
+ # => Does nothing, just slows the logging process down
+ #
+ # filter_parameter_logging :password
+ # => replaces the value to all keys matching /password/i with "[FILTERED]"
+ #
+ # filter_parameter_logging :foo, "bar"
+ # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
+ #
+ # filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i }
+ # => reverses the value to all keys matching /secret/i
+ #
+ # filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i }
+ # => reverses the value to all keys matching /secret/i, and
+ # replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
+ def filter_parameter_logging(*filter_words, &block)
+ parameter_filter = Regexp.new(filter_words.collect{ |s| s.to_s }.join('|'), true) if filter_words.length > 0
+
+ define_method(:filter_parameters) do |unfiltered_parameters|
+ filtered_parameters = {}
+
+ unfiltered_parameters.each do |key, value|
+ if key =~ parameter_filter
+ filtered_parameters[key] = '[FILTERED]'
+ elsif value.is_a?(Hash)
+ filtered_parameters[key] = filter_parameters(value)
+ elsif block_given?
+ key = key.dup
+ value = value.dup if value
+ yield key, value
+ filtered_parameters[key] = value
+ else
+ filtered_parameters[key] = value
+ end
+ end
+
+ filtered_parameters
+ end
+ protected :filter_parameters
+ end
+ end
+
+ module InstanceMethodsForNewBase
+ # TODO : Fix the order of information inside such that it's exactly same as the old base
+ def process(*)
+ ret = super
+
+ if logger
+ parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
+ parameters = parameters.except!(:controller, :action, :format, :_method)
+
+ unless parameters.empty?
+ # TODO : Move DelayedLog to AS
+ log = AbstractController::Logger::DelayedLog.new { " Parameters: #{parameters.inspect}" }
+ logger.info(log)
+ end
+ end
+
+ ret
+ end
+ end
+
+ private
+
+ # TODO : This method is not needed for the new base
+ def log_processing_for_parameters
+ parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
+ parameters = parameters.except!(:controller, :action, :format, :_method)
+
+ logger.info " Parameters: #{parameters.inspect}" unless parameters.empty?
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 14f73e1edd..41b2a859bc 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -32,6 +32,7 @@ module ActionController
autoload :RequestForgeryProtection, 'action_controller/base/request_forgery_protection'
autoload :Streaming, 'action_controller/base/streaming'
autoload :HttpAuthentication, 'action_controller/base/http_authentication'
+ autoload :FilterParameterLogging, 'action_controller/base/filter_parameter_logging'
require 'action_controller/routing'
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 88686d29d0..0c85896a00 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -33,6 +33,7 @@ module ActionController
include ActionController::Streaming
include ActionController::HttpAuthentication::Basic::ControllerMethods
include ActionController::HttpAuthentication::Digest::ControllerMethods
+ include ActionController::FilterParameterLogging
# TODO: Extract into its own module
# This should be moved together with other normalizing behavior
diff --git a/actionpack/test/controller/filter_params_test.rb b/actionpack/test/controller/filter_params_test.rb
index 0b259a7980..8c9e4f81de 100644
--- a/actionpack/test/controller/filter_params_test.rb
+++ b/actionpack/test/controller/filter_params_test.rb
@@ -1,13 +1,30 @@
require 'abstract_unit'
class FilterParamController < ActionController::Base
+ def payment
+ head :ok
+ end
end
-class FilterParamTest < Test::Unit::TestCase
- def setup
- @controller = FilterParamController.new
+class FilterParamTest < ActionController::TestCase
+ tests FilterParamController
+
+ class MockLogger
+ attr_reader :logged
+ attr_accessor :level
+
+ def initialize
+ @level = Logger::DEBUG
+ end
+
+ def method_missing(method, *args)
+ @logged ||= []
+ @logged << args.first
+ end
end
+ setup :set_logger
+
def test_filter_parameters
assert FilterParamController.respond_to?(:filter_parameter_logging)
assert !@controller.respond_to?(:filter_parameters)
@@ -46,4 +63,26 @@ class FilterParamTest < Test::Unit::TestCase
assert !FilterParamController.action_methods.include?('filter_parameters')
assert_raise(NoMethodError) { @controller.filter_parameters([{'password' => '[FILTERED]'}]) }
end
+
+ def test_filter_parameters_inside_logs
+ FilterParamController.filter_parameter_logging(:lifo, :amount)
+
+ get :payment, :lifo => 'Pratik', :amount => '420', :step => '1'
+
+ filtered_params_logs = logs.detect {|l| l =~ /\AParameters/ }
+
+ assert filtered_params_logs.index('"amount"=>"[FILTERED]"')
+ assert filtered_params_logs.index('"lifo"=>"[FILTERED]"')
+ assert filtered_params_logs.index('"step"=>"1"')
+ end
+
+ private
+
+ def set_logger
+ @controller.logger = MockLogger.new
+ end
+
+ def logs
+ @logs ||= @controller.logger.logged.compact.map {|l| l.to_s.strip}
+ end
end
--
cgit v1.2.3
From e976c489e6416cdc4714721df78dd43dd6d13d99 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Sat, 23 May 2009 00:17:05 +0200
Subject: Add all the existing helpers related features to the new base
---
actionpack/Rakefile | 2 +-
.../lib/action_controller/abstract/helpers.rb | 27 ++++-
actionpack/lib/action_controller/base/helpers.rb | 22 ++--
actionpack/lib/action_controller/new_base.rb | 1 +
actionpack/lib/action_controller/new_base/base.rb | 4 +-
.../lib/action_controller/new_base/helpers.rb | 133 +++++++++++++++++++++
actionpack/test/controller/helper_test.rb | 6 +-
actionpack/test/new_base/abstract_unit.rb | 3 +
actionpack/test/new_base/render_text_test.rb | 3 -
9 files changed, 175 insertions(+), 26 deletions(-)
create mode 100644 actionpack/lib/action_controller/new_base/helpers.rb
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index c9ed9ac532..0ce6f7823b 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -66,7 +66,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
render render_json render_xml
send_file request_forgery_protection rescue url_rewriter verification webservice
http_basic_authentication http_digest_authentication
- action_pack_assertions assert_select filter_params
+ action_pack_assertions assert_select filter_params helper
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/lib/action_controller/abstract/helpers.rb b/actionpack/lib/action_controller/abstract/helpers.rb
index 968d3080c1..41decfd0c7 100644
--- a/actionpack/lib/action_controller/abstract/helpers.rb
+++ b/actionpack/lib/action_controller/abstract/helpers.rb
@@ -24,11 +24,30 @@ module AbstractController
super
end
-
+
+ # Makes all the (instance) methods in the helper module available to templates rendered through this controller.
+ # See ActionView::Helpers (link:classes/ActionView/Helpers.html) for more about making your own helper modules
+ # available to the templates.
def add_template_helper(mod)
master_helper_module.module_eval { include mod }
end
-
+
+ # Declare a controller method as a helper. For example, the following
+ # makes the +current_user+ controller method available to the view:
+ # class ApplicationController < ActionController::Base
+ # helper_method :current_user, :logged_in?
+ #
+ # def current_user
+ # @current_user ||= User.find_by_id(session[:user])
+ # end
+ #
+ # def logged_in?
+ # current_user != nil
+ # end
+ # end
+ #
+ # In a view:
+ # <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
def helper_method(*meths)
meths.flatten.each do |meth|
master_helper_module.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
@@ -39,14 +58,14 @@ module AbstractController
end
end
- def helper(*args, &blk)
+ def helper(*args, &block)
args.flatten.each do |arg|
case arg
when Module
add_template_helper(arg)
end
end
- master_helper_module.module_eval(&blk) if block_given?
+ master_helper_module.module_eval(&block) if block_given?
end
end
diff --git a/actionpack/lib/action_controller/base/helpers.rb b/actionpack/lib/action_controller/base/helpers.rb
index ba65032f6a..96fa7896a9 100644
--- a/actionpack/lib/action_controller/base/helpers.rb
+++ b/actionpack/lib/action_controller/base/helpers.rb
@@ -3,23 +3,19 @@ require 'active_support/dependencies'
# FIXME: helper { ... } is broken on Ruby 1.9
module ActionController #:nodoc:
module Helpers #:nodoc:
- def self.included(base)
+ extend ActiveSupport::DependencyModule
+
+ included do
# Initialize the base module to aggregate its helpers.
- base.class_inheritable_accessor :master_helper_module
- base.master_helper_module = Module.new
+ class_inheritable_accessor :master_helper_module
+ self.master_helper_module = Module.new
# Set the default directory for helpers
- base.class_inheritable_accessor :helpers_dir
- base.helpers_dir = (defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/app/helpers" : "app/helpers")
-
- # Extend base with class methods to declare helpers.
- base.extend(ClassMethods)
+ class_inheritable_accessor :helpers_dir
+ self.helpers_dir = (defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/app/helpers" : "app/helpers")
- base.class_eval do
- # Wrap inherited to create a new master helper module for subclasses.
- class << self
- alias_method_chain :inherited, :helper
- end
+ class << self
+ alias_method_chain :inherited, :helper
end
end
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 41b2a859bc..d6107d3653 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -13,6 +13,7 @@ module ActionController
autoload :Testing, "action_controller/new_base/testing"
autoload :UrlFor, "action_controller/new_base/url_for"
autoload :Session, "action_controller/new_base/session"
+ autoload :Helpers, "action_controller/new_base/helpers"
# Ported modules
# require 'action_controller/routing'
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 0c85896a00..6340b7fde9 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -4,9 +4,9 @@ module ActionController
include AbstractController::Benchmarker
include AbstractController::Callbacks
- include AbstractController::Helpers
include AbstractController::Logger
-
+
+ include ActionController::Helpers
include ActionController::HideActions
include ActionController::UrlFor
include ActionController::Redirector
diff --git a/actionpack/lib/action_controller/new_base/helpers.rb b/actionpack/lib/action_controller/new_base/helpers.rb
new file mode 100644
index 0000000000..401741c249
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/helpers.rb
@@ -0,0 +1,133 @@
+require 'active_support/core_ext/load_error'
+require 'active_support/core_ext/name_error'
+require 'active_support/dependencies'
+
+module ActionController
+ module Helpers
+ extend ActiveSupport::DependencyModule
+
+ depends_on AbstractController::Helpers
+
+ included do
+ # Set the default directory for helpers
+ class_inheritable_accessor :helpers_dir
+ self.helpers_dir = (defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/app/helpers" : "app/helpers")
+ end
+
+ module ClassMethods
+ def inherited(klass)
+ # klass.master_helper_module = Module.new
+ # klass.master_helper_module.__send__ :include, master_helper_module
+ klass.__send__ :default_helper_module!
+ super
+ end
+
+ # The +helper+ class method can take a series of helper module names, a block, or both.
+ #
+ # * *args : One or more modules, strings or symbols, or the special symbol :all .
+ # * &block : A block defining helper methods.
+ #
+ # ==== Examples
+ # When the argument is a string or symbol, the method will provide the "_helper" suffix, require the file
+ # and include the module in the template class. The second form illustrates how to include custom helpers
+ # when working with namespaced controllers, or other cases where the file containing the helper definition is not
+ # in one of Rails' standard load paths:
+ # helper :foo # => requires 'foo_helper' and includes FooHelper
+ # helper 'resources/foo' # => requires 'resources/foo_helper' and includes Resources::FooHelper
+ #
+ # When the argument is a module it will be included directly in the template class.
+ # helper FooHelper # => includes FooHelper
+ #
+ # When the argument is the symbol :all , the controller will include all helpers beneath
+ # ActionController::Base.helpers_dir (defaults to app/helpers/**/*.rb under RAILS_ROOT).
+ # helper :all
+ #
+ # Additionally, the +helper+ class method can receive and evaluate a block, making the methods defined available
+ # to the template.
+ # # One line
+ # helper { def hello() "Hello, world!" end }
+ # # Multi-line
+ # helper do
+ # def foo(bar)
+ # "#{bar} is the very best"
+ # end
+ # end
+ #
+ # Finally, all the above styles can be mixed together, and the +helper+ method can be invoked with a mix of
+ # +symbols+, +strings+, +modules+ and blocks.
+ # helper(:three, BlindHelper) { def mice() 'mice' end }
+ #
+ def helper(*args, &block)
+ args.flatten.each do |arg|
+ case arg
+ when :all
+ helper all_application_helpers
+ when String, Symbol
+ file_name = arg.to_s.underscore + '_helper'
+ class_name = file_name.camelize
+
+ begin
+ require_dependency(file_name)
+ rescue LoadError => load_error
+ requiree = / -- (.*?)(\.rb)?$/.match(load_error.message).to_a[1]
+ if requiree == file_name
+ msg = "Missing helper file helpers/#{file_name}.rb"
+ raise LoadError.new(msg).copy_blame!(load_error)
+ else
+ raise
+ end
+ end
+
+ add_template_helper(class_name.constantize)
+ else
+ # Explcit 'return' here so that the supplied block ( if any ) doesn't get included twice
+ return super
+ end
+ end
+
+ # Evaluate block in template class if given.
+ master_helper_module.module_eval(&block) if block_given?
+ end
+
+ # Declares helper accessors for controller attributes. For example, the
+ # following adds new +name+ and name= instance methods to a
+ # controller and makes them available to the view:
+ # helper_attr :name
+ # attr_accessor :name
+ def helper_attr(*attrs)
+ attrs.flatten.each { |attr| helper_method(attr, "#{attr}=") }
+ end
+
+ # Provides a proxy to access helpers methods from outside the view.
+ def helpers
+ unless @helper_proxy
+ @helper_proxy = ActionView::Base.new
+ @helper_proxy.extend master_helper_module
+ else
+ @helper_proxy
+ end
+ end
+
+ private
+
+ def default_helper_module!
+ unless name.blank?
+ module_name = name.sub(/Controller$|$/, 'Helper')
+ module_path = module_name.split('::').map { |m| m.underscore }.join('/')
+ require_dependency module_path
+ helper module_name.constantize
+ end
+ rescue MissingSourceFile => e
+ raise unless e.is_missing? module_path
+ rescue NameError => e
+ raise unless e.missing_name? module_name
+ end
+
+ # Extract helper names from files in app/helpers/**/*.rb
+ def all_application_helpers
+ extract = /^#{Regexp.quote(helpers_dir)}\/?(.*)_helper.rb$/
+ Dir["#{helpers_dir}/**/*_helper.rb"].map { |file| file.sub extract, '\1' }
+ end
+ end # ClassMethods
+ end
+end
diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb
index 3bbda9eb3a..5b9feb3630 100644
--- a/actionpack/test/controller/helper_test.rb
+++ b/actionpack/test/controller/helper_test.rb
@@ -27,7 +27,7 @@ module Fun
end
end
-class ApplicationController < ActionController::Base
+class AllHelpersController < ActionController::Base
helper :all
end
@@ -127,7 +127,7 @@ class HelperTest < Test::Unit::TestCase
end
def test_all_helpers
- methods = ApplicationController.master_helper_module.instance_methods.map(&:to_s)
+ methods = AllHelpersController.master_helper_module.instance_methods.map(&:to_s)
# abc_helper.rb
assert methods.include?('bare_a')
@@ -154,7 +154,7 @@ class HelperTest < Test::Unit::TestCase
end
def test_helper_proxy
- methods = ApplicationController.helpers.methods.map(&:to_s)
+ methods = AllHelpersController.helpers.methods.map(&:to_s)
# ActionView
assert methods.include?('pluralize')
diff --git a/actionpack/test/new_base/abstract_unit.rb b/actionpack/test/new_base/abstract_unit.rb
index 5df3467ff5..569e4e764f 100644
--- a/actionpack/test/new_base/abstract_unit.rb
+++ b/actionpack/test/new_base/abstract_unit.rb
@@ -2,6 +2,9 @@ $:.unshift(File.dirname(__FILE__) + '/../../lib')
$:.unshift(File.dirname(__FILE__) + '/../../../activesupport/lib')
$:.unshift(File.dirname(__FILE__) + '/../lib')
+$:.unshift(File.dirname(__FILE__) + '/../fixtures/helpers')
+$:.unshift(File.dirname(__FILE__) + '/../fixtures/alternate_helpers')
+
ENV['new_base'] = "true"
$stderr.puts "Running old tests on new_base"
diff --git a/actionpack/test/new_base/render_text_test.rb b/actionpack/test/new_base/render_text_test.rb
index aed903ee8a..ffc149283b 100644
--- a/actionpack/test/new_base/render_text_test.rb
+++ b/actionpack/test/new_base/render_text_test.rb
@@ -1,8 +1,5 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
-class ApplicationController < ActionController::Base
-end
-
module RenderText
class SimpleController < ActionController::Base
self.view_paths = [ActionView::Template::FixturePath.new]
--
cgit v1.2.3
From 01129534cde293e3561dd7cc3cb5ae9ac3de9e8c Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 22 May 2009 12:28:40 -0700
Subject: Cleaned up the #render_to_body chain by extracting determining the
templates to render to a separate hook point.
---
.../lib/action_controller/abstract/layouts.rb | 4 ----
.../lib/action_controller/abstract/renderer.rb | 24 ++++++++++++++--------
.../lib/action_controller/new_base/renderer.rb | 24 ++++++++++++++--------
3 files changed, 30 insertions(+), 22 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 557d68d866..dec394a021 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -57,10 +57,6 @@ module AbstractController
end
end
end
-
- def _render_template(template, options)
- _action_view._render_template_from_controller(template, options[:_layout], options, options[:_partial])
- end
private
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index f2044a35ec..d7c68549e1 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -33,16 +33,12 @@ module AbstractController
#
# :api: plugin
def render_to_body(options = {})
- name = options[:_template_name] || action_name
-
# TODO: Refactor so we can just use the normal template logic for this
if options[:_partial_object]
_action_view._render_partial_from_controller(options)
- else
- options[:_template] ||= view_paths.find_by_parts(name.to_s, {:formats => formats},
- options[:_prefix], options[:_partial])
-
- _render_template(options[:_template], options)
+ else
+ _determine_template(options)
+ _render_template(options)
end
end
@@ -56,8 +52,8 @@ module AbstractController
AbstractController::Renderer.body_to_s(render_to_body(options))
end
- def _render_template(template, options)
- _action_view._render_template_from_controller(template, nil, options, options[:_partial])
+ def _render_template(options)
+ _action_view._render_template_from_controller(options[:_template], options[:_layout], options, options[:_partial])
end
def view_paths() _view_paths end
@@ -74,6 +70,16 @@ module AbstractController
end
end
+ private
+
+ def _determine_template(options)
+ name = (options[:_template_name] || action_name).to_s
+
+ options[:_template] ||= view_paths.find_by_parts(
+ name, { :formats => formats }, options[:_prefix], options[:_partial]
+ )
+ end
+
module ClassMethods
def append_view_path(path)
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 59df3c51da..987751a601 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -27,6 +27,20 @@ module ActionController
def render_to_body(options)
_process_options(options)
+ if options.key?(:partial)
+ _render_partial(options[:partial], options)
+ end
+
+ super
+ end
+
+ private
+
+ def _prefix
+ controller_path
+ end
+
+ def _determine_template(options)
if options.key?(:text)
options[:_template] = ActionView::TextTemplate.new(options[:text], formats.first)
elsif options.key?(:inline)
@@ -37,21 +51,13 @@ module ActionController
options[:_template_name] = options[:template]
elsif options.key?(:file)
options[:_template_name] = options[:file]
- elsif options.key?(:partial)
- _render_partial(options[:partial], options)
- else
+ elsif !options.key?(:partial)
options[:_template_name] = (options[:action] || action_name).to_s
options[:_prefix] = _prefix
end
super
end
-
- private
-
- def _prefix
- controller_path
- end
def _render_partial(partial, options)
case partial
--
cgit v1.2.3
From 72a574b5073b1debd58c954b34c54d3bdee7749f Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 22 May 2009 15:16:28 -0700
Subject: Get controller/layout_test.rb running on new base except for
ActionController::Base.exempt_from_layout which is going to be deprecated.
---
actionpack/Rakefile | 13 +++++++------
.../lib/action_controller/abstract/layouts.rb | 6 +++---
.../lib/action_controller/new_base/layouts.rb | 21 +++++++++------------
actionpack/lib/action_view/template/template.rb | 2 +-
actionpack/lib/action_view/template/text.rb | 4 ++++
actionpack/test/controller/layout_test.rb | 17 ++++++++++-------
6 files changed, 34 insertions(+), 29 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 0ce6f7823b..6c820636d5 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -61,12 +61,13 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
# layout
# Dir.glob( "test/{dispatch,template}/**/*_test.rb" ).sort +
t.test_files = %w(
- addresses_render base benchmark caching capture content_type dispatcher
- flash mime_responds record_identifier redirect
- render render_json render_xml
- send_file request_forgery_protection rescue url_rewriter verification webservice
- http_basic_authentication http_digest_authentication
- action_pack_assertions assert_select filter_params helper
+ action_pack_assertions addresses_render assert_select
+ base benchmark caching capture content_type dispatcher
+ filter_params flash helper http_basic_authentication
+ http_digest_authentication layout mime_responds
+ record_identifier redirect render render_json render_xml
+ send_file request_forgery_protection rescue url_rewriter
+ verification webservice
).map { |name| "test/controller/#{name}_test.rb" }
end
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index dec394a021..b3b743d6e8 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -65,12 +65,12 @@ module AbstractController
# :api: plugin
# ====
# Override this to mutate the inbound layout name
- def _layout_for_name(name)
+ def _layout_for_name(name, details = {:formats => formats})
unless [String, FalseClass, NilClass].include?(name.class)
raise ArgumentError, "String, false, or nil expected; you passed #{name.inspect}"
end
- name && view_paths.find_by_parts(name, {:formats => formats}, _layout_prefix(name))
+ name && view_paths.find_by_parts(name, details, _layout_prefix(name))
end
# TODO: Decide if this is the best hook point for the feature
@@ -78,7 +78,7 @@ module AbstractController
"layouts"
end
- def _default_layout(require_layout = false)
+ def _default_layout(require_layout = false, details = {:formats => formats})
if require_layout && _action_has_layout? && !_layout
raise ArgumentError,
"There was no default layout for #{self.class} in #{view_paths.inspect}"
diff --git a/actionpack/lib/action_controller/new_base/layouts.rb b/actionpack/lib/action_controller/new_base/layouts.rb
index bf5b14c4e1..35068db770 100644
--- a/actionpack/lib/action_controller/new_base/layouts.rb
+++ b/actionpack/lib/action_controller/new_base/layouts.rb
@@ -11,23 +11,20 @@ module ActionController
end
end
- def render_to_body(options)
- # render :text => ..., :layout => ...
- # or
- # render :anything_else
+ private
+
+ def _determine_template(options)
+ super
if (!options.key?(:text) && !options.key?(:inline) && !options.key?(:partial)) || options.key?(:layout)
- options[:_layout] = options.key?(:layout) ? _layout_for_option(options[:layout]) : _default_layout
+ options[:_layout] = _layout_for_option(options.key?(:layout) ? options[:layout] : :none, options[:_template].details)
end
-
- super
end
-
- private
- def _layout_for_option(name)
+ def _layout_for_option(name, details)
case name
- when String then _layout_for_name(name)
- when true then _default_layout(true)
+ when String then _layout_for_name(name, details)
+ when true then _default_layout(true, details)
+ when :none then _default_layout(false, details)
when false, nil then nil
else
raise ArgumentError,
diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb
index 0eedc596d2..d58f4ec19e 100644
--- a/actionpack/lib/action_view/template/template.rb
+++ b/actionpack/lib/action_view/template/template.rb
@@ -7,7 +7,7 @@ require "action_view/template/path"
module ActionView
class Template
extend TemplateHandlers
- attr_reader :source, :identifier, :handler, :mime_type
+ attr_reader :source, :identifier, :handler, :mime_type, :details
def initialize(source, identifier, handler, details)
@source = source
diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb
index a86c3915c2..fd57b1677e 100644
--- a/actionpack/lib/action_view/template/text.rb
+++ b/actionpack/lib/action_view/template/text.rb
@@ -6,6 +6,10 @@ module ActionView #:nodoc:
@content_type = Mime[content_type]
end
+ def details
+ {:formats => [@content_type.to_sym]}
+ end
+
def identifier() self end
def render(*) self end
diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb
index 1cd448d5e8..04da0a7f86 100644
--- a/actionpack/test/controller/layout_test.rb
+++ b/actionpack/test/controller/layout_test.rb
@@ -174,15 +174,18 @@ class LayoutSetInResponseTest < ActionController::TestCase
assert_nil @controller.template.layout
end
- def test_exempt_from_layout_honored_by_render_template
- ActionController::Base.exempt_from_layout :erb
- @controller = RenderWithTemplateOptionController.new
+ for_tag(:old_base) do
+ # exempt_from_layout is deprecated
+ def test_exempt_from_layout_honored_by_render_template
+ ActionController::Base.exempt_from_layout :erb
+ @controller = RenderWithTemplateOptionController.new
- get :hello
- assert_equal "alt/hello.rhtml", @response.body.strip
+ get :hello
+ assert_equal "alt/hello.rhtml", @response.body.strip
- ensure
- ActionController::Base.exempt_from_layout.delete(ERB)
+ ensure
+ ActionController::Base.exempt_from_layout.delete(ERB)
+ end
end
def test_layout_is_picked_from_the_controller_instances_view_path
--
cgit v1.2.3
From 8a336d01d2c403f0a2fb818edb8db836ddc367ef Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Sat, 23 May 2009 00:30:11 +0200
Subject: Use super wherever possible in ActionController::Helpers#helper
---
actionpack/lib/action_controller/new_base/helpers.rb | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base/helpers.rb b/actionpack/lib/action_controller/new_base/helpers.rb
index 401741c249..e00c3c338b 100644
--- a/actionpack/lib/action_controller/new_base/helpers.rb
+++ b/actionpack/lib/action_controller/new_base/helpers.rb
@@ -16,8 +16,6 @@ module ActionController
module ClassMethods
def inherited(klass)
- # klass.master_helper_module = Module.new
- # klass.master_helper_module.__send__ :include, master_helper_module
klass.__send__ :default_helper_module!
super
end
@@ -78,10 +76,9 @@ module ActionController
end
end
- add_template_helper(class_name.constantize)
+ super class_name.constantize
else
- # Explcit 'return' here so that the supplied block ( if any ) doesn't get included twice
- return super
+ super args
end
end
--
cgit v1.2.3
From df2d96a7f05aebca3e9d2367c2a248125b24dca6 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Fri, 22 May 2009 11:10:41 -0700
Subject: Move misplaced test
---
actionmailer/test/adv_attr_test.rb | 18 ++++++++++++++++++
actionpack/test/adv_attr_test.rb | 20 --------------------
2 files changed, 18 insertions(+), 20 deletions(-)
create mode 100644 actionmailer/test/adv_attr_test.rb
delete mode 100644 actionpack/test/adv_attr_test.rb
diff --git a/actionmailer/test/adv_attr_test.rb b/actionmailer/test/adv_attr_test.rb
new file mode 100644
index 0000000000..fd909a5627
--- /dev/null
+++ b/actionmailer/test/adv_attr_test.rb
@@ -0,0 +1,18 @@
+require 'abstract_unit'
+require 'action_mailer/adv_attr_accessor'
+
+class AdvAttrTest < Test::Unit::TestCase
+ class Person
+ include ActionMailer::AdvAttrAccessor
+ adv_attr_accessor :name
+ end
+
+ def test_adv_attr
+ bob = Person.new
+ assert_nil bob.name
+ bob.name 'Bob'
+ assert_equal 'Bob', bob.name
+
+ assert_raise(ArgumentError) {bob.name 'x', 'y'}
+ end
+end
diff --git a/actionpack/test/adv_attr_test.rb b/actionpack/test/adv_attr_test.rb
deleted file mode 100644
index fdda4ad92d..0000000000
--- a/actionpack/test/adv_attr_test.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require File.dirname(__FILE__) + '/abstract_unit'
-require 'action_mailer/adv_attr_accessor'
-
-class AdvAttrTest < Test::Unit::TestCase
- class Person
- include ActionMailer::AdvAttrAccessor
- adv_attr_accessor :name
- end
-
- def test_adv_attr
- bob = Person.new
- assert_nil bob.name
- bob.name 'Bob'
- assert_equal 'Bob', bob.name
-
- assert_raise(ArgumentError) {bob.name 'x', 'y'}
- end
-
-
-end
\ No newline at end of file
--
cgit v1.2.3
From 3c13551aa2c7f43f7863349ef5699d42dd255801 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Fri, 22 May 2009 11:12:51 -0700
Subject: Complain if new_base/abstract_unit was already loaded
---
actionpack/test/abstract_unit.rb | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 5ae54d097a..c71da7fa6c 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -1,3 +1,7 @@
+if ENV['new_base']
+ puts *caller
+ raise 'new_base/abstract_unit already loaded'
+end
$:.unshift(File.dirname(__FILE__) + '/../lib')
$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
$:.unshift(File.dirname(__FILE__) + '/fixtures/helpers')
--
cgit v1.2.3
From 98f856d7723bd8aa8ccc05dfb7219c897b4dcab7 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Fri, 22 May 2009 11:13:34 -0700
Subject: Set ENV['NEW'] to run any test task with the new Base.
---
actionpack/Rakefile | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 6c820636d5..79a582033a 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -24,8 +24,9 @@ task :default => [ :test ]
desc "Run all unit tests"
task :test => [:test_action_pack, :test_active_record_integration, :test_new_base, :test_new_base_on_old_tests]
+test_lib_dir = ENV["NEW"] ? "test/new_base" : "test"
Rake::TestTask.new(:test_action_pack) do |t|
- t.libs << "test"
+ t.libs << test_lib_dir
# make sure we include the tests in alphabetical order as on some systems
# this will not happen automatically and the tests (as a whole) will error
@@ -37,27 +38,27 @@ end
task :isolated_test do
ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
Dir.glob("test/{controller,dispatch,template}/**/*_test.rb").all? do |file|
- system(ruby, '-Ilib:test', file)
+ system(ruby, "-Ilib:#{test_lib_dir}", file)
end or raise "Failures"
end
desc 'ActiveRecord Integration Tests'
Rake::TestTask.new(:test_active_record_integration) do |t|
- t.libs << "test"
+ t.libs << test_lib_dir
t.test_files = Dir.glob("test/activerecord/*_test.rb")
t.verbose = true
end
desc 'New Controller Tests'
Rake::TestTask.new(:test_new_base) do |t|
- t.libs << "test"
+ t.libs << "test/new_base"
t.test_files = Dir.glob("test/{abstract_controller,new_base}/*_test.rb")
t.verbose = true
end
desc 'Old Controller Tests on New Base'
Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
- t.libs << "test/new_base" << "test"
+ t.libs << "test/new_base"
# layout
# Dir.glob( "test/{dispatch,template}/**/*_test.rb" ).sort +
t.test_files = %w(
@@ -71,7 +72,6 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
).map { |name| "test/controller/#{name}_test.rb" }
end
-
# Genereate the RDoc documentation
Rake::RDocTask.new { |rdoc|
--
cgit v1.2.3
From ca7207838844f02f50afbb18beb0f535903f7929 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Fri, 22 May 2009 16:11:54 -0700
Subject: Move fake controllers and models to a common load path
---
actionpack/Rakefile | 12 ++++----
actionpack/test/controller/fake_controllers.rb | 33 ----------------------
actionpack/test/controller/fake_models.rb | 19 -------------
actionpack/test/controller/layout_test.rb | 2 +-
actionpack/test/lib/controller/fake_controllers.rb | 33 ++++++++++++++++++++++
actionpack/test/lib/controller/fake_models.rb | 19 +++++++++++++
6 files changed, 59 insertions(+), 59 deletions(-)
delete mode 100644 actionpack/test/controller/fake_controllers.rb
delete mode 100644 actionpack/test/controller/fake_models.rb
create mode 100644 actionpack/test/lib/controller/fake_controllers.rb
create mode 100644 actionpack/test/lib/controller/fake_models.rb
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 79a582033a..6ad061b0b1 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -24,9 +24,9 @@ task :default => [ :test ]
desc "Run all unit tests"
task :test => [:test_action_pack, :test_active_record_integration, :test_new_base, :test_new_base_on_old_tests]
-test_lib_dir = ENV["NEW"] ? "test/new_base" : "test"
+test_lib_dirs = [ENV["NEW"] ? "test/new_base" : "test", "test/lib"]
Rake::TestTask.new(:test_action_pack) do |t|
- t.libs << test_lib_dir
+ t.libs.concat test_lib_dirs
# make sure we include the tests in alphabetical order as on some systems
# this will not happen automatically and the tests (as a whole) will error
@@ -38,27 +38,27 @@ end
task :isolated_test do
ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
Dir.glob("test/{controller,dispatch,template}/**/*_test.rb").all? do |file|
- system(ruby, "-Ilib:#{test_lib_dir}", file)
+ system(ruby, "-Ilib:#{test_lib_dirs * ':'}", file)
end or raise "Failures"
end
desc 'ActiveRecord Integration Tests'
Rake::TestTask.new(:test_active_record_integration) do |t|
- t.libs << test_lib_dir
+ t.libs.concat test_lib_dirs
t.test_files = Dir.glob("test/activerecord/*_test.rb")
t.verbose = true
end
desc 'New Controller Tests'
Rake::TestTask.new(:test_new_base) do |t|
- t.libs << "test/new_base"
+ t.libs << "test/new_base" << "test/lib"
t.test_files = Dir.glob("test/{abstract_controller,new_base}/*_test.rb")
t.verbose = true
end
desc 'Old Controller Tests on New Base'
Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
- t.libs << "test/new_base"
+ t.libs << "test/new_base" << "test/lib"
# layout
# Dir.glob( "test/{dispatch,template}/**/*_test.rb" ).sort +
t.test_files = %w(
diff --git a/actionpack/test/controller/fake_controllers.rb b/actionpack/test/controller/fake_controllers.rb
deleted file mode 100644
index 75c114c103..0000000000
--- a/actionpack/test/controller/fake_controllers.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-class << Object; alias_method :const_available?, :const_defined?; end
-
-class ContentController < Class.new(ActionController::Base)
-end
-class NotAController
-end
-module Admin
- class << self; alias_method :const_available?, :const_defined?; end
- class UserController < Class.new(ActionController::Base); end
- class NewsFeedController < Class.new(ActionController::Base); end
-end
-
-# For speed test
-class SpeedController < ActionController::Base; end
-class SearchController < SpeedController; end
-class VideosController < SpeedController; end
-class VideoFileController < SpeedController; end
-class VideoSharesController < SpeedController; end
-class VideoAbusesController < SpeedController; end
-class VideoUploadsController < SpeedController; end
-class VideoVisitsController < SpeedController; end
-class UsersController < SpeedController; end
-class SettingsController < SpeedController; end
-class ChannelsController < SpeedController; end
-class ChannelVideosController < SpeedController; end
-class SessionsController < SpeedController; end
-class LostPasswordsController < SpeedController; end
-class PagesController < SpeedController; end
-
-ActionController::Routing::Routes.draw do |map|
- map.route_one 'route_one', :controller => 'elsewhere', :action => 'flash_me'
- map.connect ':controller/:action/:id'
-end
diff --git a/actionpack/test/controller/fake_models.rb b/actionpack/test/controller/fake_models.rb
deleted file mode 100644
index 0b30c79b10..0000000000
--- a/actionpack/test/controller/fake_models.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-class Customer < Struct.new(:name, :id)
- def to_param
- id.to_s
- end
-end
-
-class BadCustomer < Customer
-end
-
-class GoodCustomer < Customer
-end
-
-module Quiz
- class Question < Struct.new(:name, :id)
- def to_param
- id.to_s
- end
- end
-end
diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb
index 04da0a7f86..cb9bdf57bb 100644
--- a/actionpack/test/controller/layout_test.rb
+++ b/actionpack/test/controller/layout_test.rb
@@ -9,7 +9,7 @@ ActionView::Template::register_template_handler :mab,
ActionController::Base.view_paths = [ File.dirname(__FILE__) + '/../fixtures/layout_tests/' ]
-require "lib/fixture_template"
+require "fixture_template"
class LayoutTest < ActionController::Base
def self.controller_path; 'views' end
diff --git a/actionpack/test/lib/controller/fake_controllers.rb b/actionpack/test/lib/controller/fake_controllers.rb
new file mode 100644
index 0000000000..75c114c103
--- /dev/null
+++ b/actionpack/test/lib/controller/fake_controllers.rb
@@ -0,0 +1,33 @@
+class << Object; alias_method :const_available?, :const_defined?; end
+
+class ContentController < Class.new(ActionController::Base)
+end
+class NotAController
+end
+module Admin
+ class << self; alias_method :const_available?, :const_defined?; end
+ class UserController < Class.new(ActionController::Base); end
+ class NewsFeedController < Class.new(ActionController::Base); end
+end
+
+# For speed test
+class SpeedController < ActionController::Base; end
+class SearchController < SpeedController; end
+class VideosController < SpeedController; end
+class VideoFileController < SpeedController; end
+class VideoSharesController < SpeedController; end
+class VideoAbusesController < SpeedController; end
+class VideoUploadsController < SpeedController; end
+class VideoVisitsController < SpeedController; end
+class UsersController < SpeedController; end
+class SettingsController < SpeedController; end
+class ChannelsController < SpeedController; end
+class ChannelVideosController < SpeedController; end
+class SessionsController < SpeedController; end
+class LostPasswordsController < SpeedController; end
+class PagesController < SpeedController; end
+
+ActionController::Routing::Routes.draw do |map|
+ map.route_one 'route_one', :controller => 'elsewhere', :action => 'flash_me'
+ map.connect ':controller/:action/:id'
+end
diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb
new file mode 100644
index 0000000000..0b30c79b10
--- /dev/null
+++ b/actionpack/test/lib/controller/fake_models.rb
@@ -0,0 +1,19 @@
+class Customer < Struct.new(:name, :id)
+ def to_param
+ id.to_s
+ end
+end
+
+class BadCustomer < Customer
+end
+
+class GoodCustomer < Customer
+end
+
+module Quiz
+ class Question < Struct.new(:name, :id)
+ def to_param
+ id.to_s
+ end
+ end
+end
--
cgit v1.2.3
From b7c031f52ecca11558edd494d292ff6b99dd21b7 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Fri, 22 May 2009 16:21:21 -0700
Subject: Move active_record_unit to shared load path
---
actionpack/test/active_record_unit.rb | 104 ------------------------------
actionpack/test/lib/active_record_unit.rb | 104 ++++++++++++++++++++++++++++++
2 files changed, 104 insertions(+), 104 deletions(-)
delete mode 100644 actionpack/test/active_record_unit.rb
create mode 100644 actionpack/test/lib/active_record_unit.rb
diff --git a/actionpack/test/active_record_unit.rb b/actionpack/test/active_record_unit.rb
deleted file mode 100644
index 9e0c66055d..0000000000
--- a/actionpack/test/active_record_unit.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-require 'abstract_unit'
-
-# Define the essentials
-class ActiveRecordTestConnector
- cattr_accessor :able_to_connect
- cattr_accessor :connected
-
- # Set our defaults
- self.connected = false
- self.able_to_connect = true
-end
-
-# Try to grab AR
-if defined?(ActiveRecord) && defined?(Fixtures)
- $stderr.puts 'Active Record is already loaded, running tests'
-else
- $stderr.print 'Attempting to load Active Record... '
- begin
- PATH_TO_AR = "#{File.dirname(__FILE__)}/../../activerecord/lib"
- raise LoadError, "#{PATH_TO_AR} doesn't exist" unless File.directory?(PATH_TO_AR)
- $LOAD_PATH.unshift PATH_TO_AR
- require 'active_record'
- require 'active_record/fixtures'
- $stderr.puts 'success'
- rescue LoadError => e
- $stderr.print "failed. Skipping Active Record assertion tests: #{e}"
- ActiveRecordTestConnector.able_to_connect = false
- end
-end
-$stderr.flush
-
-
-# Define the rest of the connector
-class ActiveRecordTestConnector
- class << self
- def setup
- unless self.connected || !self.able_to_connect
- setup_connection
- load_schema
- require_fixture_models
- self.connected = true
- end
- rescue Exception => e # errors from ActiveRecord setup
- $stderr.puts "\nSkipping ActiveRecord assertion tests: #{e}"
- #$stderr.puts " #{e.backtrace.join("\n ")}\n"
- self.able_to_connect = false
- end
-
- private
- def setup_connection
- if Object.const_defined?(:ActiveRecord)
- defaults = { :database => ':memory:' }
- begin
- adapter = defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'
- options = defaults.merge :adapter => adapter, :timeout => 500
- ActiveRecord::Base.establish_connection(options)
- ActiveRecord::Base.configurations = { 'sqlite3_ar_integration' => options }
- ActiveRecord::Base.connection
- rescue Exception # errors from establishing a connection
- $stderr.puts 'SQLite 3 unavailable; trying SQLite 2.'
- options = defaults.merge :adapter => 'sqlite'
- ActiveRecord::Base.establish_connection(options)
- ActiveRecord::Base.configurations = { 'sqlite2_ar_integration' => options }
- ActiveRecord::Base.connection
- end
-
- Object.send(:const_set, :QUOTED_TYPE, ActiveRecord::Base.connection.quote_column_name('type')) unless Object.const_defined?(:QUOTED_TYPE)
- else
- raise "Can't setup connection since ActiveRecord isn't loaded."
- end
- end
-
- # Load actionpack sqlite tables
- def load_schema
- File.read(File.dirname(__FILE__) + "/fixtures/db_definitions/sqlite.sql").split(';').each do |sql|
- ActiveRecord::Base.connection.execute(sql) unless sql.blank?
- end
- end
-
- def require_fixture_models
- Dir.glob(File.dirname(__FILE__) + "/fixtures/*.rb").each {|f| require f}
- end
- end
-end
-
-class ActiveRecordTestCase < ActionController::TestCase
- include ActiveRecord::TestFixtures
-
- # Set our fixture path
- if ActiveRecordTestConnector.able_to_connect
- self.fixture_path = [FIXTURE_LOAD_PATH]
- self.use_transactional_fixtures = false
- end
-
- def self.fixtures(*args)
- super if ActiveRecordTestConnector.connected
- end
-
- def run(*args)
- super if ActiveRecordTestConnector.connected
- end
-end
-
-ActiveRecordTestConnector.setup
diff --git a/actionpack/test/lib/active_record_unit.rb b/actionpack/test/lib/active_record_unit.rb
new file mode 100644
index 0000000000..1ba308e9d7
--- /dev/null
+++ b/actionpack/test/lib/active_record_unit.rb
@@ -0,0 +1,104 @@
+require 'abstract_unit'
+
+# Define the essentials
+class ActiveRecordTestConnector
+ cattr_accessor :able_to_connect
+ cattr_accessor :connected
+
+ # Set our defaults
+ self.connected = false
+ self.able_to_connect = true
+end
+
+# Try to grab AR
+if defined?(ActiveRecord) && defined?(Fixtures)
+ $stderr.puts 'Active Record is already loaded, running tests'
+else
+ $stderr.print 'Attempting to load Active Record... '
+ begin
+ PATH_TO_AR = "#{File.dirname(__FILE__)}/../../../activerecord/lib"
+ raise LoadError, "#{PATH_TO_AR} doesn't exist" unless File.directory?(PATH_TO_AR)
+ $LOAD_PATH.unshift PATH_TO_AR
+ require 'active_record'
+ require 'active_record/fixtures'
+ $stderr.puts 'success'
+ rescue LoadError => e
+ $stderr.print "failed. Skipping Active Record assertion tests: #{e}"
+ ActiveRecordTestConnector.able_to_connect = false
+ end
+end
+$stderr.flush
+
+
+# Define the rest of the connector
+class ActiveRecordTestConnector
+ class << self
+ def setup
+ unless self.connected || !self.able_to_connect
+ setup_connection
+ load_schema
+ require_fixture_models
+ self.connected = true
+ end
+ rescue Exception => e # errors from ActiveRecord setup
+ $stderr.puts "\nSkipping ActiveRecord assertion tests: #{e}"
+ #$stderr.puts " #{e.backtrace.join("\n ")}\n"
+ self.able_to_connect = false
+ end
+
+ private
+ def setup_connection
+ if Object.const_defined?(:ActiveRecord)
+ defaults = { :database => ':memory:' }
+ begin
+ adapter = defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'
+ options = defaults.merge :adapter => adapter, :timeout => 500
+ ActiveRecord::Base.establish_connection(options)
+ ActiveRecord::Base.configurations = { 'sqlite3_ar_integration' => options }
+ ActiveRecord::Base.connection
+ rescue Exception # errors from establishing a connection
+ $stderr.puts 'SQLite 3 unavailable; trying SQLite 2.'
+ options = defaults.merge :adapter => 'sqlite'
+ ActiveRecord::Base.establish_connection(options)
+ ActiveRecord::Base.configurations = { 'sqlite2_ar_integration' => options }
+ ActiveRecord::Base.connection
+ end
+
+ Object.send(:const_set, :QUOTED_TYPE, ActiveRecord::Base.connection.quote_column_name('type')) unless Object.const_defined?(:QUOTED_TYPE)
+ else
+ raise "Can't setup connection since ActiveRecord isn't loaded."
+ end
+ end
+
+ # Load actionpack sqlite tables
+ def load_schema
+ File.read(File.dirname(__FILE__) + "/../fixtures/db_definitions/sqlite.sql").split(';').each do |sql|
+ ActiveRecord::Base.connection.execute(sql) unless sql.blank?
+ end
+ end
+
+ def require_fixture_models
+ Dir.glob(File.dirname(__FILE__) + "/../fixtures/*.rb").each {|f| require f}
+ end
+ end
+end
+
+class ActiveRecordTestCase < ActionController::TestCase
+ include ActiveRecord::TestFixtures
+
+ # Set our fixture path
+ if ActiveRecordTestConnector.able_to_connect
+ self.fixture_path = [FIXTURE_LOAD_PATH]
+ self.use_transactional_fixtures = false
+ end
+
+ def self.fixtures(*args)
+ super if ActiveRecordTestConnector.connected
+ end
+
+ def run(*args)
+ super if ActiveRecordTestConnector.connected
+ end
+end
+
+ActiveRecordTestConnector.setup
--
cgit v1.2.3
From 444480c9a5d9c75568a243bb73a040b3cf050814 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Fri, 22 May 2009 16:23:48 -0700
Subject: Verbose test_new_base_on_old_tests
---
actionpack/Rakefile | 1 +
1 file changed, 1 insertion(+)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 6ad061b0b1..18e5b3d96a 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -70,6 +70,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
send_file request_forgery_protection rescue url_rewriter
verification webservice
).map { |name| "test/controller/#{name}_test.rb" }
+ t.verbose = true
end
# Genereate the RDoc documentation
--
cgit v1.2.3
From a01d2a25867dbe5235c29557673f3a5692b82aec Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Fri, 22 May 2009 16:25:49 -0700
Subject: Remove gratuitous filter_chain internal testing. Not part of the API
and other tests are sufficient to catch regressions.
---
actionpack/test/controller/filters_test.rb | 25 -------------------------
1 file changed, 25 deletions(-)
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index afefc6a77e..490061ed9b 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -1,6 +1,5 @@
require 'abstract_unit'
-# FIXME: crashes Ruby 1.9
class FilterTest < Test::Unit::TestCase
include ActionController::TestProcess
@@ -141,14 +140,6 @@ class FilterTest < Test::Unit::TestCase
before_filter :clean_up_tmp, :if => Proc.new { |c| false }
end
- class EmptyFilterChainController < TestController
- self.filter_chain.clear
- def show
- @action_executed = true
- render :text => "yawp!"
- end
- end
-
class PrependingController < TestController
prepend_before_filter :wonderful_life
# skip_before_filter :fire_flash
@@ -455,12 +446,6 @@ class FilterTest < Test::Unit::TestCase
assert_equal ["filter_one", "zomg it didn't yield"], controller.assigns['filters']
end
- def test_empty_filter_chain
- assert_equal 0, EmptyFilterChainController.filter_chain.size
- test_process(EmptyFilterChainController)
- assert @controller.template.assigns['action_executed']
- end
-
def test_added_filter_to_inheritance_graph
assert_equal [ :ensure_login ], TestController.before_filters
end
@@ -614,7 +599,6 @@ class FilterTest < Test::Unit::TestCase
end
def test_running_prepended_before_and_after_filter
- assert_equal 3, PrependingBeforeAndAfterController.filter_chain.length
test_process(PrependingBeforeAndAfterController)
assert_equal %w( before_all between_before_all_and_after_all after_all ), @controller.template.assigns["ran_filter"]
end
@@ -818,15 +802,6 @@ class YieldingAroundFiltersTest < Test::Unit::TestCase
include PostsController::AroundExceptions
include ActionController::TestProcess
- def test_filters_registering
- assert_equal 1, ControllerWithFilterMethod.filter_chain.size
- assert_equal 1, ControllerWithFilterClass.filter_chain.size
- assert_equal 1, ControllerWithFilterInstance.filter_chain.size
- assert_equal 3, ControllerWithSymbolAsFilter.filter_chain.size
- assert_equal 6, ControllerWithNestedFilters.filter_chain.size
- assert_equal 4, ControllerWithAllTypesOfFilters.filter_chain.size
- end
-
def test_base
controller = PostsController
assert_nothing_raised { test_process(controller,'no_raise') }
--
cgit v1.2.3
From f766f669464fa9900197d6b3559c2e00e53de9cd Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Sat, 23 May 2009 01:36:09 +0200
Subject: Make logging_test pass with the new base
---
actionpack/Rakefile | 2 +-
actionpack/lib/action_controller/base/filter_parameter_logging.rb | 2 +-
actionpack/test/controller/logging_test.rb | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 18e5b3d96a..2b48b2cad5 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -68,7 +68,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
http_digest_authentication layout mime_responds
record_identifier redirect render render_json render_xml
send_file request_forgery_protection rescue url_rewriter
- verification webservice
+ verification webservice logging
).map { |name| "test/controller/#{name}_test.rb" }
t.verbose = true
end
diff --git a/actionpack/lib/action_controller/base/filter_parameter_logging.rb b/actionpack/lib/action_controller/base/filter_parameter_logging.rb
index 8e012b2a25..f5a678ca03 100644
--- a/actionpack/lib/action_controller/base/filter_parameter_logging.rb
+++ b/actionpack/lib/action_controller/base/filter_parameter_logging.rb
@@ -71,7 +71,7 @@ module ActionController
if logger
parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
- parameters = parameters.except!(:controller, :action, :format, :_method)
+ parameters = parameters.except!(:controller, :action, :format, :_method, :only_path)
unless parameters.empty?
# TODO : Move DelayedLog to AS
diff --git a/actionpack/test/controller/logging_test.rb b/actionpack/test/controller/logging_test.rb
index 75afa2d133..a7ed1b8665 100644
--- a/actionpack/test/controller/logging_test.rb
+++ b/actionpack/test/controller/logging_test.rb
@@ -35,7 +35,7 @@ class LoggingTest < ActionController::TestCase
end
def test_logging_with_parameters
- get :show, :id => 10
+ get :show, :id => '10'
assert_equal 3, logs.size
params = logs.detect {|l| l =~ /Parameters/ }
@@ -49,6 +49,6 @@ class LoggingTest < ActionController::TestCase
end
def logs
- @logs ||= @controller.logger.logged.compact.map {|l| l.strip}
+ @logs ||= @controller.logger.logged.compact.map {|l| l.to_s.strip}
end
end
--
cgit v1.2.3
From b77602824afe07dfd8fd8e48407a6086802ec7ef Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Sat, 23 May 2009 01:40:50 +0200
Subject: Add some more tests to the test_new_base_on_old_tests task
---
actionpack/Rakefile | 2 +-
actionpack/test/controller/routing_test.rb | 1 +
actionpack/test/controller/selector_test.rb | 1 +
actionpack/test/new_base/abstract_unit.rb | 1 +
4 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 2b48b2cad5..448acf20cb 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -68,7 +68,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
http_digest_authentication layout mime_responds
record_identifier redirect render render_json render_xml
send_file request_forgery_protection rescue url_rewriter
- verification webservice logging
+ verification webservice logging resources routing
).map { |name| "test/controller/#{name}_test.rb" }
t.verbose = true
end
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index 77abb68f32..11bffdb42e 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'controller/fake_controllers'
+require 'active_support/dependencies'
class MilestonesController < ActionController::Base
def index() head :ok end
diff --git a/actionpack/test/controller/selector_test.rb b/actionpack/test/controller/selector_test.rb
index 9d0613d1e2..5a5dc840b5 100644
--- a/actionpack/test/controller/selector_test.rb
+++ b/actionpack/test/controller/selector_test.rb
@@ -5,6 +5,7 @@
require 'abstract_unit'
require 'controller/fake_controllers'
+require 'action_controller/vendor/html-scanner'
class SelectorTest < Test::Unit::TestCase
#
diff --git a/actionpack/test/new_base/abstract_unit.rb b/actionpack/test/new_base/abstract_unit.rb
index 569e4e764f..0b71488bd6 100644
--- a/actionpack/test/new_base/abstract_unit.rb
+++ b/actionpack/test/new_base/abstract_unit.rb
@@ -10,6 +10,7 @@ $stderr.puts "Running old tests on new_base"
require 'test/unit'
require 'active_support'
+require 'active_support/core_ext'
require 'active_support/test_case'
require 'action_controller/abstract'
require 'action_controller/new_base'
--
cgit v1.2.3
From 63ed43cb9901cc7adc352a51fa256c3ba7b6637f Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 22 May 2009 15:50:31 -0700
Subject: Added render_other_test.rb to the new base test runner
---
actionpack/Rakefile | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 448acf20cb..99ef542f3e 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -61,14 +61,24 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
t.libs << "test/new_base" << "test/lib"
# layout
# Dir.glob( "test/{dispatch,template}/**/*_test.rb" ).sort +
+
+ # ==== Not ported
+ # * cookie
+ # * filters
+ # * integration
+ # * render_js
+ # * selector
+ # * test
+ # * translation
+ # * view_paths
t.test_files = %w(
action_pack_assertions addresses_render assert_select
base benchmark caching capture content_type dispatcher
filter_params flash helper http_basic_authentication
- http_digest_authentication layout mime_responds
- record_identifier redirect render render_json render_xml
- send_file request_forgery_protection rescue url_rewriter
- verification webservice logging resources routing
+ http_digest_authentication layout logging mime_responds
+ record_identifier redirect render render_json render_other render_xml
+ request_forgery_protection rescue resources routing send_file
+ url_rewriter verification webservice
).map { |name| "test/controller/#{name}_test.rb" }
t.verbose = true
end
--
cgit v1.2.3
From 28dbeb3a643eeb35767df55ed579f54438c3ee18 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 22 May 2009 16:50:26 -0700
Subject: Get controller/render_other_test.rb to pass on new base and fixed a
bug in new base with regards to rendering layouts.
---
actionpack/lib/action_controller/abstract/layouts.rb | 2 +-
actionpack/lib/action_view/template/template.rb | 3 ++-
actionpack/test/controller/render_other_test.rb | 14 +++++++++++---
3 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index b3b743d6e8..8721e5f4dc 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -85,7 +85,7 @@ module AbstractController
end
begin
- _layout_for_name(_layout) if _action_has_layout?
+ _layout_for_name(_layout, details) if _action_has_layout?
rescue NameError => e
raise NoMethodError,
"You specified #{@_layout.inspect} as the layout, but no such method was found"
diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb
index d58f4ec19e..f61dd591a5 100644
--- a/actionpack/lib/action_view/template/template.rb
+++ b/actionpack/lib/action_view/template/template.rb
@@ -15,11 +15,12 @@ module ActionView
@handler = handler
@details = details
- format = details[:format] || begin
+ format = details.delete(:format) || begin
# TODO: Clean this up
handler.respond_to?(:default_format) ? handler.default_format.to_sym.to_s : "html"
end
@mime_type = Mime::Type.lookup_by_extension(format.to_s)
+ @details[:formats] = Array.wrap(format && format.to_sym)
end
def render(view, locals, &blk)
diff --git a/actionpack/test/controller/render_other_test.rb b/actionpack/test/controller/render_other_test.rb
index 3c52b7036d..05645e47fa 100644
--- a/actionpack/test/controller/render_other_test.rb
+++ b/actionpack/test/controller/render_other_test.rb
@@ -4,6 +4,7 @@ require 'pathname'
class TestController < ActionController::Base
protect_from_forgery
+ layout :determine_layout
module RenderTestHelper
def rjs_helper_method_from_module
@@ -113,9 +114,16 @@ private
def determine_layout
case action_name
- when "render_js_with_explicit_template",
- "render_js_with_explicit_action_template",
- "delete_with_js", "update_page", "update_page_with_instance_variables"
+ when "hello_world", "layout_test", "rendering_without_layout",
+ "rendering_nothing_on_layout", "render_text_hello_world",
+ "render_text_hello_world_with_layout",
+ "hello_world_with_layout_false",
+ "partial_only", "partial_only_with_layout",
+ "accessing_params_in_template",
+ "accessing_params_in_template_with_layout",
+ "render_with_explicit_template",
+ "render_with_explicit_string_template",
+ "update_page", "update_page_with_instance_variables"
"layouts/standard"
when "action_talk_to_layout", "layout_overriding_layout"
--
cgit v1.2.3
From c90f613ad68253cb253bf47cb812f9e027c35d10 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Sat, 23 May 2009 01:59:23 +0200
Subject: Add Translation to the new base
---
actionpack/lib/action_controller/new_base.rb | 1 +
actionpack/lib/action_controller/new_base/base.rb | 1 +
actionpack/test/new_base/abstract_unit.rb | 3 +++
3 files changed, 5 insertions(+)
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index d6107d3653..ad0e07e261 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -34,6 +34,7 @@ module ActionController
autoload :Streaming, 'action_controller/base/streaming'
autoload :HttpAuthentication, 'action_controller/base/http_authentication'
autoload :FilterParameterLogging, 'action_controller/base/filter_parameter_logging'
+ autoload :Translation, 'action_controller/translation'
require 'action_controller/routing'
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 6340b7fde9..85354bfea3 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -34,6 +34,7 @@ module ActionController
include ActionController::HttpAuthentication::Basic::ControllerMethods
include ActionController::HttpAuthentication::Digest::ControllerMethods
include ActionController::FilterParameterLogging
+ include ActionController::Translation
# TODO: Extract into its own module
# This should be moved together with other normalizing behavior
diff --git a/actionpack/test/new_base/abstract_unit.rb b/actionpack/test/new_base/abstract_unit.rb
index 0b71488bd6..5df2576916 100644
--- a/actionpack/test/new_base/abstract_unit.rb
+++ b/actionpack/test/new_base/abstract_unit.rb
@@ -10,7 +10,10 @@ $stderr.puts "Running old tests on new_base"
require 'test/unit'
require 'active_support'
+
+# TODO : Revisit requiring all the core extensions here
require 'active_support/core_ext'
+
require 'active_support/test_case'
require 'action_controller/abstract'
require 'action_controller/new_base'
--
cgit v1.2.3
From f9dde8fe4e14e7750e9a00c666b052bb409ead05 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Fri, 22 May 2009 16:57:45 -0700
Subject: Port cookies to new base
---
actionpack/Rakefile | 3 +-
actionpack/lib/action_controller/new_base.rb | 3 +-
actionpack/lib/action_controller/new_base/base.rb | 1 +
actionpack/test/controller/cookie_test.rb | 40 +++++++++++++++--------
4 files changed, 31 insertions(+), 16 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 99ef542f3e..c31d11503c 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -63,7 +63,6 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
# Dir.glob( "test/{dispatch,template}/**/*_test.rb" ).sort +
# ==== Not ported
- # * cookie
# * filters
# * integration
# * render_js
@@ -73,7 +72,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
# * view_paths
t.test_files = %w(
action_pack_assertions addresses_render assert_select
- base benchmark caching capture content_type dispatcher
+ base benchmark caching capture content_type cookie dispatcher
filter_params flash helper http_basic_authentication
http_digest_authentication layout logging mime_responds
record_identifier redirect render render_json render_other render_xml
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index ad0e07e261..276be50614 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -35,9 +35,10 @@ module ActionController
autoload :HttpAuthentication, 'action_controller/base/http_authentication'
autoload :FilterParameterLogging, 'action_controller/base/filter_parameter_logging'
autoload :Translation, 'action_controller/translation'
+ autoload :Cookies, 'action_controller/base/cookies'
require 'action_controller/routing'
end
require 'action_dispatch'
-require 'action_view'
\ No newline at end of file
+require 'action_view'
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 85354bfea3..e321d97ac1 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -26,6 +26,7 @@ module ActionController
# Rails 2.x compatibility
include ActionController::Rails2Compatibility
+ include ActionController::Cookies
include ActionController::Session
include ActionController::Flash
include ActionController::Verification
diff --git a/actionpack/test/controller/cookie_test.rb b/actionpack/test/controller/cookie_test.rb
index 0f22714071..39d0017dd8 100644
--- a/actionpack/test/controller/cookie_test.rb
+++ b/actionpack/test/controller/cookie_test.rb
@@ -4,44 +4,48 @@ class CookieTest < ActionController::TestCase
class TestController < ActionController::Base
def authenticate
cookies["user_name"] = "david"
+ head :ok
end
def set_with_with_escapable_characters
cookies["that & guy"] = "foo & bar => baz"
+ head :ok
end
def authenticate_for_fourteen_days
cookies["user_name"] = { "value" => "david", "expires" => Time.utc(2005, 10, 10,5) }
+ head :ok
end
def authenticate_for_fourteen_days_with_symbols
cookies[:user_name] = { :value => "david", :expires => Time.utc(2005, 10, 10,5) }
+ head :ok
end
def set_multiple_cookies
cookies["user_name"] = { "value" => "david", "expires" => Time.utc(2005, 10, 10,5) }
cookies["login"] = "XJ-122"
+ head :ok
end
def access_frozen_cookies
cookies["will"] = "work"
+ head :ok
end
def logout
cookies.delete("user_name")
+ head :ok
end
def delete_cookie_with_path
cookies.delete("user_name", :path => '/beaten')
- render :text => "hello world"
+ head :ok
end
def authenticate_with_http_only
cookies["user_name"] = { :value => "david", :httponly => true }
- end
-
- def rescue_action(e)
- raise unless ActionView::MissingTemplate # No templates here, and we don't care about the output
+ head :ok
end
end
@@ -54,38 +58,38 @@ class CookieTest < ActionController::TestCase
def test_setting_cookie
get :authenticate
- assert_equal "user_name=david; path=/", @response.headers["Set-Cookie"]
+ assert_cookie_header "user_name=david; path=/"
assert_equal({"user_name" => "david"}, @response.cookies)
end
def test_setting_with_escapable_characters
get :set_with_with_escapable_characters
- assert_equal "that+%26+guy=foo+%26+bar+%3D%3E+baz; path=/", @response.headers["Set-Cookie"]
+ assert_cookie_header "that+%26+guy=foo+%26+bar+%3D%3E+baz; path=/"
assert_equal({"that & guy" => "foo & bar => baz"}, @response.cookies)
end
def test_setting_cookie_for_fourteen_days
get :authenticate_for_fourteen_days
- assert_equal "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT", @response.headers["Set-Cookie"]
+ assert_cookie_header "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT"
assert_equal({"user_name" => "david"}, @response.cookies)
end
def test_setting_cookie_for_fourteen_days_with_symbols
get :authenticate_for_fourteen_days_with_symbols
- assert_equal "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT", @response.headers["Set-Cookie"]
+ assert_cookie_header "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT"
assert_equal({"user_name" => "david"}, @response.cookies)
end
def test_setting_cookie_with_http_only
get :authenticate_with_http_only
- assert_equal "user_name=david; path=/; HttpOnly", @response.headers["Set-Cookie"]
+ assert_cookie_header "user_name=david; path=/; HttpOnly"
assert_equal({"user_name" => "david"}, @response.cookies)
end
def test_multiple_cookies
get :set_multiple_cookies
assert_equal 2, @response.cookies.size
- assert_equal "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT\nlogin=XJ-122; path=/", @response.headers["Set-Cookie"]
+ assert_cookie_header "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT\nlogin=XJ-122; path=/"
assert_equal({"login" => "XJ-122", "user_name" => "david"}, @response.cookies)
end
@@ -95,7 +99,7 @@ class CookieTest < ActionController::TestCase
def test_expiring_cookie
get :logout
- assert_equal "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT", @response.headers["Set-Cookie"]
+ assert_cookie_header "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
assert_equal({"user_name" => nil}, @response.cookies)
end
@@ -116,6 +120,16 @@ class CookieTest < ActionController::TestCase
def test_delete_cookie_with_path
get :delete_cookie_with_path
- assert_equal "user_name=; path=/beaten; expires=Thu, 01-Jan-1970 00:00:00 GMT", @response.headers["Set-Cookie"]
+ assert_cookie_header "user_name=; path=/beaten; expires=Thu, 01-Jan-1970 00:00:00 GMT"
end
+
+ private
+ def assert_cookie_header(expected)
+ header = @response.headers["Set-Cookie"]
+ if header.respond_to?(:to_str)
+ assert_equal expected, header
+ else
+ assert_equal expected.split("\n"), header
+ end
+ end
end
--
cgit v1.2.3
From 3a72b55229f63d2cba3337c39cd118cf532ebbbc Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Sat, 23 May 2009 02:07:50 +0200
Subject: Add missing selector_test to the list
---
actionpack/Rakefile | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index c31d11503c..ea12adb921 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -66,9 +66,7 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
# * filters
# * integration
# * render_js
- # * selector
# * test
- # * translation
# * view_paths
t.test_files = %w(
action_pack_assertions addresses_render assert_select
@@ -76,8 +74,8 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
filter_params flash helper http_basic_authentication
http_digest_authentication layout logging mime_responds
record_identifier redirect render render_json render_other render_xml
- request_forgery_protection rescue resources routing send_file
- url_rewriter verification webservice
+ request_forgery_protection rescue resources routing selector send_file
+ translation url_rewriter verification webservice
).map { |name| "test/controller/#{name}_test.rb" }
t.verbose = true
end
--
cgit v1.2.3
From 7b3fb1d43f57d6ebe3edb75434cae01e140483d0 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 22 May 2009 17:07:40 -0700
Subject: Got controller/render_js_test.rb to pass on new base
---
actionpack/Rakefile | 7 +++----
actionpack/lib/action_controller/new_base/base.rb | 1 +
actionpack/lib/action_controller/new_base/render_options.rb | 10 ++++++++++
actionpack/test/controller/render_js_test.rb | 2 ++
4 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index ea12adb921..b9819d4a83 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -65,7 +65,6 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
# ==== Not ported
# * filters
# * integration
- # * render_js
# * test
# * view_paths
t.test_files = %w(
@@ -73,9 +72,9 @@ Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
base benchmark caching capture content_type cookie dispatcher
filter_params flash helper http_basic_authentication
http_digest_authentication layout logging mime_responds
- record_identifier redirect render render_json render_other render_xml
- request_forgery_protection rescue resources routing selector send_file
- translation url_rewriter verification webservice
+ record_identifier redirect render render_js render_json
+ render_other render_xml request_forgery_protection rescue
+ resources routing selector send_file url_rewriter verification webservice
).map { |name| "test/controller/#{name}_test.rb" }
t.verbose = true
end
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index e321d97ac1..adb760ea7e 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -12,6 +12,7 @@ module ActionController
include ActionController::Redirector
include ActionController::Renderer
include ActionController::Renderers::Json
+ include ActionController::Renderers::Js
include ActionController::Renderers::Xml
include ActionController::Renderers::Rjs
include ActionController::Layouts
diff --git a/actionpack/lib/action_controller/new_base/render_options.rb b/actionpack/lib/action_controller/new_base/render_options.rb
index 2ce9d0c7ae..33f8957f6e 100644
--- a/actionpack/lib/action_controller/new_base/render_options.rb
+++ b/actionpack/lib/action_controller/new_base/render_options.rb
@@ -62,6 +62,16 @@ module ActionController
end
end
+ module Js
+ include RenderOption
+ register_renderer :js
+
+ def _render_js(js, options)
+ response.content_type ||= Mime::JS
+ self.response_body = js
+ end
+ end
+
module Xml
include RenderOption
register_renderer :xml
diff --git a/actionpack/test/controller/render_js_test.rb b/actionpack/test/controller/render_js_test.rb
index 7b50242910..d02fd3fd4c 100644
--- a/actionpack/test/controller/render_js_test.rb
+++ b/actionpack/test/controller/render_js_test.rb
@@ -19,6 +19,8 @@ class TestController < ActionController::Base
end
class RenderTest < ActionController::TestCase
+ tests TestController
+
def test_render_vanilla_js
get :render_vanilla_js_hello
assert_equal "alert('hello')", @response.body
--
cgit v1.2.3
From 8a03a999ef2ed47c7f2ead1a9dd639120c569e03 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Fri, 22 May 2009 17:15:56 -0700
Subject: Cordon off missing filter methods
---
actionpack/test/controller/filters_test.rb | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index 490061ed9b..22aa50adb2 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -1,5 +1,13 @@
require 'abstract_unit'
+class << ActionController::Base
+ %w(append_around_filter prepend_after_filter prepend_around_filter prepend_before_filter skip_after_filter skip_before_filter skip_filter).each do |pending|
+ define_method(pending) do |*args|
+ $stderr.puts "#{pending} unimplemented: #{args.inspect}"
+ end unless method_defined?(pending)
+ end
+end
+
class FilterTest < Test::Unit::TestCase
include ActionController::TestProcess
--
cgit v1.2.3
From da9e53ec3b92fd583346896dd15c5b2533c8af6a Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Fri, 22 May 2009 17:17:14 -0700
Subject: Move testing_sandbox to test/lib
---
actionpack/test/lib/testing_sandbox.rb | 15 +++++++++++++++
actionpack/test/testing_sandbox.rb | 15 ---------------
2 files changed, 15 insertions(+), 15 deletions(-)
create mode 100644 actionpack/test/lib/testing_sandbox.rb
delete mode 100644 actionpack/test/testing_sandbox.rb
diff --git a/actionpack/test/lib/testing_sandbox.rb b/actionpack/test/lib/testing_sandbox.rb
new file mode 100644
index 0000000000..c36585104f
--- /dev/null
+++ b/actionpack/test/lib/testing_sandbox.rb
@@ -0,0 +1,15 @@
+module TestingSandbox
+ # Temporarily replaces KCODE for the block
+ def with_kcode(kcode)
+ if RUBY_VERSION < '1.9'
+ old_kcode, $KCODE = $KCODE, kcode
+ begin
+ yield
+ ensure
+ $KCODE = old_kcode
+ end
+ else
+ yield
+ end
+ end
+end
diff --git a/actionpack/test/testing_sandbox.rb b/actionpack/test/testing_sandbox.rb
deleted file mode 100644
index c36585104f..0000000000
--- a/actionpack/test/testing_sandbox.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-module TestingSandbox
- # Temporarily replaces KCODE for the block
- def with_kcode(kcode)
- if RUBY_VERSION < '1.9'
- old_kcode, $KCODE = $KCODE, kcode
- begin
- yield
- ensure
- $KCODE = old_kcode
- end
- else
- yield
- end
- end
-end
--
cgit v1.2.3
From 69a1ea8b5d4befe93ca4d11c052e831c7bd2e2b2 Mon Sep 17 00:00:00 2001
From: Yehuda Katz + Carl Lerche
Date: Fri, 22 May 2009 17:15:46 -0700
Subject: Created an ActionController::Renderers::All that includes all the
default render options (:json, :js, :rjs, :xml)
---
actionpack/lib/action_controller/new_base/base.rb | 5 +----
actionpack/lib/action_controller/new_base/render_options.rb | 11 +++++++++++
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index adb760ea7e..ffe608ade4 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -11,10 +11,7 @@ module ActionController
include ActionController::UrlFor
include ActionController::Redirector
include ActionController::Renderer
- include ActionController::Renderers::Json
- include ActionController::Renderers::Js
- include ActionController::Renderers::Xml
- include ActionController::Renderers::Rjs
+ include ActionController::Renderers::All
include ActionController::Layouts
include ActionController::ConditionalGet
diff --git a/actionpack/lib/action_controller/new_base/render_options.rb b/actionpack/lib/action_controller/new_base/render_options.rb
index 33f8957f6e..581a92cb7b 100644
--- a/actionpack/lib/action_controller/new_base/render_options.rb
+++ b/actionpack/lib/action_controller/new_base/render_options.rb
@@ -92,5 +92,16 @@ module ActionController
self.response_body = generator.to_s
end
end
+
+ module All
+ extend ActiveSupport::DependencyModule
+
+ included do
+ include ::ActionController::Renderers::Json
+ include ::ActionController::Renderers::Js
+ include ::ActionController::Renderers::Xml
+ include ::ActionController::Renderers::Rjs
+ end
+ end
end
end
--
cgit v1.2.3
From 595107f22e6a26e20860d0023478437a51daa5c6 Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Sat, 23 May 2009 02:20:28 +0200
Subject: Move html-scanner tests one dir up
---
actionpack/Rakefile | 2 +-
.../controller/html-scanner/cdata_node_test.rb | 15 --
.../test/controller/html-scanner/document_test.rb | 148 -----------
.../test/controller/html-scanner/node_test.rb | 89 -------
.../test/controller/html-scanner/sanitizer_test.rb | 273 ---------------------
.../test/controller/html-scanner/tag_node_test.rb | 238 ------------------
.../test/controller/html-scanner/text_node_test.rb | 50 ----
.../test/controller/html-scanner/tokenizer_test.rb | 131 ----------
actionpack/test/html-scanner/cdata_node_test.rb | 15 ++
actionpack/test/html-scanner/document_test.rb | 148 +++++++++++
actionpack/test/html-scanner/node_test.rb | 89 +++++++
actionpack/test/html-scanner/sanitizer_test.rb | 273 +++++++++++++++++++++
actionpack/test/html-scanner/tag_node_test.rb | 238 ++++++++++++++++++
actionpack/test/html-scanner/text_node_test.rb | 50 ++++
actionpack/test/html-scanner/tokenizer_test.rb | 131 ++++++++++
15 files changed, 945 insertions(+), 945 deletions(-)
delete mode 100644 actionpack/test/controller/html-scanner/cdata_node_test.rb
delete mode 100644 actionpack/test/controller/html-scanner/document_test.rb
delete mode 100644 actionpack/test/controller/html-scanner/node_test.rb
delete mode 100644 actionpack/test/controller/html-scanner/sanitizer_test.rb
delete mode 100644 actionpack/test/controller/html-scanner/tag_node_test.rb
delete mode 100644 actionpack/test/controller/html-scanner/text_node_test.rb
delete mode 100644 actionpack/test/controller/html-scanner/tokenizer_test.rb
create mode 100644 actionpack/test/html-scanner/cdata_node_test.rb
create mode 100644 actionpack/test/html-scanner/document_test.rb
create mode 100644 actionpack/test/html-scanner/node_test.rb
create mode 100644 actionpack/test/html-scanner/sanitizer_test.rb
create mode 100644 actionpack/test/html-scanner/tag_node_test.rb
create mode 100644 actionpack/test/html-scanner/text_node_test.rb
create mode 100644 actionpack/test/html-scanner/tokenizer_test.rb
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index b9819d4a83..9ce897aae8 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -30,7 +30,7 @@ Rake::TestTask.new(:test_action_pack) do |t|
# make sure we include the tests in alphabetical order as on some systems
# this will not happen automatically and the tests (as a whole) will error
- t.test_files = Dir.glob( "test/{controller,dispatch,template}/**/*_test.rb" ).sort
+ t.test_files = Dir.glob( "test/{controller,dispatch,template,html-scanner}/**/*_test.rb" ).sort
t.verbose = true
#t.warning = true
diff --git a/actionpack/test/controller/html-scanner/cdata_node_test.rb b/actionpack/test/controller/html-scanner/cdata_node_test.rb
deleted file mode 100644
index 1822cc565a..0000000000
--- a/actionpack/test/controller/html-scanner/cdata_node_test.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'abstract_unit'
-
-class CDATANodeTest < Test::Unit::TestCase
- def setup
- @node = HTML::CDATA.new(nil, 0, 0, "howdy
")
- end
-
- def test_to_s
- assert_equal "howdy]]>", @node.to_s
- end
-
- def test_content
- assert_equal "howdy
", @node.content
- end
-end
diff --git a/actionpack/test/controller/html-scanner/document_test.rb b/actionpack/test/controller/html-scanner/document_test.rb
deleted file mode 100644
index c68f04fa75..0000000000
--- a/actionpack/test/controller/html-scanner/document_test.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-require 'abstract_unit'
-
-class DocumentTest < Test::Unit::TestCase
- def test_handle_doctype
- doc = nil
- assert_nothing_raised do
- doc = HTML::Document.new <<-HTML.strip
-
-
-
- HTML
- end
- assert_equal 3, doc.root.children.length
- assert_equal %{}, doc.root.children[0].content
- assert_match %r{\s+}m, doc.root.children[1].content
- assert_equal "html", doc.root.children[2].name
- end
-
- def test_find_img
- doc = HTML::Document.new <<-HTML.strip
-
-
-
-
-
- HTML
- assert doc.find(:tag=>"img", :attributes=>{"src"=>"hello.gif"})
- end
-
- def test_find_all
- doc = HTML::Document.new <<-HTML.strip
-
-
-
-
-
something
-
here is more
-
-
-
- HTML
- all = doc.find_all :attributes => { :class => "test" }
- assert_equal 3, all.length
- assert_equal [ "p", "p", "em" ], all.map { |n| n.name }
- end
-
- def test_find_with_text
- doc = HTML::Document.new <<-HTML.strip
-
-
- Some text
-
-
- HTML
- assert doc.find(:content => "Some text")
- assert doc.find(:tag => "p", :child => { :content => "Some text" })
- assert doc.find(:tag => "p", :child => "Some text")
- assert doc.find(:tag => "p", :content => "Some text")
- end
-
- def test_parse_xml
- assert_nothing_raised { HTML::Document.new(" ", true, true) }
- assert_nothing_raised { HTML::Document.new(" something ", true, true) }
- end
-
- def test_parse_document
- doc = HTML::Document.new(<<-HTML)
-
- HTML
- assert_not_nil doc.find(:tag => "div", :children => { :count => 1, :only => { :tag => "table" } })
- end
-
- def test_tag_nesting_nothing_to_s
- doc = HTML::Document.new(" ")
- assert_equal " ", doc.root.to_s
- end
-
- def test_tag_nesting_space_to_s
- doc = HTML::Document.new(" ")
- assert_equal " ", doc.root.to_s
- end
-
- def test_tag_nesting_text_to_s
- doc = HTML::Document.new("text ")
- assert_equal "text ", doc.root.to_s
- end
-
- def test_tag_nesting_tag_to_s
- doc = HTML::Document.new(" ")
- assert_equal " ", doc.root.to_s
- end
-
- def test_parse_cdata
- doc = HTML::Document.new(<<-HTML)
-
-
-
- ]]>
-
-
- this document has <br> for a title
-
-
-HTML
-
- assert_nil doc.find(:tag => "title", :descendant => { :tag => "br" })
- assert doc.find(:tag => "title", :child => " ")
- end
-
- def test_find_empty_tag
- doc = HTML::Document.new("
")
- assert_nil doc.find(:tag => "div", :attributes => { :id => "map" }, :content => /./)
- assert doc.find(:tag => "div", :attributes => { :id => "map" }, :content => /\A\Z/)
- assert doc.find(:tag => "div", :attributes => { :id => "map" }, :content => /^$/)
- assert doc.find(:tag => "div", :attributes => { :id => "map" }, :content => "")
- assert doc.find(:tag => "div", :attributes => { :id => "map" }, :content => nil)
- end
-
- def test_parse_invalid_document
- assert_nothing_raised do
- doc = HTML::Document.new("
-
- ")
- end
- end
-
- def test_invalid_document_raises_exception_when_strict
- assert_raise RuntimeError do
- doc = HTML::Document.new("
-
- ", true)
- end
- end
-
-end
diff --git a/actionpack/test/controller/html-scanner/node_test.rb b/actionpack/test/controller/html-scanner/node_test.rb
deleted file mode 100644
index b0df36877e..0000000000
--- a/actionpack/test/controller/html-scanner/node_test.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-require 'abstract_unit'
-
-class NodeTest < Test::Unit::TestCase
-
- class MockNode
- def initialize(matched, value)
- @matched = matched
- @value = value
- end
-
- def find(conditions)
- @matched && self
- end
-
- def to_s
- @value.to_s
- end
- end
-
- def setup
- @node = HTML::Node.new("parent")
- @node.children.concat [MockNode.new(false,1), MockNode.new(true,"two"), MockNode.new(false,:three)]
- end
-
- def test_match
- assert !@node.match("foo")
- end
-
- def test_tag
- assert !@node.tag?
- end
-
- def test_to_s
- assert_equal "1twothree", @node.to_s
- end
-
- def test_find
- assert_equal "two", @node.find('blah').to_s
- end
-
- def test_parse_strict
- s = ""
- assert_raise(RuntimeError) { HTML::Node.parse(nil,0,0,s) }
- end
-
- def test_parse_relaxed
- s = ""
- node = nil
- assert_nothing_raised { node = HTML::Node.parse(nil,0,0,s,false) }
- assert node.attributes.has_key?("foo")
- assert !node.attributes.has_key?("bar")
- end
-
- def test_to_s_with_boolean_attrs
- s = ""
- node = HTML::Node.parse(nil,0,0,s)
- assert node.attributes.has_key?("foo")
- assert node.attributes.has_key?("bar")
- assert "", node.to_s
- end
-
- def test_parse_with_unclosed_tag
- s = "contents ', node.content
- end
-
- def test_parse_strict_with_unterminated_cdata_section
- s = ""))
- assert_equal("Dont touch me", sanitizer.sanitize("Dont touch me"))
- assert_equal("This is a test.", sanitizer.sanitize(" This is a test .
"))
- assert_equal("Weirdos", sanitizer.sanitize("Wei<a onclick='alert(document.cookie);' />rdos"))
- assert_equal("This is a test.", sanitizer.sanitize("This is a test."))
- assert_equal(
- %{This is a test.\n\n\nIt no longer contains any HTML.\n}, sanitizer.sanitize(
- %{This is a test . \n\n\n\nIt no longer contains any HTML .
\n}))
- assert_equal "This has a here.", sanitizer.sanitize("This has a here.")
- assert_equal "This has a here.", sanitizer.sanitize("This has a ]]> here.")
- assert_equal "This has an unclosed ", sanitizer.sanitize("This has an unclosed ]] here...")
- [nil, '', ' '].each { |blank| assert_equal blank, sanitizer.sanitize(blank) }
- end
-
- def test_strip_links
- sanitizer = HTML::LinkSanitizer.new
- assert_equal "Dont touch me", sanitizer.sanitize("Dont touch me")
- assert_equal "on my mind\nall day long", sanitizer.sanitize("on my mind \nall day long ")
- assert_equal "0wn3d", sanitizer.sanitize("0wn3d ")
- assert_equal "Magic", sanitizer.sanitize("Mag ic")
- assert_equal "FrrFox", sanitizer.sanitize("FrrFox ")
- assert_equal "My mind\nall day long", sanitizer.sanitize("My mind \nall day long ")
- assert_equal "all day long", sanitizer.sanitize("<a href='hello'>all day long< /a>")
-
- assert_equal " ", ''
- end
-
- def test_sanitize_plaintext
- raw = "foo "
- assert_sanitized raw, "foo "
- end
-
- def test_sanitize_script
- assert_sanitized "a b cd e f", "a b cd e f"
- end
-
- # fucked
- def test_sanitize_js_handlers
- raw = %{onthis="do that" hello }
- assert_sanitized raw, %{onthis="do that" hello }
- end
-
- def test_sanitize_javascript_href
- raw = %{href="javascript:bang" foo , bar }
- assert_sanitized raw, %{href="javascript:bang" foo , bar }
- end
-
- def test_sanitize_image_src
- raw = %{src="javascript:bang" foo, bar }
- assert_sanitized raw, %{src="javascript:bang" foo, bar }
- end
-
- HTML::WhiteListSanitizer.allowed_tags.each do |tag_name|
- define_method "test_should_allow_#{tag_name}_tag" do
- assert_sanitized "start <#{tag_name} title=\"1\" onclick=\"foo\">foo bar baz#{tag_name}> end", %(start <#{tag_name} title="1">foo bar baz#{tag_name}> end)
- end
- end
-
- def test_should_allow_anchors
- assert_sanitized %( ), %( )
- end
-
- # RFC 3986, sec 4.2
- def test_allow_colons_in_path_component
- assert_sanitized("foo ")
- end
-
- %w(src width height alt).each do |img_attr|
- define_method "test_should_allow_image_#{img_attr}_attribute" do
- assert_sanitized %( ), %( )
- end
- end
-
- def test_should_handle_non_html
- assert_sanitized 'abc'
- end
-
- def test_should_handle_blank_text
- assert_sanitized nil
- assert_sanitized ''
- end
-
- def test_should_allow_custom_tags
- text = "foo "
- sanitizer = HTML::WhiteListSanitizer.new
- assert_equal(text, sanitizer.sanitize(text, :tags => %w(u)))
- end
-
- def test_should_allow_only_custom_tags
- text = "foo with bar "
- sanitizer = HTML::WhiteListSanitizer.new
- assert_equal("foo with bar", sanitizer.sanitize(text, :tags => %w(u)))
- end
-
- def test_should_allow_custom_tags_with_attributes
- text = %(foo )
- sanitizer = HTML::WhiteListSanitizer.new
- assert_equal(text, sanitizer.sanitize(text))
- end
-
- def test_should_allow_custom_tags_with_custom_attributes
- text = %(Lorem ipsum )
- sanitizer = HTML::WhiteListSanitizer.new
- assert_equal(text, sanitizer.sanitize(text, :attributes => ['foo']))
- end
-
- [%w(img src), %w(a href)].each do |(tag, attr)|
- define_method "test_should_strip_#{attr}_attribute_in_#{tag}_with_bad_protocols" do
- assert_sanitized %(<#{tag} #{attr}="javascript:bang" title="1">boo#{tag}>), %(<#{tag} title="1">boo#{tag}>)
- end
- end
-
- def test_should_flag_bad_protocols
- sanitizer = HTML::WhiteListSanitizer.new
- %w(about chrome data disk hcp help javascript livescript lynxcgi lynxexec ms-help ms-its mhtml mocha opera res resource shell vbscript view-source vnd.ms.radio wysiwyg).each do |proto|
- assert sanitizer.send(:contains_bad_protocols?, 'src', "#{proto}://bad")
- end
- end
-
- def test_should_accept_good_protocols
- sanitizer = HTML::WhiteListSanitizer.new
- HTML::WhiteListSanitizer.allowed_protocols.each do |proto|
- assert !sanitizer.send(:contains_bad_protocols?, 'src', "#{proto}://good")
- end
- end
-
- def test_should_reject_hex_codes_in_protocol
- assert_sanitized %(1 ), "1 "
- assert @sanitizer.send(:contains_bad_protocols?, 'src', "%6A%61%76%61%73%63%72%69%70%74%3A%61%6C%65%72%74%28%22%58%53%53%22%29")
- end
-
- def test_should_block_script_tag
- assert_sanitized %(), ""
- end
-
- [%( ),
- %( ),
- %( ),
- %( ">),
- %( ),
- %( ),
- %( ),
- %( ),
- %( ),
- %( ),
- %( ),
- %( ),
- %( ),
- %( ),
- %( )].each_with_index do |img_hack, i|
- define_method "test_should_not_fall_for_xss_image_hack_#{i+1}" do
- assert_sanitized img_hack, " "
- end
- end
-
- def test_should_sanitize_tag_broken_up_by_null
- assert_sanitized %(alert(\"XSS\") ), "alert(\"XSS\")"
- end
-
- def test_should_sanitize_invalid_script_tag
- assert_sanitized %(), ""
- end
-
- def test_should_sanitize_script_tag_with_multiple_open_brackets
- assert_sanitized %(<), "<"
- assert_sanitized %(