aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG15
-rw-r--r--actionpack/lib/action_controller/metal/cookies.rb5
-rw-r--r--actionpack/lib/action_controller/metal/responder.rb2
-rw-r--r--actionpack/lib/action_controller/metal/verification.rb2
-rwxr-xr-xactionpack/lib/action_dispatch/http/request.rb60
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb42
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb19
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb10
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb3
-rw-r--r--actionpack/lib/action_view/helpers/url_helper.rb7
-rw-r--r--actionpack/lib/action_view/template.rb6
-rw-r--r--actionpack/test/controller/integration_test.rb2
-rw-r--r--actionpack/test/controller/verification_test.rb2
-rw-r--r--actionpack/test/dispatch/rack_test.rb2
-rw-r--r--actionpack/test/dispatch/request_test.rb20
-rw-r--r--actionpack/test/dispatch/routing_test.rb68
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb18
-rw-r--r--activesupport/lib/active_support/inflector/transliterate.rb5
-rw-r--r--activesupport/test/inflector_test_cases.rb12
-rwxr-xr-xtools/profile10
20 files changed, 231 insertions, 79 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 7c2cebcff1..c4ebedf1b0 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,3 +1,18 @@
+*Rails 3.0.0 [Edge] (pending)*
+
+* Changed the object used in routing constraints to be an instance of
+ ActionDispatch::Request rather than Rack::Request
+
+* Changed ActionDispatch::Request#method to return a String, to be compatible
+ with Rack::Request. Added ActionDispatch::Request#method_symbol to
+ return a symbol form of the request method.
+
+* Changed ActionDispatch::Request#method to return the original
+ method and #request_method to return the overridden method in the
+ case of methodoverride being used (this means that #method returns
+ "HEAD" and #request_method returns "GET" in HEAD requests). This
+ is for compatibility with Rack::Request
+
*Rails 3.0.0 [beta 2] (April 1st, 2010)*
* #concat is now deprecated in favor of using <%= %> helpers [YK]
diff --git a/actionpack/lib/action_controller/metal/cookies.rb b/actionpack/lib/action_controller/metal/cookies.rb
index 75e5d40a63..4aaa705203 100644
--- a/actionpack/lib/action_controller/metal/cookies.rb
+++ b/actionpack/lib/action_controller/metal/cookies.rb
@@ -7,10 +7,11 @@ module ActionController #:nodoc:
included do
helper_method :cookies
end
-
+
private
def cookies
- request.cookie_jar
+ raise "You must set config.cookie_secret in your app's config" if config.secret.blank?
+ request.cookie_jar(:signing_secret => config.secret)
end
end
end
diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb
index 0b2cee6868..d97c10a293 100644
--- a/actionpack/lib/action_controller/metal/responder.rb
+++ b/actionpack/lib/action_controller/metal/responder.rb
@@ -216,7 +216,7 @@ module ActionController #:nodoc:
# the verb is POST.
#
def default_action
- @action ||= ACTIONS_FOR_VERBS[request.method]
+ @action ||= ACTIONS_FOR_VERBS[request.method_symbol]
end
end
end
diff --git a/actionpack/lib/action_controller/metal/verification.rb b/actionpack/lib/action_controller/metal/verification.rb
index bce942b588..b7fc2b7421 100644
--- a/actionpack/lib/action_controller/metal/verification.rb
+++ b/actionpack/lib/action_controller/metal/verification.rb
@@ -108,7 +108,7 @@ module ActionController #:nodoc:
end
def verify_method(options) # :nodoc:
- [*options[:method]].all? { |v| request.method != v.to_sym } if options[:method]
+ [*options[:method]].all? { |v| request.method_symbol != v.to_sym } if options[:method]
end
def verify_request_xhr_status(options) # :nodoc:
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 8b8426b5aa..8560a6fc9c 100755
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -45,47 +45,65 @@ module ActionDispatch
HTTP_METHODS = %w(get head put post delete options)
HTTP_METHOD_LOOKUP = HTTP_METHODS.inject({}) { |h, m| h[m] = h[m.upcase] = m.to_sym; h }
- # Returns the true HTTP request \method as a lowercase symbol, such as
- # <tt>:get</tt>. If the request \method is not listed in the HTTP_METHODS
- # constant above, an UnknownHttpMethod exception is raised.
+ # Returns the HTTP \method that the application should see.
+ # In the case where the \method was overridden by a middleware
+ # (for instance, if a HEAD request was converted to a GET,
+ # or if a _method parameter was used to determine the \method
+ # the application should use), this \method returns the overridden
+ # value, not the original.
def request_method
- method = env["rack.methodoverride.original_method"] || env["REQUEST_METHOD"]
+ method = env["REQUEST_METHOD"]
HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
+ method
+ end
+
+ # Returns a symbol form of the #request_method
+ def request_method_symbol
+ HTTP_METHOD_LOOKUP[request_method]
end
- # Returns the HTTP request \method used for action processing as a
- # lowercase symbol, such as <tt>:post</tt>. (Unlike #request_method, this
- # method returns <tt>:get</tt> for a HEAD request because the two are
- # functionally equivalent from the application's perspective.)
+ # Returns the original value of the environment's REQUEST_METHOD,
+ # even if it was overridden by middleware. See #request_method for
+ # more information.
def method
- method = env["REQUEST_METHOD"]
+ method = env["rack.methodoverride.original_method"] || env['REQUEST_METHOD']
HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
+ method
+ end
+
+ # Returns a symbol form of the #method
+ def method_symbol
+ HTTP_METHOD_LOOKUP[method]
end
- # Is this a GET (or HEAD) request? Equivalent to <tt>request.method == :get</tt>.
+ # Is this a GET (or HEAD) request?
+ # Equivalent to <tt>request.request_method == :get</tt>.
def get?
- method == :get
+ HTTP_METHOD_LOOKUP[request_method] == :get
end
- # Is this a POST request? Equivalent to <tt>request.method == :post</tt>.
+ # Is this a POST request?
+ # Equivalent to <tt>request.request_method == :post</tt>.
def post?
- method == :post
+ HTTP_METHOD_LOOKUP[request_method] == :post
end
- # Is this a PUT request? Equivalent to <tt>request.method == :put</tt>.
+ # Is this a PUT request?
+ # Equivalent to <tt>request.request_method == :put</tt>.
def put?
- method == :put
+ HTTP_METHOD_LOOKUP[request_method] == :put
end
- # Is this a DELETE request? Equivalent to <tt>request.method == :delete</tt>.
+ # Is this a DELETE request?
+ # Equivalent to <tt>request.request_method == :delete</tt>.
def delete?
- method == :delete
+ HTTP_METHOD_LOOKUP[request_method] == :delete
end
- # Is this a HEAD request? Since <tt>request.method</tt> sees HEAD as <tt>:get</tt>,
- # this \method checks the actual HTTP \method directly.
+ # Is this a HEAD request?
+ # Equivalent to <tt>request.method == :head</tt>.
def head?
- request_method == :head
+ HTTP_METHOD_LOOKUP[method] == :head
end
# Provides access to the request's HTTP headers, for example:
@@ -96,7 +114,7 @@ module ActionDispatch
end
def forgery_whitelisted?
- method == :get || xhr? || content_mime_type.nil? || !content_mime_type.verify_request?
+ get? || xhr? || content_mime_type.nil? || !content_mime_type.verify_request?
end
def media_type
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index cb0d12cab1..71dcac9e94 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -1,7 +1,7 @@
module ActionDispatch
class Request
- def cookie_jar
- env['action_dispatch.cookies'] ||= Cookies::CookieJar.build(self)
+ def cookie_jar(config = {})
+ env['action_dispatch.cookies'] ||= Cookies::CookieJar.build(self, config)
end
end
@@ -51,17 +51,18 @@ module ActionDispatch
# only HTTP. Defaults to +false+.
class Cookies
class CookieJar < Hash #:nodoc:
- def self.build(request)
- new.tap do |hash|
+ def self.build(request, config = {})
+ new(config).tap do |hash|
hash.update(request.cookies)
end
end
- def initialize
+ def initialize(config = {})
+ @config = config
@set_cookies = {}
@delete_cookies = {}
- super
+ super()
end
# Returns the value of the cookie by +name+, or +nil+ if no such cookie exists.
@@ -111,7 +112,7 @@ module ActionDispatch
# cookies.permanent.signed[:remember_me] = current_user.id
# # => Set-Cookie: discount=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT
def permanent
- @permanent ||= PermanentCookieJar.new(self)
+ @permanent ||= PermanentCookieJar.new(self, @config)
end
# Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from
@@ -119,7 +120,7 @@ module ActionDispatch
# cookie was tampered with by the user (or a 3rd party), an ActiveSupport::MessageVerifier::InvalidSignature exception will
# be raised.
#
- # This jar requires that you set a suitable secret for the verification on ActionController::Base.cookie_verifier_secret.
+ # This jar requires that you set a suitable secret for the verification on your app's config.cookie_secret.
#
# Example:
#
@@ -128,7 +129,7 @@ module ActionDispatch
#
# cookies.signed[:discount] # => 45
def signed
- @signed ||= SignedCookieJar.new(self)
+ @signed ||= SignedCookieJar.new(self, @config)
end
def write(response)
@@ -138,8 +139,9 @@ module ActionDispatch
end
class PermanentCookieJar < CookieJar #:nodoc:
- def initialize(parent_jar)
+ def initialize(parent_jar, config = {})
@parent_jar = parent_jar
+ @config = config
end
def []=(key, options)
@@ -154,11 +156,7 @@ module ActionDispatch
end
def signed
- @signed ||= SignedCookieJar.new(self)
- end
-
- def controller
- @parent_jar.controller
+ @signed ||= SignedCookieJar.new(self, @config)
end
def method_missing(method, *arguments, &block)
@@ -167,18 +165,16 @@ module ActionDispatch
end
class SignedCookieJar < CookieJar #:nodoc:
- def initialize(parent_jar)
- unless ActionController::Base.config.secret
- raise "You must set ActionController::Base.config.secret"
- end
-
+ def initialize(parent_jar, config = {})
+ raise 'Missing cookie signing secret' if config[:signing_secret].blank?
@parent_jar = parent_jar
- @verifier = ActiveSupport::MessageVerifier.new(ActionController::Base.config.secret)
+ @config = config
+ @verifier = ActiveSupport::MessageVerifier.new(config[:signing_secret])
end
def [](name)
- if value = @parent_jar[name]
- @verifier.verify(value)
+ if signed_message = @parent_jar[name]
+ @verifier.verify(signed_message)
end
end
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 2c7ee7dad0..925e91f081 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -5,20 +5,20 @@ module ActionDispatch
module Routing
class Mapper
class Constraints #:nodoc:
- def self.new(app, constraints = [])
+ def self.new(app, constraints, request = Rack::Request)
if constraints.any?
- super(app, constraints)
+ super(app, constraints, request)
else
app
end
end
- def initialize(app, constraints = [])
- @app, @constraints = app, constraints
+ def initialize(app, constraints, request)
+ @app, @constraints, @request = app, constraints, request
end
def call(env)
- req = Rack::Request.new(env)
+ req = @request.new(env)
@constraints.each { |constraint|
if constraint.respond_to?(:matches?) && !constraint.matches?(req)
@@ -83,7 +83,8 @@ module ActionDispatch
def app
Constraints.new(
to.respond_to?(:call) ? to : Routing::RouteSet::Dispatcher.new(:defaults => defaults),
- blocks
+ blocks,
+ @set.request_class
)
end
@@ -242,7 +243,11 @@ module ActionDispatch
lambda do |env|
req = Request.new(env)
- uri = URI.parse(path_proc.call(req.symbolized_path_parameters))
+
+ params = [req.symbolized_path_parameters]
+ params << req if path_proc.arity > 1
+
+ uri = URI.parse(path_proc.call(*params))
uri.scheme ||= req.scheme
uri.host ||= req.host
uri.port ||= req.port unless req.port == 80
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index c8e4371bb7..f1965f38b9 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -187,18 +187,19 @@ module ActionDispatch
attr_accessor :routes, :named_routes
attr_accessor :disable_clear_and_finalize, :resources_path_names
- attr_accessor :default_url_options
+ attr_accessor :default_url_options, :request_class
def self.default_resources_path_names
{ :new => 'new', :edit => 'edit' }
end
- def initialize
+ def initialize(request_class = ActionDispatch::Request)
self.routes = []
self.named_routes = NamedRouteCollection.new
self.resources_path_names = self.class.default_resources_path_names.dup
self.controller_namespaces = Set.new
self.default_url_options = {}
+ self.request_class = request_class
@disable_clear_and_finalize = false
clear!
@@ -232,7 +233,10 @@ module ActionDispatch
@finalized = false
routes.clear
named_routes.clear
- @set = ::Rack::Mount::RouteSet.new(:parameters_key => PARAMETERS_KEY)
+ @set = ::Rack::Mount::RouteSet.new(
+ :parameters_key => PARAMETERS_KEY,
+ :request_class => request_class
+ )
end
def install_helpers(destinations = [ActionController::Base, ActionView::Base], regenerate_code = false)
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 031fa1dfb4..8d107d9aa5 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -266,11 +266,12 @@ module ActionDispatch
"HTTP_ACCEPT" => accept
}
+ session = Rack::Test::Session.new(@mock_session)
+
(rack_environment || {}).each do |key, value|
env[key] = value
end
- session = Rack::Test::Session.new(@mock_session)
session.request(path, env)
@request_count += 1
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index 1415966869..5925faf810 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -10,6 +10,12 @@ module ActionView
# This allows you to use the same format for links in views
# and controllers.
module UrlHelper
+ # This helper may be included in any class that includes the
+ # URL helpers of a router (router.url_helpers). Some methods
+ # provided here will only work in the context of a request
+ # (link_to_unless_current, for instance), which must be provided
+ # as a method called #request on the context.
+
extend ActiveSupport::Concern
include ActionDispatch::Routing::UrlFor
@@ -307,7 +313,6 @@ module ActionView
# # </div>
# # </form>"
# #
-
def button_to(name, options = {}, html_options = {})
html_options = html_options.stringify_keys
convert_boolean_attributes!(html_options, %w( disabled ))
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 3df2bd8eed..3c0cd35359 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -18,7 +18,7 @@ module ActionView
attr_reader :source, :identifier, :handler, :virtual_path, :formats
- def self.finalizer_for(method_name)
+ Finalizer = proc do |method_name|
proc do
ActionView::CompiledTemplates.module_eval do
remove_possible_method method_name
@@ -77,7 +77,6 @@ module ActionView
private
def compile(locals, view)
method_name = build_method_name(locals)
-
return method_name if view.respond_to?(method_name)
locals_code = locals.keys.map! { |key| "#{key} = local_assigns[:#{key}];" }.join
@@ -106,7 +105,8 @@ module ActionView
begin
ActionView::CompiledTemplates.module_eval(source, identifier, line)
- ObjectSpace.define_finalizer(self, self.class.finalizer_for(method_name))
+ ObjectSpace.define_finalizer(self, Finalizer[method_name])
+
method_name
rescue Exception => e # errors from template code
if logger = (view && view.logger)
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index 1e2ee06adc..14c0c3708b 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -236,7 +236,7 @@ class IntegrationProcessTest < ActionController::IntegrationTest
end
def method
- render :text => "method: #{request.method}"
+ render :text => "method: #{request.method.downcase}"
end
def cookie_monster
diff --git a/actionpack/test/controller/verification_test.rb b/actionpack/test/controller/verification_test.rb
index 11d0d10897..0600ec2ec1 100644
--- a/actionpack/test/controller/verification_test.rb
+++ b/actionpack/test/controller/verification_test.rb
@@ -71,7 +71,7 @@ class VerificationTest < ActionController::TestCase
end
def guarded_by_method
- render :text => "#{request.method}"
+ render :text => "#{request.method.downcase}"
end
def guarded_by_xhr
diff --git a/actionpack/test/dispatch/rack_test.rb b/actionpack/test/dispatch/rack_test.rb
index 504bebbb86..698f980296 100644
--- a/actionpack/test/dispatch/rack_test.rb
+++ b/actionpack/test/dispatch/rack_test.rb
@@ -142,7 +142,7 @@ class RackRequestTest < BaseRackTest
assert_equal "google.com", @request.remote_host
assert_equal "kevin", @request.remote_ident
assert_equal "kevin", @request.remote_user
- assert_equal :get, @request.request_method
+ assert_equal "GET", @request.request_method
assert_equal "/dispatch.fcgi", @request.script_name
assert_equal "glu.ttono.us", @request.server_name
assert_equal 8007, @request.server_port
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index 9093e1ed65..e5ee412021 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -223,10 +223,17 @@ class RequestTest < ActiveSupport::TestCase
assert request.ssl?
end
- test "symbolized request methods" do
+ test "String request methods" do
[:get, :post, :put, :delete].each do |method|
request = stub_request 'REQUEST_METHOD' => method.to_s.upcase
- assert_equal method, request.method
+ assert_equal method.to_s.upcase, request.method
+ end
+ end
+
+ test "Symbol forms of request methods via method_symbol" do
+ [:get, :post, :put, :delete].each do |method|
+ request = stub_request 'REQUEST_METHOD' => method.to_s.upcase
+ assert_equal method, request.method_symbol
end
end
@@ -238,9 +245,9 @@ class RequestTest < ActiveSupport::TestCase
end
test "allow method hacking on post" do
- [:get, :options, :put, :post, :delete].each do |method|
+ %w(GET OPTIONS PUT POST DELETE).each do |method|
request = stub_request "REQUEST_METHOD" => method.to_s.upcase
- assert_equal(method == :head ? :get : method, request.method)
+ assert_equal(method == "HEAD" ? "GET" : method, request.method)
end
end
@@ -255,13 +262,14 @@ class RequestTest < ActiveSupport::TestCase
[:get, :put, :delete].each do |method|
request = stub_request 'REQUEST_METHOD' => method.to_s.upcase,
'action_dispatch.request.request_parameters' => { :_method => 'put' }
- assert_equal method, request.method
+ assert_equal method.to_s.upcase, request.method
end
end
test "head masquerading as get" do
request = stub_request 'REQUEST_METHOD' => 'GET', "rack.methodoverride.original_method" => "HEAD"
- assert_equal :get, request.method
+ assert_equal "HEAD", request.method
+ assert_equal "GET", request.request_method
assert request.get?
assert request.head?
end
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 19538cb88b..6ff478aec1 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -39,6 +39,8 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
match 'account/modulo/:name', :to => redirect("/%{name}s")
match 'account/proc/:name', :to => redirect {|params| "/#{params[:name].pluralize}" }
+ match 'account/proc_req' => redirect {|params, req| "/#{req.method}" }
+
match 'account/google' => redirect('http://www.google.com/')
match 'openid/login', :via => [:get, :post], :to => "openid#login"
@@ -187,6 +189,63 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
+ class TestAltApp < ActionController::IntegrationTest
+ class AltRequest
+ def initialize(env)
+ @env = env
+ end
+
+ def path_info
+ "/"
+ end
+
+ def request_method
+ "GET"
+ end
+
+ def x_header
+ @env["HTTP_X_HEADER"] || ""
+ end
+ end
+
+ class XHeader
+ def call(env)
+ [200, {"Content-Type" => "text/html"}, ["XHeader"]]
+ end
+ end
+
+ class AltApp
+ def call(env)
+ [200, {"Content-Type" => "text/html"}, ["Alternative App"]]
+ end
+ end
+
+ AltRoutes = ActionDispatch::Routing::RouteSet.new(AltRequest)
+ AltRoutes.draw do
+ get "/" => XHeader.new, :constraints => {:x_header => /HEADER/}
+ get "/" => AltApp.new
+ end
+
+ def app
+ AltRoutes
+ end
+
+ def test_alt_request_without_header
+ get "/"
+ assert_equal "Alternative App", @response.body
+ end
+
+ def test_alt_request_with_matched_header
+ get "/", {}, "HTTP_X_HEADER" => "HEADER"
+ assert_equal "XHeader", @response.body
+ end
+
+ def test_alt_request_with_unmatched_header
+ get "/", {}, "HTTP_X_HEADER" => "NON_MATCH"
+ assert_equal "Alternative App", @response.body
+ end
+ end
+
def app
Routes
end
@@ -294,6 +353,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
+ def test_redirect_proc_with_request
+ with_test_routes do
+ get '/account/proc_req'
+ assert_equal 301, @response.status
+ assert_equal 'http://www.example.com/GET', @response.headers['Location']
+ assert_equal 'Moved Permanently', @response.body
+ end
+ end
+
def test_openid
with_test_routes do
get '/openid/login'
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index c1e539d573..b55b08bf9d 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1168,4 +1168,22 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
client = firm.clients_using_primary_key.create!(:name => 'test')
assert_equal firm.name, client.firm_name
end
+
+ def test_defining_has_many_association_with_delete_all_dependency_lazily_evaluates_target_class
+ ActiveRecord::Reflection::AssociationReflection.any_instance.expects(:class_name).never
+ class_eval <<-EOF
+ class DeleteAllModel < ActiveRecord::Base
+ has_many :nonentities, :dependent => :delete_all
+ end
+ EOF
+ end
+
+ def test_defining_has_many_association_with_nullify_dependency_lazily_evaluates_target_class
+ ActiveRecord::Reflection::AssociationReflection.any_instance.expects(:class_name).never
+ class_eval <<-EOF
+ class NullifyModel < ActiveRecord::Base
+ has_many :nonentities, :dependent => :nullify
+ end
+ EOF
+ end
end
diff --git a/activesupport/lib/active_support/inflector/transliterate.rb b/activesupport/lib/active_support/inflector/transliterate.rb
index 2ce27cf406..ca591abc7d 100644
--- a/activesupport/lib/active_support/inflector/transliterate.rb
+++ b/activesupport/lib/active_support/inflector/transliterate.rb
@@ -1,5 +1,6 @@
# encoding: utf-8
require 'iconv'
+require 'kconv'
require 'active_support/core_ext/string/multibyte'
module ActiveSupport
@@ -44,6 +45,8 @@ module ActiveSupport
# <%= link_to(@person.name, person_path(@person)) %>
# # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
def parameterize(string, sep = '-')
+ # remove malformed utf8 characters
+ string = string.toutf8 unless string.is_utf8?
# replace accented chars with their ascii equivalents
parameterized_string = transliterate(string)
# Turn unwanted chars into the separator
@@ -58,4 +61,4 @@ module ActiveSupport
parameterized_string.downcase
end
end
-end \ No newline at end of file
+end
diff --git a/activesupport/test/inflector_test_cases.rb b/activesupport/test/inflector_test_cases.rb
index 56372903f3..8dad9d8155 100644
--- a/activesupport/test/inflector_test_cases.rb
+++ b/activesupport/test/inflector_test_cases.rb
@@ -159,7 +159,8 @@ module InflectorTestCases
"Trailing bad characters!@#" => "trailing-bad-characters",
"!@#Leading bad characters" => "leading-bad-characters",
"Squeeze separators" => "squeeze-separators",
- "Test with + sign" => "test-with-sign"
+ "Test with + sign" => "test-with-sign",
+ "Test with malformed utf8 \251" => "test-with-malformed-utf8"
}
StringToParameterizeWithNoSeparator = {
@@ -168,7 +169,8 @@ module InflectorTestCases
"Trailing bad characters!@#" => "trailingbadcharacters",
"!@#Leading bad characters" => "leadingbadcharacters",
"Squeeze separators" => "squeezeseparators",
- "Test with + sign" => "testwithsign"
+ "Test with + sign" => "testwithsign",
+ "Test with malformed utf8 \251" => "testwithmalformedutf8"
}
StringToParameterizeWithUnderscore = {
@@ -177,12 +179,14 @@ module InflectorTestCases
"Trailing bad characters!@#" => "trailing_bad_characters",
"!@#Leading bad characters" => "leading_bad_characters",
"Squeeze separators" => "squeeze_separators",
- "Test with + sign" => "test_with_sign"
+ "Test with + sign" => "test_with_sign",
+ "Test with malformed utf8 \251" => "test_with_malformed_utf8"
}
StringToParameterizedAndNormalized = {
"Malmö" => "malmo",
- "Garçons" => "garcons"
+ "Garçons" => "garcons",
+ "Ops\331" => "ops"
}
UnderscoreToHuman = {
diff --git a/tools/profile b/tools/profile
index 927467bc4e..0ccef6c26c 100755
--- a/tools/profile
+++ b/tools/profile
@@ -60,8 +60,14 @@ after = GC.allocated_size
usage = (after - before) / 1024.0
if mode
- File.open("#{File.basename(path, '.rb')}.#{mode}.callgrind", 'w') do |out|
- RubyProf::CallTreePrinter.new(results).print(out)
+ if RubyProf.const_defined?(:CallStackPrinter)
+ File.open("#{File.basename(path, '.rb')}.#{mode}.html", 'w') do |out|
+ RubyProf::CallStackPrinter.new(results).print(out)
+ end
+ else
+ File.open("#{File.basename(path, '.rb')}.#{mode}.callgrind", 'w') do |out|
+ RubyProf::CallTreePrinter.new(results).print(out)
+ end
end
end