diff options
author | Xavier Noria <fxn@hashref.com> | 2011-08-31 04:27:59 -0700 |
---|---|---|
committer | Xavier Noria <fxn@hashref.com> | 2011-08-31 04:27:59 -0700 |
commit | 47b8415bef7edb25bb750685d6f9331f044bbd80 (patch) | |
tree | e408066b7c5df43b2e1b2fbc4f0ff5478f5efdab /activesupport | |
parent | 6d772c0953b418da774b2c3bf5cc297508669da7 (diff) | |
parent | e746c4047cd34accd7f63aa5d09cbb35011c24e2 (diff) | |
download | rails-47b8415bef7edb25bb750685d6f9331f044bbd80.tar.gz rails-47b8415bef7edb25bb750685d6f9331f044bbd80.tar.bz2 rails-47b8415bef7edb25bb750685d6f9331f044bbd80.zip |
Merge branch 'master' of git://github.com/rails/rails
Diffstat (limited to 'activesupport')
21 files changed, 208 insertions, 40 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index a25720adbf..3508ec0f34 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,11 +1,13 @@ *Rails 3.2.0 (unreleased)* +* Added Array#prepend as an alias for Array#unshift and Array#append as an alias for Array#<< [DHH] + * The definition of blank string for Ruby 1.9 has been extended to Unicode whitespace. Also, in 1.8 the ideographic space U+3000 is considered to be whitespace. [Akira Matsuda, Damien Mathieu] * The inflector understands acronyms. [dlee] -* Deprecated ActiveSupport::Memoizable in favor of Ruby memoization pattern [José Valim] +* Deprecated ActiveSupport::Memoizable in favor of Ruby memoization pattern [José Valim] * Added Time#all_day/week/quarter/year as a way of generating ranges (example: Event.where(created_at: Time.now.all_week)) [DHH] @@ -18,6 +20,18 @@ Also, in 1.8 the ideographic space U+3000 is considered to be whitespace. [Akira *Rails 3.1.0 (unreleased)* +* ActiveSupport::Dependencies#load and ActiveSupport::Dependencies#require now +return the value from `super` [Aaron Patterson] + +* Fixed ActiveSupport::Gzip to work properly in Ruby 1.8 [Guillermo Iguaran] + +* Kernel.require_library_or_gem was deprecated and will be removed in Rails 3.2.0 [Josh Kalderimis] + +* ActiveSupport::Duration#duplicable? was fixed for Ruby 1.8 [thedarkone] + +* ActiveSupport::BufferedLogger set log encoding to BINARY, but still use text +mode to output portable newlines. [fxn] + * ActiveSupport::Dependencies now raises NameError if it finds an existing constant in load_missing_constant. This better reflects the nature of the error which is usually caused by calling constantize on a nested constant. [Andrew White] * Deprecated ActiveSupport::SecureRandom in favour of SecureRandom from the standard library [Jon Leighton] diff --git a/activesupport/lib/active_support/core_ext/array.rb b/activesupport/lib/active_support/core_ext/array.rb index 4688468a8f..268c9bed4c 100644 --- a/activesupport/lib/active_support/core_ext/array.rb +++ b/activesupport/lib/active_support/core_ext/array.rb @@ -5,3 +5,4 @@ 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/prepend_and_append.rb b/activesupport/lib/active_support/core_ext/array/prepend_and_append.rb new file mode 100644 index 0000000000..27718f19d4 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/array/prepend_and_append.rb @@ -0,0 +1,7 @@ +class Array + # The human way of thinking about adding stuff to the end of a list is with append + alias_method :append, :<< + + # The human way of thinking about adding stuff to the beginning of a list is with prepend + alias_method :prepend, :unshift +end
\ No newline at end of file diff --git a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb index 080604147d..391bdc925d 100644 --- a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb +++ b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb @@ -29,8 +29,11 @@ class BigDecimal coder.represent_scalar(nil, YAML_MAPPING[string] || string) end - def to_d - self + # Backport this method if it doesn't exist + unless method_defined?(:to_d) + def to_d + self + end end DEFAULT_STRING_FORMAT = 'F' diff --git a/activesupport/lib/active_support/core_ext/io.rb b/activesupport/lib/active_support/core_ext/io.rb new file mode 100644 index 0000000000..75f1055191 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/io.rb @@ -0,0 +1,15 @@ +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/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb index 149b849b12..7de824a77f 100644 --- a/activesupport/lib/active_support/core_ext/module/delegation.rb +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -106,35 +106,48 @@ class Module unless options.is_a?(Hash) && to = options[:to] raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)." end + prefix, to, allow_nil = options[:prefix], options[:to], options[:allow_nil] - if options[:prefix] == true && options[:to].to_s =~ /^[^a-z_]/ + if prefix == true && to.to_s =~ /^[^a-z_]/ raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method." end - prefix = options[:prefix] ? "#{options[:prefix] == true ? to : options[:prefix]}_" : '' + method_prefix = + if prefix + "#{prefix == true ? to : prefix}_" + else + '' + end file, line = caller.first.split(':', 2) line = line.to_i methods.each do |method| - on_nil = - if options[:allow_nil] - 'return' - else - %(raise "#{self}##{prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") - end + method = method.to_s - module_eval(<<-EOS, file, line - 5) - 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} # return # depends on :allow_nil - else # else - raise # raise - end # end - end # end - EOS + if allow_nil + module_eval(<<-EOS, file, line - 2) + def #{method_prefix}#{method}(*args, &block) # def customer_name(*args, &block) + if #{to} || #{to}.respond_to?(:#{method}) # if client || client.respond_to?(:name) + #{to}.__send__(:#{method}, *args, &block) # client.__send__(:name, *args, &block) + end # end + end # end + EOS + else + exception = %(raise "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") + + module_eval(<<-EOS, file, line - 1) + def #{method_prefix}#{method}(*args, &block) # def customer_name(*args, &block) + #{to}.__send__(:#{method}, *args, &block) # client.__send__(:name, *args, &block) + rescue NoMethodError # rescue NoMethodError + if #{to}.nil? # if client.nil? + #{exception} # # add helpful message to the exception + else # else + raise # raise + end # end + end # end + EOS + end end end end 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 6d6c4912bb..f111c8e5a3 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -20,7 +20,7 @@ class ERB if s.html_safe? s else - s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }.html_safe + s.to_s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/</, "<").html_safe end end diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index c5fbbcf890..a15a06d0e4 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -1,5 +1,6 @@ require 'active_support/duration' require 'active_support/core_ext/time/zones' +require 'active_support/core_ext/time/conversions' class Time COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 3f6c93e860..c072a8e646 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -229,11 +229,15 @@ module ActiveSupport #:nodoc: end def load(file, *) - load_dependency(file) { super } + result = false + load_dependency(file) { result = super } + result end def require(file, *) - load_dependency(file) { super } + result = false + load_dependency(file) { result = super } + result end # Mark the given constant as unloadable. Unloadable constants are removed each @@ -417,7 +421,8 @@ module ActiveSupport #:nodoc: end def load_once_path?(path) - autoload_once_paths.any? { |base| path.starts_with? base } + # to_s works around a ruby1.9 issue where #starts_with?(Pathname) will always return false + autoload_once_paths.any? { |base| path.starts_with? base.to_s } end # Attempt to autoload the provided module name by searching for a directory diff --git a/activesupport/lib/active_support/gzip.rb b/activesupport/lib/active_support/gzip.rb index 62f9c9aa2e..9651f02c73 100644 --- a/activesupport/lib/active_support/gzip.rb +++ b/activesupport/lib/active_support/gzip.rb @@ -1,5 +1,6 @@ require 'zlib' require 'stringio' +require 'active_support/core_ext/string/encoding' module ActiveSupport # A convenient wrapper for the zlib standard library that allows compression/decompression of strings with gzip. diff --git a/activesupport/lib/active_support/i18n_railtie.rb b/activesupport/lib/active_support/i18n_railtie.rb index a25e951080..4c59fe9ac9 100644 --- a/activesupport/lib/active_support/i18n_railtie.rb +++ b/activesupport/lib/active_support/i18n_railtie.rb @@ -1,5 +1,4 @@ require "active_support" -require "rails" require "active_support/file_update_checker" require "active_support/core_ext/array/wrap" @@ -38,6 +37,8 @@ module I18n protected + @i18n_inited = false + # Setup i18n configuration def self.initialize_i18n(app) return if @i18n_inited diff --git a/activesupport/lib/active_support/inflections.rb b/activesupport/lib/active_support/inflections.rb index 06ceccdb22..daf2a1e1d9 100644 --- a/activesupport/lib/active_support/inflections.rb +++ b/activesupport/lib/active_support/inflections.rb @@ -54,6 +54,7 @@ module ActiveSupport inflect.irregular('sex', 'sexes') inflect.irregular('move', 'moves') inflect.irregular('cow', 'kine') + inflect.irregular('zombie', 'zombies') inflect.uncountable(%w(equipment information rice money species series fish sheep jeans)) end diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb index 77696eb1db..b5a70d5933 100644 --- a/activesupport/lib/active_support/notifications.rb +++ b/activesupport/lib/active_support/notifications.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/module/delegation' - module ActiveSupport # Notifications provides an instrumentation API for Ruby. To instrument an # action in Ruby you just need to do: diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb index 04df2ea562..1638512af0 100644 --- a/activesupport/lib/active_support/railtie.rb +++ b/activesupport/lib/active_support/railtie.rb @@ -1,5 +1,4 @@ require "active_support" -require "rails" require "active_support/i18n_railtie" module ActiveSupport diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 728921a069..4fb487ade1 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -195,12 +195,8 @@ module ActiveSupport # (GMT). Seconds were chosen as the offset unit because that is the unit that # Ruby uses to represent time zone offsets (see Time#utc_offset). def initialize(name, utc_offset = nil, tzinfo = nil) - begin - require 'tzinfo' - rescue LoadError => e - $stderr.puts "You don't have tzinfo installed in your application. Please add it to your Gemfile and run bundle install" - raise e - end + self.class.send(:require_tzinfo) + @name = name @utc_offset = utc_offset @tzinfo = tzinfo || TimeZone.find_tzinfo(name) @@ -337,7 +333,12 @@ module ActiveSupport end def zones_map - @zones_map ||= Hash[MAPPING.map { |place, _| [place, create(place)] }] + @zones_map ||= begin + new_zones_names = MAPPING.keys - lazy_zones_map.keys + new_zones = Hash[new_zones_names.map { |place| [place, create(place)] }] + + lazy_zones_map.merge(new_zones) + end end # Locate a specific time zone object. If the argument is a string, it @@ -349,7 +350,7 @@ module ActiveSupport case arg when String begin - zones_map[arg] ||= lookup(arg).tap { |tz| tz.utc_offset } + lazy_zones_map[arg] ||= lookup(arg).tap { |tz| tz.utc_offset } rescue TZInfo::InvalidTimezoneIdentifier nil end @@ -367,11 +368,28 @@ module ActiveSupport @us_zones ||= all.find_all { |z| z.name =~ /US|Arizona|Indiana|Hawaii|Alaska/ } end + protected + + def require_tzinfo + require 'tzinfo' + rescue LoadError + $stderr.puts "You don't have tzinfo installed in your application. Please add it to your Gemfile and run bundle install" + raise + end + private def lookup(name) (tzinfo = find_tzinfo(name)) && create(tzinfo.name.freeze) end + + def lazy_zones_map + require_tzinfo + + @lazy_zones_map ||= Hash.new do |hash, place| + hash[place] = create(place) if MAPPING.has_key?(place) + end + end end end end diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb index e532010b18..52231aaeb0 100644 --- a/activesupport/test/core_ext/array_ext_test.rb +++ b/activesupport/test/core_ext/array_ext_test.rb @@ -465,3 +465,13 @@ class ArrayWrapperTests < Test::Unit::TestCase assert_equal DoubtfulToAry.new.to_ary, Array.wrap(DoubtfulToAry.new) end end + +class ArrayPrependAppendTest < Test::Unit::TestCase + def test_append + assert_equal [1, 2], [1].append(2) + end + + def test_prepend + assert_equal [2, 1], [1].prepend(2) + end +end diff --git a/activesupport/test/core_ext/io_test.rb b/activesupport/test/core_ext/io_test.rb new file mode 100644 index 0000000000..b9abf685da --- /dev/null +++ b/activesupport/test/core_ext/io_test.rb @@ -0,0 +1,23 @@ +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/module_test.rb b/activesupport/test/core_ext/module_test.rb index a95cf1591f..449d3810e2 100644 --- a/activesupport/test/core_ext/module_test.rb +++ b/activesupport/test/core_ext/module_test.rb @@ -26,11 +26,20 @@ module Yz end end -Somewhere = Struct.new(:street, :city) +Somewhere = Struct.new(:street, :city) do + attr_accessor :name +end -Someone = Struct.new(:name, :place) do +class Someone < Struct.new(:name, :place) delegate :street, :city, :to_f, :to => :place + delegate :name=, :to => :place, :prefix => true delegate :upcase, :to => "place.city" + + FAILED_DELEGATE_LINE = __LINE__ + 1 + delegate :foo, :to => :place + + FAILED_DELEGATE_LINE_2 = __LINE__ + 1 + delegate :bar, :to => :place, :allow_nil => true end Invoice = Struct.new(:client) do @@ -69,6 +78,11 @@ class ModuleTest < Test::Unit::TestCase assert_equal "Chicago", @david.city end + def test_delegation_to_assignment_method + @david.place_name = "Fred" + assert_equal "Fred", @david.place.name + end + def test_delegation_down_hierarchy assert_equal "CHICAGO", @david.upcase end @@ -164,6 +178,24 @@ class ModuleTest < Test::Unit::TestCase end end + def test_delegation_exception_backtrace + someone = Someone.new("foo", "bar") + someone.foo + rescue NoMethodError => e + file_and_line = "#{__FILE__}:#{Someone::FAILED_DELEGATE_LINE}" + assert e.backtrace.first.include?(file_and_line), + "[#{e.backtrace.first}] did not include [#{file_and_line}]" + end + + def test_delegation_exception_backtrace_with_allow_nil + someone = Someone.new("foo", "bar") + someone.bar + rescue NoMethodError => e + file_and_line = "#{__FILE__}:#{Someone::FAILED_DELEGATE_LINE_2}" + assert e.backtrace.first.include?(file_and_line), + "[#{e.backtrace.first}] did not include [#{file_and_line}]" + end + def test_parent assert_equal Yz::Zy, Yz::Zy::Cd.parent assert_equal Yz, Yz::Zy.parent diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index a4bba056df..81a284dded 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -7,10 +7,17 @@ require 'active_support/inflector' require 'active_support/core_ext/string' require 'active_support/time' require 'active_support/core_ext/string/strip' +require 'active_support/core_ext/string/output_safety' class StringInflectionsTest < Test::Unit::TestCase include InflectorTestCases + def test_erb_escape + string = [192, 60].pack('CC') + expected = 192.chr + "<" + assert_equal expected, ERB::Util.html_escape(string) + end + def test_strip_heredoc_on_an_empty_string assert_equal '', ''.strip_heredoc end diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index b0e96731cc..fe8f51e11a 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -520,6 +520,24 @@ class DependenciesTest < Test::Unit::TestCase ActiveSupport::Dependencies.autoload_once_paths = [] end + def test_autoload_once_pathnames_do_not_add_to_autoloaded_constants + with_autoloading_fixtures do + pathnames = ActiveSupport::Dependencies.autoload_paths.collect{|p| Pathname.new(p)} + ActiveSupport::Dependencies.autoload_paths = pathnames + ActiveSupport::Dependencies.autoload_once_paths = pathnames + + assert ! ActiveSupport::Dependencies.autoloaded?("ModuleFolder") + assert ! ActiveSupport::Dependencies.autoloaded?("ModuleFolder::NestedClass") + assert ! ActiveSupport::Dependencies.autoloaded?(ModuleFolder) + + 1 if ModuleFolder::NestedClass # 1 if to avoid warning + assert ! ActiveSupport::Dependencies.autoloaded?(ModuleFolder::NestedClass) + end + ensure + Object.class_eval { remove_const :ModuleFolder } + ActiveSupport::Dependencies.autoload_once_paths = [] + end + def test_application_should_special_case_application_controller with_autoloading_fixtures do require_dependency 'application' diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb index cc0dc564f7..884ee61547 100644 --- a/activesupport/test/notifications_test.rb +++ b/activesupport/test/notifications_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'active_support/core_ext/module/delegation' module Notifications class TestCase < ActiveSupport::TestCase |