diff options
81 files changed, 509 insertions, 1064 deletions
@@ -47,7 +47,7 @@ instance_eval File.read '.Gemfile' if File.exists? '.Gemfile' platforms :mri do group :test do - gem 'ruby-prof' if RUBY_VERSION < '1.9.3' + gem 'ruby-prof' end end diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec index 7ecc35b7c7..b506f8804c 100644 --- a/actionmailer/actionmailer.gemspec +++ b/actionmailer/actionmailer.gemspec @@ -6,7 +6,7 @@ Gem::Specification.new do |s| s.version = version s.summary = 'Email composition, delivery, and receiving framework (part of Rails).' s.description = 'Email on Rails. Compose, deliver, receive, and test emails using the familiar controller/view pattern. First-class support for multipart email and attachments.' - s.required_ruby_version = '>= 1.8.7' + s.required_ruby_version = '>= 1.9.3' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index fe5bed70a9..e369277e5a 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -6,7 +6,7 @@ Gem::Specification.new do |s| s.version = version s.summary = 'Web-flow and rendering framework putting the VC in MVC (part of Rails).' s.description = 'Web apps on Rails. Simple, battle-tested conventions for building and testing MVC web applications. Works with any Rack-compatible server.' - s.required_ruby_version = '>= 1.8.7' + s.required_ruby_version = '>= 1.9.3' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index 264806cd36..56335a22cb 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -192,12 +192,15 @@ module ActionController return false unless password method = request.env['rack.methodoverride.original_method'] || request.env['REQUEST_METHOD'] - uri = credentials[:uri][0,1] == '/' ? request.fullpath : request.url + uri = credentials[:uri][0,1] == '/' ? request.original_fullpath : request.original_url - [true, false].any? do |password_is_ha1| - expected = expected_response(method, uri, credentials, password, password_is_ha1) - expected == credentials[:response] - end + [true, false].any? do |trailing_question_mark| + [true, false].any? do |password_is_ha1| + _uri = trailing_question_mark ? uri + "?" : uri + expected = expected_response(method, _uri, credentials, password, password_is_ha1) + expected == credentials[:response] + end + end end end diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index c5c48ec489..820921252d 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -122,10 +122,18 @@ module ActionDispatch Http::Headers.new(@env) end + def original_fullpath + @original_fullpath ||= (env["ORIGINAL_FULLPATH"] || fullpath) + end + def fullpath @fullpath ||= super end + def original_url + base_url + original_fullpath + end + def media_type content_mime_type.to_s end diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 5797c63924..84732085f0 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -121,14 +121,7 @@ module ActionDispatch # :nodoc: def body=(body) @blank = true if body == EMPTY - # Explicitly check for strings. This is *wrong* theoretically - # but if we don't check this, the performance on string bodies - # is bad on Ruby 1.8 (because strings responds to each then). - @body = if body.respond_to?(:to_str) || !body.respond_to?(:each) - [body] - else - body - end + @body = body.respond_to?(:each) ? body : [body] end def body_parts diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb index dabbabb1e6..b903f98761 100644 --- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb @@ -76,7 +76,7 @@ module ActionDispatch end def stderr_logger - @stderr_logger ||= Logger.new($stderr) + @stderr_logger ||= ActiveSupport::Logger.new($stderr) end end end diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb index 6ded9dbfed..1cb803ffb9 100644 --- a/actionpack/lib/action_dispatch/middleware/params_parser.rb +++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb @@ -69,7 +69,7 @@ module ActionDispatch end def logger(env) - env['action_dispatch.logger'] || Logger.new($stderr) + env['action_dispatch.logger'] || ActiveSupport::Logger.new($stderr) end end end diff --git a/actionpack/lib/action_dispatch/middleware/request_id.rb b/actionpack/lib/action_dispatch/middleware/request_id.rb index bee446c8a5..d5a0b80fd5 100644 --- a/actionpack/lib/action_dispatch/middleware/request_id.rb +++ b/actionpack/lib/action_dispatch/middleware/request_id.rb @@ -33,7 +33,7 @@ module ActionDispatch end def internal_request_id - SecureRandom.hex(16) + SecureRandom.uuid end end end diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index f895cad058..3ee0d8ebc5 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -584,7 +584,7 @@ module ActionView # [nil, []] # { nil => [] } # - if !choices.empty? && Array === choices.first.last + if !choices.empty? && choices.first.respond_to?(:last) && Array === choices.first.last option_tags = grouped_options_for_select(choices, :selected => selected_value, :disabled => options[:disabled]) else option_tags = options_for_select(choices, :selected => selected_value, :disabled => options[:disabled]) diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index b37e837a23..1c0fdb8ff9 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -1,7 +1,6 @@ # encoding: utf-8 require 'active_support/core_ext/big_decimal/conversions' -require 'active_support/core_ext/float/rounding' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/output_safety' diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index f855ea257c..7fa86866a7 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -1,6 +1,5 @@ require "pathname" require "active_support/core_ext/class" -require "active_support/core_ext/io" require "action_view/template" module ActionView diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb index b011536717..a91e3cafa5 100644 --- a/actionpack/test/controller/http_digest_authentication_test.rb +++ b/actionpack/test/controller/http_digest_authentication_test.rb @@ -139,7 +139,7 @@ class HttpDigestAuthenticationTest < ActionController::TestCase test "authentication request with request-uri that doesn't match credentials digest-uri" do @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please') - @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest/altered/uri" + @request.env['ORIGINAL_FULLPATH'] = "/http_digest_authentication_test/dummy_digest/altered/uri" get :display assert_response :unauthorized @@ -208,6 +208,44 @@ class HttpDigestAuthenticationTest < ActionController::TestCase assert !ActionController::HttpAuthentication::Digest.validate_digest_response(@request, "SuperSecret"){nil} end + test "authentication request with request-uri ending in '/'" do + @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest/" + @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please') + + # simulate normalizing PATH_INFO + @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest" + get :display + + assert_response :success + assert_equal 'Definitely Maybe', @response.body + end + + test "authentication request with request-uri ending in '?'" do + @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest/?" + @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please') + + # simulate normalizing PATH_INFO + @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest" + get :display + + assert_response :success + assert_equal 'Definitely Maybe', @response.body + end + + test "authentication request with absolute uri in credentials (as in IE) ending with /" do + @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest/" + @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:uri => "http://test.host/http_digest_authentication_test/dummy_digest/", + :username => 'pretty', :password => 'please') + + # simulate normalizing PATH_INFO + @request.env['PATH_INFO'] = "/http_digest_authentication_test/dummy_digest" + get :display + + assert_response :success + assert assigns(:logged_in) + assert_equal 'Definitely Maybe', @response.body + end + private def encode_credentials(options) @@ -228,7 +266,10 @@ class HttpDigestAuthenticationTest < ActionController::TestCase credentials = decode_credentials(@response.headers['WWW-Authenticate']) credentials.merge!(options) - credentials.merge!(:uri => @request.env['PATH_INFO'].to_s) + path_info = @request.env['PATH_INFO'].to_s + uri = options[:uri] || path_info + credentials.merge!(:uri => uri) + @request.env["ORIGINAL_FULLPATH"] = path_info ActionController::HttpAuthentication::Digest.encode_credentials(method, credentials, password, options[:password_is_ha1]) end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index f40d663ae8..a60da65ae5 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -81,10 +81,6 @@ class LegacyRouteSetTests < Test::Unit::TestCase @rs = ::ActionDispatch::Routing::RouteSet.new end - def teardown - @rs.clear! - end - def test_class_and_lambda_constraints subdomain = Class.new { def matches? request diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb index b64e275363..0e75a23cfd 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_test.rb @@ -665,13 +665,8 @@ XML FILES_DIR = File.dirname(__FILE__) + '/../fixtures/multipart' - if RUBY_VERSION < '1.9' - READ_BINARY = 'rb' - READ_PLAIN = 'r' - else - READ_BINARY = 'rb:binary' - READ_PLAIN = 'r:binary' - end + READ_BINARY = 'rb:binary' + READ_PLAIN = 'r:binary' def test_test_uploaded_file filename = 'mona_lisa.jpg' diff --git a/actionpack/test/dispatch/request_id_test.rb b/actionpack/test/dispatch/request_id_test.rb index b6e8b6c3ad..4b98cd32f2 100644 --- a/actionpack/test/dispatch/request_id_test.rb +++ b/actionpack/test/dispatch/request_id_test.rb @@ -14,7 +14,7 @@ class RequestIdTest < ActiveSupport::TestCase end test "generating a request id when none is supplied" do - assert_match(/\w+/, stub_request.uuid) + assert_match(/\w+-\w+-\w+-\w+-\w+/, stub_request.uuid) end private diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 4d805464c2..5b3d38c48c 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -618,6 +618,30 @@ class RequestTest < ActiveSupport::TestCase assert_equal "/authenticate?secret", path end + test "original_fullpath returns ORIGINAL_FULLPATH" do + request = stub_request('ORIGINAL_FULLPATH' => "/foo?bar") + + path = request.original_fullpath + assert_equal "/foo?bar", path + end + + test "original_url returns url built using ORIGINAL_FULLPATH" do + request = stub_request('ORIGINAL_FULLPATH' => "/foo?bar", + 'HTTP_HOST' => "example.org", + 'rack.url_scheme' => "http") + + url = request.original_url + assert_equal "http://example.org/foo?bar", url + end + + test "original_fullpath returns fullpath if ORIGINAL_FULLPATH is not present" do + request = stub_request('PATH_INFO' => "/foo", + 'QUERY_STRING' => "bar") + + path = request.original_fullpath + assert_equal "/foo?bar", path + end + protected def stub_request(env = {}) diff --git a/actionpack/test/lib/testing_sandbox.rb b/actionpack/test/lib/testing_sandbox.rb deleted file mode 100644 index c36585104f..0000000000 --- a/actionpack/test/lib/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 diff --git a/actionpack/test/template/capture_helper_test.rb b/actionpack/test/template/capture_helper_test.rb index 13e2d5b595..a37e3a8d6a 100644 --- a/actionpack/test/template/capture_helper_test.rb +++ b/actionpack/test/template/capture_helper_test.rb @@ -131,17 +131,15 @@ class CaptureHelperTest < ActionView::TestCase assert buffer.equal?(@av.output_buffer) end - unless RUBY_VERSION < '1.9' - def test_with_output_buffer_sets_proper_encoding - @av.output_buffer = ActionView::OutputBuffer.new + def test_with_output_buffer_sets_proper_encoding + @av.output_buffer = ActionView::OutputBuffer.new - # Ensure we set the output buffer to an encoding different than the default one. - alt_encoding = alt_encoding(@av.output_buffer) - @av.output_buffer.force_encoding(alt_encoding) + # Ensure we set the output buffer to an encoding different than the default one. + alt_encoding = alt_encoding(@av.output_buffer) + @av.output_buffer.force_encoding(alt_encoding) - @av.with_output_buffer do - assert_equal alt_encoding, @av.output_buffer.encoding - end + @av.with_output_buffer do + assert_equal alt_encoding, @av.output_buffer.encoding end end @@ -165,14 +163,12 @@ class CaptureHelperTest < ActionView::TestCase assert_equal '', view.output_buffer end - unless RUBY_VERSION < '1.9' - def test_flush_output_buffer_preserves_the_encoding_of_the_output_buffer - view = view_with_controller - alt_encoding = alt_encoding(view.output_buffer) - view.output_buffer.force_encoding(alt_encoding) - flush_output_buffer - assert_equal alt_encoding, view.output_buffer.encoding - end + def test_flush_output_buffer_preserves_the_encoding_of_the_output_buffer + view = view_with_controller + alt_encoding = alt_encoding(view.output_buffer) + view.output_buffer.force_encoding(alt_encoding) + flush_output_buffer + assert_equal alt_encoding, view.output_buffer.encoding end def alt_encoding(output_buffer) diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index 469718e1bd..4a889beadd 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -596,6 +596,24 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_select_with_nil + @post = Post.new + @post.category = "othervalue" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\"></option>\n<option value=\"othervalue\" selected=\"selected\">othervalue</option></select>", + select("post", "category", [nil, "othervalue"]) + ) + end + + def test_select_with_fixnum + @post = Post.new + @post.category = "" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\">Please select</option>\n<option value=\"\"></option>\n<option value=\"1\">1</option></select>", + select("post", "category", [1], :prompt => true, :include_blank => true) + ) + end + def test_list_of_lists @post = Post.new @post.category = "" diff --git a/actionpack/test/template/output_safety_helper_test.rb b/actionpack/test/template/output_safety_helper_test.rb index fc127c24e9..76c71c9e6d 100644 --- a/actionpack/test/template/output_safety_helper_test.rb +++ b/actionpack/test/template/output_safety_helper_test.rb @@ -1,9 +1,7 @@ require 'abstract_unit' -require 'testing_sandbox' class OutputSafetyHelperTest < ActionView::TestCase tests ActionView::Helpers::OutputSafetyHelper - include TestingSandbox def setup @string = "hello" diff --git a/actionpack/test/template/sanitize_helper_test.rb b/actionpack/test/template/sanitize_helper_test.rb index 222d4dbf4c..4182af590e 100644 --- a/actionpack/test/template/sanitize_helper_test.rb +++ b/actionpack/test/template/sanitize_helper_test.rb @@ -1,11 +1,9 @@ require 'abstract_unit' -require 'testing_sandbox' # The exhaustive tests are in test/controller/html/sanitizer_test.rb. # This tests the that the helpers hook up correctly to the sanitizer classes. class SanitizeHelperTest < ActionView::TestCase tests ActionView::Helpers::SanitizeHelper - include TestingSandbox def test_strip_links assert_equal "Dont touch me", strip_links("Dont touch me") diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index a0afb77f05..839bf900dc 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -1,10 +1,8 @@ # encoding: utf-8 require 'abstract_unit' -require 'testing_sandbox' class TextHelperTest < ActionView::TestCase tests ActionView::Helpers::TextHelper - include TestingSandbox def setup super @@ -82,25 +80,13 @@ class TextHelperTest < ActionView::TestCase assert_equal "Hello Big[...]", truncate("Hello Big World!", :omission => "[...]", :length => 15, :separator => ' ') end - if RUBY_VERSION < '1.9.0' - def test_truncate_multibyte - with_kcode 'none' do - assert_equal "\354\225\210\353\205\225\355...", truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", :length => 10) - end - with_kcode 'u' do - assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...", - truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244", :length => 10) - end - end - else - def test_truncate_multibyte - # .mb_chars always returns a UTF-8 String. - # assert_equal "\354\225\210\353\205\225\355...", - # truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", :length => 10) + def test_truncate_multibyte + # .mb_chars always returns a UTF-8 String. + # assert_equal "\354\225\210\353\205\225\355...", + # truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", :length => 10) - assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'), - truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8'), :length => 10) - end + assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'), + truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8'), :length => 10) end def test_highlight_should_be_html_safe @@ -243,21 +229,10 @@ class TextHelperTest < ActionView::TestCase ) end - if RUBY_VERSION < '1.9' - def test_excerpt_with_utf8 - with_kcode('u') do - assert_equal("...\357\254\203ciency could not be...", excerpt("That's why e\357\254\203ciency could not be helped", 'could', 8)) - end - with_kcode('none') do - assert_equal("...\203ciency could not be...", excerpt("That's why e\357\254\203ciency could not be helped", 'could', 8)) - end - end - else - def test_excerpt_with_utf8 - assert_equal("...\357\254\203ciency could not be...".force_encoding('UTF-8'), excerpt("That's why e\357\254\203ciency could not be helped".force_encoding('UTF-8'), 'could', 8)) - # .mb_chars always returns UTF-8, even in 1.9. This is not great, but it's how it works. Let's work this out. - # assert_equal("...\203ciency could not be...", excerpt("That's why e\357\254\203ciency could not be helped".force_encoding("BINARY"), 'could', 8)) - end + def test_excerpt_with_utf8 + assert_equal("...\357\254\203ciency could not be...".force_encoding('UTF-8'), excerpt("That's why e\357\254\203ciency could not be helped".force_encoding('UTF-8'), 'could', 8)) + # .mb_chars always returns UTF-8, even in 1.9. This is not great, but it's how it works. Let's work this out. + # assert_equal("...\203ciency could not be...", excerpt("That's why e\357\254\203ciency could not be helped".force_encoding("BINARY"), 'could', 8)) end def test_word_wrap diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec index 283c3ee324..60c1d16934 100644 --- a/activemodel/activemodel.gemspec +++ b/activemodel/activemodel.gemspec @@ -7,7 +7,7 @@ Gem::Specification.new do |s| s.summary = 'A toolkit for building modeling frameworks (part of Rails).' s.description = 'A toolkit for building modeling frameworks like Active Record and Active Resource. Rich support for attributes, callbacks, validations, observers, serialization, internationalization, and testing.' - s.required_ruby_version = '>= 1.8.7' + s.required_ruby_version = '>= 1.9.3' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' diff --git a/activemodel/lib/active_model/locale/en.yml b/activemodel/lib/active_model/locale/en.yml index 44425b4a28..ba49c6beaa 100644 --- a/activemodel/lib/active_model/locale/en.yml +++ b/activemodel/lib/active_model/locale/en.yml @@ -23,5 +23,6 @@ en: equal_to: "must be equal to %{count}" less_than: "must be less than %{count}" less_than_or_equal_to: "must be less than or equal to %{count}" + other_than: "must be other than %{count}" odd: "must be odd" even: "must be even" diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index 34d447a0fa..bb9f9679fc 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -5,7 +5,7 @@ module ActiveModel class NumericalityValidator < EachValidator CHECKS = { :greater_than => :>, :greater_than_or_equal_to => :>=, :equal_to => :==, :less_than => :<, :less_than_or_equal_to => :<=, - :odd => :odd?, :even => :even? }.freeze + :odd => :odd?, :even => :even?, :other_than => :!= }.freeze RESERVED_OPTIONS = CHECKS.keys + [:only_integer] @@ -99,6 +99,7 @@ module ActiveModel # * <tt>:equal_to</tt> - Specifies the value must be equal to the supplied value. # * <tt>:less_than</tt> - Specifies the value must be less than the supplied value. # * <tt>:less_than_or_equal_to</tt> - Specifies the value must be less than or equal the supplied value. + # * <tt>:other_than</tt> - Specifies the value must be other than the supplied value. # * <tt>:odd</tt> - Specifies the value must be an odd number. # * <tt>:even</tt> - Specifies the value must be an even number. # * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should @@ -107,7 +108,7 @@ module ActiveModel # * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should # not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The # method, proc or string should return or evaluate to a true or false value. - # * <tt>:strict</tt> - Specifies whether validation should be strict. + # * <tt>:strict</tt> - Specifies whether validation should be strict. # See <tt>ActiveModel::Validation#validates!</tt> for more information # # The following checks can also be supplied with a proc or a symbol which corresponds to a method: diff --git a/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb b/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb index 676937b5e1..3660b9b1e5 100644 --- a/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb +++ b/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb @@ -1,5 +1,5 @@ require "cases/helper" -require 'logger' +require 'active_support/logger' require 'active_support/core_ext/object/inclusion' class SanitizerTest < ActiveModel::TestCase @@ -28,7 +28,7 @@ class SanitizerTest < ActiveModel::TestCase test "debug mass assignment removal with LoggerSanitizer" do original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' } log = StringIO.new - self.logger = Logger.new(log) + self.logger = ActiveSupport::Logger.new(log) @logger_sanitizer.sanitize(original_attributes, @authorizer) assert_match(/admin/, log.string, "Should log removed attributes: #{log.string}") end diff --git a/activemodel/test/cases/validations/numericality_validation_test.rb b/activemodel/test/cases/validations/numericality_validation_test.rb index 08f6169ca5..6742a4bab0 100644 --- a/activemodel/test/cases/validations/numericality_validation_test.rb +++ b/activemodel/test/cases/validations/numericality_validation_test.rb @@ -106,6 +106,13 @@ class NumericalityValidationTest < ActiveModel::TestCase valid!([2]) end + def test_validates_numericality_with_other_than + Topic.validates_numericality_of :approved, :other_than => 0 + + invalid!([0, 0.0]) + valid!([-1, 42]) + end + def test_validates_numericality_with_proc Topic.send(:define_method, :min_approved, lambda { 5 }) Topic.validates_numericality_of :approved, :greater_than_or_equal_to => Proc.new {|topic| topic.min_approved } diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 348873d759..ee2811c2be 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,9 @@ +## Rails 4.0.0 (unreleased) ## + +* PostgreSQL hstore records can be created. + +* PostgreSQL hstore types are automatically deserialized from the database. + ## Rails 3.2.0 (unreleased) ## * Added ability to run migrations only for given scope, which allows diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec index b6a8db1ac0..4a889c1340 100644 --- a/activerecord/activerecord.gemspec +++ b/activerecord/activerecord.gemspec @@ -7,7 +7,7 @@ Gem::Specification.new do |s| s.summary = 'Object-relational mapper framework (part of Rails).' s.description = 'Databases on Rails. Build a persistent domain model by mapping database tables to Ruby classes. Strong conventions for associations, validations, aggregations, migrations, and testing come baked-in.' - s.required_ruby_version = '>= 1.8.7' + s.required_ruby_version = '>= 1.9.3' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 650fa3fc42..131ef09f57 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -16,7 +16,6 @@ module ActiveRecord include TimeZoneConversion include Dirty include Serialization - include DeprecatedUnderscoreRead # Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example, # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). diff --git a/activerecord/lib/active_record/attribute_methods/deprecated_underscore_read.rb b/activerecord/lib/active_record/attribute_methods/deprecated_underscore_read.rb deleted file mode 100644 index 0eb0db65b1..0000000000 --- a/activerecord/lib/active_record/attribute_methods/deprecated_underscore_read.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'active_support/concern' -require 'active_support/deprecation' - -module ActiveRecord - module AttributeMethods - module DeprecatedUnderscoreRead - extend ActiveSupport::Concern - - included do - attribute_method_prefix "_" - end - - module ClassMethods - protected - - def define_method__attribute(attr_name) - # Do nothing, let it hit method missing instead. - end - end - - protected - - def _attribute(attr_name) - ActiveSupport::Deprecation.warn( - "You have called '_#{attr_name}'. This is deprecated. Please use " \ - "either '#{attr_name}' or read_attribute('#{attr_name}')." - ) - read_attribute(attr_name) - end - end - end -end diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb index 5d37088d98..a7785f8786 100644 --- a/activerecord/lib/active_record/attribute_methods/primary_key.rb +++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb @@ -80,10 +80,6 @@ module ActiveRecord end end - def original_primary_key #:nodoc: - deprecated_original_property_getter :primary_key - end - # Sets the name of the primary key column. # # class Project < ActiveRecord::Base @@ -103,11 +99,6 @@ module ActiveRecord @primary_key = value && value.to_s @quoted_primary_key = nil end - - def set_primary_key(value = nil, &block) #:nodoc: - deprecated_property_setter :primary_key, value, block - @quoted_primary_key = nil - end end end end 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 698da34d26..401398c56b 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -162,34 +162,6 @@ module ActiveRecord end end - def columns - with_connection do |c| - c.schema_cache.columns - end - end - deprecate :columns - - def columns_hash - with_connection do |c| - c.schema_cache.columns_hash - end - end - deprecate :columns_hash - - def primary_keys - with_connection do |c| - c.schema_cache.primary_keys - end - end - deprecate :primary_keys - - def clear_cache! - with_connection do |c| - c.schema_cache.clear! - end - end - deprecate :clear_cache! - # Return any checked-out connections back to the pool by threads that # are no longer alive. def clear_stale_cached_connections! diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 0214154c51..6aa4a2c5b3 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -83,6 +83,7 @@ module ActiveRecord when :date then klass.value_to_date(value) when :binary then klass.binary_to_string(value) when :boolean then klass.value_to_boolean(value) + when :hstore then klass.cast_hstore(value) else value end end @@ -100,6 +101,7 @@ module ActiveRecord when :date then "#{klass}.value_to_date(#{var_name})" when :binary then "#{klass}.binary_to_string(#{var_name})" when :boolean then "#{klass}.value_to_boolean(#{var_name})" + when :hstore then "#{klass}.cast_hstore(#{var_name})" else var_name end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 6b742ed858..d7adcdc5d4 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -49,6 +49,42 @@ module ActiveRecord super end end + + def cast_hstore(object) + if Hash === object + object.map { |k,v| + "#{escape_hstore(k)}=>#{escape_hstore(v)}" + }.join ', ' + else + kvs = object.scan(/(?<!\\)".*?(?<!\\)"/).map { |o| + unescape_hstore(o[1...-1]) + } + Hash[kvs.each_slice(2).to_a] + end + end + + private + HSTORE_ESCAPE = { + ' ' => '\\ ', + '\\' => '\\\\', + '"' => '\\"', + '=' => '\\=', + } + HSTORE_ESCAPE_RE = Regexp.union(HSTORE_ESCAPE.keys) + HSTORE_UNESCAPE = HSTORE_ESCAPE.invert + HSTORE_UNESCAPE_RE = Regexp.union(HSTORE_UNESCAPE.keys) + + def unescape_hstore(value) + value.gsub(HSTORE_UNESCAPE_RE) do |match| + HSTORE_UNESCAPE[match] + end + end + + def escape_hstore(value) + value.gsub(HSTORE_ESCAPE_RE) do |match| + HSTORE_ESCAPE[match] + end + end end # :startdoc: @@ -79,53 +115,55 @@ module ActiveRecord # Maps PostgreSQL-specific data types to logical Rails types. def simplified_type(field_type) case field_type - # Numeric and monetary types - when /^(?:real|double precision)$/ - :float - # Monetary types - when 'money' - :decimal - # Character types - when /^(?:character varying|bpchar)(?:\(\d+\))?$/ - :string - # Binary data types - when 'bytea' - :binary - # Date/time types - when /^timestamp with(?:out)? time zone$/ - :datetime - when 'interval' - :string - # Geometric types - when /^(?:point|line|lseg|box|"?path"?|polygon|circle)$/ - :string - # Network address types - when /^(?:cidr|inet|macaddr)$/ - :string - # Bit strings - when /^bit(?: varying)?(?:\(\d+\))?$/ - :string - # XML type - when 'xml' - :xml - # tsvector type - when 'tsvector' - :tsvector - # Arrays - when /^\D+\[\]$/ - :string - # Object identifier types - when 'oid' - :integer - # UUID type - when 'uuid' - :string - # Small and big integer types - when /^(?:small|big)int$/ - :integer - # Pass through all types that are not specific to PostgreSQL. - else - super + # Numeric and monetary types + when /^(?:real|double precision)$/ + :float + # Monetary types + when 'money' + :decimal + when 'hstore' + :hstore + # Character types + when /^(?:character varying|bpchar)(?:\(\d+\))?$/ + :string + # Binary data types + when 'bytea' + :binary + # Date/time types + when /^timestamp with(?:out)? time zone$/ + :datetime + when 'interval' + :string + # Geometric types + when /^(?:point|line|lseg|box|"?path"?|polygon|circle)$/ + :string + # Network address types + when /^(?:cidr|inet|macaddr)$/ + :string + # Bit strings + when /^bit(?: varying)?(?:\(\d+\))?$/ + :string + # XML type + when 'xml' + :xml + # tsvector type + when 'tsvector' + :tsvector + # Arrays + when /^\D+\[\]$/ + :string + # Object identifier types + when 'oid' + :integer + # UUID type + when 'uuid' + :string + # Small and big integer types + when /^(?:small|big)int$/ + :integer + # Pass through all types that are not specific to PostgreSQL. + else + super end end @@ -215,6 +253,10 @@ module ActiveRecord options = args.extract_options! column(args[0], 'tsvector', options) end + + def hstore(name, options = {}) + column(name, 'hstore', options) + end end ADAPTER_NAME = 'PostgreSQL' diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index ce0a165660..7815889b47 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -144,26 +144,18 @@ module ActiveRecord lock_optimistically && columns_hash[locking_column] end + # Set the column to use for optimistic locking. Defaults to +lock_version+. def locking_column=(value) @original_locking_column = @locking_column if defined?(@locking_column) @locking_column = value.to_s end - # Set the column to use for optimistic locking. Defaults to +lock_version+. - def set_locking_column(value = nil, &block) - deprecated_property_setter :locking_column, value, block - end - # The version column used for optimistic locking. Defaults to +lock_version+. def locking_column reset_locking_column unless defined?(@locking_column) @locking_column end - def original_locking_column #:nodoc: - deprecated_original_property_getter :locking_column - end - # Quote the column name used for optimistic locking. def quoted_locking_column connection.quote_column_name(locking_column) diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index 36417d89f7..1de820b3a6 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -105,10 +105,6 @@ module ActiveRecord @table_name end - def original_table_name #:nodoc: - deprecated_original_property_getter :table_name - end - # Sets the table name explicitly. Example: # # class Project < ActiveRecord::Base @@ -125,13 +121,6 @@ module ActiveRecord @relation = Relation.new(self, arel_table) end - def set_table_name(value = nil, &block) #:nodoc: - deprecated_property_setter :table_name, value, block - @quoted_table_name = nil - @arel_table = nil - @relation = Relation.new(self, arel_table) - end - # Returns a quoted version of the table name, used to construct SQL statements. def quoted_table_name @quoted_table_name ||= connection.quote_table_name(table_name) @@ -161,20 +150,12 @@ module ActiveRecord end end - def original_inheritance_column #:nodoc: - deprecated_original_property_getter :inheritance_column - end - # Sets the value of inheritance_column def inheritance_column=(value) @original_inheritance_column = inheritance_column @inheritance_column = value.to_s end - def set_inheritance_column(value = nil, &block) #:nodoc: - deprecated_property_setter :inheritance_column, value, block - end - def sequence_name if base_class == self @sequence_name ||= reset_sequence_name @@ -183,10 +164,6 @@ module ActiveRecord end end - def original_sequence_name #:nodoc: - deprecated_original_property_getter :sequence_name - end - def reset_sequence_name #:nodoc: self.sequence_name = connection.default_sequence_name(table_name, primary_key) end @@ -210,10 +187,6 @@ module ActiveRecord @sequence_name = value.to_s end - def set_sequence_name(value = nil, &block) #:nodoc: - deprecated_property_setter :sequence_name, value, block - end - # Indicates whether the table associated with this class exists def table_exists? connection.schema_cache.table_exists?(table_name) @@ -329,34 +302,6 @@ module ActiveRecord base.table_name end end - - def deprecated_property_setter(property, value, block) - if block - ActiveSupport::Deprecation.warn( - "Calling set_#{property} is deprecated. If you need to lazily evaluate " \ - "the #{property}, define your own `self.#{property}` class method. You can use `super` " \ - "to get the default #{property} where you would have called `original_#{property}`." - ) - - define_attr_method property, value, false, &block - else - ActiveSupport::Deprecation.warn( - "Calling set_#{property} is deprecated. Please use `self.#{property} = 'the_name'` instead." - ) - - define_attr_method property, value, false - end - end - - def deprecated_original_property_getter(property) - ActiveSupport::Deprecation.warn("original_#{property} is deprecated. Define self.#{property} and call super instead.") - - if !instance_variable_defined?("@original_#{property}") && respond_to?("reset_#{property}") - send("reset_#{property}") - else - instance_variable_get("@original_#{property}") - end - end end end end diff --git a/activerecord/lib/active_record/test_case.rb b/activerecord/lib/active_record/test_case.rb index ffe9b08dce..21aff475a8 100644 --- a/activerecord/lib/active_record/test_case.rb +++ b/activerecord/lib/active_record/test_case.rb @@ -56,18 +56,5 @@ module ActiveRecord ensure ActiveRecord::SQLCounter.ignored_sql = prev_ignored_sql end - - def with_kcode(kcode) - if RUBY_VERSION < '1.9' - orig_kcode, $KCODE = $KCODE, kcode - begin - yield - ensure - $KCODE = orig_kcode - end - else - yield - end - end end end diff --git a/activerecord/test/cases/adapters/postgresql/hstore_test.rb b/activerecord/test/cases/adapters/postgresql/hstore_test.rb new file mode 100644 index 0000000000..33bf4478cc --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/hstore_test.rb @@ -0,0 +1,89 @@ +require "cases/helper" + +class PostgresqlHstoreTest < ActiveRecord::TestCase + class Hstore < ActiveRecord::Base + self.table_name = 'hstores' + end + + def setup + @connection = ActiveRecord::Base.connection + begin + @connection.transaction do + @connection.create_table('hstores') do |t| + t.hstore 'tags' + end + end + rescue ActiveRecord::StatementInvalid + return skip "do not test on PG without hstore" + end + end + + def teardown + @connection.execute 'drop table if exists hstores' + end + + def test_column + column = Hstore.columns.find { |c| c.name == 'tags' } + assert column + assert_equal :hstore, column.type + end + + def test_type_cast_hstore + column = Hstore.columns.find { |c| c.name == 'tags' } + assert column + + data = "\"1\"=>\"2\"" + hash = column.class.cast_hstore data + assert_equal({'1' => '2'}, hash) + assert_equal({'1' => '2'}, column.type_cast(data)) + end + + def test_select + @connection.execute "insert into hstores (tags) VALUES ('1=>2')" + x = Hstore.find :first + assert_equal({'1' => '2'}, x.tags) + end + + def test_select_multikey + @connection.execute "insert into hstores (tags) VALUES ('1=>2,2=>3')" + x = Hstore.find :first + assert_equal({'1' => '2', '2' => '3'}, x.tags) + end + + def test_create + assert_cycle('a' => 'b', '1' => '2') + end + + def test_quotes + assert_cycle('a' => 'b"ar', '1"foo' => '2') + end + + def test_whitespace + assert_cycle('a b' => 'b ar', '1"foo' => '2') + end + + def test_backslash + assert_cycle('a\\b' => 'b\\ar', '1"foo' => '2') + end + + def test_comma + assert_cycle('a, b' => 'bar', '1"foo' => '2') + end + + def test_arrow + assert_cycle('a=>b' => 'bar', '1"foo' => '2') + end + + private + def assert_cycle hash + x = Hstore.create!(:tags => hash) + x.reload + assert_equal(hash, x.tags) + + # make sure updates work + x.tags = hash + x.save! + x.reload + assert_equal(hash, x.tags) + end +end 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 2cf9f89c3c..1e1958410c 100644 --- a/activerecord/test/cases/associations/eager_load_nested_include_test.rb +++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb @@ -6,7 +6,6 @@ require 'models/comment' require 'models/category' require 'models/categorization' require 'models/tagging' -require 'active_support/core_ext/array/random_access' module Remembered extend ActiveSupport::Concern diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index 1dc71ac4cc..3d759e64f8 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -1095,4 +1095,11 @@ class EagerAssociationTest < ActiveRecord::TestCase Post.includes(:comments).order(nil).where(:comments => {:body => "Thank you for the welcome"}).first end end + + def test_deep_including_through_habtm + posts = Post.find(:all, :include => {:categories => :categorizations}, :order => "posts.id") + assert_no_queries { assert_equal 2, posts[0].categories[0].categorizations.length } + assert_no_queries { assert_equal 1, posts[0].categories[1].categorizations.length } + assert_no_queries { assert_equal 2, posts[1].categories[0].categorizations.length } + end end diff --git a/activerecord/test/cases/associations/extension_test.rb b/activerecord/test/cases/associations/extension_test.rb index 395b59258d..d7c489c2b5 100644 --- a/activerecord/test/cases/associations/extension_test.rb +++ b/activerecord/test/cases/associations/extension_test.rb @@ -36,11 +36,6 @@ class AssociationsExtensionsTest < ActiveRecord::TestCase end def test_marshalling_extensions - if ENV['TRAVIS'] && RUBY_VERSION == "1.8.7" - return skip("Marshalling tests disabled for Ruby 1.8.7 on Travis CI due to what appears " \ - "to be a Ruby bug.") - end - david = developers(:david) assert_equal projects(:action_controller), david.projects.find_most_recent @@ -51,11 +46,6 @@ class AssociationsExtensionsTest < ActiveRecord::TestCase end def test_marshalling_named_extensions - if ENV['TRAVIS'] && RUBY_VERSION == "1.8.7" - return skip("Marshalling tests disabled for Ruby 1.8.7 on Travis CI due to what appears " \ - "to be a Ruby bug.") - end - david = developers(:david) assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 5e9f8028e9..8e509a9792 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -102,7 +102,6 @@ class AttributeMethodsTest < ActiveRecord::TestCase def test_respond_to? topic = Topic.find(1) assert_respond_to topic, "title" - assert_respond_to topic, "_title" assert_respond_to topic, "title?" assert_respond_to topic, "title=" assert_respond_to topic, :title @@ -114,19 +113,12 @@ class AttributeMethodsTest < ActiveRecord::TestCase assert !topic.respond_to?(:nothingness) end - def test_deprecated_underscore_method - topic = Topic.find(1) - assert_equal topic.title, assert_deprecated { topic._title } - end - def test_respond_to_with_custom_primary_key keyboard = Keyboard.create assert_not_nil keyboard.key_number assert_equal keyboard.key_number, keyboard.id assert keyboard.respond_to?('key_number') - assert keyboard.respond_to?('_key_number') assert keyboard.respond_to?('id') - assert keyboard.respond_to?('_id') end # Syck calls respond_to? before actually calling initialize diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 1012bfbd94..f102634ef1 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -1357,22 +1357,6 @@ class BasicsTest < ActiveRecord::TestCase assert_equal author_name, Topic.find(topic.id).author_name end - if RUBY_VERSION < '1.9' - def test_quote_chars - with_kcode('UTF8') do - str = 'The Narrator' - topic = Topic.create(:author_name => str) - assert_equal str, topic.author_name - - assert_kind_of ActiveSupport::Multibyte.proxy_class, str.mb_chars - topic = Topic.find_by_author_name(str.mb_chars) - - assert_kind_of Topic, topic - assert_equal str, topic.author_name, "The right topic should have been found by name even with name passed as Chars" - end - end - end - def test_toggle_attribute assert !topics(:first).approved? topics(:first).toggle!(:approved) @@ -1399,17 +1383,6 @@ class BasicsTest < ActiveRecord::TestCase assert_equal dev, dev.reload end - def test_set_table_name_with_value - k = Class.new( ActiveRecord::Base ) - k.table_name = "foo" - assert_equal "foo", k.table_name - - assert_deprecated do - k.set_table_name "bar" - end - assert_equal "bar", k.table_name - end - def test_switching_between_table_name assert_difference("GoodJoke.count") do Joke.table_name = "cold_jokes" @@ -1432,17 +1405,6 @@ class BasicsTest < ActiveRecord::TestCase assert_equal klass.connection.quote_table_name("bar"), klass.quoted_table_name end - def test_set_table_name_with_block - k = Class.new( ActiveRecord::Base ) - assert_deprecated do - k.set_table_name "foo" - k.set_table_name do - ActiveSupport::Deprecation.silence { original_table_name } + "ks" - end - end - assert_equal "fooks", k.table_name - end - def test_set_table_name_with_inheritance k = Class.new( ActiveRecord::Base ) def k.name; "Foo"; end @@ -1450,145 +1412,6 @@ class BasicsTest < ActiveRecord::TestCase assert_equal "foosks", k.table_name end - def test_original_table_name - k = Class.new(ActiveRecord::Base) - def k.name; "Foo"; end - k.table_name = "bar" - - assert_deprecated do - assert_equal "foos", k.original_table_name - end - - k = Class.new(ActiveRecord::Base) - k.table_name = "omg" - k.table_name = "wtf" - - assert_deprecated do - assert_equal "omg", k.original_table_name - end - end - - def test_set_primary_key_with_value - k = Class.new( ActiveRecord::Base ) - k.primary_key = "foo" - assert_equal "foo", k.primary_key - - assert_deprecated do - k.set_primary_key "bar" - end - assert_equal "bar", k.primary_key - end - - def test_set_primary_key_with_block - k = Class.new( ActiveRecord::Base ) - k.primary_key = 'id' - - assert_deprecated do - k.set_primary_key do - "sys_" + ActiveSupport::Deprecation.silence { original_primary_key } - end - end - assert_equal "sys_id", k.primary_key - end - - def test_original_primary_key - k = Class.new(ActiveRecord::Base) - def k.name; "Foo"; end - k.table_name = "posts" - k.primary_key = "bar" - - assert_deprecated do - assert_equal "id", k.original_primary_key - end - - k = Class.new(ActiveRecord::Base) - k.primary_key = "omg" - k.primary_key = "wtf" - - assert_deprecated do - assert_equal "omg", k.original_primary_key - end - end - - def test_set_inheritance_column_with_value - k = Class.new( ActiveRecord::Base ) - k.inheritance_column = "foo" - assert_equal "foo", k.inheritance_column - - assert_deprecated do - k.set_inheritance_column "bar" - end - assert_equal "bar", k.inheritance_column - end - - def test_set_inheritance_column_with_block - k = Class.new( ActiveRecord::Base ) - assert_deprecated do - k.set_inheritance_column do - ActiveSupport::Deprecation.silence { original_inheritance_column } + "_id" - end - end - assert_equal "type_id", k.inheritance_column - end - - def test_original_inheritance_column - k = Class.new(ActiveRecord::Base) - def k.name; "Foo"; end - k.inheritance_column = "omg" - - assert_deprecated do - assert_equal "type", k.original_inheritance_column - end - end - - def test_set_sequence_name_with_value - k = Class.new( ActiveRecord::Base ) - k.sequence_name = "foo" - assert_equal "foo", k.sequence_name - - assert_deprecated do - k.set_sequence_name "bar" - end - assert_equal "bar", k.sequence_name - end - - def test_set_sequence_name_with_block - k = Class.new( ActiveRecord::Base ) - k.table_name = "projects" - orig_name = k.sequence_name - return skip "sequences not supported by db" unless orig_name - - assert_deprecated do - k.set_sequence_name do - ActiveSupport::Deprecation.silence { original_sequence_name } + "_lol" - end - end - assert_equal orig_name + "_lol", k.sequence_name - end - - def test_original_sequence_name - k = Class.new(ActiveRecord::Base) - k.table_name = "projects" - orig_name = k.sequence_name - return skip "sequences not supported by db" unless orig_name - - k = Class.new(ActiveRecord::Base) - k.table_name = "projects" - k.sequence_name = "omg" - - assert_deprecated do - assert_equal orig_name, k.original_sequence_name - end - - k = Class.new(ActiveRecord::Base) - k.table_name = "projects" - k.sequence_name = "omg" - k.sequence_name = "wtf" - assert_deprecated do - assert_equal "omg", k.original_sequence_name - end - end - def test_sequence_name_with_abstract_class ak = Class.new(ActiveRecord::Base) ak.abstract_class = true @@ -1914,7 +1737,7 @@ class BasicsTest < ActiveRecord::TestCase def test_benchmark_with_log_level original_logger = ActiveRecord::Base.logger log = StringIO.new - ActiveRecord::Base.logger = Logger.new(log) + ActiveRecord::Base.logger = ActiveSupport::Logger.new(log) ActiveRecord::Base.logger.level = Logger::WARN ActiveRecord::Base.benchmark("Debug Topic Count", :level => :debug) { Topic.count } ActiveRecord::Base.benchmark("Warn Topic Count", :level => :warn) { Topic.count } @@ -1929,7 +1752,7 @@ class BasicsTest < ActiveRecord::TestCase def test_benchmark_with_use_silence original_logger = ActiveRecord::Base.logger log = StringIO.new - ActiveRecord::Base.logger = Logger.new(log) + ActiveRecord::Base.logger = ActiveSupport::Logger.new(log) ActiveRecord::Base.benchmark("Logging", :level => :debug, :silence => false) { ActiveRecord::Base.logger.debug "Quiet" } assert_match(/Quiet/, log.string) ensure @@ -1981,11 +1804,6 @@ class BasicsTest < ActiveRecord::TestCase end def test_marshal_round_trip - if ENV['TRAVIS'] && RUBY_VERSION == "1.8.7" - return skip("Marshalling tests disabled for Ruby 1.8.7 on Travis CI due to what appears " \ - "to be a Ruby bug.") - end - expected = posts(:welcome) marshalled = Marshal.dump(expected) actual = Marshal.load(marshalled) @@ -1994,11 +1812,6 @@ class BasicsTest < ActiveRecord::TestCase end def test_marshal_new_record_round_trip - if ENV['TRAVIS'] && RUBY_VERSION == "1.8.7" - return skip("Marshalling tests disabled for Ruby 1.8.7 on Travis CI due to what appears " \ - "to be a Ruby bug.") - end - marshalled = Marshal.dump(Post.new) post = Marshal.load(marshalled) @@ -2006,11 +1819,6 @@ class BasicsTest < ActiveRecord::TestCase end def test_marshalling_with_associations - if ENV['TRAVIS'] && RUBY_VERSION == "1.8.7" - return skip("Marshalling tests disabled for Ruby 1.8.7 on Travis CI due to what appears " \ - "to be a Ruby bug.") - end - post = Post.new post.comments.build diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index be7edb858f..f7ee83998d 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -226,48 +226,6 @@ class OptimisticLockingTest < ActiveRecord::TestCase end end -class SetLockingColumnTest < ActiveRecord::TestCase - def test_set_set_locking_column_with_value - k = Class.new( ActiveRecord::Base ) - k.locking_column = "foo" - assert_equal "foo", k.locking_column - - assert_deprecated do - k.set_locking_column "bar" - end - assert_equal "bar", k.locking_column - end - - def test_set_locking_column_with_block - k = Class.new( ActiveRecord::Base ) - k.locking_column = 'foo' - - assert_deprecated do - k.set_locking_column do - "lock_" + ActiveSupport::Deprecation.silence { original_locking_column } - end - end - assert_equal "lock_foo", k.locking_column - end - - def test_original_locking_column - k = Class.new(ActiveRecord::Base) - k.locking_column = "bar" - - assert_deprecated do - assert_equal ActiveRecord::Locking::Optimistic::ClassMethods::DEFAULT_LOCKING_COLUMN, k.original_locking_column - end - - k = Class.new(ActiveRecord::Base) - k.locking_column = "omg" - k.locking_column = "wtf" - - assert_deprecated do - assert_equal "omg", k.original_locking_column - end - end -end - class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase fixtures :people, :legacy_things, :references @@ -421,16 +379,6 @@ unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter) || in_memory_db? assert first.end > second.end end - # Hit by ruby deadlock detection since connection checkout is mutexed. - if RUBY_VERSION < '1.9.0' - def test_second_lock_waits - assert [0.2, 1, 5].any? { |zzz| - first, second = duel(zzz) { Person.find 1, :lock => true } - second.end > first.end - } - end - end - protected def duel(zzz = 5) t0, t1, t2, t3 = nil, nil, nil, nil diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 0eb3d900bd..e17ba76437 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -1,5 +1,4 @@ require "cases/helper" -require 'active_support/core_ext/array/random_access' require 'models/post' require 'models/topic' require 'models/comment' diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb index bc3dfb1078..296621c0d1 100644 --- a/activerecord/test/cases/pooled_connections_test.rb +++ b/activerecord/test/cases/pooled_connections_test.rb @@ -33,14 +33,6 @@ class PooledConnectionsTest < ActiveRecord::TestCase end # Will deadlock due to lack of Monitor timeouts in 1.9 - if RUBY_VERSION < '1.9' - def test_pooled_connection_checkout - checkout_connections - assert_equal 2, @connections.length - assert_equal 2, @timed_out - end - end - def checkout_checkin_connections(pool_size, threads) ActiveRecord::Base.establish_connection(@connection.merge({:pool => pool_size, :wait_timeout => 0.5})) @connection_count = 0 diff --git a/activerecord/test/cases/validations/association_validation_test.rb b/activerecord/test/cases/validations/association_validation_test.rb index 768fbc5b0a..f155b9bc40 100644 --- a/activerecord/test/cases/validations/association_validation_test.rb +++ b/activerecord/test/cases/validations/association_validation_test.rb @@ -91,14 +91,12 @@ class AssociationValidationTest < ActiveRecord::TestCase end def test_validates_size_of_association_utf8 - with_kcode('UTF8') do - assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 } - o = Owner.new('name' => 'あいうえおかきくけこ') - assert !o.save - assert o.errors[:pets].any? - o.pets.build('name' => 'あいうえおかきくけこ') - assert o.valid? - end + assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 } + o = Owner.new('name' => 'あいうえおかきくけこ') + assert !o.save + assert o.errors[:pets].any? + o.pets.build('name' => 'あいうえおかきくけこ') + assert o.valid? end def test_validates_presence_of_belongs_to_association__parent_is_new_record diff --git a/activerecord/test/cases/validations/uniqueness_validation_test.rb b/activerecord/test/cases/validations/uniqueness_validation_test.rb index 0f1b3667cc..382ad0a06a 100644 --- a/activerecord/test/cases/validations/uniqueness_validation_test.rb +++ b/activerecord/test/cases/validations/uniqueness_validation_test.rb @@ -149,16 +149,14 @@ class UniquenessValidationTest < ActiveRecord::TestCase assert t2.valid?, "should validate with nil" assert t2.save, "should save with nil" - with_kcode('UTF8') do - t_utf8 = Topic.new("title" => "Я тоже уникальный!") - assert t_utf8.save, "Should save t_utf8 as unique" - - # If database hasn't UTF-8 character set, this test fails - if Topic.find(t_utf8, :select => 'LOWER(title) AS title').title == "я тоже уникальный!" - t2_utf8 = Topic.new("title" => "я тоже УНИКАЛЬНЫЙ!") - assert !t2_utf8.valid?, "Shouldn't be valid" - assert !t2_utf8.save, "Shouldn't save t2_utf8 as unique" - end + t_utf8 = Topic.new("title" => "Я тоже уникальный!") + assert t_utf8.save, "Should save t_utf8 as unique" + + # If database hasn't UTF-8 character set, this test fails + if Topic.find(t_utf8, :select => 'LOWER(title) AS title').title == "я тоже уникальный!" + t2_utf8 = Topic.new("title" => "я тоже УНИКАЛЬНЫЙ!") + assert !t2_utf8.valid?, "Shouldn't be valid" + assert !t2_utf8.save, "Shouldn't save t2_utf8 as unique" end end @@ -256,13 +254,11 @@ class UniquenessValidationTest < ActiveRecord::TestCase end def test_validate_uniqueness_with_limit_and_utf8 - with_kcode('UTF8') do - # Event.title is limited to 5 characters - e1 = Event.create(:title => "一二三四五") - assert e1.valid?, "Could not create an event with a unique, 5 character title" - e2 = Event.create(:title => "一二三四五六七八") - assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique" - end + # Event.title is limited to 5 characters + e1 = Event.create(:title => "一二三四五") + assert e1.valid?, "Could not create an event with a unique, 5 character title" + e2 = Event.create(:title => "一二三四五六七八") + assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique" end def test_validate_straight_inheritance_uniqueness diff --git a/activeresource/activeresource.gemspec b/activeresource/activeresource.gemspec index f5c26f38df..ae1972a7d7 100644 --- a/activeresource/activeresource.gemspec +++ b/activeresource/activeresource.gemspec @@ -7,7 +7,7 @@ Gem::Specification.new do |s| s.summary = 'REST modeling framework (part of Rails).' s.description = 'REST on Rails. Wrap your RESTful web app with Ruby classes and work with them like Active Record models.' - s.required_ruby_version = '>= 1.8.7' + s.required_ruby_version = '>= 1.9.3' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index 10cc727bd9..548990cb70 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -1413,7 +1413,7 @@ module ActiveResource namespaces = module_names[0, module_names.size-1].map do |module_name| receiver = receiver.const_get(module_name) end - const_args = RUBY_VERSION < "1.9" ? [resource_name] : [resource_name, false] + const_args = [resource_name, false] if namespace = namespaces.reverse.detect { |ns| ns.const_defined?(*const_args) } namespace.const_get(*const_args) else @@ -1425,7 +1425,7 @@ module ActiveResource def find_or_create_resource_for(name) resource_name = name.to_s.camelize - const_args = RUBY_VERSION < "1.9" ? [resource_name] : [resource_name, false] + const_args = [resource_name, false] if self.class.const_defined?(*const_args) self.class.const_get(*const_args) else diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index 70d17fb580..4db22a0dbd 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -7,7 +7,7 @@ Gem::Specification.new do |s| s.summary = 'A toolkit of support libraries and Ruby core extensions extracted from the Rails framework.' s.description = 'A toolkit of support libraries and Ruby core extensions extracted from the Rails framework. Rich support for multibyte strings, internationalization, time zones, and testing.' - s.required_ruby_version = '>= 1.8.7' + s.required_ruby_version = '>= 1.9.3' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' diff --git a/activesupport/lib/active_support/base64.rb b/activesupport/lib/active_support/base64.rb index 35014cb3d5..b43d2ce9a3 100644 --- a/activesupport/lib/active_support/base64.rb +++ b/activesupport/lib/active_support/base64.rb @@ -1,35 +1,7 @@ -begin - require 'base64' -rescue LoadError -end +require 'base64' module ActiveSupport - if defined? ::Base64 - Base64 = ::Base64 - else - # Base64 provides utility methods for encoding and de-coding binary data - # using a base 64 representation. A base 64 representation of binary data - # consists entirely of printable US-ASCII characters. The Base64 module - # is included in Ruby 1.8, but has been removed in Ruby 1.9. - module Base64 - # Encodes a string to its base 64 representation. Each 60 characters of - # output is separated by a newline character. - # - # ActiveSupport::Base64.encode64("Original unencoded string") - # # => "T3JpZ2luYWwgdW5lbmNvZGVkIHN0cmluZw==\n" - def self.encode64(data) - [data].pack("m") - end - - # Decodes a base 64 encoded string to its original representation. - # - # ActiveSupport::Base64.decode64("T3JpZ2luYWwgdW5lbmNvZGVkIHN0cmluZw==") - # # => "Original unencoded string" - def self.decode64(data) - data.unpack("m").first - end - end - end + Base64 = ::Base64 # Encodes the value as base64 without the newline breaks. This makes the base64 encoding readily usable as URL parameters # or memcache keys without further processing. diff --git a/activesupport/lib/active_support/core_ext/array.rb b/activesupport/lib/active_support/core_ext/array.rb index 268c9bed4c..79ba79192a 100644 --- a/activesupport/lib/active_support/core_ext/array.rb +++ b/activesupport/lib/active_support/core_ext/array.rb @@ -4,5 +4,4 @@ require 'active_support/core_ext/array/uniq_by' require 'active_support/core_ext/array/conversions' require 'active_support/core_ext/array/extract_options' require 'active_support/core_ext/array/grouping' -require 'active_support/core_ext/array/random_access' require 'active_support/core_ext/array/prepend_and_append' diff --git a/activesupport/lib/active_support/core_ext/array/random_access.rb b/activesupport/lib/active_support/core_ext/array/random_access.rb deleted file mode 100644 index bb1807a68a..0000000000 --- a/activesupport/lib/active_support/core_ext/array/random_access.rb +++ /dev/null @@ -1,30 +0,0 @@ -class Array - # Backport of Array#sample based on Marc-Andre Lafortune's https://github.com/marcandre/backports/ - # Returns a random element or +n+ random elements from the array. - # If the array is empty and +n+ is nil, returns <tt>nil</tt>. - # If +n+ is passed and its value is less than 0, it raises an +ArgumentError+ exception. - # If the value of +n+ is equal or greater than 0 it returns <tt>[]</tt>. - # - # [1,2,3,4,5,6].sample # => 4 - # [1,2,3,4,5,6].sample(3) # => [2, 4, 5] - # [1,2,3,4,5,6].sample(-3) # => ArgumentError: negative array size - # [].sample # => nil - # [].sample(3) # => [] - def sample(n=nil) - return self[Kernel.rand(size)] if n.nil? - n = n.to_int - rescue Exception => e - raise TypeError, "Coercion error: #{n.inspect}.to_int => Integer failed:\n(#{e.message})" - else - raise TypeError, "Coercion error: obj.to_int did NOT return an Integer (was #{n.class})" unless n.kind_of? Integer - raise ArgumentError, "negative array size" if n < 0 - n = size if n > size - result = Array.new(self) - n.times do |i| - r = i + Kernel.rand(size - i) - result[i], result[r] = result[r], result[i] - end - result[n..size] = [] - result - end unless method_defined? :sample -end diff --git a/activesupport/lib/active_support/core_ext/date/freeze.rb b/activesupport/lib/active_support/core_ext/date/freeze.rb deleted file mode 100644 index a731f8345e..0000000000 --- a/activesupport/lib/active_support/core_ext/date/freeze.rb +++ /dev/null @@ -1,33 +0,0 @@ -# Date memoizes some instance methods using metaprogramming to wrap -# the methods with one that caches the result in an instance variable. -# -# If a Date is frozen but the memoized method hasn't been called, the -# first call will result in a frozen object error since the memo -# instance variable is uninitialized. -# -# Work around by eagerly memoizing before the first freeze. -# -# Ruby 1.9 uses a preinitialized instance variable so it's unaffected. -# This hack is as close as we can get to feature detection: -if RUBY_VERSION < '1.9' - require 'date' - begin - ::Date.today.freeze.jd - rescue => frozen_object_error - if frozen_object_error.message =~ /frozen/ - class Date #:nodoc: - def freeze - unless frozen? - self.class.private_instance_methods(false).each do |m| - if m.to_s =~ /\A__\d+__\Z/ - instance_variable_set(:"@#{m}", [send(m)]) - end - end - end - - super - end - end - end - end -end diff --git a/activesupport/lib/active_support/core_ext/float.rb b/activesupport/lib/active_support/core_ext/float.rb deleted file mode 100644 index 7570471b95..0000000000 --- a/activesupport/lib/active_support/core_ext/float.rb +++ /dev/null @@ -1 +0,0 @@ -require 'active_support/core_ext/float/rounding' diff --git a/activesupport/lib/active_support/core_ext/float/rounding.rb b/activesupport/lib/active_support/core_ext/float/rounding.rb deleted file mode 100644 index 0d4fb87665..0000000000 --- a/activesupport/lib/active_support/core_ext/float/rounding.rb +++ /dev/null @@ -1,19 +0,0 @@ -class Float - alias precisionless_round round - private :precisionless_round - - # Rounds the float with the specified precision. - # - # x = 1.337 - # x.round # => 1 - # x.round(1) # => 1.3 - # x.round(2) # => 1.34 - def round(precision = nil) - if precision - magnitude = 10.0 ** precision - (self * magnitude).round / magnitude - else - precisionless_round - end - end -end if RUBY_VERSION < '1.9' diff --git a/activesupport/lib/active_support/core_ext/io.rb b/activesupport/lib/active_support/core_ext/io.rb deleted file mode 100644 index 75f1055191..0000000000 --- a/activesupport/lib/active_support/core_ext/io.rb +++ /dev/null @@ -1,15 +0,0 @@ -if RUBY_VERSION < '1.9.2' - -# :stopdoc: -class IO - def self.binread(name, length = nil, offset = nil) - return File.read name unless length || offset - File.open(name, 'rb') { |f| - f.seek offset if offset - f.read length - } - end -end -# :startdoc: - -end diff --git a/activesupport/lib/active_support/core_ext/kernel/singleton_class.rb b/activesupport/lib/active_support/core_ext/kernel/singleton_class.rb index 33612155fb..9bbf1bbd73 100644 --- a/activesupport/lib/active_support/core_ext/kernel/singleton_class.rb +++ b/activesupport/lib/active_support/core_ext/kernel/singleton_class.rb @@ -1,11 +1,4 @@ module Kernel - # Returns the object's singleton class. - def singleton_class - class << self - self - end - end unless respond_to?(:singleton_class) # exists in 1.9.2 - # class_eval on an object acts like singleton_class.class_eval. def class_eval(*args, &block) singleton_class.class_eval(*args, &block) diff --git a/activesupport/lib/active_support/core_ext/object/blank.rb b/activesupport/lib/active_support/core_ext/object/blank.rb index fe27f45295..7271671908 100644 --- a/activesupport/lib/active_support/core_ext/object/blank.rb +++ b/activesupport/lib/active_support/core_ext/object/blank.rb @@ -89,9 +89,6 @@ class Hash end class String - # 0x3000: fullwidth whitespace - NON_WHITESPACE_REGEXP = %r![^\s#{[0x3000].pack("U")}]! - # A string is blank if it's empty or contains whitespaces only: # # "".blank? # => true @@ -100,12 +97,7 @@ class String # " something here ".blank? # => false # def blank? - # 1.8 does not takes [:space:] properly - if encoding_aware? - self !~ /[^[:space:]]/ - else - self !~ NON_WHITESPACE_REGEXP - end + self !~ /[^[:space:]]/ end end diff --git a/activesupport/lib/active_support/core_ext/string/conversions.rb b/activesupport/lib/active_support/core_ext/string/conversions.rb index 0f8933b658..73eedf5982 100644 --- a/activesupport/lib/active_support/core_ext/string/conversions.rb +++ b/activesupport/lib/active_support/core_ext/string/conversions.rb @@ -1,37 +1,8 @@ -# encoding: utf-8 require 'date' require 'active_support/core_ext/time/publicize_conversion_methods' require 'active_support/core_ext/time/calculations' class String - # Returns the codepoint of the first character of the string, assuming a - # single-byte character encoding: - # - # "a".ord # => 97 - # "à".ord # => 224, in ISO-8859-1 - # - # This method is defined in Ruby 1.8 for Ruby 1.9 forward compatibility on - # these character encodings. - # - # <tt>ActiveSupport::Multibyte::Chars#ord</tt> is forward compatible with - # Ruby 1.9 on UTF8 strings: - # - # "a".mb_chars.ord # => 97 - # "à".mb_chars.ord # => 224, in UTF8 - # - # Note that the 224 is different in both examples. In ISO-8859-1 "à" is - # represented as a single byte, 224. In UTF8 it is represented with two - # bytes, namely 195 and 160, but its Unicode codepoint is 224. If we - # call +ord+ on the UTF8 string "à" the return value will be 195. That is - # not an error, because UTF8 is unsupported, the call itself would be - # bogus. - def ord - self[0] - end unless method_defined?(:ord) - - # +getbyte+ backport from Ruby 1.9 - alias_method :getbyte, :[] unless method_defined?(:getbyte) - # Form can be either :utc (default) or :local. def to_time(form = :utc) return nil if self.blank? diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index c6d861d124..6cb2ea68b3 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -6,33 +6,21 @@ class ERB HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"' } JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' } - # Detect whether 1.9 can transcode with XML escaping. - if '"><&""' == ('><&"'.encode('utf-8', :xml => :attr) rescue false) - # A utility method for escaping HTML tag characters. - # This method is also aliased as <tt>h</tt>. - # - # In your ERB templates, use this method to escape any unsafe content. For example: - # <%=h @person.name %> - # - # ==== Example: - # puts html_escape("is a > 0 & a < 10?") - # # => is a > 0 & a < 10? - def html_escape(s) - s = s.to_s - if s.html_safe? - s - else - s.encode(s.encoding, :xml => :attr)[1...-1].html_safe - end - end - else - def html_escape(s) #:nodoc: - s = s.to_s - if s.html_safe? - s - else - s.gsub(/[&"><]/n) { |special| HTML_ESCAPE[special] }.html_safe - end + # A utility method for escaping HTML tag characters. + # This method is also aliased as <tt>h</tt>. + # + # In your ERB templates, use this method to escape any unsafe content. For example: + # <%=h @person.name %> + # + # ==== Example: + # puts html_escape("is a > 0 & a < 10?") + # # => is a > 0 & a < 10? + def html_escape(s) + s = s.to_s + if s.html_safe? + s + else + s.encode(s.encoding, :xml => :attr)[1...-1].html_safe end end diff --git a/activesupport/lib/active_support/time.rb b/activesupport/lib/active_support/time.rb index 86f057d676..4ef289a414 100644 --- a/activesupport/lib/active_support/time.rb +++ b/activesupport/lib/active_support/time.rb @@ -21,7 +21,6 @@ require 'active_support/core_ext/time/conversions' require 'active_support/core_ext/time/zones' require 'active_support/core_ext/date/acts_like' -require 'active_support/core_ext/date/freeze' require 'active_support/core_ext/date/calculations' require 'active_support/core_ext/date/conversions' require 'active_support/core_ext/date/zones' diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb index 52231aaeb0..6739b4afbd 100644 --- a/activesupport/test/core_ext/array_ext_test.rb +++ b/activesupport/test/core_ext/array_ext_test.rb @@ -363,34 +363,6 @@ class ArrayUniqByTests < Test::Unit::TestCase end end -class ArrayExtRandomTests < ActiveSupport::TestCase - def test_sample_from_array - assert_nil [].sample - assert_equal [], [].sample(5) - assert_equal 42, [42].sample - assert_equal [42], [42].sample(5) - - a = [:foo, :bar, 42] - s = a.sample(2) - assert_equal 2, s.size - assert_equal 1, (a-s).size - assert_equal [], a-(0..20).sum{a.sample(2)} - - o = Object.new - def o.to_int; 1; end - assert_equal [0], [0].sample(o) - - o = Object.new - assert_raises(TypeError) { [0].sample(o) } - - o = Object.new - def o.to_int; ''; end - assert_raises(TypeError) { [0].sample(o) } - - assert_raises(ArgumentError) { [0].sample(-7) } - end -end - class ArrayWrapperTests < Test::Unit::TestCase class FakeCollection def to_ary diff --git a/activesupport/test/core_ext/float_ext_test.rb b/activesupport/test/core_ext/float_ext_test.rb deleted file mode 100644 index ac7e7a8ed6..0000000000 --- a/activesupport/test/core_ext/float_ext_test.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'abstract_unit' -require 'active_support/core_ext/float/rounding' - -class FloatExtRoundingTests < Test::Unit::TestCase - def test_round_for_positive_number - assert_equal 1, 1.4.round - assert_equal 2, 1.6.round - assert_equal 2, 1.6.round(0) - assert_equal 1.4, 1.4.round(1) - assert_equal 1.4, 1.4.round(3) - assert_equal 1.5, 1.45.round(1) - assert_equal 1.45, 1.445.round(2) - end - - def test_round_for_negative_number - assert_equal( -1, -1.4.round ) - assert_equal( -2, -1.6.round ) - assert_equal( -1.4, -1.4.round(1) ) - assert_equal( -1.5, -1.45.round(1) ) - end - - def test_round_with_negative_precision - assert_equal 123460.0, 123456.0.round(-1) - assert_equal 123500.0, 123456.0.round(-2) - end -end diff --git a/activesupport/test/core_ext/io_test.rb b/activesupport/test/core_ext/io_test.rb deleted file mode 100644 index b9abf685da..0000000000 --- a/activesupport/test/core_ext/io_test.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'abstract_unit' - -require 'active_support/core_ext/io' - -class IOTest < Test::Unit::TestCase - def test_binread_one_arg - assert_equal File.read(__FILE__), IO.binread(__FILE__) - end - - def test_binread_two_args - assert_equal File.read(__FILE__).bytes.first(10).pack('C*'), - IO.binread(__FILE__, 10) - end - - def test_binread_three_args - actual = IO.binread(__FILE__, 5, 10) - expected = File.open(__FILE__, 'rb') { |f| - f.seek 10 - f.read 5 - } - assert_equal expected, actual - end -end diff --git a/activesupport/test/core_ext/kernel_test.rb b/activesupport/test/core_ext/kernel_test.rb index 995bc0751a..73a7179872 100644 --- a/activesupport/test/core_ext/kernel_test.rb +++ b/activesupport/test/core_ext/kernel_test.rb @@ -42,11 +42,6 @@ class KernelTest < Test::Unit::TestCase assert_equal 1, silence_stderr { 1 } end - def test_singleton_class - o = Object.new - assert_equal class << o; self end, o.singleton_class - end - def test_class_eval o = Object.new class << o; @x = 1; end @@ -112,4 +107,4 @@ class KernelDebuggerTest < Test::Unit::TestCase ensure Object.send(:remove_const, "Rails") end -end
\ No newline at end of file +end diff --git a/rails.gemspec b/rails.gemspec index 3377b4e175..1d4c6c36c8 100644 --- a/rails.gemspec +++ b/rails.gemspec @@ -7,7 +7,7 @@ Gem::Specification.new do |s| s.summary = 'Full-stack web application framework.' s.description = 'Ruby on Rails is a full-stack web framework optimized for programmer happiness and sustainable productivity. It encourages beautiful code by favoring convention over configuration.' - s.required_ruby_version = '>= 1.8.7' + s.required_ruby_version = '>= 1.9.3' s.required_rubygems_version = ">= 1.3.6" s.author = 'David Heinemeier Hansson' diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 0bd76df6d7..555d466ca4 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -32,19 +32,6 @@ * Remove old 'config.paths.app.controller' API in favor of 'config.paths["app/controller"]' API *Guillermo Iguaran* -* Rails 3.1.1 - -* Add jquery-rails to Gemfile of plugins, test/dummy app needs it. Closes #3091. *Santiago Pastorino* - -* Add config.assets.initialize_on_precompile which, when set to false, forces - `rake assets:precompile` to load the application but does not initialize it. - - To the app developer, this means configuration add in - config/initializers/* will not be executed. - - Plugins developers need to special case their initializers that are - meant to be run in the assets group by adding :group => :assets. - ## Rails 3.1.2 (unreleased) ## * Engines: don't blow up if db/seeds.rb is missing. @@ -55,6 +42,19 @@ *GH 2564* *José Valim* + +## Rails 3.1.1 ## + +* Add jquery-rails to Gemfile of plugins, test/dummy app needs it. Closes #3091. *Santiago Pastorino* + +* Add config.assets.initialize_on_precompile which, when set to false, forces + `rake assets:precompile` to load the application but does not initialize it. + + To the app developer, this means configuration add in + config/initializers/* will not be executed. + + Plugins developers need to special case their initializers that are + meant to be run in the assets group by adding :group => :assets. ## Rails 3.1.0 (August 30, 2011) ## diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index 6646e9cd05..cf9185a324 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -177,19 +177,6 @@ end NOTE: Defined in +active_support/core_ext/object/try.rb+. -h4. +singleton_class+ - -The method +singleton_class+ returns the singleton class of the receiver: - -<ruby> -String.singleton_class # => #<Class:String> -String.new.singleton_class # => #<Class:#<String:0x17a1d1c>> -</ruby> - -WARNING: Fixnums and symbols have no singleton classes, +singleton_class+ raises +TypeError+ on them. Moreover, the singleton classes of +nil+, +true+, and +false+, are +NilClass+, +TrueClass+, and +FalseClass+, respectively. - -NOTE: Defined in +active_support/core_ext/kernel/singleton_class.rb+. - h4. +class_eval(*args, &block)+ You can evaluate code in the context of any object's singleton class using +class_eval+: @@ -1851,43 +1838,6 @@ NOTE: Defined in +active_support/core_ext/string/inflections.rb+. h4(#string-conversions). Conversions -h5. +ord+ - -Ruby 1.9 defines +ord+ to be the codepoint of the first character of the receiver. Active Support backports +ord+ for single-byte encodings like ASCII or ISO-8859-1 in Ruby 1.8: - -<ruby> -"a".ord # => 97 -"à".ord # => 224, in ISO-8859-1 -</ruby> - -In Ruby 1.8 +ord+ doesn't work in general in UTF8 strings, use the multibyte support in Active Support for that: - -<ruby> -"a".mb_chars.ord # => 97 -"à".mb_chars.ord # => 224, in UTF8 -</ruby> - -Note that the 224 is different in both examples. In ISO-8859-1 "à" is represented as a single byte, 224. Its single-character representation in UTF8 has two bytes, namely 195 and 160, but its Unicode codepoint is 224. If we call +ord+ on the UTF8 string "à" the return value will be 195 in Ruby 1.8. That is not an error, because UTF8 is unsupported, the call itself would be bogus. - -INFO: +ord+ is equivalent to +getbyte(0)+. - -NOTE: Defined in +active_support/core_ext/string/conversions.rb+. - -h5. +getbyte+ - -Active Support backports +getbyte+ from Ruby 1.9: - -<ruby> -"foo".getbyte(0) # => 102, same as "foo".ord -"foo".getbyte(1) # => 111 -"foo".getbyte(9) # => nil -"foo".getbyte(-1) # => 111 -</ruby> - -INFO: +getbyte+ is equivalent to +[]+. - -NOTE: Defined in +active_support/core_ext/string/conversions.rb+. - h5. +to_date+, +to_time+, +to_datetime+ The methods +to_date+, +to_time+, and +to_datetime+ are basically convenience wrappers around +Date._parse+: @@ -1974,38 +1924,12 @@ The method +ordinalize+ returns the ordinal string corresponding to the receiver NOTE: Defined in +active_support/core_ext/integer/inflections.rb+. -h3. Extensions to +Float+ - -h4. +round+ - -The built-in method +Float#round+ rounds a float to the nearest integer. In Ruby 1.9 this method takes an optional argument to let you specify a precision. Active Support adds that functionality to +round+ in previous versions of Ruby: - -<ruby> -Math::E.round(4) # => 2.7183 -</ruby> - -NOTE: Defined in +active_support/core_ext/float/rounding.rb+. - h3. Extensions to +BigDecimal+ ... h3. Extensions to +Enumerable+ -h4. +group_by+ - -Active Support redefines +group_by+ in Ruby 1.8.7 so that it returns an ordered hash as in 1.9: - -<ruby> -entries_by_surname_initial = address_book.group_by do |entry| - entry.surname.at(0).upcase -end -</ruby> - -Distinct block return values are added to the hash as they come, so that's the resulting order. - -NOTE: Defined in +active_support/core_ext/enumerable.rb+. - h4. +sum+ The method +sum+ adds the elements of an enumerable: @@ -2160,20 +2084,6 @@ The methods +second+, +third+, +fourth+, and +fifth+ return the corresponding el NOTE: Defined in +active_support/core_ext/array/access.rb+. -h4. Random Access - -Active Support backports +sample+ from Ruby 1.9: - -<ruby> -shape_type = [Circle, Square, Triangle].sample -# => Square, for example - -shape_types = [Circle, Square, Triangle].sample(2) -# => [Triangle, Circle], for example -</ruby> - -NOTE: Defined in +active_support/core_ext/array/random_access.rb+. - h4. Adding Elements h5. +prepend+ @@ -2926,14 +2836,6 @@ WARNING: The original +Range#include?+ is still the one aliased to +Range#===+. NOTE: Defined in +active_support/core_ext/range/include_range.rb+. -h4. +cover?+ - -Ruby 1.9 provides +cover?+, and Active Support defines it for previous versions as an alias for +include?+. - -The method +include?+ in Ruby 1.9 is different from the one in 1.8 for non-numeric ranges: instead of being based on comparisons between the value and the range's endpoints, it walks the range with +succ+ looking for value. This works better for ranges with holes, but it has different complexity and may not finish in some other cases. - -In Ruby 1.9 the old behavior is still available in the new +cover?+, which Active Support backports for forward compatibility. For example, Rails uses +cover?+ for ranges in +validates_inclusion_of+. - h4. +overlaps?+ The method +Range#overlaps?+ says whether any two given ranges have non-void intersection: diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile index 58855bc80b..fa783edc58 100644 --- a/railties/guides/source/command_line.textile +++ b/railties/guides/source/command_line.textile @@ -381,16 +381,16 @@ h4. +about+ <shell> $ rake about About your application's environment -Ruby version 1.8.7 (x86_64-linux) +Ruby version 1.9.3 (x86_64-linux) RubyGems version 1.3.6 Rack version 1.3 -Rails version 3.2.0.beta +Rails version 4.0.0.beta JavaScript Runtime Node.js (V8) -Active Record version 3.2.0.beta -Action Pack version 3.2.0.beta -Active Resource version 3.2.0.beta -Action Mailer version 3.2.0.beta -Active Support version 3.2.0.beta +Active Record version 4.0.0.beta +Action Pack version 4.0.0.beta +Active Resource version 4.0.0.beta +Action Mailer version 4.0.0.beta +Active Support version 4.0.0.beta Middleware ActionDispatch::Static, Rack::Lock, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::DebugExceptions, ActionDispatch::RemoteIp, ActionDispatch::Reloader, ActionDispatch::Callbacks, ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::QueryCache, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ParamsParser, ActionDispatch::Head, Rack::ConditionalGet, Rack::ETag, ActionDispatch::BestStandardsSupport Application root /home/foobar/commandsapp Environment development diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index b20634c5a9..19e8426e60 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -215,6 +215,11 @@ module Rails config.helpers_paths end + def call(env) + env["ORIGINAL_FULLPATH"] = build_original_fullpath(env) + super(env) + end + protected alias :build_middleware_stack :app @@ -291,5 +296,17 @@ module Rails require "rails/console/app" require "rails/console/helpers" end + + def build_original_fullpath(env) + path_info = env["PATH_INFO"] + query_string = env["QUERY_STRING"] + script_name = env["SCRIPT_NAME"] + + if query_string.present? + "#{script_name}#{path_info}?#{query_string}" + else + "#{script_name}#{path_info}" + end + end end end diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index f38a487a4e..af743a9c51 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -128,13 +128,13 @@ module Rails # # ==== Boolean hooks # - # In some cases, you want to provide a boolean hook. For example, webrat + # In some cases, you may want to provide a boolean hook. For example, webrat # developers might want to have webrat available on controller generator. # This can be achieved as: # # Rails::Generators::ControllerGenerator.hook_for :webrat, :type => :boolean # - # Then, if you want, webrat to be invoked, just supply: + # Then, if you want webrat to be invoked, just supply: # # rails generate controller Account --webrat # @@ -146,7 +146,7 @@ module Rails # # You can also supply a block to hook_for to customize how the hook is # going to be invoked. The block receives two arguments, an instance - # of the current class and the klass to be invoked. + # of the current class and the class to be invoked. # # For example, in the resource generator, the controller should be invoked # with a pluralized class name. But by default it is invoked with the same diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index 60ea394d2f..5e9c385ab8 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -19,7 +19,7 @@ source 'https://rubygems.org' # gem 'unicorn' # Deploy with Capistrano -# gem 'capistrano' +# gem 'capistrano', :group => :development # To use debugger # <%= ruby_debugger_gemfile_entry %> diff --git a/railties/lib/rails/tasks/documentation.rake b/railties/lib/rails/tasks/documentation.rake index 1e7da5ccae..1c28b2c8e6 100644 --- a/railties/lib/rails/tasks/documentation.rake +++ b/railties/lib/rails/tasks/documentation.rake @@ -63,7 +63,7 @@ namespace :doc do rdoc.template = "#{ENV['template']}.rb" if ENV['template'] rdoc.title = "Rails Framework Documentation" rdoc.options << '--line-numbers' - rdoc.rdoc_files.include('README') + rdoc.rdoc_files.include('README.rdoc') gem_path('actionmailer') do |actionmailer| %w(README.rdoc CHANGELOG.md MIT-LICENSE lib/action_mailer/base.rb).each do |file| diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake index 52d92cdd96..62c8de8d22 100644 --- a/railties/lib/rails/test_unit/testing.rake +++ b/railties/lib/rails/test_unit/testing.rake @@ -1,32 +1,40 @@ require 'rbconfig' require 'rake/testtask' -# Monkey-patch to silence the description from Rake::TestTask to cut down on rake -T noise -class TestTaskWithoutDescription < Rake::TestTask - # Create the tasks defined by this task lib. - def define - lib_path = @libs.join(File::PATH_SEPARATOR) - task @name do - run_code = '' - RakeFileUtils.verbose(@verbose) do - run_code = - case @loader - when :direct - "-e 'ARGV.each{|f| load f}'" - when :testrb - "-S testrb #{fix}" - when :rake - rake_loader +module Rails + # Don't abort when tests fail; move on the next test task. + # Silence the default description to cut down on `rake -T` noise. + class SubTestTask < Rake::TestTask + # Create the tasks defined by this task lib. + def define + lib_path = @libs.join(File::PATH_SEPARATOR) + task @name do + run_code = '' + RakeFileUtils.verbose(@verbose) do + run_code = + case @loader + when :direct + "-e 'ARGV.each{|f| load f}'" + when :testrb + "-S testrb #{fix}" + when :rake + rake_loader + end + @ruby_opts.unshift( "-I\"#{lib_path}\"" ) + @ruby_opts.unshift( "-w" ) if @warning + + begin + ruby @ruby_opts.join(" ") + + " \"#{run_code}\" " + + file_list.collect { |fn| "\"#{fn}\"" }.join(' ') + + " #{option_list}" + rescue => error + warn "Error running #{@name}: #{error.inspect}" end - @ruby_opts.unshift( "-I\"#{lib_path}\"" ) - @ruby_opts.unshift( "-w" ) if @warning - ruby @ruby_opts.join(" ") + - " \"#{run_code}\" " + - file_list.collect { |fn| "\"#{fn}\"" }.join(' ') + - " #{option_list}" + end end + self end - self end end @@ -76,20 +84,7 @@ task :default => :test desc 'Runs test:units, test:functionals, test:integration together (also available: test:benchmark, test:profile, test:plugins)' task :test do - tests_to_run = ENV['TEST'] ? ["test:single"] : %w(test:units test:functionals test:integration) - errors = tests_to_run.collect do |task| - begin - Rake::Task[task].invoke - nil - rescue => e - { :task => task, :exception => e } - end - end.compact - - if errors.any? - puts errors.map { |e| "Errors running #{e[:task]}! #{e[:exception].inspect}" }.join("\n") - abort - end + Rake::Task[ENV['TEST'] ? 'test:single' : 'test:run'].invoke end namespace :test do @@ -97,6 +92,8 @@ namespace :test do # Placeholder task for other Railtie and plugins to enhance. See Active Record for an example. end + task :run => %w(test:units test:functionals test:integration) + Rake::TestTask.new(:recent => "test:prepare") do |t| since = TEST_CHANGES_SINCE touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } + @@ -134,33 +131,33 @@ namespace :test do t.libs << "test" end - TestTaskWithoutDescription.new(:units => "test:prepare") do |t| + Rails::SubTestTask.new(:units => "test:prepare") do |t| t.libs << "test" t.pattern = 'test/unit/**/*_test.rb' end - TestTaskWithoutDescription.new(:functionals => "test:prepare") do |t| + Rails::SubTestTask.new(:functionals => "test:prepare") do |t| t.libs << "test" t.pattern = 'test/functional/**/*_test.rb' end - TestTaskWithoutDescription.new(:integration => "test:prepare") do |t| + Rails::SubTestTask.new(:integration => "test:prepare") do |t| t.libs << "test" t.pattern = 'test/integration/**/*_test.rb' end - TestTaskWithoutDescription.new(:benchmark => 'test:prepare') do |t| + Rails::SubTestTask.new(:benchmark => 'test:prepare') do |t| t.libs << 'test' t.pattern = 'test/performance/**/*_test.rb' t.options = '-- --benchmark' end - TestTaskWithoutDescription.new(:profile => 'test:prepare') do |t| + Rails::SubTestTask.new(:profile => 'test:prepare') do |t| t.libs << 'test' t.pattern = 'test/performance/**/*_test.rb' end - TestTaskWithoutDescription.new(:plugins => :environment) do |t| + Rails::SubTestTask.new(:plugins => :environment) do |t| t.libs << "test" if ENV['PLUGIN'] diff --git a/railties/railties.gemspec b/railties/railties.gemspec index a7b9407daf..82655ad394 100644 --- a/railties/railties.gemspec +++ b/railties/railties.gemspec @@ -6,7 +6,7 @@ Gem::Specification.new do |s| s.version = version s.summary = 'Tools for creating, working with, and running Rails applications.' s.description = 'Rails internals: application bootup, plugins, generators, and rake tasks.' - s.required_ruby_version = '>= 1.8.7' + s.required_ruby_version = '>= 1.9.3' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' diff --git a/railties/test/application/build_original_fullpath_test.rb b/railties/test/application/build_original_fullpath_test.rb new file mode 100644 index 0000000000..7a679ea04e --- /dev/null +++ b/railties/test/application/build_original_fullpath_test.rb @@ -0,0 +1,27 @@ +require "abstract_unit" + +module ApplicationTests + class BuildOriginalPathTest < Test::Unit::TestCase + def test_include_original_PATH_info_in_ORIGINAL_FULLPATH + env = { 'PATH_INFO' => '/foo/' } + assert_equal "/foo/", Rails.application.send(:build_original_fullpath, env) + end + + def test_include_SCRIPT_NAME + env = { + 'SCRIPT_NAME' => '/foo', + 'PATH_INFO' => '/bar' + } + + assert_equal "/foo/bar", Rails.application.send(:build_original_fullpath, env) + end + + def test_include_QUERY_STRING + env = { + 'PATH_INFO' => '/foo', + 'QUERY_STRING' => 'bar', + } + assert_equal "/foo?bar", Rails.application.send(:build_original_fullpath, env) + end + end +end diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 578370cfca..9e02ef9c66 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -1,5 +1,6 @@ require 'isolation/abstract_unit' require 'stringio' +require 'rack/test' module ApplicationTests class MiddlewareTest < Test::Unit::TestCase @@ -75,7 +76,7 @@ module ApplicationTests add_to_config "config.force_ssl = true" add_to_config "config.ssl_options = { :host => 'example.com' }" boot! - + assert_equal AppTemplate::Application.middleware.first.args, [{:host => 'example.com'}] end @@ -193,6 +194,14 @@ module ApplicationTests assert_equal nil, last_response.headers["Etag"] end + test "ORIGINAL_FULLPATH is passed to env" do + boot! + env = ::Rack::MockRequest.env_for("/foo/?something") + Rails.application.call(env) + + assert_equal "/foo/?something", env["ORIGINAL_FULLPATH"] + end + private def boot! |