diff options
author | José Valim <jose.valim@gmail.com> | 2010-09-27 20:10:04 +0200 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2010-09-27 20:10:04 +0200 |
commit | 756b32ef3986992d6e49ed0862ed0f2e314aec6f (patch) | |
tree | d6ae3e85c63ca7b40f9454c975b9e91373f94c95 /activesupport/lib | |
parent | fbd1d306b95cc2efb6422e12d26d5818a3a42343 (diff) | |
parent | 9c57bd8578e5ed47f143a2755b03ffd2ef85c65d (diff) | |
download | rails-756b32ef3986992d6e49ed0862ed0f2e314aec6f.tar.gz rails-756b32ef3986992d6e49ed0862ed0f2e314aec6f.tar.bz2 rails-756b32ef3986992d6e49ed0862ed0f2e314aec6f.zip |
Merge remote branch 'thedarkone/performance'
Diffstat (limited to 'activesupport/lib')
5 files changed, 78 insertions, 15 deletions
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 |