aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@gmail.com>2010-09-27 20:10:04 +0200
committerJosé Valim <jose.valim@gmail.com>2010-09-27 20:10:04 +0200
commit756b32ef3986992d6e49ed0862ed0f2e314aec6f (patch)
treed6ae3e85c63ca7b40f9454c975b9e91373f94c95
parentfbd1d306b95cc2efb6422e12d26d5818a3a42343 (diff)
parent9c57bd8578e5ed47f143a2755b03ffd2ef85c65d (diff)
downloadrails-756b32ef3986992d6e49ed0862ed0f2e314aec6f.tar.gz
rails-756b32ef3986992d6e49ed0862ed0f2e314aec6f.tar.bz2
rails-756b32ef3986992d6e49ed0862ed0f2e314aec6f.zip
Merge remote branch 'thedarkone/performance'
-rw-r--r--actionpack/lib/action_controller/metal/url_for.rb20
-rw-r--r--actionpack/lib/action_controller/railtie.rb10
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/polymorphic_routes.rb10
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb31
-rw-r--r--actionpack/lib/action_view/base.rb3
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb30
-rw-r--r--actionpack/lib/action_view/helpers/url_helper.rb28
-rw-r--r--activemodel/lib/active_model/naming.rb6
-rw-r--r--activesupport/lib/active_support/configurable.rb24
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb22
-rw-r--r--activesupport/lib/active_support/core_ext/hash/keys.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/module/attr_internal.rb19
-rw-r--r--activesupport/lib/active_support/ordered_options.rb18
-rw-r--r--activesupport/test/configurable_test.rb18
-rw-r--r--activesupport/test/core_ext/hash_ext_test.rb2
16 files changed, 179 insertions, 76 deletions
diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb
index 85c6b0a9b5..ef1071bb3d 100644
--- a/actionpack/lib/action_controller/metal/url_for.rb
+++ b/actionpack/lib/action_controller/metal/url_for.rb
@@ -5,16 +5,18 @@ module ActionController
include AbstractController::UrlFor
def url_options
- options = {}
- if _routes.equal?(env["action_dispatch.routes"])
- options[:script_name] = request.script_name.dup
- end
+ @_url_options ||= begin
+ options = {}
+ if _routes.equal?(env["action_dispatch.routes"])
+ options[:script_name] = request.script_name.dup
+ end
- super.merge(options).reverse_merge(
- :host => request.host_with_port,
- :protocol => request.protocol,
- :_path_segments => request.symbolized_path_parameters
- )
+ super.merge(options).reverse_merge(
+ :host => request.host_with_port,
+ :protocol => request.protocol,
+ :_path_segments => request.symbolized_path_parameters
+ ).freeze
+ end
end
end
end
diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb
index aea28d9265..4c57d82f1c 100644
--- a/actionpack/lib/action_controller/railtie.rb
+++ b/actionpack/lib/action_controller/railtie.rb
@@ -26,6 +26,10 @@ module ActionController
options.stylesheets_dir ||= paths.public.stylesheets.to_a.first
options.page_cache_directory ||= paths.public.to_a.first
+ # make sure readers methods get compiled
+ options.asset_path ||= nil
+ options.asset_host ||= nil
+
ActiveSupport.on_load(:action_controller) do
include app.routes.mounted_helpers
extend ::AbstractController::Railties::RoutesHelpers.with(app.routes)
@@ -33,5 +37,11 @@ module ActionController
options.each { |k,v| send("#{k}=", v) }
end
end
+
+ config.after_initialize do
+ ActiveSupport.on_load(:action_controller) do
+ config.crystalize! if config.respond_to?(:crystalize!)
+ end
+ end
end
end
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 2e39d0dbc2..3e5cd6a2f9 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -15,12 +15,12 @@ module ActionDispatch
# Returns 'https://' if this is an SSL request and 'http://' otherwise.
def protocol
- ssl? ? 'https://' : 'http://'
+ @protocol ||= ssl? ? 'https://' : 'http://'
end
# Is this an SSL request?
def ssl?
- @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https'
+ @ssl ||= @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https'
end
# Returns the \host for this request, such as "example.com".
diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
index 02ba5236ee..49e237f8db 100644
--- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
+++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
@@ -105,7 +105,7 @@ module ActionDispatch
else [ record_or_hash_or_array ]
end
- inflection = if options[:action].to_s == "new"
+ inflection = if options[:action] && options[:action].to_s == "new"
args.pop
:singular
elsif (record.respond_to?(:persisted?) && !record.persisted?)
@@ -168,10 +168,7 @@ module ActionDispatch
end
def build_named_route_call(records, inflection, options = {})
- unless records.is_a?(Array)
- record = extract_record(records)
- route = []
- else
+ if records.is_a?(Array)
record = records.pop
route = records.map do |parent|
if parent.is_a?(Symbol) || parent.is_a?(String)
@@ -180,6 +177,9 @@ module ActionDispatch
ActiveModel::Naming.route_key(parent).singularize
end
end
+ else
+ record = extract_record(records)
+ route = []
end
if record.is_a?(Symbol) || record.is_a?(String)
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 1a5f21bd09..eeec10a403 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -334,6 +334,19 @@ module ActionDispatch
end
class Generator #:nodoc:
+ PARAMETERIZE = {
+ :parameterize => lambda do |name, value|
+ if name == :controller
+ value
+ elsif value.is_a?(Array)
+ value.map { |v| Rack::Mount::Utils.escape_uri(v.to_param) }.join('/')
+ else
+ return nil unless param = value.to_param
+ param.split('/').map { |v| Rack::Mount::Utils.escape_uri(v) }.join("/")
+ end
+ end
+ }
+
attr_reader :options, :recall, :set, :named_route
def initialize(options, recall, set, extras = false)
@@ -422,7 +435,7 @@ module ActionDispatch
end
def generate
- path, params = @set.set.generate(:path_info, named_route, options, recall, opts)
+ path, params = @set.set.generate(:path_info, named_route, options, recall, PARAMETERIZE)
raise_routing_error unless path
@@ -430,26 +443,12 @@ module ActionDispatch
return [path, params.keys] if @extras
- path << "?#{params.to_query}" if params.any?
+ path << "?#{params.to_query}" unless params.empty?
path
rescue Rack::Mount::RoutingError
raise_routing_error
end
- def opts
- parameterize = lambda do |name, value|
- if name == :controller
- value
- elsif value.is_a?(Array)
- value.map { |v| Rack::Mount::Utils.escape_uri(v.to_param) }.join('/')
- else
- return nil unless param = value.to_param
- param.split('/').map { |v| Rack::Mount::Utils.escape_uri(v) }.join("/")
- end
- end
- {:parameterize => parameterize}
- end
-
def raise_routing_error
raise ActionController::RoutingError.new("No route matches #{options.inspect}")
end
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 3fa46d0f43..0bef3e3a08 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -209,8 +209,7 @@ module ActionView #:nodoc:
@_request = controller.request if controller.respond_to?(:request)
end
- config = controller && controller.respond_to?(:config) ? controller.config : {}
- @_config = ActiveSupport::InheritableOptions.new(config)
+ @_config = controller && controller.respond_to?(:config) ? controller.config.inheritable_copy : {}
@_content_for = Hash.new { |h,k| h[k] = ActiveSupport::SafeBuffer.new }
@_virtual_path = nil
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 687cb83d75..c1dfbe5dc3 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -705,19 +705,29 @@ module ActionView
private
- def rewrite_extension?(source, dir, ext)
- source_ext = File.extname(source)[1..-1]
- ext && (source_ext.blank? || (ext != source_ext && File.exist?(File.join(config.assets_dir, dir, "#{source}.#{ext}"))))
+ def rewrite_extension(source, dir, ext)
+ source_ext = File.extname(source)
+
+ if source_ext.empty?
+ "#{source}.#{ext}"
+ elsif ext != source_ext[1..-1]
+ with_ext = "#{source}.#{ext}"
+ with_ext if File.exist?(File.join(config.assets_dir, dir, with_ext))
+ end || source
end
def rewrite_host_and_protocol(source, has_request)
host = compute_asset_host(source)
- if has_request && host.present? && !is_uri?(host)
+ if has_request && host && !is_uri?(host)
host = "#{controller.request.protocol}#{host}"
end
"#{host}#{source}"
end
+ def rewrite_relative_url_root(source, relative_url_root)
+ relative_url_root && !source.starts_with?("#{relative_url_root}/") ? "#{relative_url_root}#{source}" : source
+ end
+
# Add the the extension +ext+ if not present. Return full URLs otherwise untouched.
# Prefix with <tt>/dir/</tt> if lacking a leading +/+. Account for relative URL
# roots. Rewrite the asset path for cache-busting asset ids. Include
@@ -725,17 +735,15 @@ module ActionView
def compute_public_path(source, dir, ext = nil, include_host = true)
return source if is_uri?(source)
- source += ".#{ext}" if rewrite_extension?(source, dir, ext)
- source = "/#{dir}/#{source}" unless source[0] == ?/
+ source = rewrite_extension(source, dir, ext) if ext
+ source = "/#{dir}/#{source}" unless source[0] == ?/
if controller.respond_to?(:env) && controller.env["action_dispatch.asset_path"]
source = rewrite_asset_path(source, controller.env["action_dispatch.asset_path"])
end
source = rewrite_asset_path(source, config.asset_path)
has_request = controller.respond_to?(:request)
- if has_request && include_host && source !~ %r{^#{controller.config.relative_url_root}/}
- source = "#{controller.config.relative_url_root}#{source}"
- end
+ source = rewrite_relative_url_root(source, controller.config.relative_url_root) if has_request && include_host
source = rewrite_host_and_protocol(source, has_request) if include_host
source
@@ -802,10 +810,10 @@ module ActionView
end
asset_id = rails_asset_id(source)
- if asset_id.blank?
+ if asset_id.empty?
source
else
- source + "?#{asset_id}"
+ "#{source}?#{asset_id}"
end
end
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index f8147840ed..1c3ca78d28 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -95,7 +95,7 @@ module ActionView
# # => javascript:history.back()
def url_for(options = {})
options ||= {}
- url = case options
+ case options
when String
options
when Hash
@@ -106,8 +106,6 @@ module ActionView
else
polymorphic_path(options)
end
-
- url
end
# Creates a link tag of the given +name+ using a URL created by the set
@@ -586,20 +584,24 @@ module ActionView
private
def convert_options_to_data_attributes(options, html_options)
- html_options = {} if html_options.nil?
- html_options = html_options.stringify_keys
+ if html_options.nil?
+ link_to_remote_options?(options) ? {'data-remote' => 'true'} : {}
+ else
+ html_options = html_options.stringify_keys
+ html_options['data-remote'] = 'true' if link_to_remote_options?(options) || link_to_remote_options?(html_options)
- if (options.is_a?(Hash) && options.key?('remote') && options.delete('remote')) || (html_options.is_a?(Hash) && html_options.key?('remote') && html_options.delete('remote'))
- html_options['data-remote'] = 'true'
- end
+ confirm = html_options.delete('confirm')
+ method = html_options.delete('method')
- confirm = html_options.delete("confirm")
- method, href = html_options.delete("method"), html_options['href']
+ add_confirm_to_attributes!(html_options, confirm) if confirm
+ add_method_to_attributes!(html_options, method) if method
- add_confirm_to_attributes!(html_options, confirm) if confirm
- add_method_to_attributes!(html_options, method) if method
+ html_options
+ end
+ end
- html_options
+ def link_to_remote_options?(options)
+ options.is_a?(Hash) && options.key?('remote') && options.delete('remote')
end
def add_confirm_to_attributes!(html_options, confirm)
diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb
index fc2abacb6d..2d580fd325 100644
--- a/activemodel/lib/active_model/naming.rb
+++ b/activemodel/lib/active_model/naming.rb
@@ -73,8 +73,10 @@ module ActiveModel
# Returns an ActiveModel::Name object for module. It can be
# used to retrieve all kinds of naming-related information.
def model_name
- namespace = self.parents.detect { |n| n.respond_to?(:_railtie) }
- @_model_name ||= ActiveModel::Name.new(self, namespace)
+ @_model_name ||= begin
+ namespace = self.parents.detect { |n| n.respond_to?(:_railtie) }
+ ActiveModel::Name.new(self, namespace)
+ end
end
# Returns the plural class name of a record or class. Examples:
diff --git a/activesupport/lib/active_support/configurable.rb b/activesupport/lib/active_support/configurable.rb
index 5b85f9394a..1914f10669 100644
--- a/activesupport/lib/active_support/configurable.rb
+++ b/activesupport/lib/active_support/configurable.rb
@@ -9,9 +9,29 @@ module ActiveSupport
module Configurable
extend ActiveSupport::Concern
+ class Configuration < ActiveSupport::InheritableOptions
+ def crystalize!
+ self.class.crystalize!(keys.reject {|key| respond_to?(key)})
+ end
+
+ # compiles reader methods so we don't have to go through method_missing
+ def self.crystalize!(keys)
+ keys.each do |key|
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def #{key}; _get(#{key.inspect}); end
+ RUBY
+ end
+ end
+ end
+
module ClassMethods
def config
- @_config ||= ActiveSupport::InheritableOptions.new(superclass.respond_to?(:config) ? superclass.config : {})
+ @_config ||= if superclass.respond_to?(:config)
+ superclass.config.inheritable_copy
+ else
+ # create a new "anonymous" class that will host the compiled reader methods
+ Class.new(Configuration).new
+ end
end
def configure
@@ -48,7 +68,7 @@ module ActiveSupport
# user.config.level # => 1
#
def config
- @_config ||= ActiveSupport::InheritableOptions.new(self.class.config)
+ @_config ||= self.class.config.inheritable_copy
end
end
end
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
index 688cba03db..511f26963e 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -72,11 +72,20 @@ class Class
remove_possible_method(:#{name})
define_method(:#{name}) { val }
end
+
+ if singleton_class?
+ class_eval do
+ remove_possible_method(:#{name})
+ def #{name}
+ defined?(@#{name}) ? @#{name} : singleton_class.#{name}
+ end
+ end
+ end
val
end
def #{name}
- defined?(@#{name}) ? @#{name} : singleton_class.#{name}
+ defined?(@#{name}) ? @#{name} : self.class.#{name}
end
def #{name}?
@@ -87,4 +96,15 @@ class Class
attr_writer name if instance_writer
end
end
+
+ private
+ def singleton_class?
+ # in case somebody is crazy enough to overwrite allocate
+ allocate = Class.instance_method(:allocate)
+ # object.class always points to a real (non-singleton) class
+ allocate.bind(self).call.class != self
+ rescue TypeError
+ # MRI/YARV/JRuby all disallow creating new instances of a singleton class
+ true
+ end
end
diff --git a/activesupport/lib/active_support/core_ext/hash/keys.rb b/activesupport/lib/active_support/core_ext/hash/keys.rb
index 045a6944fa..d8748b1138 100644
--- a/activesupport/lib/active_support/core_ext/hash/keys.rb
+++ b/activesupport/lib/active_support/core_ext/hash/keys.rb
@@ -35,11 +35,13 @@ class Hash
# as keys, this will fail.
#
# ==== Examples
- # { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years"
- # { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): name, age"
+ # { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: years"
+ # { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key: name"
# { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
def assert_valid_keys(*valid_keys)
- unknown_keys = keys - [valid_keys].flatten
- raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
+ valid_keys.flatten!
+ each_key do |k|
+ raise(ArgumentError, "Unknown key: #{k}") unless valid_keys.include?(k)
+ end
end
end
diff --git a/activesupport/lib/active_support/core_ext/module/attr_internal.rb b/activesupport/lib/active_support/core_ext/module/attr_internal.rb
index 28bc30ae26..00db75bfec 100644
--- a/activesupport/lib/active_support/core_ext/module/attr_internal.rb
+++ b/activesupport/lib/active_support/core_ext/module/attr_internal.rb
@@ -1,16 +1,12 @@
class Module
# Declares an attribute reader backed by an internally-named instance variable.
def attr_internal_reader(*attrs)
- attrs.each do |attr|
- module_eval "def #{attr}() #{attr_internal_ivar_name(attr)} end", __FILE__, __LINE__
- end
+ attrs.each {|attr_name| attr_internal_define(attr_name, :reader)}
end
# Declares an attribute writer backed by an internally-named instance variable.
def attr_internal_writer(*attrs)
- attrs.each do |attr|
- module_eval "def #{attr}=(v) #{attr_internal_ivar_name(attr)} = v end", __FILE__, __LINE__
- end
+ attrs.each {|attr_name| attr_internal_define(attr_name, :writer)}
end
# Declares an attribute reader and writer backed by an internally-named instance
@@ -29,4 +25,15 @@ class Module
def attr_internal_ivar_name(attr)
Module.attr_internal_naming_format % attr
end
+
+ def attr_internal_define(attr_name, type)
+ internal_name = attr_internal_ivar_name(attr_name).sub(/\A@/, '')
+ class_eval do # class_eval is necessary on 1.9 or else the methods a made private
+ # use native attr_* methods as they are faster on some Ruby implementations
+ send("attr_#{type}", internal_name)
+ end
+ attr_name, internal_name = "#{attr_name}=", "#{internal_name}=" if type == :writer
+ alias_method attr_name, internal_name
+ remove_method internal_name
+ end
end
diff --git a/activesupport/lib/active_support/ordered_options.rb b/activesupport/lib/active_support/ordered_options.rb
index 37e357552c..124e1a74f8 100644
--- a/activesupport/lib/active_support/ordered_options.rb
+++ b/activesupport/lib/active_support/ordered_options.rb
@@ -18,6 +18,9 @@ require 'active_support/ordered_hash'
#
module ActiveSupport #:nodoc:
class OrderedOptions < OrderedHash
+ alias_method :_get, :[] # preserve the original #[] method
+ protected :_get # make it protected
+
def []=(key, value)
super(key.to_sym, value)
end
@@ -36,8 +39,19 @@ module ActiveSupport #:nodoc:
end
class InheritableOptions < OrderedOptions
- def initialize(parent)
- super() { |h,k| parent[k] }
+ def initialize(parent = nil)
+ if parent.kind_of?(OrderedOptions)
+ # use the faster _get when dealing with OrderedOptions
+ super() { |h,k| parent._get(k) }
+ elsif parent
+ super() { |h,k| parent[k] }
+ else
+ super()
+ end
+ end
+
+ def inheritable_copy
+ self.class.new(self)
end
end
end
diff --git a/activesupport/test/configurable_test.rb b/activesupport/test/configurable_test.rb
index cef67e3cf9..4f288eb4d5 100644
--- a/activesupport/test/configurable_test.rb
+++ b/activesupport/test/configurable_test.rb
@@ -39,4 +39,22 @@ class ConfigurableActiveSupport < ActiveSupport::TestCase
assert_equal :baz, instance.config.foo
assert_equal :bar, Parent.config.foo
end
+
+ test "configuration is crystalizeable" do
+ parent = Class.new { include ActiveSupport::Configurable }
+ child = Class.new(parent)
+
+ parent.config.bar = :foo
+ assert !parent.config.respond_to?(:bar)
+ assert !child.config.respond_to?(:bar)
+ assert !child.new.config.respond_to?(:bar)
+
+ parent.config.crystalize!
+ assert_equal :foo, parent.config.bar
+ assert_equal :foo, child.new.config.bar
+
+ assert_respond_to parent.config, :bar
+ assert_respond_to child.config, :bar
+ assert_respond_to child.new.config, :bar
+ end
end \ No newline at end of file
diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb
index fc8d8170a1..e5438745e0 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -282,7 +282,7 @@ class HashExtTest < Test::Unit::TestCase
{ :failure => "stuff", :funny => "business" }.assert_valid_keys(:failure, :funny)
end
- assert_raise(ArgumentError, "Unknown key(s): failore") do
+ assert_raise(ArgumentError, "Unknown key: failore") do
{ :failore => "stuff", :funny => "business" }.assert_valid_keys([ :failure, :funny ])
{ :failore => "stuff", :funny => "business" }.assert_valid_keys(:failure, :funny)
end