diff options
Diffstat (limited to 'activesupport')
30 files changed, 328 insertions, 125 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 09ec4ed618..8165b89cde 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -27,6 +27,11 @@ * Unicode database updated to 6.1.0. +## Rails 3.2.2 (March 1, 2012) ## + +* No changes. + + ## Rails 3.2.1 (January 26, 2012) ## * Documentation fixes and improvements. diff --git a/activesupport/lib/active_support/basic_object.rb b/activesupport/lib/active_support/basic_object.rb index c3c7ab0112..6ccb0cd525 100644 --- a/activesupport/lib/active_support/basic_object.rb +++ b/activesupport/lib/active_support/basic_object.rb @@ -10,5 +10,4 @@ module ActiveSupport ::Object.send(:raise, *args) end end - end diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index d7408eff9f..b9f196d7a9 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -91,6 +91,7 @@ module ActiveSupport case when key.respond_to?(:cache_key) then key.cache_key when key.is_a?(Array) then key.map { |element| retrieve_cache_key(element) }.to_param + when key.respond_to?(:to_a) then retrieve_cache_key(key.to_a) else key.to_param end.to_s end diff --git a/activesupport/lib/active_support/core_ext/hash/slice.rb b/activesupport/lib/active_support/core_ext/hash/slice.rb index 0484d8e5d8..45181f0e16 100644 --- a/activesupport/lib/active_support/core_ext/hash/slice.rb +++ b/activesupport/lib/active_support/core_ext/hash/slice.rb @@ -13,17 +13,15 @@ class Hash # valid_keys = [:mass, :velocity, :time] # search(options.slice(*valid_keys)) def slice(*keys) - keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key) - hash = self.class.new - keys.each { |k| hash[k] = self[k] if has_key?(k) } - hash + keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true) + keys.each_with_object(self.class.new) { |k, hash| hash[k] = self[k] if has_key?(k) } end # Replaces the hash with only the given keys. # Returns a hash contained the removed key/value pairs # {:a => 1, :b => 2, :c => 3, :d => 4}.slice!(:a, :b) # => {:c => 3, :d => 4} def slice!(*keys) - keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key) + keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true) omit = slice(*self.keys - keys) hash = slice(*keys) replace(hash) @@ -33,8 +31,6 @@ class Hash # Removes and returns the key/value pairs matching the given keys. # {:a => 1, :b => 2, :c => 3, :d => 4}.extract!(:a, :b) # => {:a => 1, :b => 2} def extract!(*keys) - result = {} - keys.each {|key| result[key] = delete(key) } - result + keys.each_with_object({}) {|key, result| result[key] = delete(key) } end end diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb index ac2a63d3a1..af92b869fd 100644 --- a/activesupport/lib/active_support/core_ext/module/delegation.rb +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -106,9 +106,11 @@ 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 prefix == true && to.to_s =~ /^[^a-z_]/ + to = to.to_s + prefix, allow_nil = options.values_at(:prefix, :allow_nil) + + if prefix == true && to =~ /^[^a-z_]/ raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method." end @@ -122,10 +124,8 @@ class Module file, line = caller.first.split(':', 2) line = line.to_i - methods.each do |method| - method = method.to_s - - if allow_nil + if allow_nil + methods.each do |method| 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) @@ -133,7 +133,9 @@ class Module end # end end # end EOS - else + end + else + methods.each do |method| exception = %(raise "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") module_eval(<<-EOS, file, line - 1) diff --git a/activesupport/lib/active_support/core_ext/object/duplicable.rb b/activesupport/lib/active_support/core_ext/object/duplicable.rb index 9d044eba71..9d1630bb7c 100644 --- a/activesupport/lib/active_support/core_ext/object/duplicable.rb +++ b/activesupport/lib/active_support/core_ext/object/duplicable.rb @@ -104,3 +104,16 @@ class Module false end end + +require 'bigdecimal' +class BigDecimal + begin + BigDecimal.new('4.56').dup + + def duplicable? + true + end + rescue TypeError + # can't dup, so use superclass implementation + end +end diff --git a/activesupport/lib/active_support/core_ext/proc.rb b/activesupport/lib/active_support/core_ext/proc.rb index 94bb5fb0cb..cd63740940 100644 --- a/activesupport/lib/active_support/core_ext/proc.rb +++ b/activesupport/lib/active_support/core_ext/proc.rb @@ -1,7 +1,10 @@ require "active_support/core_ext/kernel/singleton_class" +require "active_support/deprecation" class Proc #:nodoc: def bind(object) + ActiveSupport::Deprecation.warn 'Proc#bind is deprecated and will be removed in future versions', caller + block, time = self, Time.now object.class_eval do method_name = "__bind_#{time.to_i}_#{time.usec}" diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 2c5950edf5..745a131524 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -129,16 +129,14 @@ module ActiveSupport #:nodoc: # Add a set of modules to the watch stack, remembering the initial constants def watch_namespaces(namespaces) - watching = [] - namespaces.map do |namespace| + @watching << namespaces.map do |namespace| module_name = Dependencies.to_constant_name(namespace) original_constants = Dependencies.qualified_const_defined?(module_name) ? Inflector.constantize(module_name).local_constants : [] - watching << module_name @stack[module_name] << original_constants + module_name end - @watching << watching end private @@ -365,7 +363,7 @@ module ActiveSupport #:nodoc: # Record history *after* loading so first load gets warnings. history << expanded - return result + result end # Is the provided constant path defined? @@ -434,7 +432,7 @@ module ActiveSupport #:nodoc: mod = Module.new into.const_set const_name, mod autoloaded_constants << qualified_name unless autoload_once_paths.include?(base_path) - return mod + mod end # Load the file at the provided path. +const_paths+ is a set of qualified @@ -458,7 +456,7 @@ module ActiveSupport #:nodoc: autoloaded_constants.concat newly_defined_paths unless load_once_path?(path) autoloaded_constants.uniq! log "loading #{path} defined #{newly_defined_paths * ', '}" unless newly_defined_paths.empty? - return result + result end # Return the constant path for the provided parent and constant name. @@ -505,7 +503,7 @@ module ActiveSupport #:nodoc: raise NameError, "uninitialized constant #{qualified_name}", - caller.reject {|l| l.starts_with? __FILE__ } + caller.reject { |l| l.starts_with? __FILE__ } end # Remove the constants that have been autoloaded, and those that have been @@ -543,10 +541,7 @@ module ActiveSupport #:nodoc: def safe_get(key) key = key.name if key.respond_to?(:name) - @store[key] || begin - klass = Inflector.safe_constantize(key) - @store[key] = klass - end + @store[key] ||= Inflector.safe_constantize(key) end def store(klass) @@ -600,10 +595,10 @@ module ActiveSupport #:nodoc: def mark_for_unload(const_desc) name = to_constant_name const_desc if explicitly_unloadable_constants.include? name - return false + false else explicitly_unloadable_constants << name - return true + true end end @@ -631,10 +626,10 @@ module ActiveSupport #:nodoc: return new_constants unless aborting log "Error during loading, removing partially loaded constants " - new_constants.each {|c| remove_constant(c) }.clear + new_constants.each { |c| remove_constant(c) }.clear end - return [] + [] end # Convert the provided const desc to a qualified constant name (as a string). @@ -663,7 +658,7 @@ module ActiveSupport #:nodoc: constantized.before_remove_const if constantized.respond_to?(:before_remove_const) parent.instance_eval { remove_const to_remove } - return true + true end protected diff --git a/activesupport/lib/active_support/dependencies/autoload.rb b/activesupport/lib/active_support/dependencies/autoload.rb index 4c771da096..a1626ebeba 100644 --- a/activesupport/lib/active_support/dependencies/autoload.rb +++ b/activesupport/lib/active_support/dependencies/autoload.rb @@ -9,13 +9,16 @@ module ActiveSupport @@eager_autoload = false def autoload(const_name, path = @@at_path) - full = [self.name, @@under_path, const_name.to_s, path].compact.join("::") - location = path || Inflector.underscore(full) + unless path + full = [name, @@under_path, const_name.to_s, path].compact.join("::") + path = Inflector.underscore(full) + end if @@eager_autoload - @@autoloads[const_name] = location + @@autoloads[const_name] = path end - super const_name, location + + super const_name, path end def autoload_under(path) diff --git a/activesupport/lib/active_support/file_update_checker.rb b/activesupport/lib/active_support/file_update_checker.rb index 2ede084e95..fe22b9515b 100644 --- a/activesupport/lib/active_support/file_update_checker.rb +++ b/activesupport/lib/active_support/file_update_checker.rb @@ -1,5 +1,3 @@ -require "active_support/core_ext/array/extract_options" - module ActiveSupport # \FileUpdateChecker specifies the API used by Rails to watch files # and control reloading. The API depends on four methods: @@ -93,10 +91,10 @@ module ActiveSupport def updated_at #:nodoc: @updated_at || begin - all = [] - all.concat @files.select { |f| File.exists?(f) } + all = @files.select { |f| File.exists?(f) } all.concat Dir[@glob] if @glob - all.map { |path| File.mtime(path) }.max || Time.at(0) + all.map! { |path| File.mtime(path) } + all.max || Time.at(0) end end @@ -104,13 +102,16 @@ module ActiveSupport hash.freeze # Freeze so changes aren't accidently pushed return if hash.empty? - globs = [] - hash.each do |key, value| - globs << "#{key}/**/*#{compile_ext(value)}" + globs = hash.map do |key, value| + "#{escape(key)}/**/*#{compile_ext(value)}" end "{#{globs.join(",")}}" end + def escape(key) + key.gsub(',','\,') + end + def compile_ext(array) #:nodoc: array = Array(array) return if array.empty? diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index e4a13870d7..91459f3e5b 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -5,7 +5,7 @@ module ActiveSupport # people can write <tt>params[:key]</tt> instead of <tt>params['key']</tt> # and they get the same value for both keys. class HashWithIndifferentAccess < Hash - + # Always returns true, so that <tt>Array#extract_options!</tt> finds members of this class. def extractable_options? true @@ -42,6 +42,10 @@ module ActiveSupport end end + def self.[](*args) + new.merge(Hash[*args]) + end + alias_method :regular_writer, :[]= unless method_defined?(:regular_writer) alias_method :regular_update, :update unless method_defined?(:regular_update) diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 48ea5653c7..4cebad742f 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -1,3 +1,5 @@ +# encoding: utf-8 + require 'active_support/inflector/inflections' module ActiveSupport @@ -112,7 +114,7 @@ module ActiveSupport # "TheManWithoutAPast".titleize # => "The Man Without A Past" # "raiders_of_the_lost_ark".titleize # => "Raiders Of The Lost Ark" def titleize(word) - humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize } + humanize(underscore(word)).gsub(/\b(['’`]?[a-z])/) { $1.capitalize } end # Create the name of a table like Rails does for models to table names. This method @@ -209,7 +211,7 @@ module ActiveSupport def constantize(camel_cased_word) #:nodoc: names = camel_cased_word.split('::') names.shift if names.empty? || names.first.empty? - + names.inject(Object) do |constant, name| constant.const_get(name, false) end diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb index 58938cdc3d..d2a6e1bd82 100644 --- a/activesupport/lib/active_support/log_subscriber.rb +++ b/activesupport/lib/active_support/log_subscriber.rb @@ -3,7 +3,7 @@ require 'active_support/core_ext/class/attribute' module ActiveSupport # ActiveSupport::LogSubscriber is an object set to consume ActiveSupport::Notifications - # with the sole purpose of logging them. The log subscriber dispatches notifications to + # with the sole purpose of logging them. The log subscriber dispatches notifications to # a registered object based on its given namespace. # # An example would be Active Record log subscriber responsible for logging queries: @@ -75,7 +75,8 @@ module ActiveSupport @@flushable_loggers ||= begin loggers = log_subscribers.map(&:logger) loggers.uniq! - loggers.select { |l| l.respond_to?(:flush) } + loggers.select! { |l| l.respond_to?(:flush) } + loggers end end @@ -101,8 +102,7 @@ module ActiveSupport %w(info debug warn error fatal unknown).each do |level| class_eval <<-METHOD, __FILE__, __LINE__ + 1 def #{level}(progname = nil, &block) - return unless logger - logger.#{level}(progname, &block) + logger.#{level}(progname, &block) if logger end METHOD end diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb index 13f675c654..8cf7bdafda 100644 --- a/activesupport/lib/active_support/notifications.rb +++ b/activesupport/lib/active_support/notifications.rb @@ -1,3 +1,6 @@ +require 'active_support/notifications/instrumenter' +require 'active_support/notifications/fanout' + module ActiveSupport # = Notifications # @@ -105,10 +108,6 @@ module ActiveSupport # to log subscribers in a thread. You can use any queue implementation you want. # module Notifications - autoload :Instrumenter, 'active_support/notifications/instrumenter' - autoload :Event, 'active_support/notifications/instrumenter' - autoload :Fanout, 'active_support/notifications/fanout' - @instrumenters = Hash.new { |h,k| h[k] = notifier.listening?(k) } class << self diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb index a9aa5464e9..17c99089c1 100644 --- a/activesupport/lib/active_support/notifications/fanout.rb +++ b/activesupport/lib/active_support/notifications/fanout.rb @@ -9,18 +9,25 @@ module ActiveSupport end def subscribe(pattern = nil, block = Proc.new) - subscriber = Subscriber.new(pattern, block).tap do |s| - @subscribers << s - end + subscriber = Subscribers.new pattern, block + @subscribers << subscriber @listeners_for.clear subscriber end def unsubscribe(subscriber) - @subscribers.reject! {|s| s.matches?(subscriber)} + @subscribers.reject! { |s| s.matches?(subscriber) } @listeners_for.clear end + def start(name, id, payload) + listeners_for(name).each { |s| s.start(name, id, payload) } + end + + def finish(name, id, payload) + listeners_for(name).each { |s| s.finish(name, id, payload) } + end + def publish(name, *args) listeners_for(name).each { |s| s.publish(name, *args) } end @@ -37,23 +44,89 @@ module ActiveSupport def wait end - class Subscriber #:nodoc: - def initialize(pattern, delegate) - @pattern = pattern - @delegate = delegate + module Subscribers # :nodoc: + def self.new(pattern, listener) + if listener.respond_to?(:call) + subscriber = Timed.new pattern, listener + else + subscriber = Evented.new pattern, listener + end + + unless pattern + AllMessages.new(subscriber) + else + subscriber + end end - def publish(message, *args) - @delegate.call(message, *args) + class Evented #:nodoc: + def initialize(pattern, delegate) + @pattern = pattern + @delegate = delegate + end + + def start(name, id, payload) + @delegate.start name, id, payload + end + + def finish(name, id, payload) + @delegate.finish name, id, payload + end + + def subscribed_to?(name) + @pattern === name.to_s + end + + def matches?(subscriber_or_name) + self === subscriber_or_name || + @pattern && @pattern === subscriber_or_name + end end - def subscribed_to?(name) - !@pattern || @pattern === name.to_s + class Timed < Evented + def initialize(pattern, delegate) + @timestack = Hash.new { |h,id| + h[id] = Hash.new { |ids,name| ids[name] = [] } + } + super + end + + def publish(name, *args) + @delegate.call name, *args + end + + def start(name, id, payload) + @timestack[id][name].push Time.now + end + + def finish(name, id, payload) + started = @timestack[id][name].pop + @delegate.call(name, started, Time.now, id, payload) + end end - def matches?(subscriber_or_name) - self === subscriber_or_name || - @pattern && @pattern === subscriber_or_name + class AllMessages # :nodoc: + def initialize(delegate) + @delegate = delegate + end + + def start(name, id, payload) + @delegate.start name, id, payload + end + + def finish(name, id, payload) + @delegate.finish name, id, payload + end + + def publish(name, *args) + @delegate.publish name, *args + end + + def subscribed_to?(name) + true + end + + alias :matches? :=== end end end diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb index 3941c285a2..58e292c658 100644 --- a/activesupport/lib/active_support/notifications/instrumenter.rb +++ b/activesupport/lib/active_support/notifications/instrumenter.rb @@ -1,7 +1,6 @@ -require 'active_support/core_ext/module/delegation' - module ActiveSupport module Notifications + # Instrumentors are stored in a thread local. class Instrumenter attr_reader :id @@ -14,15 +13,14 @@ module ActiveSupport # and publish it. Notice that events get sent even if an error occurs # in the passed-in block def instrument(name, payload={}) - started = Time.now - + @notifier.start(name, @id, payload) begin yield rescue Exception => e payload[:exception] = [e.class.name, e.message] raise e ensure - @notifier.publish(name, started, Time.now, @id, payload) + @notifier.finish(name, @id, payload) end end diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb index f696716cc8..d1c62c5087 100644 --- a/activesupport/lib/active_support/railtie.rb +++ b/activesupport/lib/active_support/railtie.rb @@ -8,30 +8,6 @@ module ActiveSupport initializer "active_support.deprecation_behavior" do |app| if deprecation = app.config.active_support.deprecation ActiveSupport::Deprecation.behavior = deprecation - else - defaults = {"development" => :log, - "production" => :notify, - "test" => :stderr} - - env = Rails.env - - if defaults.key?(env) - msg = "You did not specify how you would like Rails to report " \ - "deprecation notices for your #{env} environment, please " \ - "set config.active_support.deprecation to :#{defaults[env]} " \ - "at config/environments/#{env}.rb" - - warn msg - ActiveSupport::Deprecation.behavior = defaults[env] - else - msg = "You did not specify how you would like Rails to report " \ - "deprecation notices for your #{env} environment, please " \ - "set config.active_support.deprecation to :log, :notify or " \ - ":stderr at config/environments/#{env}.rb" - - warn msg - ActiveSupport::Deprecation.behavior = :stderr - end end end @@ -42,8 +18,7 @@ module ActiveSupport zone_default = Time.find_zone!(app.config.time_zone) unless zone_default - raise \ - 'Value assigned to config.time_zone not recognized.' + + raise 'Value assigned to config.time_zone not recognized. ' \ 'Run "rake -D time" for a list of tasks for finding appropriate time zone names.' end diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb index 0f4a06468a..85e84bc203 100644 --- a/activesupport/lib/active_support/rescuable.rb +++ b/activesupport/lib/active_support/rescuable.rb @@ -108,7 +108,11 @@ module ActiveSupport when Symbol method(rescuer) when Proc - rescuer.bind(self) + if rescuer.arity == 0 + Proc.new { instance_exec(&rescuer) } + else + Proc.new { |_exception| instance_exec(_exception, &rescuer) } + end end end end diff --git a/activesupport/lib/active_support/tagged_logging.rb b/activesupport/lib/active_support/tagged_logging.rb index f6ad861353..538a36f6d9 100644 --- a/activesupport/lib/active_support/tagged_logging.rb +++ b/activesupport/lib/active_support/tagged_logging.rb @@ -13,7 +13,7 @@ module ActiveSupport # This is used by the default Rails.logger as configured by Railties to make it easy to stamp log lines # with subdomains, request ids, and anything else to aid debugging of multi-user production applications. module TaggedLogging - class Formatter < ActiveSupport::Logger::SimpleFormatter # :nodoc: + module Formatter # :nodoc: # This method is invoked when a log event occurs def call(severity, timestamp, progname, msg) super(severity, timestamp, progname, "#{tags_text}#{msg}") @@ -37,7 +37,7 @@ module ActiveSupport end def self.new(logger) - logger.formatter = Formatter.new + logger.formatter.extend Formatter logger.extend(self) end @@ -45,7 +45,7 @@ module ActiveSupport tags = formatter.current_tags new_tags = new_tags.flatten.reject(&:blank?) tags.concat new_tags - yield + yield self ensure tags.pop(new_tags.size) end diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index bfbb838ea7..ce46c46092 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -168,8 +168,7 @@ module ActiveSupport "Auckland" => "Pacific/Auckland", "Wellington" => "Pacific/Auckland", "Nuku'alofa" => "Pacific/Tongatapu" - }.each { |name, zone| name.freeze; zone.freeze } - MAPPING.freeze + } UTC_OFFSET_WITH_COLON = '%s%02d:%02d' UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.sub(':', '') @@ -267,7 +266,7 @@ module ActiveSupport # Time.zone.parse('22:30:00') # => Fri, 31 Dec 1999 22:30:00 HST -10:00 def parse(str, now=now) date_parts = Date._parse(str) - return if date_parts.blank? + return if date_parts.empty? time = Time.parse(str, now) rescue DateTime.parse(str) if date_parts[:offset].nil? ActiveSupport::TimeWithZone.new(nil, self, time) @@ -282,7 +281,7 @@ module ActiveSupport # Time.zone = 'Hawaii' # => "Hawaii" # Time.zone.now # => Wed, 23 Jan 2008 20:24:27 HST -10:00 def now - Time.now.utc.in_time_zone(self) + time_now.utc.in_time_zone(self) end # Return the current date in this time zone. @@ -391,5 +390,11 @@ module ActiveSupport end end end + + private + + def time_now + Time.now + end end end diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index b03865da93..ba027f1ff0 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -69,6 +69,10 @@ class CacheKeyTest < ActiveSupport::TestCase def test_expand_cache_key_of_true assert_equal 'true', ActiveSupport::Cache.expand_cache_key(true) end + + def test_expand_cache_key_of_array_like_object + assert_equal 'foo/bar/baz', ActiveSupport::Cache.expand_cache_key(%w{foo bar baz}.to_enum) + end end class CacheStoreSettingTest < ActiveSupport::TestCase diff --git a/activesupport/test/core_ext/duplicable_test.rb b/activesupport/test/core_ext/duplicable_test.rb index 3e54266051..1105353e45 100644 --- a/activesupport/test/core_ext/duplicable_test.rb +++ b/activesupport/test/core_ext/duplicable_test.rb @@ -4,17 +4,25 @@ require 'active_support/core_ext/object/duplicable' require 'active_support/core_ext/numeric/time' class DuplicableTest < ActiveSupport::TestCase - RAISE_DUP = [nil, false, true, :symbol, 1, 2.3, BigDecimal.new('4.56'), 5.seconds] + RAISE_DUP = [nil, false, true, :symbol, 1, 2.3, 5.seconds] YES = ['1', Object.new, /foo/, [], {}, Time.now] NO = [Class.new, Module.new] + begin + bd = BigDecimal.new('4.56') + YES << bd.dup + rescue TypeError + RAISE_DUP << bd + end + + def test_duplicable (RAISE_DUP + NO).each do |v| assert !v.duplicable? end YES.each do |v| - assert v.duplicable? + assert v.duplicable?, "#{v.class} should be duplicable" end (YES + NO).each do |v| diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 38cdda6c5c..80b3c16328 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -388,6 +388,15 @@ class HashExtTest < ActiveSupport::TestCase assert_equal expected, hash end + def test_constructor_on_indifferent_access + hash = HashWithIndifferentAccess[:foo, 1] + assert_equal 1, hash[:foo] + assert_equal 1, hash['foo'] + hash[:foo] = 3 + assert_equal 3, hash[:foo] + assert_equal 3, hash['foo'] + end + def test_reverse_merge defaults = { :a => "x", :b => "y", :c => 10 }.freeze options = { :a => 1, :b => 2 } @@ -486,6 +495,13 @@ class HashExtTest < ActiveSupport::TestCase assert_equal 'bender', slice['login'] end + def test_extract + original = {:a => 1, :b => 2, :c => 3, :d => 4} + expected = {:a => 1, :b => 2} + + assert_equal expected, original.extract!(:a, :b) + end + def test_except original = { :a => 'x', :b => 'y', :c => 10 } expected = { :a => 'x', :b => 'y' } diff --git a/activesupport/test/core_ext/proc_test.rb b/activesupport/test/core_ext/proc_test.rb index 690bfd3bf8..c4d5592196 100644 --- a/activesupport/test/core_ext/proc_test.rb +++ b/activesupport/test/core_ext/proc_test.rb @@ -3,10 +3,12 @@ require 'active_support/core_ext/proc' class ProcTests < ActiveSupport::TestCase def test_bind_returns_method_with_changed_self - block = Proc.new { self } - assert_equal self, block.call - bound_block = block.bind("hello") - assert_not_equal block, bound_block - assert_equal "hello", bound_block.call + assert_deprecated do + block = Proc.new { self } + assert_equal self, block.call + bound_block = block.bind("hello") + assert_not_equal block, bound_block + assert_equal "hello", bound_block.call + end end end diff --git a/activesupport/test/file_update_checker_test.rb b/activesupport/test/file_update_checker_test.rb index dd2483287b..066db7c0f9 100644 --- a/activesupport/test/file_update_checker_test.rb +++ b/activesupport/test/file_update_checker_test.rb @@ -1,5 +1,6 @@ require 'abstract_unit' require 'fileutils' +require 'thread' MTIME_FIXTURES_PATH = File.expand_path("../fixtures", __FILE__) @@ -79,4 +80,18 @@ class FileUpdateCheckerWithEnumerableTest < ActiveSupport::TestCase assert !checker.execute_if_updated assert_equal 0, i end + + def test_should_not_block_if_a_strange_filename_used + FileUtils.mkdir_p("tmp_watcher/valid,yetstrange,path,") + FileUtils.touch(FILES.map { |file_name| "tmp_watcher/valid,yetstrange,path,/#{file_name}" }) + + test = Thread.new do + ActiveSupport::FileUpdateChecker.new([],"tmp_watcher/valid,yetstrange,path," => :txt) { i += 1 } + Thread.exit + end + test.priority = -1 + test.join(5) + + assert !test.alive? + end end diff --git a/activesupport/test/inflector_test_cases.rb b/activesupport/test/inflector_test_cases.rb index 809b8b46c9..879c3c1125 100644 --- a/activesupport/test/inflector_test_cases.rb +++ b/activesupport/test/inflector_test_cases.rb @@ -220,7 +220,9 @@ module InflectorTestCases 'Actionwebservice' => 'Actionwebservice', "david's code" => "David's Code", "David's code" => "David's Code", - "david's Code" => "David's Code" + "david's Code" => "David's Code", + "Fred’s" => "Fred’s", + "Fred`s" => "Fred`s" } OrdinalNumbers = { diff --git a/activesupport/test/notifications/evented_notification_test.rb b/activesupport/test/notifications/evented_notification_test.rb new file mode 100644 index 0000000000..f77a0eb3fa --- /dev/null +++ b/activesupport/test/notifications/evented_notification_test.rb @@ -0,0 +1,67 @@ +require 'abstract_unit' + +module ActiveSupport + module Notifications + class EventedTest < ActiveSupport::TestCase + class Listener + attr_reader :events + + def initialize + @events = [] + end + + def start(name, id, payload) + @events << [:start, name, id, payload] + end + + def finish(name, id, payload) + @events << [:finish, name, id, payload] + end + end + + def test_evented_listener + notifier = Fanout.new + listener = Listener.new + notifier.subscribe 'hi', listener + notifier.start 'hi', 1, {} + notifier.start 'hi', 2, {} + notifier.finish 'hi', 2, {} + notifier.finish 'hi', 1, {} + + assert_equal 4, listener.events.length + assert_equal [ + [:start, 'hi', 1, {}], + [:start, 'hi', 2, {}], + [:finish, 'hi', 2, {}], + [:finish, 'hi', 1, {}], + ], listener.events + end + + def test_evented_listener_no_events + notifier = Fanout.new + listener = Listener.new + notifier.subscribe 'hi', listener + notifier.start 'world', 1, {} + assert_equal 0, listener.events.length + end + + def test_listen_to_everything + notifier = Fanout.new + listener = Listener.new + notifier.subscribe nil, listener + notifier.start 'hello', 1, {} + notifier.start 'world', 1, {} + notifier.finish 'world', 1, {} + notifier.finish 'hello', 1, {} + + assert_equal 4, listener.events.length + assert_equal [ + [:start, 'hello', 1, {}], + [:start, 'world', 1, {}], + [:finish, 'world', 1, {}], + [:finish, 'hello', 1, {}], + ], listener.events + end + end + end +end diff --git a/activesupport/test/ordered_options_test.rb b/activesupport/test/ordered_options_test.rb index 0eee991e20..3526c7a366 100644 --- a/activesupport/test/ordered_options_test.rb +++ b/activesupport/test/ordered_options_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'active_support/ordered_options' class OrderedOptionsTest < ActiveSupport::TestCase def test_usage diff --git a/activesupport/test/tagged_logging_test.rb b/activesupport/test/tagged_logging_test.rb index dd4ae319e5..0751c2469e 100644 --- a/activesupport/test/tagged_logging_test.rb +++ b/activesupport/test/tagged_logging_test.rb @@ -18,7 +18,7 @@ class TaggedLoggingTest < ActiveSupport::TestCase @logger.tagged("BCX") { @logger.info "Funky time" } assert_equal "[BCX] Funky time\n", @output.string end - + test "tagged twice" do @logger.tagged("BCX") { @logger.tagged("Jason") { @logger.info "Funky time" } } assert_equal "[BCX] [Jason] Funky time\n", @output.string @@ -29,6 +29,11 @@ class TaggedLoggingTest < ActiveSupport::TestCase assert_equal "[BCX] [Jason] [New] Funky time\n", @output.string end + test "provides access to the logger instance" do + @logger.tagged("BCX") { |logger| logger.info "Funky time" } + assert_equal "[BCX] Funky time\n", @output.string + end + test "tagged once with blank and nil" do @logger.tagged(nil, "", "New") { @logger.info "Funky time" } assert_equal "[New] Funky time\n", @output.string diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index e26256f9c6..d14d01dc30 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -48,8 +48,8 @@ class TimeZoneTest < ActiveSupport::TestCase def test_now with_env_tz 'US/Eastern' do - Time.stubs(:now).returns(Time.local(2000)) - zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'].dup + def zone.time_now; Time.local(2000); end assert_instance_of ActiveSupport::TimeWithZone, zone.now assert_equal Time.utc(2000,1,1,5), zone.now.utc assert_equal Time.utc(2000), zone.now.time @@ -59,8 +59,11 @@ class TimeZoneTest < ActiveSupport::TestCase def test_now_enforces_spring_dst_rules with_env_tz 'US/Eastern' do - Time.stubs(:now).returns(Time.local(2006,4,2,2)) # 2AM springs forward to 3AM - zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'].dup + def zone.time_now + Time.local(2006,4,2,2) # 2AM springs forward to 3AM + end + assert_equal Time.utc(2006,4,2,3), zone.now.time assert_equal true, zone.now.dst? end @@ -68,8 +71,10 @@ class TimeZoneTest < ActiveSupport::TestCase def test_now_enforces_fall_dst_rules with_env_tz 'US/Eastern' do - Time.stubs(:now).returns(Time.at(1162098000)) # equivalent to 1AM DST - zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'].dup + def zone.time_now + Time.at(1162098000) # equivalent to 1AM DST + end assert_equal Time.utc(2006,10,29,1), zone.now.time assert_equal true, zone.now.dst? end |