Rails 2.3.1

Update to the release version of Rails 2.3.1.
This commit is contained in:
Jacques Distler 2009-03-05 07:54:17 -06:00
parent bd9fa0ed0c
commit 5e7d2cf973
25 changed files with 199 additions and 26 deletions

View file

@ -1,4 +1,4 @@
*2.3.1 [RC2] (February ?, 2009)* *2.3.1 [RC2] (March 5, 2009)*
* Fixed that ActionMailer should send correctly formatted Return-Path in MAIL FROM for SMTP #1842 [Matt Jones] * Fixed that ActionMailer should send correctly formatted Return-Path in MAIL FROM for SMTP #1842 [Matt Jones]

View file

@ -1,4 +1,6 @@
*2.3.1 [RC2] (February ?, 2009)* *2.3.1 [RC2] (March 5, 2009)*
* Fixed that redirection would just log the options, not the final url (which lead to "Redirected to #<Post:0x23150b8>") [DHH]
* Added ability to pass in :public => true to fresh_when, stale?, and expires_in to make the request proxy cachable #2095 [Gregg Pollack] * Added ability to pass in :public => true to fresh_when, stale?, and expires_in to make the request proxy cachable #2095 [Gregg Pollack]

View file

@ -1101,7 +1101,6 @@ module ActionController #:nodoc:
end end
response.redirected_to = options response.redirected_to = options
logger.info("Redirected to #{options}") if logger && logger.info?
case options case options
# The scheme name consist of a letter followed by any combination of # The scheme name consist of a letter followed by any combination of
@ -1124,6 +1123,7 @@ module ActionController #:nodoc:
def redirect_to_full_url(url, status) def redirect_to_full_url(url, status)
raise DoubleRenderError if performed? raise DoubleRenderError if performed?
logger.info("Redirected to #{url}") if logger && logger.info?
response.redirect(url, interpret_status(status)) response.redirect(url, interpret_status(status))
@performed_redirect = true @performed_redirect = true
end end

View file

@ -317,18 +317,22 @@ module ActionController
end end
def regexp_chunk def regexp_chunk
'(\.[^/?\.]+)?' '/|(\.[^/?\.]+)?'
end end
def to_s def to_s
'(.:format)?' '(.:format)?'
end end
def extract_value
"#{local_name} = options[:#{key}] && options[:#{key}].to_s.downcase"
end
#the value should not include the period (.) #the value should not include the period (.)
def match_extraction(next_capture) def match_extraction(next_capture)
%[ %[
if (m = match[#{next_capture}]) if (m = match[#{next_capture}])
params[:#{key}] = URI.unescape(m.from(1)) params[:#{key}] = CGI.unescape(m.from(1))
end end
] ]
end end

View file

@ -21,6 +21,11 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest
render :text => "foo: #{session[:foo].inspect}" render :text => "foo: #{session[:foo].inspect}"
end end
def call_reset_session
reset_session
head :ok
end
def rescue_action(e) raise end def rescue_action(e) raise end
end end
@ -61,6 +66,22 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest
end end
end end
def test_setting_session_value_after_session_reset
with_test_route_set do
get '/set_session_value'
assert_response :success
assert cookies['_session_id']
get '/call_reset_session'
assert_response :success
assert_not_equal [], headers['Set-Cookie']
get '/get_session_value'
assert_response :success
assert_equal 'foo: nil', response.body
end
end
def test_prevents_session_fixation def test_prevents_session_fixation
with_test_route_set do with_test_route_set do
get '/set_session_value' get '/set_session_value'

View file

@ -750,9 +750,17 @@ class ResourcesTest < ActionController::TestCase
end end
def test_with_path_segment def test_with_path_segment
with_restful_routing :messages, :as => 'reviews' do with_restful_routing :messages do
assert_simply_restful_for :messages, :as => 'reviews' assert_simply_restful_for :messages
assert_recognizes({:controller => "messages", :action => "index"}, "/messages")
assert_recognizes({:controller => "messages", :action => "index"}, "/messages/")
end end
with_restful_routing :messages, :as => 'reviews' do
assert_simply_restful_for :messages, :as => 'reviews'
assert_recognizes({:controller => "messages", :action => "index"}, "/reviews")
assert_recognizes({:controller => "messages", :action => "index"}, "/reviews/")
end
end end
def test_multiple_with_path_segment_and_controller def test_multiple_with_path_segment_and_controller

View file

@ -2237,6 +2237,22 @@ class RouteSetTest < Test::Unit::TestCase
) )
end end
def test_format_is_not_inherit
set.draw do |map|
map.connect '/posts.:format', :controller => 'posts'
end
assert_equal '/posts', set.generate(
{:controller => 'posts'},
{:controller => 'posts', :action => 'index', :format => 'xml'}
)
assert_equal '/posts.xml', set.generate(
{:controller => 'posts', :format => 'xml'},
{:controller => 'posts', :action => 'index', :format => 'xml'}
)
end
def test_expiry_determination_should_consider_values_with_to_param def test_expiry_determination_should_consider_values_with_to_param
set.draw { |map| map.connect 'projects/:project_id/:controller/:action' } set.draw { |map| map.connect 'projects/:project_id/:controller/:action' }
assert_equal '/projects/1/post/show', set.generate( assert_equal '/projects/1/post/show', set.generate(

View file

@ -1,4 +1,4 @@
*2.3.1 [RC2] (February ?, 2009)* *2.3.1 [RC2] (March 5, 2009)*
* Added ActiveRecord::Base.each and ActiveRecord::Base.find_in_batches for batch processing [DHH/Jamis Buck] * Added ActiveRecord::Base.each and ActiveRecord::Base.find_in_batches for batch processing [DHH/Jamis Buck]

View file

@ -287,8 +287,7 @@ module ActiveRecord
def get_session(env, sid) def get_session(env, sid)
Base.silence do Base.silence do
sid ||= generate_sid sid ||= generate_sid
session = @@session_class.find_by_session_id(sid) session = find_session(sid)
session ||= @@session_class.new(:session_id => sid, :data => {})
env[SESSION_RECORD_KEY] = session env[SESSION_RECORD_KEY] = session
[sid, session.data] [sid, session.data]
end end
@ -296,7 +295,7 @@ module ActiveRecord
def set_session(env, sid, session_data) def set_session(env, sid, session_data)
Base.silence do Base.silence do
record = env[SESSION_RECORD_KEY] record = env[SESSION_RECORD_KEY] ||= find_session(sid)
record.data = session_data record.data = session_data
return false unless record.save return false unless record.save
@ -310,5 +309,10 @@ module ActiveRecord
return true return true
end end
def find_session(id)
@@session_class.find_by_session_id(id) ||
@@session_class.new(:session_id => id, :data => {})
end
end end
end end

View file

@ -1,4 +1,4 @@
*2.3.1 [RC2] (February ?, 2009)* *2.3.1 [RC2] (March 5, 2009)*
* Nothing new, just included in 2.3.1 * Nothing new, just included in 2.3.1

View file

@ -1,4 +1,4 @@
*2.3.1 [RC2] (February ?, 2009)* *2.3.1 [RC2] (March 5, 2009)*
* Vendorize i18n 0.1.3 gem (fixes issues with incompatible character encodings in Ruby 1.9) #2038 [Akira Matsuda] * Vendorize i18n 0.1.3 gem (fixes issues with incompatible character encodings in Ruby 1.9) #2038 [Akira Matsuda]

View file

@ -54,7 +54,7 @@ module ActiveSupport
end end
def to_hash def to_hash
Hash.new(self) self
end end
def each_key def each_key
@ -93,7 +93,7 @@ module ActiveSupport
end end
def inspect def inspect
"#<OrderedHash #{self.to_hash.inspect}>" "#<OrderedHash #{super}>"
end end
private private

View file

@ -20,7 +20,7 @@ module ActiveSupport
alias_method :method_name, :name alias_method :method_name, :name
else else
# TODO: Figure out how to get the Rails::BacktraceFilter into minitest/unit # TODO: Figure out how to get the Rails::BacktraceFilter into minitest/unit
if defined?(Rails) if defined?(Rails) && ENV['BACKTRACE'].nil?
require 'rails/backtrace_cleaner' require 'rails/backtrace_cleaner'
Test::Unit::Util::BacktraceFilter.module_eval { include Rails::BacktraceFilterForTestUnit } Test::Unit::Util::BacktraceFilter.module_eval { include Rails::BacktraceFilterForTestUnit }
end end

View file

@ -4,9 +4,11 @@ class OrderedHashTest < Test::Unit::TestCase
def setup def setup
@keys = %w( blue green red pink orange ) @keys = %w( blue green red pink orange )
@values = %w( 000099 009900 aa0000 cc0066 cc6633 ) @values = %w( 000099 009900 aa0000 cc0066 cc6633 )
@hash = Hash.new
@ordered_hash = ActiveSupport::OrderedHash.new @ordered_hash = ActiveSupport::OrderedHash.new
@keys.each_with_index do |key, index| @keys.each_with_index do |key, index|
@hash[key] = @values[index]
@ordered_hash[key] = @values[index] @ordered_hash[key] = @values[index]
end end
end end
@ -17,7 +19,7 @@ class OrderedHashTest < Test::Unit::TestCase
end end
def test_access def test_access
assert @keys.zip(@values).all? { |k, v| @ordered_hash[k] == v } assert @hash.all? { |k, v| @ordered_hash[k] == v }
end end
def test_assignment def test_assignment
@ -45,6 +47,10 @@ class OrderedHashTest < Test::Unit::TestCase
assert_nil @ordered_hash.delete(bad_key) assert_nil @ordered_hash.delete(bad_key)
end end
def test_to_hash
assert_same @ordered_hash, @ordered_hash.to_hash
end
def test_has_key def test_has_key
assert_equal true, @ordered_hash.has_key?('blue') assert_equal true, @ordered_hash.has_key?('blue')
assert_equal true, @ordered_hash.key?('blue') assert_equal true, @ordered_hash.key?('blue')
@ -148,4 +154,8 @@ class OrderedHashTest < Test::Unit::TestCase
@ordered_hash.keys.pop @ordered_hash.keys.pop
assert_equal original, @ordered_hash.keys assert_equal original, @ordered_hash.keys
end end
end
def test_inspect
assert @ordered_hash.inspect.include?(@hash.inspect)
end
end

View file

@ -1,4 +1,4 @@
*2.3.1 [RC2] (February ?, 2009)* *2.3.1 [RC2] (March 5, 2009)*
* Allow metal to live in plugins #2045 [Matthew Rudy] * Allow metal to live in plugins #2045 [Matthew Rudy]

View file

@ -344,9 +344,12 @@ task :pgem => [:gem] do
`ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'`
end end
desc "Publish the API documentation" desc "Publish the guides"
task :pdoc => :rdoc do task :pguides => :guides do
# railties API isn't separately published 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
`ssh web.rubyonrails.org 'cd /u/sites/guides.rubyonrails.org/public/ && tar -xvzf guides.gz && mv guides/output/* . && rm -rf guides*'`
end end
desc "Publish the release files to RubyForge." desc "Publish the release files to RubyForge."

View file

@ -559,6 +559,7 @@ Run `rake gems:install` to install the missing gems.
end end
def initialize_metal def initialize_metal
Rails::Rack::Metal.requested_metals = configuration.metals
Rails::Rack::Metal.metal_paths += plugin_loader.engine_metal_paths Rails::Rack::Metal.metal_paths += plugin_loader.engine_metal_paths
configuration.middleware.insert_before( configuration.middleware.insert_before(
@ -715,6 +716,11 @@ Run `rake gems:install` to install the missing gems.
@plugins = plugins.nil? ? nil : plugins.map { |p| p.to_sym } @plugins = plugins.nil? ? nil : plugins.map { |p| p.to_sym }
end end
# The list of metals to load. If this is set to <tt>nil</tt>, all metals will
# be loaded in alphabetical order. If this is set to <tt>[]</tt>, no metals will
# be loaded. Otherwise metals will be loaded in the order specified
attr_accessor :metals
# The path to the root of the plugins directory. By default, it is in # The path to the root of the plugins directory. By default, it is in
# <tt>vendor/plugins</tt>. # <tt>vendor/plugins</tt>.
attr_accessor :plugin_paths attr_accessor :plugin_paths

View file

@ -2,6 +2,8 @@ module Rails
class BacktraceCleaner < ActiveSupport::BacktraceCleaner class BacktraceCleaner < ActiveSupport::BacktraceCleaner
ERB_METHOD_SIG = /:in `_run_erb_.*/ ERB_METHOD_SIG = /:in `_run_erb_.*/
RAILS_GEMS = %w( actionpack activerecord actionmailer activesupport activeresource rails )
VENDOR_DIRS = %w( vendor/gems vendor/rails ) VENDOR_DIRS = %w( vendor/gems vendor/rails )
SERVER_DIRS = %w( lib/mongrel bin/mongrel SERVER_DIRS = %w( lib/mongrel bin/mongrel
lib/passenger bin/passenger-spawn-server lib/passenger bin/passenger-spawn-server
@ -20,6 +22,7 @@ module Rails
add_filter { |line| line.sub('./', '/') } # for tests add_filter { |line| line.sub('./', '/') } # for tests
add_filter { |line| line.sub(/(#{GEMS_DIR})\/gems\/([a-z]+)-([0-9.]+)\/(.*)/, '\2 (\3) \4')} # http://gist.github.com/30430 add_filter { |line| line.sub(/(#{GEMS_DIR})\/gems\/([a-z]+)-([0-9.]+)\/(.*)/, '\2 (\3) \4')} # http://gist.github.com/30430
add_silencer { |line| ALL_NOISE.any? { |dir| line.include?(dir) } } add_silencer { |line| ALL_NOISE.any? { |dir| line.include?(dir) } }
add_silencer { |line| RAILS_GEMS.any? { |gem| line =~ /^#{gem} / } }
add_silencer { |line| line =~ %r(vendor/plugins/[^\/]+/lib) } add_silencer { |line| line =~ %r(vendor/plugins/[^\/]+/lib) }
end end
end end

View file

@ -8,16 +8,26 @@ module Rails
cattr_accessor :metal_paths cattr_accessor :metal_paths
self.metal_paths = ["#{Rails.root}/app/metal"] self.metal_paths = ["#{Rails.root}/app/metal"]
cattr_accessor :requested_metals
def self.metals def self.metals
matcher = /#{Regexp.escape('/app/metal/')}(.*)\.rb\Z/ matcher = /#{Regexp.escape('/app/metal/')}(.*)\.rb\Z/
metal_glob = metal_paths.map{ |base| "#{base}/**/*.rb" } metal_glob = metal_paths.map{ |base| "#{base}/**/*.rb" }
all_metals = {}
Dir[*metal_glob].sort.map do |file| Dir[*metal_glob].sort.map do |file|
path = file.match(matcher)[1] file = file.match(matcher)[1]
require path all_metals[file.classify] = file
path.classify.constantize
end end
load_list = requested_metals || all_metals.keys
load_list.map do |requested_metal|
if metal = all_metals[requested_metal]
require metal
requested_metal.constantize
end
end.compact
end end
def initialize(app) def initialize(app)

View file

@ -0,0 +1,5 @@
class MetalA < Rails::Rack::Metal
def self.call(env)
[200, { "Content-Type" => "text/html"}, "Hi"]
end
end

View file

@ -0,0 +1,5 @@
class MetalB < Rails::Rack::Metal
def self.call(env)
[200, { "Content-Type" => "text/html"}, "Hi"]
end
end

View file

@ -0,0 +1,5 @@
class FooMetal < Rails::Rack::Metal
def self.call(env)
[200, { "Content-Type" => "text/html"}, "Hi"]
end
end

View file

@ -0,0 +1,7 @@
module Folder
class MetalA < Rails::Rack::Metal
def self.call(env)
[200, { "Content-Type" => "text/html"}, "Hi"]
end
end
end

View file

@ -0,0 +1,7 @@
module Folder
class MetalB < Rails::Rack::Metal
def self.call(env)
[200, { "Content-Type" => "text/html"}, "Hi"]
end
end
end

View file

@ -0,0 +1,57 @@
require 'abstract_unit'
require 'initializer'
class MetalTest < Test::Unit::TestCase
def test_metals_should_return_list_of_found_metal_apps
use_appdir("singlemetal") do
assert_equal(["FooMetal"], found_metals_as_string_array)
end
end
def test_metals_should_return_alphabetical_list_of_found_metal_apps
use_appdir("multiplemetals") do
assert_equal(["MetalA", "MetalB"], found_metals_as_string_array)
end
end
def test_metals_load_order_should_be_overriden_by_requested_metals
use_appdir("multiplemetals") do
Rails::Rack::Metal.requested_metals = ["MetalB", "MetalA"]
assert_equal(["MetalB", "MetalA"], found_metals_as_string_array)
end
end
def test_metals_not_listed_should_not_load
use_appdir("multiplemetals") do
Rails::Rack::Metal.requested_metals = ["MetalB"]
assert_equal(["MetalB"], found_metals_as_string_array)
end
end
def test_metal_finding_should_work_with_subfolders
use_appdir("subfolders") do
assert_equal(["Folder::MetalA", "Folder::MetalB"], found_metals_as_string_array)
end
end
def test_metal_finding_with_requested_metals_should_work_with_subfolders
use_appdir("subfolders") do
Rails::Rack::Metal.requested_metals = ["Folder::MetalB"]
assert_equal(["Folder::MetalB"], found_metals_as_string_array)
end
end
private
def use_appdir(root)
dir = "#{File.dirname(__FILE__)}/fixtures/metal/#{root}"
Rails::Rack::Metal.metal_paths = ["#{dir}/app/metal"]
Rails::Rack::Metal.requested_metals = nil
$LOAD_PATH << "#{dir}/app/metal"
yield
end
def found_metals_as_string_array
Rails::Rack::Metal.metals.map { |m| m.to_s }
end
end