From 1382f4de1f9b0e443e7884bd4da53c20f0754568 Mon Sep 17 00:00:00 2001 From: David Burger Date: Sun, 17 May 2009 21:36:44 -0700 Subject: Fix that Hash#to_xml and Array#to_xml shouldn't modify their options hashes [#672 state:resolved] Signed-off-by: Pratik Naik --- activesupport/lib/active_support/core_ext/array/conversions.rb | 1 + activesupport/lib/active_support/core_ext/hash/conversions.rb | 1 + 2 files changed, 2 insertions(+) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index 11846f265c..c53cf3f530 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -159,6 +159,7 @@ class Array raise "Not all elements respond to to_xml" unless all? { |e| e.respond_to? :to_xml } require 'builder' unless defined?(Builder) + options = options.dup options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? ActiveSupport::Inflector.pluralize(ActiveSupport::Inflector.underscore(first.class.name)) : "records" options[:children] ||= options[:root].singularize options[:indent] ||= 2 diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb index 2a34874d08..bd9419e1a2 100644 --- a/activesupport/lib/active_support/core_ext/hash/conversions.rb +++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb @@ -86,6 +86,7 @@ class Hash def to_xml(options = {}) require 'builder' unless defined?(Builder) + options = options.dup options[:indent] ||= 2 options.reverse_merge!({ :builder => Builder::XmlMarkup.new(:indent => options[:indent]), :root => "hash" }) -- cgit v1.2.3 From ca92d44e7637ae6d28d6b88b67873d2795290cb5 Mon Sep 17 00:00:00 2001 From: Andrew Moreland Date: Sun, 9 Aug 2009 15:38:30 -0700 Subject: Support deep-merging HashWithIndifferentAccess. [#2732 state:committed] Signed-off-by: Jeremy Kemper --- activesupport/lib/active_support/core_ext/hash/deep_merge.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb index ffde34a741..24d0a2a481 100644 --- a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb +++ b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb @@ -1,11 +1,12 @@ class Hash # Returns a new hash with +self+ and +other_hash+ merged recursively. def deep_merge(other_hash) - merge(other_hash) do |key, oldval, newval| - oldval = oldval.to_hash if oldval.respond_to?(:to_hash) - newval = newval.to_hash if newval.respond_to?(:to_hash) - oldval.is_a?( Hash ) && newval.is_a?( Hash ) ? oldval.deep_merge(newval) : newval + target = dup + other_hash.each_pair do |k,v| + tv = target[k] + target[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? tv.deep_merge(v) : v end + target end # Returns a new hash with +self+ and +other_hash+ merged recursively. -- cgit v1.2.3 From e4ceea3795ecc7adcec28a1b9d63782be1401256 Mon Sep 17 00:00:00 2001 From: jeem Date: Sun, 9 Aug 2009 20:04:15 -0500 Subject: make private_and_public_methods unmemoizable [#2372 state:resolved] Signed-off-by: Joshua Peek --- activesupport/lib/active_support/memoizable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index fa6db683d4..7724b9d88b 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -59,7 +59,7 @@ module ActiveSupport def flush_cache(*syms, &block) syms.each do |sym| - methods.each do |m| + (methods + private_methods + protected_methods).each do |m| if m.to_s =~ /^_unmemoized_(#{sym})/ ivar = ActiveSupport::Memoizable.memoized_ivar_for($1) instance_variable_get(ivar).clear if instance_variable_defined?(ivar) -- cgit v1.2.3 From 4dda9b644df5e4386f693a4b7bd00fe787f41a28 Mon Sep 17 00:00:00 2001 From: Erik Ostrom Date: Sun, 9 Aug 2009 18:57:25 -0700 Subject: Add rindex to ActiveSupport::Multibyte::Chars. Signed-off-by: Jeremy Kemper --- activesupport/lib/active_support/multibyte/chars.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index 96ed35f0e0..3c16999e43 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -210,6 +210,19 @@ module ActiveSupport #:nodoc: index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil end + # Returns the position _needle_ in the string, counting in + # codepoints, searching backward from _offset_ or the end of the + # string. Returns +nil+ if _needle_ isn't found. + # + # Example: + # 'Café périferôl'.mb_chars.rindex('é') #=> 5 + # 'Café périferôl'.mb_chars.rindex(/\w/u) #=> 13 + def rindex(needle, offset=nil) + offset ||= length + index = @wrapped_string.rindex(needle, offset) + index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil + end + # Like String#[]=, except instead of byte offsets you specify character offsets. # # Example: -- cgit v1.2.3 From 82dd725fc195eb52eea9cbde9530ab9dff122e32 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Fri, 4 Jul 2008 14:04:50 +0700 Subject: Fix that irregular plural inflections should not be double-pluralized: 'people'.pluralize should return 'people' not 'peoples'. [#1183 state:committed] Signed-off-by: Jeremy Kemper --- activesupport/lib/active_support/inflector.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/inflector.rb b/activesupport/lib/active_support/inflector.rb index 4ee96b13b4..67aea2782f 100644 --- a/activesupport/lib/active_support/inflector.rb +++ b/activesupport/lib/active_support/inflector.rb @@ -69,10 +69,13 @@ module ActiveSupport @uncountables.delete(plural) if singular[0,1].upcase == plural[0,1].upcase plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1]) + plural(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + plural[1..-1]) singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1]) else plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1]) plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1]) + plural(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), plural[0,1].upcase + plural[1..-1]) + plural(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), plural[0,1].downcase + plural[1..-1]) singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1]) singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1]) end -- cgit v1.2.3 From b3381cacaf7735ec6eb108e378ba255ebf6ffb14 Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Sun, 9 Aug 2009 11:27:17 +0400 Subject: Fix that JSON parser fails to read escaped backslashes. [#973 state:committed] Signed-off-by: Jeremy Kemper --- activesupport/lib/active_support/json/backends/yaml.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/json/backends/yaml.rb b/activesupport/lib/active_support/json/backends/yaml.rb index 92dd31cfbc..59d2c37e40 100644 --- a/activesupport/lib/active_support/json/backends/yaml.rb +++ b/activesupport/lib/active_support/json/backends/yaml.rb @@ -20,7 +20,7 @@ module ActiveSupport rescue ArgumentError => e raise ParseError, "Invalid JSON string" end - + protected # Ensure that ":" and "," are always followed by a space def convert_json_to_yaml(json) #:nodoc: @@ -42,6 +42,8 @@ module ActiveSupport end when ":","," marks << scanner.pos - 1 unless quoting + when "\\" + scanner.skip(/\\/) end end @@ -89,3 +91,4 @@ module ActiveSupport end end end + -- cgit v1.2.3 From 7d16e94d827197d030fdd611db4310396aeb0114 Mon Sep 17 00:00:00 2001 From: Erik Ostrom Date: Sun, 9 Aug 2009 22:14:59 -0700 Subject: Correctly handle offsets in Multibyte::Chars#index and #rindex. The offset in codepoints was being passed directly to the wrapped string's index/rindex method. Now we translate the offset into bytes first. [#3028 state:committed] Signed-off-by: Jeremy Kemper --- activesupport/lib/active_support/multibyte/chars.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index 3c16999e43..64a35dca40 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -206,7 +206,8 @@ module ActiveSupport #:nodoc: # 'Café périferôl'.mb_chars.index('ô') #=> 12 # 'Café périferôl'.mb_chars.index(/\w/u) #=> 0 def index(needle, offset=0) - index = @wrapped_string.index(needle, offset) + wrapped_offset = self.first(offset).wrapped_string.length + index = @wrapped_string.index(needle, wrapped_offset) index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil end @@ -215,11 +216,12 @@ module ActiveSupport #:nodoc: # string. Returns +nil+ if _needle_ isn't found. # # Example: - # 'Café périferôl'.mb_chars.rindex('é') #=> 5 + # 'Café périferôl'.mb_chars.rindex('é') #=> 6 # 'Café périferôl'.mb_chars.rindex(/\w/u) #=> 13 def rindex(needle, offset=nil) offset ||= length - index = @wrapped_string.rindex(needle, offset) + wrapped_offset = self.first(offset).wrapped_string.length + index = @wrapped_string.rindex(needle, wrapped_offset) index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil end -- cgit v1.2.3 From d15ddf04ec6fb0cd6d350ba57d9981ebee3eddd0 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 10 Aug 2009 18:34:24 -0400 Subject: Allow delegating to nil, because the method might actually exist on it --- .../lib/active_support/core_ext/module/delegation.rb | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb index 11e01437aa..df8aefea5a 100644 --- a/activesupport/lib/active_support/core_ext/module/delegation.rb +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -120,10 +120,15 @@ class Module end module_eval(<<-EOS, file, line) - def #{prefix}#{method}(*args, &block) # def customer_name(*args, &block) - #{on_nil} if #{to}.nil? - #{to}.__send__(#{method.inspect}, *args, &block) # client && client.__send__(:name, *args, &block) - end # end + def #{prefix}#{method}(*args, &block) # def customer_name(*args, &block) + #{to}.__send__(#{method.inspect}, *args, &block) # client.__send__(:name, *args, &block) + rescue NoMethodError # rescue NoMethodError + if #{to}.nil? # if client.nil? + #{on_nil} + else # else + raise # raise + end # end + end # end EOS end end -- cgit v1.2.3 From 0adbeeb0c92c6de2e4a148e4b54d56cd4a325800 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 10 Aug 2009 11:40:41 -0400 Subject: Got overhead down from 127 to 85. All tests pass: * Tentatively replaced HeaderHash with SimpleHeaderHash, which does not preserve case but does handle converting Arrays to Strings in to_hash. This requires further discussion. * Moved default_charset to ActionDispatch::Response to avoid having to hop over to ActionController. Ideally, this would be a constant on AD::Response, but some tests expect to be able to change it dynamically and I didn't want to change them yet. * Completely override #initialize from Rack::Response. Previously, it was creating a HeaderHash, and then we were creating an entirely new one. There is no way to call super without incurring the overhead of creating a HeaderHash. * Override #write from Rack::Response. Its implementation tracks Content-Length, and doing so adds additional overhead that could be mooted if other middleware changes the body. It is more efficiently done at the top-level server. * Change sending_file to an instance_variable instead of header inspection. In general, if a state is important, it should be set as a property of the response not reconstructed later. * Set the Etag to @body instead of .body. AS::Cache.expand_cache_key handles Arrays fine, and it's more efficient to let it handle the body parts, since it is not forced to create a joined String. * If we detect the default cache control case, just set it, rather than setting the constituent parts and then running the normal (expensive) code to generate the string. --- .../lib/active_support/core_ext/class/attribute_accessors.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb index 74ce85a1c2..1602a609eb 100644 --- a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb @@ -46,11 +46,12 @@ class Class end # end " unless options[:instance_writer] == false } # # instance writer above is generated unless options[:instance_writer] == false EOS + self.send("#{sym}=", yield) if block_given? end end - def cattr_accessor(*syms) + def cattr_accessor(*syms, &blk) cattr_reader(*syms) - cattr_writer(*syms) + cattr_writer(*syms, &blk) end end -- cgit v1.2.3 From 4bf516e072f5279bdb462c6592e17b195fd9cf05 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 10 Aug 2009 15:49:33 -0700 Subject: More perf work: * Move #set_cookie and #delete_cookie inline to optimize. These optimizations should almost certainly be sent back upstream to Rack. The optimization involves using an ivar for cookies instead of indexing into the headers each time. * Was able to use a bare Hash for headers now that cookies have their own joining semantics (some code assumed that the raw cookies were an Array). * Cache blankness of body on body= * Improve expand_cache_key for Arrays of a single element (common in our case) * Use a simple layout condition check unless conditions are used * Cache visible actions * Lazily load the UrlRewriter * Make etag an ivar that is set on prepare! --- activesupport/lib/active_support/cache.rb | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 448db538ab..e28df8efa5 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -62,19 +62,27 @@ module ActiveSupport end end + RAILS_CACHE_ID = ENV["RAILS_CACHE_ID"] + RAILS_APP_VERION = ENV["RAILS_APP_VERION"] + EXPANDED_CACHE = RAILS_CACHE_ID || RAILS_APP_VERION + def self.expand_cache_key(key, namespace = nil) expanded_cache_key = namespace ? "#{namespace}/" : "" - if ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"] - expanded_cache_key << "#{ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]}/" + if EXPANDED_CACHE + expanded_cache_key << "#{RAILS_CACHE_ID || RAILS_APP_VERION}/" end - expanded_cache_key << case - when key.respond_to?(:cache_key) + expanded_cache_key << + if key.respond_to?(:cache_key) key.cache_key - when key.is_a?(Array) - key.collect { |element| expand_cache_key(element) }.to_param - when key + elsif key.is_a?(Array) + if key.size > 1 + key.collect { |element| expand_cache_key(element) }.to_param + else + key.first.to_param + end + elsif key key.to_param end.to_s -- cgit v1.2.3 From ccd1c5e521c020118b5bcfeb4cd5a651997b6806 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 10 Aug 2009 15:49:53 -0700 Subject: Allow superclass_delegating_accessor to take a block for initial set. --- .../lib/active_support/core_ext/class/delegating_attributes.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb index fd029544c3..6c67df7f50 100644 --- a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb +++ b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb @@ -26,13 +26,14 @@ class Class end end - def superclass_delegating_writer(*names) + def superclass_delegating_writer(*names, &block) names.each do |name| class_eval(<<-EOS, __FILE__, __LINE__ + 1) def self.#{name}=(value) # def self.property=(value) @#{name} = value # @property = value end # end EOS + self.send("#{name}=", yield) if block_given? end end @@ -42,8 +43,8 @@ class Class # delegate to their superclass unless they have been given a # specific value. This stops the strange situation where values # set after class definition don't get applied to subclasses. - def superclass_delegating_accessor(*names) + def superclass_delegating_accessor(*names, &block) superclass_delegating_reader(*names) - superclass_delegating_writer(*names) + superclass_delegating_writer(*names, &block) end end -- cgit v1.2.3 From e93d0a50c0e8cdc2507a7a211fc96404ad738152 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sat, 22 Aug 2009 15:53:19 -0700 Subject: Ruby 1.9: fix Time#beginning_of_day inaccuracy due to subtracting a Float --- activesupport/lib/active_support/core_ext/time/calculations.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 4f3b869f50..4f4492f0fd 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -172,7 +172,8 @@ class Time # Returns a new Time representing the start of the day (0:00) def beginning_of_day - (self - seconds_since_midnight).change(:usec => 0) + #(self - seconds_since_midnight).change(:usec => 0) + change(:hour => 0, :min => 0, :sec => 0, :usec => 0) end alias :midnight :beginning_of_day alias :at_midnight :beginning_of_day -- cgit v1.2.3 From 66d8063c910b166e58f77ca5149a454f721667c7 Mon Sep 17 00:00:00 2001 From: Jeffrey Hardy Date: Wed, 26 Aug 2009 12:10:42 -0400 Subject: Correct Regexp#un/optionalize assertions and fix uncovered failures [#3102 state:incomplete] Signed-off-by: Jeremy Kemper --- activesupport/lib/active_support/core_ext/regexp.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/regexp.rb b/activesupport/lib/active_support/core_ext/regexp.rb index 1a04c70d87..95d06ee6ee 100644 --- a/activesupport/lib/active_support/core_ext/regexp.rb +++ b/activesupport/lib/active_support/core_ext/regexp.rb @@ -9,6 +9,8 @@ class Regexp #:nodoc: class << self def optionalize(pattern) + return pattern if pattern == "" + case unoptionalize(pattern) when /\A(.|\(.*\))\Z/ then "#{pattern}?" else "(?:#{pattern})?" -- cgit v1.2.3 From 7316d029e60f5d531b35af9e66d233ea19e4f240 Mon Sep 17 00:00:00 2001 From: Jay Pignata Date: Mon, 31 Aug 2009 13:02:19 -0500 Subject: Duplicating the options hash in Date#advance to prevent modification of the original [#1133 state:resolved] Signed-off-by: Joshua Peek --- activesupport/lib/active_support/core_ext/date/calculations.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb index 1fe4ffb8e1..ce3bebc25a 100644 --- a/activesupport/lib/active_support/core_ext/date/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date/calculations.rb @@ -82,6 +82,7 @@ class Date # Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with # any of these keys: :years, :months, :weeks, :days. def advance(options) + options = options.dup d = self d = d >> options.delete(:years) * 12 if options[:years] d = d >> options.delete(:months) if options[:months] -- cgit v1.2.3