aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG4
-rw-r--r--activesupport/README43
-rw-r--r--activesupport/README.rdoc33
-rw-r--r--activesupport/Rakefile18
-rw-r--r--activesupport/activesupport.gemspec2
-rw-r--r--activesupport/install.rb30
-rw-r--r--activesupport/lib/active_support/buffered_logger.rb6
-rw-r--r--activesupport/lib/active_support/cache.rb102
-rw-r--r--activesupport/lib/active_support/cache/mem_cache_store.rb7
-rw-r--r--activesupport/lib/active_support/cache/memory_store.rb10
-rw-r--r--activesupport/lib/active_support/cache/strategy/local_cache.rb10
-rw-r--r--activesupport/lib/active_support/callbacks.rb18
-rw-r--r--activesupport/lib/active_support/concern.rb35
-rw-r--r--activesupport/lib/active_support/core_ext/array/conversions.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/array/uniq_by.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/array/wrap.rb34
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb30
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute_accessors.rb16
-rw-r--r--activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb28
-rw-r--r--activesupport/lib/active_support/core_ext/date/calculations.rb26
-rw-r--r--activesupport/lib/active_support/core_ext/enumerable.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/hash/conversions.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/requires.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/module/attribute_accessors.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/module/remove_method.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/object.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/object/misc.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/object/returning.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/object/to_param.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/inflections.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/multibyte.rb10
-rw-r--r--activesupport/lib/active_support/dependencies.rb19
-rw-r--r--activesupport/lib/active_support/deprecation/proxy_wrappers.rb7
-rw-r--r--activesupport/lib/active_support/descendants_tracker.rb8
-rw-r--r--activesupport/lib/active_support/duration.rb4
-rw-r--r--activesupport/lib/active_support/hash_with_indifferent_access.rb1
-rw-r--r--activesupport/lib/active_support/inflector/methods.rb12
-rw-r--r--activesupport/lib/active_support/json/backends/yaml.rb2
-rw-r--r--activesupport/lib/active_support/lazy_load_hooks.rb21
-rw-r--r--activesupport/lib/active_support/log_subscriber.rb25
-rw-r--r--activesupport/lib/active_support/log_subscriber/test_helper.rb23
-rw-r--r--activesupport/lib/active_support/message_verifier.rb8
-rw-r--r--activesupport/lib/active_support/multibyte/chars.rb73
-rw-r--r--activesupport/lib/active_support/multibyte/unicode.rb19
-rw-r--r--activesupport/lib/active_support/notifications.rb48
-rw-r--r--activesupport/lib/active_support/notifications/fanout.rb74
-rw-r--r--activesupport/lib/active_support/notifications/instrumenter.rb16
-rw-r--r--activesupport/lib/active_support/ordered_hash.rb11
-rw-r--r--activesupport/lib/active_support/ordered_options.rb16
-rw-r--r--activesupport/lib/active_support/secure_random.rb26
-rw-r--r--activesupport/lib/active_support/testing/setup_and_teardown.rb2
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb13
-rw-r--r--activesupport/lib/active_support/values/time_zone.rb6
-rw-r--r--activesupport/lib/active_support/version.rb2
-rw-r--r--activesupport/lib/active_support/xml_mini.rb8
-rw-r--r--activesupport/lib/active_support/xml_mini/libxml.rb1
-rw-r--r--activesupport/lib/active_support/xml_mini/nokogiri.rb7
-rw-r--r--activesupport/lib/active_support/xml_mini/nokogirisax.rb9
-rw-r--r--activesupport/test/autoloading_fixtures/load_path/loaded_constant.rb3
-rw-r--r--activesupport/test/autoloading_fixtures/loads_constant.rb5
-rw-r--r--activesupport/test/autoloading_fixtures/requires_constant.rb5
-rw-r--r--activesupport/test/buffered_logger_test.rb15
-rw-r--r--activesupport/test/caching_test.rb45
-rw-r--r--activesupport/test/core_ext/array_ext_test.rb20
-rw-r--r--activesupport/test/core_ext/class_test.rb9
-rw-r--r--activesupport/test/core_ext/date_time_ext_test.rb31
-rw-r--r--activesupport/test/core_ext/hash_ext_test.rb29
-rw-r--r--activesupport/test/core_ext/module_test.rb2
-rw-r--r--activesupport/test/core_ext/object/to_query_test.rb5
-rw-r--r--activesupport/test/dependencies_test.rb54
-rw-r--r--activesupport/test/deprecation/proxy_wrappers_test.rb22
-rw-r--r--activesupport/test/json/encoding_test.rb2
-rw-r--r--activesupport/test/load_paths_test.rb4
-rw-r--r--activesupport/test/memoizable_test.rb1
-rw-r--r--activesupport/test/multibyte_chars_test.rb2
-rw-r--r--activesupport/test/multibyte_test_helpers.rb5
-rw-r--r--activesupport/test/notifications_test.rb27
-rw-r--r--activesupport/test/option_merger_test.rb2
-rw-r--r--activesupport/test/ordered_hash_test.rb2
-rw-r--r--activesupport/test/rescuable_test.rb37
-rw-r--r--activesupport/test/test_test.rb2
-rw-r--r--activesupport/test/test_xml_mini.rb49
82 files changed, 884 insertions, 467 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 60586cf99a..8485e7d46b 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,4 +1,6 @@
-*Rails 3.0.0 [Release Candidate] (unreleased)*
+*Rails 3.0.0 [release candidate] (July 26th, 2010)*
+
+* Removed Object#returning, Object#tap should be used instead. [Santiago Pastorino]
* Deprecation behavior is no longer hardcoded to the name of the environment.
Instead, it is set via config.active_support.deprecation and can be one
diff --git a/activesupport/README b/activesupport/README
deleted file mode 100644
index 9fb9a80cbe..0000000000
--- a/activesupport/README
+++ /dev/null
@@ -1,43 +0,0 @@
-= Active Support -- Utility classes and standard library extensions from Rails
-
-Active Support is a collection of various utility classes and standard library extensions that were found useful
-for Rails. All these additions have hence been collected in this bundle as way to gather all that sugar that makes
-Ruby sweeter.
-
-
-== Download
-
-The latest version of Active Support can be found at
-
-* http://rubyforge.org/project/showfiles.php?group_id=182
-
-Documentation can be found at
-
-* http://as.rubyonrails.com
-
-
-== Installation
-
-The preferred method of installing Active Support is through its GEM file. You'll need to have
-RubyGems[http://rubygems.rubyforge.org/wiki/wiki.pl] installed for that, though. If you have it,
-then use:
-
- % [sudo] gem install activesupport-1.0.0.gem
-
-
-== License
-
-Active Support is released under the MIT license.
-
-
-== Support
-
-The Active Support homepage is http://www.rubyonrails.com. You can find the Active Support
-RubyForge page at http://rubyforge.org/projects/activesupport. And as Jim from Rake says:
-
- Feel free to submit commits or feature requests. If you send a patch,
- remember to update the corresponding unit tests. If fact, I prefer
- new feature to be submitted in the form of new unit tests.
-
-For other information, feel free to ask on the ruby-talk mailing list
-(which is mirrored to comp.lang.ruby) or contact mailto:david@loudthinking.com.
diff --git a/activesupport/README.rdoc b/activesupport/README.rdoc
new file mode 100644
index 0000000000..77b8a64304
--- /dev/null
+++ b/activesupport/README.rdoc
@@ -0,0 +1,33 @@
+= Active Support -- Utility classes and Ruby extensions from Rails
+
+Active Support is a collection of utility classes and standard library
+extensions that were found useful for the Rails framework. These additions
+reside in this package so they can be loaded as needed in Ruby projects
+outside of Rails.
+
+
+== Download and installation
+
+The latest version of Active Support can be installed with Rubygems:
+
+ % [sudo] gem install activesupport
+
+Source code can be downloaded as part of the Rails project on GitHub
+
+* http://github.com/rails/rails/tree/master/activesupport/
+
+
+== License
+
+Active Support is released under the MIT license.
+
+
+== Support
+
+API documentation is at
+
+* http://api.rubyonrails.com
+
+Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
+
+* https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets
diff --git a/activesupport/Rakefile b/activesupport/Rakefile
index 2aebe05de2..8e2683ef89 100644
--- a/activesupport/Rakefile
+++ b/activesupport/Rakefile
@@ -1,7 +1,7 @@
-gem 'rdoc', '= 2.2'
+gem 'rdoc', '>= 2.5.9'
require 'rdoc'
require 'rake/testtask'
-require 'rake/rdoctask'
+require 'rdoc/task'
require 'rake/gempackagetask'
task :default => :test
@@ -22,13 +22,13 @@ dist_dirs = [ "lib", "test"]
# Genereate the RDoc documentation
-Rake::RDocTask.new { |rdoc|
+RDoc::Task.new { |rdoc|
rdoc.rdoc_dir = 'doc'
rdoc.title = "Active Support -- Utility classes and standard library extensions from Rails"
- rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.options << '-f' << 'horo'
+ rdoc.options << '--main' << 'README.rdoc'
rdoc.options << '--charset' << 'utf-8'
- rdoc.template = ENV['template'] ? "#{ENV['template']}.rb" : '../doc/template/horo'
- rdoc.rdoc_files.include('README', 'CHANGELOG')
+ rdoc.rdoc_files.include('README.rdoc', 'CHANGELOG')
rdoc.rdoc_files.include('lib/active_support.rb')
rdoc.rdoc_files.include('lib/active_support/**/*.rb')
}
@@ -45,9 +45,3 @@ task :release => :package do
Rake::Gemcutter::Tasks.new(spec).define
Rake::Task['gem:push'].invoke
end
-
-desc "Publish the API documentation"
-task :pdoc => [:rdoc] do
- require 'rake/contrib/sshpublisher'
- Rake::SshDirPublisher.new("rails@api.rubyonrails.org", "public_html/as", "doc").upload
-end
diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec
index 8611a1e5fa..df7f68fecf 100644
--- a/activesupport/activesupport.gemspec
+++ b/activesupport/activesupport.gemspec
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
s.homepage = 'http://www.rubyonrails.org'
s.rubyforge_project = 'activesupport'
- s.files = Dir['CHANGELOG', 'README', 'lib/**/*']
+ s.files = Dir['CHANGELOG', 'README.rdoc', 'lib/**/*']
s.require_path = 'lib'
s.has_rdoc = true
diff --git a/activesupport/install.rb b/activesupport/install.rb
deleted file mode 100644
index 9c54d8c1a9..0000000000
--- a/activesupport/install.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require 'rbconfig'
-require 'find'
-require 'ftools'
-
-include Config
-
-# this was adapted from rdoc's install.rb by ways of Log4r
-
-$sitedir = CONFIG["sitelibdir"]
-unless $sitedir
- version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"]
- $libdir = File.join(CONFIG["libdir"], "ruby", version)
- $sitedir = $:.find {|x| x =~ /site_ruby/ }
- if !$sitedir
- $sitedir = File.join($libdir, "site_ruby")
- elsif $sitedir !~ Regexp.quote(version)
- $sitedir = File.join($sitedir, version)
- end
-end
-
-# the actual gruntwork
-Dir.chdir("lib")
-
-Find.find("active_support", "active_support.rb") { |f|
- if f[-3..-1] == ".rb"
- File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true)
- else
- File::makedirs(File.join($sitedir, *f.split(/\//)))
- end
-}
diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb
index 29c3843d16..b861a6f62a 100644
--- a/activesupport/lib/active_support/buffered_logger.rb
+++ b/activesupport/lib/active_support/buffered_logger.rb
@@ -101,7 +101,11 @@ module ActiveSupport
@guard.synchronize do
unless buffer.empty?
old_buffer = buffer
- @log.write(old_buffer.join)
+ all_content = StringIO.new
+ old_buffer.each do |content|
+ all_content << content
+ end
+ @log.write(all_content.string)
end
# Important to do this even if buffer was empty or else @buffer will
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index bef9c98ecf..30195bdea5 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -19,8 +19,6 @@ module ActiveSupport
autoload :SynchronizedMemoryStore, 'active_support/cache/synchronized_memory_store'
autoload :CompressedMemCacheStore, 'active_support/cache/compressed_mem_cache_store'
- EMPTY_OPTIONS = {}.freeze
-
# These options mean something to all cache implementations. Individual cache
# implementations may support additional options.
UNIVERSAL_OPTIONS = [:namespace, :compress, :compress_threshold, :expires_in, :race_condition_ttl]
@@ -129,13 +127,6 @@ module ActiveSupport
# cache.namespace = lambda { @last_mod_time } # Set the namespace to a variable
# @last_mod_time = Time.now # Invalidate the entire cache by changing namespace
#
- # All caches support auto expiring content after a specified number of seconds.
- # To set the cache entry time to live, you can either specify +:expires_in+ as
- # an option to the constructor to have it affect all entries or to the +fetch+
- # or +write+ methods for just one entry.
- #
- # cache = ActiveSupport::Cache::MemoryStore.new(:expire_in => 5.minutes)
- # cache.write(key, value, :expire_in => 1.minute) # Set a lower value for one entry
#
# Caches can also store values in a compressed format to save space and reduce
# time spent sending data. Since there is some overhead, values must be large
@@ -147,7 +138,7 @@ module ActiveSupport
cattr_accessor :logger, :instance_writer => true
- attr_reader :silence
+ attr_reader :silence, :options
alias :silence? :silence
# Create a new cache. The options will be passed to any write method calls except
@@ -156,11 +147,6 @@ module ActiveSupport
@options = options ? options.dup : {}
end
- # Get the default options set when the cache was created.
- def options
- @options ||= {}
- end
-
# Silence the logger.
def silence!
@silence = true
@@ -175,7 +161,7 @@ module ActiveSupport
@silence = previous_silence
end
- # Set to true if cache stores should be instrumented. By default is false.
+ # Set to true if cache stores should be instrumented. Default is false.
def self.instrument=(boolean)
Thread.current[:instrument_cache_store] = boolean
end
@@ -187,7 +173,7 @@ module ActiveSupport
# Fetches data from the cache, using the given key. If there is data in
# the cache with the given key, then that data is returned.
#
- # If there is no such data in the cache (a cache miss occurred), then
+ # If there is no such data in the cache (a cache miss occurred),
# then nil will be returned. However, if a block has been passed, then
# that block will be run in the event of a cache miss. The return value
# of the block will be written to the cache under the given cache key,
@@ -211,23 +197,30 @@ module ActiveSupport
# Setting <tt>:compress</tt> will store a large cache entry set by the call
# in a compressed format.
#
- # Setting <tt>:expires_in</tt> will set an expiration time on the cache
- # entry if it is set by call.
#
- # Setting <tt>:race_condition_ttl</tt> will invoke logic on entries set with
- # an <tt>:expires_in</tt> option. If an entry is found in the cache that is
- # expired and it has been expired for less than the number of seconds specified
- # by this option and a block was passed to the method call, then the expiration
- # future time of the entry in the cache will be updated to that many seconds
- # in the and the block will be evaluated and written to the cache.
+ # Setting <tt>:expires_in</tt> will set an expiration time on the cache. All caches
+ # support auto expiring content after a specified number of seconds. This value can
+ # be specified as an option to the construction in which call all entries will be
+ # affected. Or it can be supplied to the +fetch+ or +write+ method for just one entry.
#
- # This is very useful in situations where a cache entry is used very frequently
- # under heavy load. The first process to find an expired cache entry will then
- # become responsible for regenerating that entry while other processes continue
- # to use the slightly out of date entry. This can prevent race conditions where
- # too many processes are trying to regenerate the entry all at once. If the
- # process regenerating the entry errors out, the entry will be regenerated
- # after the specified number of seconds.
+ # cache = ActiveSupport::Cache::MemoryStore.new(:expire_in => 5.minutes)
+ # cache.write(key, value, :expire_in => 1.minute) # Set a lower value for one entry
+ #
+ # Setting <tt>:race_condition_ttl</tt> is very useful in situations where a cache entry
+ # is used very frequently unver heavy load. If a cache expires and due to heavy load
+ # seven different processes will try to read data natively and then they all will try to
+ # write to cache. To avoid that case the first process to find an expired cache entry will
+ # bump the cache expiration time by the value set in <tt>:race_condition_ttl</tt>. Yes
+ # this process is extending the time for a stale value by another few seconds. Because
+ # of extended life of the previous cache, other processes will continue to use slightly
+ # stale data for a just a big longer. In the meantime that first process will go ahead
+ # and will write into cache the new value. After that all the processes will start
+ # getting new value. The key is to keep <tt>:race_condition_ttl</tt> small.
+ #
+ # If the process regenerating the entry errors out, the entry will be regenerated
+ # after the specified number of seconds. Also note that the life of stale cache is
+ # extended only if it expired recently. Otherwise a new value is generated and
+ # <tt>:race_condition_ttl</tt> does not play any role.
#
# # Set all values to expire after one minute.
# cache = ActiveSupport::Cache::MemoryCache.new(:expires_in => 1.minute)
@@ -252,6 +245,7 @@ module ActiveSupport
#
# # val_1 => "new value 1"
# # val_2 => "original value"
+ # # sleep 10 # First thread extend the life of cache by another 10 seconds
# # cache.fetch("foo") => "new value 1"
#
# Other options will be handled by the specific cache store implementation.
@@ -353,11 +347,9 @@ module ActiveSupport
results
end
- # Writes the given value to the cache, with the given key.
+ # Writes the value to the cache, with the key.
#
- # You may also specify additional options via the +options+ argument.
- # The specific cache store implementation will decide what to do with
- # +options+.
+ # Options are passed to the underlying cache implementation.
def write(name, value, options = nil)
options = merged_options(options)
instrument(:write, name, options) do |payload|
@@ -366,7 +358,7 @@ module ActiveSupport
end
end
- # Delete an entry in the cache. Returns +true+ if there was an entry to delete.
+ # Deletes an entry in the cache. Returns +true+ if an entry is deleted.
#
# Options are passed to the underlying cache implementation.
def delete(name, options = nil)
@@ -376,7 +368,7 @@ module ActiveSupport
end
end
- # Return true if the cache contains an entry with this name.
+ # Return true if the cache contains an entry for the given key.
#
# Options are passed to the underlying cache implementation.
def exist?(name, options = nil)
@@ -391,11 +383,11 @@ module ActiveSupport
end
end
- # Delete all entries whose keys match a pattern.
+ # Delete all entries with keys matching the pattern.
#
# Options are passed to the underlying cache implementation.
#
- # Not all implementations may support +delete_matched+.
+ # All implementations may not support this method.
def delete_matched(matcher, options = nil)
raise NotImplementedError.new("#{self.class.name} does not support delete_matched")
end
@@ -404,7 +396,7 @@ module ActiveSupport
#
# Options are passed to the underlying cache implementation.
#
- # Not all implementations may support +delete_matched+.
+ # All implementations may not support this method.
def increment(name, amount = 1, options = nil)
raise NotImplementedError.new("#{self.class.name} does not support increment")
end
@@ -413,28 +405,26 @@ module ActiveSupport
#
# Options are passed to the underlying cache implementation.
#
- # Not all implementations may support +delete_matched+.
+ # All implementations may not support this method.
def decrement(name, amount = 1, options = nil)
raise NotImplementedError.new("#{self.class.name} does not support decrement")
end
- # Cleanup the cache by removing expired entries. Not all cache implementations may
- # support this method.
+ # Cleanup the cache by removing expired entries.
#
# Options are passed to the underlying cache implementation.
#
- # Not all implementations may support +delete_matched+.
+ # All implementations may not support this method.
def cleanup(options = nil)
raise NotImplementedError.new("#{self.class.name} does not support cleanup")
end
- # Clear the entire cache. Not all cache implementations may support this method.
- # You should be careful with this method since it could affect other processes
- # if you are using a shared cache.
+ # Clear the entire cache. Be careful with this method since it could
+ # affect other processes if shared cache is being used.
#
# Options are passed to the underlying cache implementation.
#
- # Not all implementations may support +delete_matched+.
+ # All implementations may not support this method.
def clear(options = nil)
raise NotImplementedError.new("#{self.class.name} does not support clear")
end
@@ -483,9 +473,9 @@ module ActiveSupport
end
end
- # Expand a key to be a consistent string value. If the object responds to +cache_key+,
- # it will be called. Otherwise, the to_param method will be called. If the key is a
- # Hash, the keys will be sorted alphabetically.
+ # Expand key to be a consistent string value. Invoke +cache_key+ if
+ # object responds to +cache_key+. Otherwise, to_param method will be
+ # called. If the key is a Hash, then keys will be sorted alphabetically.
def expanded_key(key) # :nodoc:
if key.respond_to?(:cache_key)
key = key.cache_key.to_s
@@ -502,7 +492,7 @@ module ActiveSupport
end
end
- # Prefix a key with the namespace. The two values will be delimited with a colon.
+ # Prefix a key with the namespace. Namespace and key will be delimited with a colon.
def namespaced_key(key, options)
key = expanded_key(key)
namespace = options[:namespace] if options
@@ -599,7 +589,7 @@ module ActiveSupport
end
end
- # Set a new time to live on the entry so it expires at the given time.
+ # Set a new time when the entry will expire.
def expires_at=(time)
if time
@expires_in = time.to_f - @created_at
@@ -608,12 +598,12 @@ module ActiveSupport
end
end
- # Seconds since the epoch when the cache entry will expire.
+ # Seconds since the epoch when the entry will expire.
def expires_at
@expires_in ? @created_at + @expires_in : nil
end
- # Get the size of the cached value. This could be less than value.size
+ # Returns the size of the cached value. This could be less than value.size
# if the data is compressed.
def size
if @value.nil?
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index 852defeae8..f32b562368 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -16,8 +16,7 @@ module ActiveSupport
# Special features:
# - Clustering and load balancing. One can specify multiple memcached servers,
# and MemCacheStore will load balance between all available servers. If a
- # server goes down, then MemCacheStore will ignore it until it goes back
- # online.
+ # server goes down, then MemCacheStore will ignore it until it comes back up.
#
# MemCacheStore implements the Strategy::LocalCache strategy which implements
# an in memory cache inside of a block.
@@ -69,7 +68,7 @@ module ActiveSupport
extend LocalCacheWithRaw
end
- # Reads multiple keys from the cache using a single call to the
+ # Reads multiple values from the cache using a single call to the
# servers for all keys. Options can be passed in the last argument.
def read_multi(*names)
options = names.extract_options!
@@ -113,7 +112,7 @@ module ActiveSupport
end
# Clear the entire cache on all memcached servers. This method should
- # be used with care when using a shared cache.
+ # be used with care when shared cache is being used.
def clear(options = nil)
@data.flush_all
end
diff --git a/activesupport/lib/active_support/cache/memory_store.rb b/activesupport/lib/active_support/cache/memory_store.rb
index f5c2b8af8b..b15bb42c88 100644
--- a/activesupport/lib/active_support/cache/memory_store.rb
+++ b/activesupport/lib/active_support/cache/memory_store.rb
@@ -5,9 +5,9 @@ module ActiveSupport
# A cache store implementation which stores everything into memory in the
# same process. If you're running multiple Ruby on Rails server processes
# (which is the case if you're using mongrel_cluster or Phusion Passenger),
- # then this means that your Rails server process instances won't be able
+ # then this means that Rails server process instances won't be able
# to share cache data with each other and this may not be the most
- # appropriate cache for you.
+ # appropriate cache in that scenario.
#
# This cache has a bounded size specified by the :size options to the
# initializer (default is 32Mb). When the cache exceeds the allotted size,
@@ -47,8 +47,8 @@ module ActiveSupport
end
end
- # Prune the cache down so the entries fit within the specified memory size by removing
- # the least recently accessed entries.
+ # To ensure entries fit within the specified memory prune the cache by removing the least
+ # recently accessed entries.
def prune(target_size, max_time = nil)
return if pruning?
@pruning = true
@@ -67,7 +67,7 @@ module ActiveSupport
end
end
- # Return true if the cache is currently be pruned to remove older entries.
+ # Returns true if the cache is currently being pruned.
def pruning?
@pruning
end
diff --git a/activesupport/lib/active_support/cache/strategy/local_cache.rb b/activesupport/lib/active_support/cache/strategy/local_cache.rb
index efb5ad26ab..3edba52fc4 100644
--- a/activesupport/lib/active_support/cache/strategy/local_cache.rb
+++ b/activesupport/lib/active_support/cache/strategy/local_cache.rb
@@ -8,7 +8,7 @@ module ActiveSupport
# duration of a block. Repeated calls to the cache for the same key will hit the
# in memory cache for faster access.
module LocalCache
- # Simple memory backed cache. This cache is not thread safe but is intended only
+ # Simple memory backed cache. This cache is not thread safe and is intended only
# for serving as a temporary memory cache for a single thread.
class LocalStore < Store
def initialize
@@ -16,7 +16,7 @@ module ActiveSupport
@data = {}
end
- # Since it isn't thread safe, don't allow synchronizing.
+ # Don't allow synchronizing since it isn't thread safe,
def synchronize # :nodoc:
yield
end
@@ -39,7 +39,7 @@ module ActiveSupport
end
end
- # Use a local cache to front for the cache for the duration of a block.
+ # Use a local cache for the duration of block.
def with_local_cache
save_val = Thread.current[thread_local_key]
begin
@@ -50,8 +50,8 @@ module ActiveSupport
end
end
- # Middleware class can be inserted as a Rack handler to use a local cache for the
- # duration of a request.
+ # Middleware class can be inserted as a Rack handler to be local cache for the
+ # duration of request.
def middleware
@middleware ||= begin
klass = Class.new
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 1c7802f7de..24e407c253 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -419,7 +419,10 @@ module ActiveSupport
@_keyed_callbacks ||= {}
@_keyed_callbacks[name] ||= begin
str = send("_#{kind}_callbacks").compile(name, object)
- class_eval "def #{name}() #{str} end", __FILE__, __LINE__
+ class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
+ def #{name}() #{str} end
+ protected :#{name}
+ RUBY_EVAL
true
end
end
@@ -483,7 +486,11 @@ module ActiveSupport
end
end
- # Skip a previously defined callback for a given type.
+ # Skip a previously defined callback.
+ #
+ # class Writer < Person
+ # skip_callback :validate, :before, :check_membership, :if => lambda { self.age > 18 }
+ # end
#
def skip_callback(name, *filter_list, &block)
__update_callbacks(name, filter_list, block) do |chain, type, filters, options|
@@ -523,7 +530,8 @@ module ActiveSupport
# This macro accepts the following options:
#
# * <tt>:terminator</tt> - Indicates when a before filter is considered
- # to be halted.
+ # to halted. This is a string to be eval'ed and has the result of the
+ # very filter available in the <tt>result</tt> variable:
#
# define_callbacks :validate, :terminator => "result == false"
#
@@ -568,7 +576,9 @@ module ActiveSupport
#
# would trigger <tt>Audit#before_save</tt> instead. That's constructed by calling
# <tt>"#{kind}_#{name}"</tt> on the given instance. In this case "kind" is "before" and
- # "name" is "save".
+ # "name" is "save". In this context ":kind" and ":name" have special meanings: ":kind"
+ # refers to the kind of callback (before/after/around) and ":name" refers to the
+ # method on which callbacks are being defined.
#
# A declaration like
#
diff --git a/activesupport/lib/active_support/concern.rb b/activesupport/lib/active_support/concern.rb
index eb31f7cad4..2d87e8d0e5 100644
--- a/activesupport/lib/active_support/concern.rb
+++ b/activesupport/lib/active_support/concern.rb
@@ -1,3 +1,38 @@
+# A typical module looks like this
+#
+# module M
+# def self.included(base)
+# base.send(:extend, ClassMethods)
+# base.send(:include, InstanceMethods)
+# scope :foo, :conditions => { :created_at => nil }
+# end
+#
+# module ClassMethods
+# def cm; puts 'I am a class method'; end
+# end
+#
+# module InstanceMethods
+# def im; puts 'I am an instance method'; end
+# end
+# end
+#
+# By using <tt>ActiveSupport::Concern</tt> the above module could instead be written as:
+#
+# module M
+# extend ActiveSupport::Concern
+#
+# included do
+# scope :foo, :conditions => { :created_at => nil }
+# end
+#
+# module ClassMethods
+# def cm; puts 'I am a class method'; end
+# end
+#
+# module InstanceMethods
+# def im; puts 'I am an instance method'; end
+# end
+# end
module ActiveSupport
module Concern
def self.extended(base)
diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb
index 79e3828817..7585137aca 100644
--- a/activesupport/lib/active_support/core_ext/array/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/array/conversions.rb
@@ -58,12 +58,12 @@ class Array
alias_method :to_default_s, :to_s
alias_method :to_s, :to_formatted_s
- # Returns a string that represents this array in XML by sending +to_xml+
- # to each element. Active Record collections delegate their representation
+ # Returns a string that represents the array in XML by invoking +to_xml+
+ # on each element. Active Record collections delegate their representation
# in XML to this method.
#
# All elements are expected to respond to +to_xml+, if any of them does
- # not an exception is raised.
+ # not then an exception is raised.
#
# The root node reflects the class name of the first element in plural
# if all elements belong to the same type and that's not Hash:
@@ -115,8 +115,8 @@ class Array
# <?xml version="1.0" encoding="UTF-8"?>
# <projects type="array"/>
#
- # By default root children have as node name the one of the root
- # singularized. You can change it with the <tt>:children</tt> option.
+ # By default name of the node for the children of root is <tt>root.singularize</tt>.
+ # You can change it with the <tt>:children</tt> option.
#
# The +options+ hash is passed downwards:
#
diff --git a/activesupport/lib/active_support/core_ext/array/uniq_by.rb b/activesupport/lib/active_support/core_ext/array/uniq_by.rb
index a09b2302fd..bd5c7a187f 100644
--- a/activesupport/lib/active_support/core_ext/array/uniq_by.rb
+++ b/activesupport/lib/active_support/core_ext/array/uniq_by.rb
@@ -2,7 +2,7 @@ class Array
# Return an unique array based on the criteria given as a proc.
#
# [1, 2, 3, 4].uniq_by { |i| i.odd? }
- # #=> [1, 2]
+ # # => [1, 2]
#
def uniq_by
hash, array = {}, []
diff --git a/activesupport/lib/active_support/core_ext/array/wrap.rb b/activesupport/lib/active_support/core_ext/array/wrap.rb
index e211bdeeca..06b2acd662 100644
--- a/activesupport/lib/active_support/core_ext/array/wrap.rb
+++ b/activesupport/lib/active_support/core_ext/array/wrap.rb
@@ -1,15 +1,41 @@
class Array
- # Wraps the object in an Array unless it's an Array. Converts the
- # object to an Array using #to_ary if it implements that.
+ # Wraps its argument in an array unless it is already an array (or array-like).
#
- # It differs with Array() in that it does not call +to_a+ on
- # the argument:
+ # Specifically:
+ #
+ # * If the argument is +nil+ an empty list is returned.
+ # * Otherwise, if the argument responds to +to_ary+ it is invoked, and its result returned.
+ # * Otherwise, returns an array with the argument as its single element.
+ #
+ # Array.wrap(nil) # => []
+ # Array.wrap([1, 2, 3]) # => [1, 2, 3]
+ # Array.wrap(0) # => [0]
+ #
+ # This method is similar in purpose to <tt>Kernel#Array</tt>, but there are some differences:
+ #
+ # * If the argument responds to +to_ary+ the method is invoked. <tt>Kernel#Array</tt>
+ # moves on to try +to_a+ if the returned value is +nil+, but <tt>Arraw.wrap</tt> returns
+ # such a +nil+ right away.
+ # * If the returned value from +to_ary+ is neither +nil+ nor an +Array+ object, <tt>Kernel#Array</tt>
+ # raises an exception, while <tt>Array.wrap</tt> does not, it just returns the value.
+ # * It does not call +to_a+ on the argument, though special-cases +nil+ to return an empty array.
+ #
+ # The last point is particularly worth comparing for some enumerables:
#
# Array(:foo => :bar) # => [[:foo, :bar]]
# Array.wrap(:foo => :bar) # => [{:foo => :bar}]
#
# Array("foo\nbar") # => ["foo\n", "bar"], in Ruby 1.8
# Array.wrap("foo\nbar") # => ["foo\nbar"]
+ #
+ # There's also a related idiom that uses the splat operator:
+ #
+ # [*object]
+ #
+ # which returns <tt>[nil]</tt> for +nil+, and calls to <tt>Array(object)</tt> otherwise.
+ #
+ # Thus, in this case the behavior is different for +nil+, and the differences with
+ # <tt>Kernel#Array</tt> explained above apply to the rest of +object+s.
def self.wrap(object)
if object.nil?
[]
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
index 576366e496..bfa57fe1f7 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -2,8 +2,8 @@ require 'active_support/core_ext/kernel/singleton_class'
require 'active_support/core_ext/module/remove_method'
class Class
- # Declare a class-level attribute whose value is inheritable and
- # overwritable by subclasses:
+ # Declare a class-level attribute whose value is inheritable by subclasses.
+ # Subclasses can change their own value and it will not impact parent class.
#
# class Base
# class_attribute :setting
@@ -18,12 +18,34 @@ class Class
# Subclass.setting # => false
# Base.setting # => true
#
+ # In the above case as long as Subclass does not assign a value to setting
+ # by performing <tt>Subclass.setting = _something_ </tt>, <tt>Subclass.setting</tt>
+ # would read value assigned to parent class. Once Subclass assigns a value then
+ # the value assigned by Subclass would be returned.
+ #
# This matches normal Ruby method inheritance: think of writing an attribute
- # on a subclass as overriding the reader method.
+ # on a subclass as overriding the reader method. However, you need to be aware
+ # when using +class_attribute+ with mutable structures as +Array+ or +Hash+.
+ # In such cases, you don't want to do changes in places but use setters:
+ #
+ # Base.setting = []
+ # Base.setting #=> []
+ # Subclass.setting #=> []
+ #
+ # # Appending in child changes both parent and child because it is the same object:
+ # Subclass.setting << :foo
+ # Base.setting #=> [:foo]
+ # Subclass.setting #=> [:foo]
+ #
+ # # Use setters to not propagate changes:
+ # Base.setting = []
+ # Subclass.setting += [:foo]
+ # Base.setting #=> []
+ # Subclass.setting #=> [:foo]
#
# For convenience, a query method is defined as well:
#
- # Subclass.setting? # => false
+ # Subclass.setting? # => false
#
# Instances may overwrite the class value in the same way:
#
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 feef5d2d57..4e35b1b488 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
@@ -3,11 +3,27 @@ require 'active_support/core_ext/array/extract_options'
# Extends the class object with class and instance accessors for class attributes,
# just like the native attr* accessors for instance attributes.
#
+# Note that unlike +class_attribute+, if a subclass changes the value then that would
+# also change the value for parent class. Similarly if parent class changes the value
+# then that would change the value of subclasses too.
+#
# class Person
# cattr_accessor :hair_colors
# end
#
# Person.hair_colors = [:brown, :black, :blonde, :red]
+# Person.hair_colors #=> [:brown, :black, :blonde, :red]
+# Person.new.hair_colors #=> [:brown, :black, :blonde, :red]
+#
+# To opt out of the instance writer method, pass :instance_writer => false.
+# To opt out of the instance reader method, pass :instance_reader => false.
+#
+# class Person
+# cattr_accessor :hair_colors, :instance_writer => false, :instance_reader => false
+# end
+#
+# Person.new.hair_colors = [:brown] # => NoMethodError
+# Person.new.hair_colors # => NoMethodError
class Class
def cattr_reader(*syms)
options = syms.extract_options!
diff --git a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
index 7aff05dcdf..e844cf50d1 100644
--- a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
+++ b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
@@ -1,17 +1,39 @@
require 'active_support/core_ext/object/duplicable'
require 'active_support/core_ext/array/extract_options'
-# Retain for backward compatibility. Methods are now included in Class.
+# Retained for backward compatibility. Methods are now included in Class.
module ClassInheritableAttributes # :nodoc:
end
-# Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of
+# It is recommend to use <tt>class_attribute</tt> over methods defined in this file. Please
+# refer to documentation for <tt>class_attribute</tt> for more information. Officially it is not
+# deprected but <tt>class_attribute</tt> is faster.
+#
+# Allows attributes to be shared within an inheritance hierarchy. Each descendant gets a copy of
# their parents' attributes, instead of just a pointer to the same. This means that the child can add elements
# to, for example, an array without those additions being shared with either their parent, siblings, or
-# children, which is unlike the regular class-level attributes that are shared across the entire hierarchy.
+# children. This is unlike the regular class-level attributes that are shared across the entire hierarchy.
#
# The copies of inheritable parent attributes are added to subclasses when they are created, via the
# +inherited+ hook.
+#
+# class Person
+# class_inheritable_accessor :hair_colors
+# end
+#
+# Person.hair_colors = [:brown, :black, :blonde, :red]
+# Person.hair_colors #=> [:brown, :black, :blonde, :red]
+# Person.new.hair_colors #=> [:brown, :black, :blonde, :red]
+#
+# To opt out of the instance writer method, pass :instance_writer => false.
+# To opt out of the instance reader method, pass :instance_reader => false.
+#
+# class Person
+# class_inheritable_accessor :hair_colors :instance_writer => false, :instance_reader => false
+# end
+#
+# Person.new.hair_colors = [:brown] # => NoMethodError
+# Person.new.hair_colors # => NoMethodError
class Class # :nodoc:
def class_inheritable_reader(*syms)
options = syms.extract_options!
diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb
index e6a213625c..c5b54318ce 100644
--- a/activesupport/lib/active_support/core_ext/date/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -40,23 +40,23 @@ class Date
end
end
- # Tells whether the Date object's date lies in the past
+ # Returns true if the Date object's date lies in the past. Otherwise returns false.
def past?
self < ::Date.current
end
- # Tells whether the Date object's date is today
+ # Returns true if the Date object's date is today.
def today?
self.to_date == ::Date.current # we need the to_date because of DateTime
end
- # Tells whether the Date object's date lies in the future
+ # Returns true if the Date object's date lies in the future.
def future?
self > ::Date.current
end
# Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
- # and then subtracts the specified number of seconds
+ # and then subtracts the specified number of seconds.
def ago(seconds)
to_time_in_current_zone.since(-seconds)
end
@@ -127,22 +127,22 @@ class Date
)
end
- # Returns a new Date/DateTime representing the time a number of specified months ago
+ # Returns a new Date/DateTime representing the time a number of specified months ago.
def months_ago(months)
advance(:months => -months)
end
- # Returns a new Date/DateTime representing the time a number of specified months in the future
+ # Returns a new Date/DateTime representing the time a number of specified months in the future.
def months_since(months)
advance(:months => months)
end
- # Returns a new Date/DateTime representing the time a number of specified years ago
+ # Returns a new Date/DateTime representing the time a number of specified years ago.
def years_ago(years)
advance(:years => -years)
end
- # Returns a new Date/DateTime representing the time a number of specified years in the future
+ # Returns a new Date/DateTime representing the time a number of specified years in the future.
def years_since(years)
advance(:years => years)
end
@@ -152,22 +152,22 @@ class Date
years_ago(1)
end unless method_defined?(:prev_year)
- # Short-hand for years_since(1)
+ # Shorthand for years_since(1)
def next_year
years_since(1)
end unless method_defined?(:next_year)
- # Short-hand for months_ago(1)
+ # Shorthand for months_ago(1)
def prev_month
months_ago(1)
end unless method_defined?(:prev_month)
- # Short-hand for months_since(1)
+ # Shorthand for months_since(1)
def next_month
months_since(1)
end unless method_defined?(:next_month)
- # Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00)
+ # Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00).
def beginning_of_week
days_to_monday = self.wday!=0 ? self.wday-1 : 6
result = self - days_to_monday
@@ -176,7 +176,7 @@ class Date
alias :monday :beginning_of_week
alias :at_beginning_of_week :beginning_of_week
- # Returns a new Date/DateTime representing the end of this week (Sunday, DateTime objects will have time set to 23:59:59)
+ # Returns a new Date/DateTime representing the end of this week (Sunday, DateTime objects will have time set to 23:59:59).
def end_of_week
days_to_sunday = self.wday!=0 ? 7-self.wday : 0
result = self + days_to_sunday.days
diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb
index d0821a7c68..f76ed401cd 100644
--- a/activesupport/lib/active_support/core_ext/enumerable.rb
+++ b/activesupport/lib/active_support/core_ext/enumerable.rb
@@ -66,7 +66,8 @@ module Enumerable
# +memo+ to the block. Handy for building up hashes or
# reducing collections down to one object. Examples:
#
- # %w(foo bar).each_with_object({}) { |str, hsh| hsh[str] = str.upcase } #=> {'foo' => 'FOO', 'bar' => 'BAR'}
+ # %w(foo bar).each_with_object({}) { |str, hsh| hsh[str] = str.upcase }
+ # # => {'foo' => 'FOO', 'bar' => 'BAR'}
#
# *Note* that you can't use immutable objects like numbers, true or false as
# the memo. You would think the following returns 120, but since the memo is
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index 565c9af7fb..2763af6121 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -83,7 +83,7 @@ class Hash
case value.class.to_s
when 'Hash'
if value['type'] == 'array'
- child_key, entries = Array.wrap(value.detect { |k,v| k != 'type' }) # child_key is throwaway
+ _, entries = Array.wrap(value.detect { |k,v| k != 'type' })
if entries.nil? || (c = value['__content__'] && c.blank?)
[]
else
diff --git a/activesupport/lib/active_support/core_ext/kernel/requires.rb b/activesupport/lib/active_support/core_ext/kernel/requires.rb
index d2238898d6..3bf46271d7 100644
--- a/activesupport/lib/active_support/core_ext/kernel/requires.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/requires.rb
@@ -11,13 +11,13 @@ module Kernel
# 1. Requiring the module is unsuccessful, maybe it's a gem and nobody required rubygems yet. Try.
begin
require 'rubygems'
- rescue LoadError => rubygems_not_installed
+ rescue LoadError # => rubygems_not_installed
raise cannot_require
end
# 2. Rubygems is installed and loaded. Try to load the library again
begin
require library_name
- rescue LoadError => gem_not_installed
+ rescue LoadError # => gem_not_installed
raise cannot_require
end
end
diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
index 9c4d5fae26..2d88cb57e5 100644
--- a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
@@ -5,9 +5,7 @@ class Module
options = syms.extract_options!
syms.each do |sym|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
- unless defined? @@#{sym}
- @@#{sym} = nil
- end
+ @@#{sym} = nil unless defined? @@#{sym}
def self.#{sym}
@@#{sym}
@@ -28,10 +26,6 @@ class Module
options = syms.extract_options!
syms.each do |sym|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
- unless defined? @@#{sym}
- @@#{sym} = nil
- end
-
def self.#{sym}=(obj)
@@#{sym} = obj
end
diff --git a/activesupport/lib/active_support/core_ext/module/remove_method.rb b/activesupport/lib/active_support/core_ext/module/remove_method.rb
index 2714a46b28..b8c01aca0e 100644
--- a/activesupport/lib/active_support/core_ext/module/remove_method.rb
+++ b/activesupport/lib/active_support/core_ext/module/remove_method.rb
@@ -3,4 +3,9 @@ class Module
remove_method(method)
rescue NameError
end
+
+ def redefine_method(method, &block)
+ remove_possible_method(method)
+ define_method(method, &block)
+ end
end \ No newline at end of file
diff --git a/activesupport/lib/active_support/core_ext/object.rb b/activesupport/lib/active_support/core_ext/object.rb
index 27618b55c6..d671da6711 100644
--- a/activesupport/lib/active_support/core_ext/object.rb
+++ b/activesupport/lib/active_support/core_ext/object.rb
@@ -2,12 +2,11 @@ require 'active_support/core_ext/object/acts_like'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/object/duplicable'
require 'active_support/core_ext/object/try'
+require 'active_support/core_ext/object/returning'
require 'active_support/core_ext/object/conversions'
require 'active_support/core_ext/object/instance_variables'
-require 'active_support/core_ext/object/misc'
-require 'active_support/core_ext/object/returning'
require 'active_support/core_ext/object/to_json'
require 'active_support/core_ext/object/to_param'
require 'active_support/core_ext/object/to_query'
diff --git a/activesupport/lib/active_support/core_ext/object/misc.rb b/activesupport/lib/active_support/core_ext/object/misc.rb
deleted file mode 100644
index 3e3af03cc5..0000000000
--- a/activesupport/lib/active_support/core_ext/object/misc.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require 'active_support/core_ext/object/returning'
-require 'active_support/core_ext/object/with_options'
diff --git a/activesupport/lib/active_support/core_ext/object/returning.rb b/activesupport/lib/active_support/core_ext/object/returning.rb
index 0dc2e1266a..07250b2a27 100644
--- a/activesupport/lib/active_support/core_ext/object/returning.rb
+++ b/activesupport/lib/active_support/core_ext/object/returning.rb
@@ -25,7 +25,7 @@ class Object
# end
#
# foo # => ['bar', 'baz']
- #
+ #
# # returning with a block argument
# def foo
# returning [] do |values|
@@ -33,10 +33,11 @@ class Object
# values << 'baz'
# end
# end
- #
+ #
# foo # => ['bar', 'baz']
def returning(value)
+ ActiveSupport::Deprecation.warn('Object#returning has been deprecated in favor of Object#tap.', caller)
yield(value)
value
end
-end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/core_ext/object/to_param.rb b/activesupport/lib/active_support/core_ext/object/to_param.rb
index 06f077e920..f2e7c2351e 100644
--- a/activesupport/lib/active_support/core_ext/object/to_param.rb
+++ b/activesupport/lib/active_support/core_ext/object/to_param.rb
@@ -44,6 +44,6 @@ class Hash
def to_param(namespace = nil)
collect do |key, value|
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
- end.sort * '&'
+ end * '&'
end
end
diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb
index 66c4034781..32913a06ad 100644
--- a/activesupport/lib/active_support/core_ext/string/inflections.rb
+++ b/activesupport/lib/active_support/core_ext/string/inflections.rb
@@ -1,3 +1,5 @@
+require 'active_support/inflector/methods'
+require 'active_support/inflector/inflections'
# String inflections define new methods on the String class to transform names for different purposes.
# For instance, you can figure out the name of a database from the name of a class.
#
diff --git a/activesupport/lib/active_support/core_ext/string/multibyte.rb b/activesupport/lib/active_support/core_ext/string/multibyte.rb
index 16ccd36458..0b974f5e0a 100644
--- a/activesupport/lib/active_support/core_ext/string/multibyte.rb
+++ b/activesupport/lib/active_support/core_ext/string/multibyte.rb
@@ -12,11 +12,11 @@ class String
# class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsuled string.
#
# name = 'Claus Müller'
- # name.reverse #=> "rell??M sualC"
- # name.length #=> 13
+ # name.reverse # => "rell??M sualC"
+ # name.length # => 13
#
- # name.mb_chars.reverse.to_s #=> "rellüM sualC"
- # name.mb_chars.length #=> 12
+ # name.mb_chars.reverse.to_s # => "rellüM sualC"
+ # name.mb_chars.length # => 12
#
# In Ruby 1.9 and newer +mb_chars+ returns +self+ because String is (mostly) encoding aware. This means that
# it becomes easy to run one version of your code on multiple Ruby versions.
@@ -26,7 +26,7 @@ class String
# All the methods on the Chars proxy which normally return a string will return a Chars object. This allows
# method chaining on the result of any of these methods.
#
- # name.mb_chars.reverse.length #=> 12
+ # name.mb_chars.reverse.length # => 12
#
# == Interoperability and configuration
#
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 7d5143ba37..2b80bd214f 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -72,10 +72,6 @@ module ActiveSupport #:nodoc:
methods.each { |m| class_eval "def #{m}(*) lock { super } end", __FILE__, __LINE__ }
end
- def get(key)
- (val = assoc(key)) ? val[1] : []
- end
-
locked :concat, :each, :delete_if, :<<
def new_constants_for(frames)
@@ -85,7 +81,18 @@ module ActiveSupport #:nodoc:
next unless mod.is_a?(Module)
new_constants = mod.local_constant_names - prior_constants
- get(mod_name).concat(new_constants)
+
+ # If we are checking for constants under, say, :Object, nested under something
+ # else that is checking for constants also under :Object, make sure the
+ # parent knows that we have found, and taken care of, the constant.
+ #
+ # In particular, this means that since Kernel.require discards the constants
+ # it finds, parents will be notified that about those constants, and not
+ # consider them "new". As a result, they will not be added to the
+ # autoloaded_constants list.
+ each do |key, value|
+ value.concat(new_constants) if key == mod_name
+ end
new_constants.each do |suffix|
constants << ([mod_name, suffix] - ["Object"]).join("::")
@@ -592,7 +599,7 @@ module ActiveSupport #:nodoc:
# Convert the provided const desc to a qualified constant name (as a string).
# A module, class, symbol, or string may be provided.
def to_constant_name(desc) #:nodoc:
- name = case desc
+ case desc
when String then desc.sub(/^::/, '')
when Symbol then desc.to_s
when Module
diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
index dec56715be..deb33ab702 100644
--- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
@@ -3,6 +3,13 @@ require 'active_support/inflector'
module ActiveSupport
module Deprecation
class DeprecationProxy #:nodoc:
+ def self.new(*args, &block)
+ object = args.first
+
+ return object unless object
+ super
+ end
+
instance_methods.each { |m| undef_method m unless m =~ /^__|^object_id$/ }
# Don't give a deprecation warning on inspect since test/unit and error
diff --git a/activesupport/lib/active_support/descendants_tracker.rb b/activesupport/lib/active_support/descendants_tracker.rb
index 6cba84d79e..4d1cfacc95 100644
--- a/activesupport/lib/active_support/descendants_tracker.rb
+++ b/activesupport/lib/active_support/descendants_tracker.rb
@@ -11,9 +11,9 @@ module ActiveSupport
end
def self.descendants(klass)
- @@direct_descendants[klass].inject([]) do |descendants, klass|
- descendants << klass
- descendants.concat klass.descendants
+ @@direct_descendants[klass].inject([]) do |descendants, _klass|
+ descendants << _klass
+ descendants.concat _klass.descendants
end
end
@@ -40,4 +40,4 @@ module ActiveSupport
DescendantsTracker.descendants(self)
end
end
-end \ No newline at end of file
+end
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb
index cd0d66a482..7da357730b 100644
--- a/activesupport/lib/active_support/duration.rb
+++ b/activesupport/lib/active_support/duration.rb
@@ -4,8 +4,8 @@ require 'active_support/core_ext/object/acts_like'
module ActiveSupport
# Provides accurate date and time measurements using Date#advance and
- # Time#advance, respectively. It mainly supports the methods on Numeric,
- # such as in this example:
+ # Time#advance, respectively. It mainly supports the methods on Numeric.
+ # Example:
#
# 1.month.ago # equivalent to Time.now.advance(:months => -1)
class Duration < BasicObject
diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb
index f64f0f44cc..eec5d4cf47 100644
--- a/activesupport/lib/active_support/hash_with_indifferent_access.rb
+++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb
@@ -1,3 +1,4 @@
+require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/hash/keys'
# This class has dubious semantics and we only have it so that
diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb
index b3dc5b2f3a..de49750083 100644
--- a/activesupport/lib/active_support/inflector/methods.rb
+++ b/activesupport/lib/active_support/inflector/methods.rb
@@ -20,6 +20,11 @@ module ActiveSupport
# "active_record".camelize(:lower) # => "activeRecord"
# "active_record/errors".camelize # => "ActiveRecord::Errors"
# "active_record/errors".camelize(:lower) # => "activeRecord::Errors"
+ #
+ # As a rule of thumb you can think of +camelize+ as the inverse of +underscore+,
+ # though there are cases where that does not hold:
+ #
+ # "SSLError".underscore.camelize # => "SslError"
def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
if first_letter_in_uppercase
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
@@ -28,13 +33,18 @@ module ActiveSupport
end
end
- # The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string.
+ # Makes an underscored, lowercase form from the expression in the string.
#
# Changes '::' to '/' to convert namespaces to paths.
#
# Examples:
# "ActiveRecord".underscore # => "active_record"
# "ActiveRecord::Errors".underscore # => active_record/errors
+ #
+ # As a rule of thumb you can think of +underscore+ as the inverse of +camelize+,
+ # though there are cases where that does not hold:
+ #
+ # "SSLError".underscore.camelize # => "SslError"
def underscore(camel_cased_word)
word = camel_cased_word.to_s.dup
word.gsub!(/::/, '/')
diff --git a/activesupport/lib/active_support/json/backends/yaml.rb b/activesupport/lib/active_support/json/backends/yaml.rb
index 215b3d6f90..4cb9d01077 100644
--- a/activesupport/lib/active_support/json/backends/yaml.rb
+++ b/activesupport/lib/active_support/json/backends/yaml.rb
@@ -13,7 +13,7 @@ module ActiveSupport
json = json.read
end
YAML.load(convert_json_to_yaml(json))
- rescue ArgumentError => e
+ rescue ArgumentError
raise ParseError, "Invalid JSON string"
end
diff --git a/activesupport/lib/active_support/lazy_load_hooks.rb b/activesupport/lib/active_support/lazy_load_hooks.rb
index 3664431a28..ef43fc0431 100644
--- a/activesupport/lib/active_support/lazy_load_hooks.rb
+++ b/activesupport/lib/active_support/lazy_load_hooks.rb
@@ -1,3 +1,22 @@
+# lazy_load_hooks allows rails to lazily load a lot of components and thus making the app boot faster. Because of
+# this feature now there is no need to require <tt>ActiveRecord::Base</tt> at boot time purely to apply configuration. Instead
+# a hook is registered that applies configuration once <tt>ActiveRecord::Base</tt> is loaded. Here <tt>ActiveRecord::Base</tt> is used
+# as example but this feature can be applied elsewhere too.
+#
+# Here is an example where +on_load+ method is called to register a hook.
+#
+# initializer "active_record.initialize_timezone" do
+# ActiveSupport.on_load(:active_record) do
+# self.time_zone_aware_attributes = true
+# self.default_timezone = :utc
+# end
+# end
+#
+# When the entirety of +activerecord/lib/active_record/base.rb+ has been evaluated then +run_load_hooks+ is invoked.
+# The very last line of +activerecord/lib/active_record/base.rb+ is:
+#
+# ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)
+#
module ActiveSupport
@load_hooks = Hash.new {|h,k| h[k] = [] }
@loaded = {}
@@ -24,4 +43,4 @@ module ActiveSupport
execute_hook(base, options, hook)
end
end
-end \ No newline at end of file
+end
diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb
index 891d718af3..83930b3f0d 100644
--- a/activesupport/lib/active_support/log_subscriber.rb
+++ b/activesupport/lib/active_support/log_subscriber.rb
@@ -21,7 +21,7 @@ module ActiveSupport
# ActiveRecord::LogSubscriber.attach_to :active_record
#
# Since we need to know all instance methods before attaching the log subscriber,
- # the line above shuold be called after your ActiveRecord::LogSubscriber definition.
+ # the line above should be called after your ActiveRecord::LogSubscriber definition.
#
# After configured, whenever a "sql.active_record" notification is published,
# it will properly dispatch the event (ActiveSupport::Notifications::Event) to
@@ -63,15 +63,9 @@ module ActiveSupport
@@flushable_loggers = nil
log_subscriber.public_methods(false).each do |event|
- notifier.subscribe("#{event}.#{namespace}") do |*args|
- next if log_subscriber.logger.nil?
-
- begin
- log_subscriber.send(event, ActiveSupport::Notifications::Event.new(*args))
- rescue Exception => e
- log_subscriber.logger.error "Could not log #{args[0].inspect} event. #{e.class}: #{e.message}"
- end
- end
+ next if 'call' == event.to_s
+
+ notifier.subscribe("#{event}.#{namespace}", log_subscriber)
end
end
@@ -92,6 +86,17 @@ module ActiveSupport
flushable_loggers.each(&:flush)
end
+ def call(message, *args)
+ return unless logger
+
+ method = message.split('.').first
+ begin
+ send(method, ActiveSupport::Notifications::Event.new(message, *args))
+ rescue Exception => e
+ logger.error "Could not log #{message.inspect} event. #{e.class}: #{e.message}"
+ end
+ end
+
protected
%w(info debug warn error fatal unknown).each do |level|
diff --git a/activesupport/lib/active_support/log_subscriber/test_helper.rb b/activesupport/lib/active_support/log_subscriber/test_helper.rb
index 96506a4b2b..9e52cb97a9 100644
--- a/activesupport/lib/active_support/log_subscriber/test_helper.rb
+++ b/activesupport/lib/active_support/log_subscriber/test_helper.rb
@@ -1,4 +1,5 @@
require 'active_support/log_subscriber'
+require 'active_support/buffered_logger'
module ActiveSupport
class LogSubscriber
@@ -33,7 +34,7 @@ module ActiveSupport
module TestHelper
def setup
@logger = MockLogger.new
- @notifier = ActiveSupport::Notifications::Notifier.new(queue)
+ @notifier = ActiveSupport::Notifications::Fanout.new
ActiveSupport::LogSubscriber.colorize_logging = false
@@ -47,10 +48,14 @@ module ActiveSupport
end
class MockLogger
+ include ActiveSupport::BufferedLogger::Severity
+
attr_reader :flush_count
+ attr_accessor :level
- def initialize
+ def initialize(level = DEBUG)
@flush_count = 0
+ @level = level
@logged = Hash.new { |h,k| h[k] = [] }
end
@@ -65,6 +70,14 @@ module ActiveSupport
def flush
@flush_count += 1
end
+
+ ActiveSupport::BufferedLogger::Severity.constants.each do |severity|
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
+ def #{severity.downcase}?
+ #{severity} >= @level
+ end
+ EOT
+ end
end
# Wait notifications to be published.
@@ -81,10 +94,6 @@ module ActiveSupport
def set_logger(logger)
ActiveSupport::LogSubscriber.logger = logger
end
-
- def queue
- ActiveSupport::Notifications::Fanout.new
- end
end
end
-end \ No newline at end of file
+end
diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb
index 1031662293..6c46b68eaf 100644
--- a/activesupport/lib/active_support/message_verifier.rb
+++ b/activesupport/lib/active_support/message_verifier.rb
@@ -47,11 +47,11 @@ module ActiveSupport
def secure_compare(a, b)
return false unless a.bytesize == b.bytesize
- l = a.unpack "C*"
+ l = a.unpack "C#{a.bytesize}"
- res = true
- b.each_byte { |byte| res = (byte == l.shift) && res }
- res
+ res = 0
+ b.each_byte { |byte| res |= byte ^ l.shift }
+ res == 0
end
def generate_digest(data)
diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb
index 51c2a0edac..019fb2df06 100644
--- a/activesupport/lib/active_support/multibyte/chars.rb
+++ b/activesupport/lib/active_support/multibyte/chars.rb
@@ -11,7 +11,7 @@ module ActiveSupport #:nodoc:
# String methods are proxied through the Chars object, and can be accessed through the +mb_chars+ method. Methods
# which would normally return a String object now return a Chars object so methods can be chained.
#
- # "The Perfect String ".mb_chars.downcase.strip.normalize #=> "the perfect string"
+ # "The Perfect String ".mb_chars.downcase.strip.normalize # => "the perfect string"
#
# Chars objects are perfectly interchangeable with String objects as long as no explicit class checks are made.
# If certain methods do explicitly check the class, call +to_s+ before you pass chars objects to them.
@@ -83,12 +83,13 @@ module ActiveSupport #:nodoc:
include Comparable
- # Returns <tt>-1</tt>, <tt>0</tt> or <tt>+1</tt> depending on whether the Chars object is to be sorted before,
- # equal or after the object on the right side of the operation. It accepts any object that implements +to_s+.
- # See <tt>String#<=></tt> for more details.
+ # Returns -1, 0, or 1, depending on whether the Chars object is to be sorted before,
+ # equal or after the object on the right side of the operation. It accepts any object
+ # that implements +to_s+:
#
- # Example:
- # 'é'.mb_chars <=> 'ü'.mb_chars #=> -1
+ # 'é'.mb_chars <=> 'ü'.mb_chars # => -1
+ #
+ # See <tt>String#<=></tt> for more details.
def <=>(other)
@wrapped_string <=> other.to_s
end
@@ -103,7 +104,7 @@ module ActiveSupport #:nodoc:
# Returns a new Chars object containing the _other_ object concatenated to the string.
#
# Example:
- # ('Café'.mb_chars + ' périferôl').to_s #=> "Café périferôl"
+ # ('Café'.mb_chars + ' périferôl').to_s # => "Café périferôl"
def +(other)
chars(@wrapped_string + other)
end
@@ -111,7 +112,7 @@ module ActiveSupport #:nodoc:
# Like <tt>String#=~</tt> only it returns the character offset (in codepoints) instead of the byte offset.
#
# Example:
- # 'Café périferôl'.mb_chars =~ /ô/ #=> 12
+ # 'Café périferôl'.mb_chars =~ /ô/ # => 12
def =~(other)
translate_offset(@wrapped_string =~ other)
end
@@ -119,7 +120,7 @@ module ActiveSupport #:nodoc:
# Inserts the passed string at specified codepoint offsets.
#
# Example:
- # 'Café'.mb_chars.insert(4, ' périferôl').to_s #=> "Café périferôl"
+ # 'Café'.mb_chars.insert(4, ' périferôl').to_s # => "Café périferôl"
def insert(offset, fragment)
unpacked = Unicode.u_unpack(@wrapped_string)
unless offset > unpacked.length
@@ -135,7 +136,7 @@ module ActiveSupport #:nodoc:
# Returns +true+ if contained string contains _other_. Returns +false+ otherwise.
#
# Example:
- # 'Café'.mb_chars.include?('é') #=> true
+ # 'Café'.mb_chars.include?('é') # => true
def include?(other)
# We have to redefine this method because Enumerable defines it.
@wrapped_string.include?(other)
@@ -144,8 +145,8 @@ module ActiveSupport #:nodoc:
# Returns the position _needle_ in the string, counting in codepoints. Returns +nil+ if _needle_ isn't found.
#
# Example:
- # 'Café périferôl'.mb_chars.index('ô') #=> 12
- # 'Café périferôl'.mb_chars.index(/\w/u) #=> 0
+ # 'Café périferôl'.mb_chars.index('ô') # => 12
+ # 'Café périferôl'.mb_chars.index(/\w/u) # => 0
def index(needle, offset=0)
wrapped_offset = first(offset).wrapped_string.length
index = @wrapped_string.index(needle, wrapped_offset)
@@ -157,8 +158,8 @@ module ActiveSupport #:nodoc:
# string. Returns +nil+ if _needle_ isn't found.
#
# Example:
- # 'Café périferôl'.mb_chars.rindex('é') #=> 6
- # 'Café périferôl'.mb_chars.rindex(/\w/u) #=> 13
+ # '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
wrapped_offset = first(offset).wrapped_string.length
@@ -190,7 +191,7 @@ module ActiveSupport #:nodoc:
# Returns the codepoint of the first character in the string.
#
# Example:
- # 'こんにちは'.mb_chars.ord #=> 12371
+ # 'こんにちは'.mb_chars.ord # => 12371
def ord
Unicode.u_unpack(@wrapped_string)[0]
end
@@ -200,10 +201,10 @@ module ActiveSupport #:nodoc:
# Example:
#
# "¾ cup".mb_chars.rjust(8).to_s
- # #=> " ¾ cup"
+ # # => " ¾ cup"
#
# "¾ cup".mb_chars.rjust(8, " ").to_s # Use non-breaking whitespace
- # #=> "   ¾ cup"
+ # # => "   ¾ cup"
def rjust(integer, padstr=' ')
justify(integer, :right, padstr)
end
@@ -213,10 +214,10 @@ module ActiveSupport #:nodoc:
# Example:
#
# "¾ cup".mb_chars.rjust(8).to_s
- # #=> "¾ cup "
+ # # => "¾ cup "
#
# "¾ cup".mb_chars.rjust(8, " ").to_s # Use non-breaking whitespace
- # #=> "¾ cup   "
+ # # => "¾ cup   "
def ljust(integer, padstr=' ')
justify(integer, :left, padstr)
end
@@ -226,10 +227,10 @@ module ActiveSupport #:nodoc:
# Example:
#
# "¾ cup".mb_chars.center(8).to_s
- # #=> " ¾ cup "
+ # # => " ¾ cup "
#
# "¾ cup".mb_chars.center(8, " ").to_s # Use non-breaking whitespace
- # #=> " ¾ cup  "
+ # # => " ¾ cup  "
def center(integer, padstr=' ')
justify(integer, :center, padstr)
end
@@ -244,7 +245,7 @@ module ActiveSupport #:nodoc:
# instances instead of String. This makes chaining methods easier.
#
# Example:
- # 'Café périferôl'.mb_chars.split(/é/).map { |part| part.upcase.to_s } #=> ["CAF", " P", "RIFERÔL"]
+ # 'Café périferôl'.mb_chars.split(/é/).map { |part| part.upcase.to_s } # => ["CAF", " P", "RIFERÔL"]
def split(*args)
@wrapped_string.split(*args).map { |i| i.mb_chars }
end
@@ -256,12 +257,12 @@ module ActiveSupport #:nodoc:
# s = "Müller"
# s.mb_chars[2] = "e" # Replace character with offset 2
# s
- # #=> "Müeler"
+ # # => "Müeler"
#
# s = "Müller"
# s.mb_chars[1, 2] = "ö" # Replace 2 characters at character offset 1
# s
- # #=> "Möler"
+ # # => "Möler"
def []=(*args)
replace_by = args.pop
# Indexed replace with regular expressions already works
@@ -292,7 +293,7 @@ module ActiveSupport #:nodoc:
# Reverses all characters in the string.
#
# Example:
- # 'Café'.mb_chars.reverse.to_s #=> 'éfaC'
+ # 'Café'.mb_chars.reverse.to_s # => 'éfaC'
def reverse
chars(Unicode.g_unpack(@wrapped_string).reverse.flatten.pack('U*'))
end
@@ -301,7 +302,7 @@ module ActiveSupport #:nodoc:
# character.
#
# Example:
- # 'こんにちは'.mb_chars.slice(2..3).to_s #=> "にち"
+ # 'こんにちは'.mb_chars.slice(2..3).to_s # => "にち"
def slice(*args)
if args.size > 2
raise ArgumentError, "wrong number of arguments (#{args.size} for 1)" # Do as if we were native
@@ -330,7 +331,7 @@ module ActiveSupport #:nodoc:
#
# Example:
# s = 'こんにちは'
- # s.mb_chars.limit(7) #=> "こに"
+ # s.mb_chars.limit(7) # => "こに"
def limit(limit)
slice(0...translate_offset(limit))
end
@@ -338,7 +339,7 @@ module ActiveSupport #:nodoc:
# Convert characters in the string to uppercase.
#
# Example:
- # 'Laurent, où sont les tests ?'.mb_chars.upcase.to_s #=> "LAURENT, OÙ SONT LES TESTS ?"
+ # 'Laurent, où sont les tests ?'.mb_chars.upcase.to_s # => "LAURENT, OÙ SONT LES TESTS ?"
def upcase
chars(Unicode.apply_mapping @wrapped_string, :uppercase_mapping)
end
@@ -346,7 +347,7 @@ module ActiveSupport #:nodoc:
# Convert characters in the string to lowercase.
#
# Example:
- # 'VĚDA A VÝZKUM'.mb_chars.downcase.to_s #=> "věda a výzkum"
+ # 'VĚDA A VÝZKUM'.mb_chars.downcase.to_s # => "věda a výzkum"
def downcase
chars(Unicode.apply_mapping @wrapped_string, :lowercase_mapping)
end
@@ -354,7 +355,7 @@ module ActiveSupport #:nodoc:
# Converts the first character to uppercase and the remainder to lowercase.
#
# Example:
- # 'über'.mb_chars.capitalize.to_s #=> "Über"
+ # 'über'.mb_chars.capitalize.to_s # => "Über"
def capitalize
(slice(0) || chars('')).upcase + (slice(1..-1) || chars('')).downcase
end
@@ -382,8 +383,8 @@ module ActiveSupport #:nodoc:
# Performs canonical decomposition on all the characters.
#
# Example:
- # 'é'.length #=> 2
- # 'é'.mb_chars.decompose.to_s.length #=> 3
+ # 'é'.length # => 2
+ # 'é'.mb_chars.decompose.to_s.length # => 3
def decompose
chars(Unicode.decompose_codepoints(:canonical, Unicode.u_unpack(@wrapped_string)).pack('U*'))
end
@@ -391,8 +392,8 @@ module ActiveSupport #:nodoc:
# Performs composition on all the characters.
#
# Example:
- # 'é'.length #=> 3
- # 'é'.mb_chars.compose.to_s.length #=> 2
+ # 'é'.length # => 3
+ # 'é'.mb_chars.compose.to_s.length # => 2
def compose
chars(Unicode.compose_codepoints(Unicode.u_unpack(@wrapped_string)).pack('U*'))
end
@@ -400,8 +401,8 @@ module ActiveSupport #:nodoc:
# Returns the number of grapheme clusters in the string.
#
# Example:
- # 'क्षि'.mb_chars.length #=> 4
- # 'क्षि'.mb_chars.g_length #=> 3
+ # 'क्षि'.mb_chars.length # => 4
+ # 'क्षि'.mb_chars.g_length # => 3
def g_length
Unicode.g_unpack(@wrapped_string).length
end
diff --git a/activesupport/lib/active_support/multibyte/unicode.rb b/activesupport/lib/active_support/multibyte/unicode.rb
index 11c72d873b..1139783b65 100644
--- a/activesupport/lib/active_support/multibyte/unicode.rb
+++ b/activesupport/lib/active_support/multibyte/unicode.rb
@@ -64,7 +64,7 @@ module ActiveSupport
# valid UTF-8.
#
# Example:
- # Unicode.u_unpack('Café') #=> [67, 97, 102, 233]
+ # Unicode.u_unpack('Café') # => [67, 97, 102, 233]
def u_unpack(string)
begin
string.unpack 'U*'
@@ -85,8 +85,8 @@ module ActiveSupport
# Unpack the string at grapheme boundaries. Returns a list of character lists.
#
# Example:
- # Unicode.g_unpack('क्षि') #=> [[2325, 2381], [2359], [2367]]
- # Unicode.g_unpack('Café') #=> [[67], [97], [102], [233]]
+ # Unicode.g_unpack('क्षि') # => [[2325, 2381], [2359], [2367]]
+ # Unicode.g_unpack('Café') # => [[67], [97], [102], [233]]
def g_unpack(string)
codepoints = u_unpack(string)
unpacked = []
@@ -99,15 +99,15 @@ module ActiveSupport
current = codepoints[pos]
if (
# CR X LF
- one = ( previous == database.boundary[:cr] and current == database.boundary[:lf] ) or
+ ( previous == database.boundary[:cr] and current == database.boundary[:lf] ) or
# L X (L|V|LV|LVT)
- two = ( database.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt]) ) or
+ ( database.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt]) ) or
# (LV|V) X (V|T)
- three = ( in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t]) ) or
+ ( in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t]) ) or
# (LVT|T) X (T)
- four = ( in_char_class?(previous, [:lvt,:t]) and database.boundary[:t] === current ) or
+ ( in_char_class?(previous, [:lvt,:t]) and database.boundary[:t] === current ) or
# X Extend
- five = (database.boundary[:extend] === current)
+ (database.boundary[:extend] === current)
)
else
unpacked << codepoints[marker..pos-1]
@@ -120,7 +120,7 @@ module ActiveSupport
# Reverse operation of g_unpack.
#
# Example:
- # Unicode.g_pack(Unicode.g_unpack('क्षि')) #=> 'क्षि'
+ # Unicode.g_pack(Unicode.g_unpack('क्षि')) # => 'क्षि'
def g_pack(unpacked)
(unpacked.flatten).pack('U*')
end
@@ -238,7 +238,6 @@ module ActiveSupport
bytes.each_index do |i|
byte = bytes[i]
- is_ascii = byte < 128
is_cont = byte > 127 && byte < 192
is_lead = byte > 191 && byte < 245
is_unused = byte > 240
diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb
index 1444fc1609..fd79188ba4 100644
--- a/activesupport/lib/active_support/notifications.rb
+++ b/activesupport/lib/active_support/notifications.rb
@@ -22,9 +22,9 @@ module ActiveSupport
# end
#
# event = @events.first
- # event.name #=> :render
- # event.duration #=> 10 (in milliseconds)
- # event.payload #=> { :extra => :information }
+ # event.name # => :render
+ # event.duration # => 10 (in milliseconds)
+ # event.payload # => { :extra => :information }
#
# When subscribing to Notifications, you can pass a pattern, to only consume
# events that match the pattern:
@@ -41,39 +41,37 @@ module ActiveSupport
autoload :Event, 'active_support/notifications/instrumenter'
autoload :Fanout, 'active_support/notifications/fanout'
+ @instrumenters = Hash.new { |h,k| h[k] = notifier.listening?(k) }
+
class << self
attr_writer :notifier
- delegate :publish, :subscribe, :unsubscribe, :to => :notifier
- delegate :instrument, :to => :instrumenter
-
- def notifier
- @notifier ||= Notifier.new
- end
-
- def instrumenter
- Thread.current[:"instrumentation_#{notifier.object_id}"] ||= Instrumenter.new(notifier)
- end
- end
+ delegate :publish, :to => :notifier
- class Notifier
- def initialize(queue = Fanout.new)
- @queue = queue
+ def instrument(name, payload = {})
+ if @instrumenters[name]
+ instrumenter.instrument(name, payload) { yield payload if block_given? }
+ else
+ yield payload if block_given?
+ end
end
- def publish(*args)
- @queue.publish(*args)
+ def subscribe(*args, &block)
+ notifier.subscribe(*args, &block).tap do
+ @instrumenters.clear
+ end
end
- def subscribe(pattern = nil, &block)
- @queue.bind(pattern).subscribe(&block)
+ def unsubscribe(*args)
+ notifier.unsubscribe(*args)
+ @instrumenters.clear
end
- def unsubscribe(subscriber)
- @queue.unsubscribe(subscriber)
+ def notifier
+ @notifier ||= Fanout.new
end
- def wait
- @queue.wait
+ def instrumenter
+ Thread.current[:"instrumentation_#{notifier.object_id}"] ||= Instrumenter.new(notifier)
end
end
end
diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb
index 300ec842a9..adc34f3286 100644
--- a/activesupport/lib/active_support/notifications/fanout.rb
+++ b/activesupport/lib/active_support/notifications/fanout.rb
@@ -8,85 +8,53 @@ module ActiveSupport
@listeners_for = {}
end
- def bind(pattern)
- Binding.new(self, pattern)
- end
-
- def subscribe(pattern = nil, &block)
+ def subscribe(pattern = nil, block = Proc.new)
+ subscriber = Subscriber.new(pattern, block).tap do |s|
+ @subscribers << s
+ end
@listeners_for.clear
- @subscribers << Subscriber.new(pattern, &block)
- @subscribers.last
+ subscriber
end
def unsubscribe(subscriber)
- @listeners_for.clear
@subscribers.reject! {|s| s.matches?(subscriber)}
+ @listeners_for.clear
end
def publish(name, *args)
- if listeners = @listeners_for[name]
- listeners.each { |s| s.publish(name, *args) }
- else
- @listeners_for[name] = @subscribers.select { |s| s.publish(name, *args) }
- end
+ listeners_for(name).each { |s| s.publish(name, *args) }
end
- # This is a sync queue, so there is not waiting.
- def wait
+ def listeners_for(name)
+ @listeners_for[name] ||= @subscribers.select { |s| s.subscribed_to?(name) }
end
- # Used for internal implementation only.
- class Binding #:nodoc:
- def initialize(queue, pattern)
- @queue = queue
- @pattern =
- case pattern
- when Regexp, NilClass
- pattern
- else
- /^#{Regexp.escape(pattern.to_s)}$/
- end
- end
+ def listening?(name)
+ listeners_for(name).any?
+ end
- def subscribe(&block)
- @queue.subscribe(@pattern, &block)
- end
+ # This is a sync queue, so there is not waiting.
+ def wait
end
class Subscriber #:nodoc:
- def initialize(pattern, &block)
+ def initialize(pattern, delegate)
@pattern = pattern
- @block = block
+ @delegate = delegate
end
- def publish(*args)
- return unless subscribed_to?(args.first)
- push(*args)
- true
- end
-
- def drained?
- true
+ def publish(message, *args)
+ @delegate.call(message, *args)
end
def subscribed_to?(name)
- !@pattern || @pattern =~ name.to_s
+ !@pattern || @pattern === name.to_s
end
def matches?(subscriber_or_name)
- case subscriber_or_name
- when String
- @pattern && @pattern =~ subscriber_or_name
- when self
- true
- end
+ self === subscriber_or_name ||
+ @pattern && @pattern === subscriber_or_name
end
-
- private
-
- def push(*args)
- @block.call(*args)
- end
end
end
end
diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb
index 7e89402822..441fefb491 100644
--- a/activesupport/lib/active_support/notifications/instrumenter.rb
+++ b/activesupport/lib/active_support/notifications/instrumenter.rb
@@ -15,14 +15,15 @@ module ActiveSupport
# and publish it. Notice that events get sent even if an error occurs
# in the passed-in block
def instrument(name, payload={})
- time = Time.now
+ started = Time.now
+
begin
- yield(payload) if block_given?
+ yield
rescue Exception => e
payload[:exception] = [e.class.name, e.message]
raise e
ensure
- @notifier.publish(name, time, Time.now, @id, payload)
+ @notifier.publish(name, started, Time.now, @id, payload)
end
end
@@ -33,7 +34,7 @@ module ActiveSupport
end
class Event
- attr_reader :name, :time, :end, :transaction_id, :payload
+ attr_reader :name, :time, :end, :transaction_id, :payload, :duration
def initialize(name, start, ending, transaction_id, payload)
@name = name
@@ -41,14 +42,11 @@ module ActiveSupport
@time = start
@transaction_id = transaction_id
@end = ending
- end
-
- def duration
- @duration ||= 1000.0 * (@end - @time)
+ @duration = 1000.0 * (@end - @time)
end
def parent_of?(event)
- start = (self.time - event.time) * 1000
+ start = (time - event.time) * 1000
start <= 0 && (start + duration >= event.duration)
end
end
diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb
index 6b563b9063..2e8d538d0b 100644
--- a/activesupport/lib/active_support/ordered_hash.rb
+++ b/activesupport/lib/active_support/ordered_hash.rb
@@ -4,8 +4,17 @@ YAML.add_builtin_type("omap") do |type, val|
ActiveSupport::OrderedHash[val.map(&:to_a).map(&:first)]
end
-# OrderedHash is namespaced to prevent conflicts with other implementations
module ActiveSupport
+ # The order of iteration over hashes in Ruby 1.8 is undefined. For example, you do not know the
+ # order in which +keys+ will return keys, or +each+ yield pairs. <tt>ActiveSupport::OrderedHash</tt>
+ # implements a hash that preserves insertion order, as in Ruby 1.9:
+ #
+ # oh = ActiveSupport::OrderedHash.new
+ # oh[:a] = 1
+ # oh[:b] = 2
+ # oh.keys # => [:a, :b], this order is guaranteed
+ #
+ # <tt>ActiveSupport::OrderedHash</tt> is namespaced to prevent conflicts with other implementations.
class OrderedHash < ::Hash #:nodoc:
def to_yaml_type
"!tag:yaml.org,2002:omap"
diff --git a/activesupport/lib/active_support/ordered_options.rb b/activesupport/lib/active_support/ordered_options.rb
index 61ccb79211..7fc2b45b51 100644
--- a/activesupport/lib/active_support/ordered_options.rb
+++ b/activesupport/lib/active_support/ordered_options.rb
@@ -1,5 +1,21 @@
require 'active_support/ordered_hash'
+# Usually key value pairs are handled something like this:
+#
+# h = ActiveSupport::OrderedOptions.new
+# h[:boy] = 'John'
+# h[:girl] = 'Mary'
+# h[:boy] # => 'John'
+# h[:girl] # => 'Mary'
+#
+# Using <tt>OrderedOptions</tt> above code could be reduced to:
+#
+# h = ActiveSupport::OrderedOptions.new
+# h.boy = 'John'
+# h.girl = 'Mary'
+# h.boy # => 'John'
+# h.girl # => 'Mary'
+#
module ActiveSupport #:nodoc:
class OrderedOptions < OrderedHash
def []=(key, value)
diff --git a/activesupport/lib/active_support/secure_random.rb b/activesupport/lib/active_support/secure_random.rb
index cfbce4d754..73344498cb 100644
--- a/activesupport/lib/active_support/secure_random.rb
+++ b/activesupport/lib/active_support/secure_random.rb
@@ -26,25 +26,25 @@ module ActiveSupport
# == Example
#
# # random hexadecimal string.
- # p SecureRandom.hex(10) #=> "52750b30ffbc7de3b362"
- # p SecureRandom.hex(10) #=> "92b15d6c8dc4beb5f559"
- # p SecureRandom.hex(11) #=> "6aca1b5c58e4863e6b81b8"
- # p SecureRandom.hex(12) #=> "94b2fff3e7fd9b9c391a2306"
- # p SecureRandom.hex(13) #=> "39b290146bea6ce975c37cfc23"
+ # p SecureRandom.hex(10) # => "52750b30ffbc7de3b362"
+ # p SecureRandom.hex(10) # => "92b15d6c8dc4beb5f559"
+ # p SecureRandom.hex(11) # => "6aca1b5c58e4863e6b81b8"
+ # p SecureRandom.hex(12) # => "94b2fff3e7fd9b9c391a2306"
+ # p SecureRandom.hex(13) # => "39b290146bea6ce975c37cfc23"
# ...
#
# # random base64 string.
- # p SecureRandom.base64(10) #=> "EcmTPZwWRAozdA=="
- # p SecureRandom.base64(10) #=> "9b0nsevdwNuM/w=="
- # p SecureRandom.base64(10) #=> "KO1nIU+p9DKxGg=="
- # p SecureRandom.base64(11) #=> "l7XEiFja+8EKEtY="
- # p SecureRandom.base64(12) #=> "7kJSM/MzBJI+75j8"
- # p SecureRandom.base64(13) #=> "vKLJ0tXBHqQOuIcSIg=="
+ # p SecureRandom.base64(10) # => "EcmTPZwWRAozdA=="
+ # p SecureRandom.base64(10) # => "9b0nsevdwNuM/w=="
+ # p SecureRandom.base64(10) # => "KO1nIU+p9DKxGg=="
+ # p SecureRandom.base64(11) # => "l7XEiFja+8EKEtY="
+ # p SecureRandom.base64(12) # => "7kJSM/MzBJI+75j8"
+ # p SecureRandom.base64(13) # => "vKLJ0tXBHqQOuIcSIg=="
# ...
#
# # random binary string.
- # p SecureRandom.random_bytes(10) #=> "\016\t{\370g\310pbr\301"
- # p SecureRandom.random_bytes(10) #=> "\323U\030TO\234\357\020\a\337"
+ # p SecureRandom.random_bytes(10) # => "\016\t{\370g\310pbr\301"
+ # p SecureRandom.random_bytes(10) # => "\323U\030TO\234\357\020\a\337"
# ...
module SecureRandom
# SecureRandom.random_bytes generates a random binary string.
diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb
index d8942c3974..b2d9ddfeb7 100644
--- a/activesupport/lib/active_support/testing/setup_and_teardown.rb
+++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb
@@ -96,7 +96,7 @@ module ActiveSupport
protected
def retrieve_mocha_counter(result) #:nodoc:
- if using_mocha = respond_to?(:mocha_verify)
+ if respond_to?(:mocha_verify) # using mocha
if defined?(Mocha::TestCaseAdapter::AssertionCounter)
Mocha::TestCaseAdapter::AssertionCounter.new(result)
else
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index 62d02bdeb6..ad6c3de1f5 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -5,9 +5,9 @@ module ActiveSupport
# A Time-like class that can represent a time in any time zone. Necessary because standard Ruby Time instances are
# limited to UTC and the system's <tt>ENV['TZ']</tt> zone.
#
- # You shouldn't ever need to create a TimeWithZone instance directly via <tt>new</tt> -- instead, Rails provides the methods
- # +local+, +parse+, +at+ and +now+ on TimeZone instances, and +in_time_zone+ on Time and DateTime instances, for a more
- # user-friendly syntax. Examples:
+ # You shouldn't ever need to create a TimeWithZone instance directly via <tt>new</tt> . Instead use methods
+ # +local+, +parse+, +at+ and +now+ on TimeZone instances, and +in_time_zone+ on Time and DateTime instances.
+ # Examples:
#
# Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
# Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
@@ -18,7 +18,8 @@ module ActiveSupport
#
# See Time and TimeZone for further documentation of these methods.
#
- # TimeWithZone instances implement the same API as Ruby Time instances, so that Time and TimeWithZone instances are interchangeable. Examples:
+ # TimeWithZone instances implement the same API as Ruby Time instances, so that Time and TimeWithZone instances are interchangeable.
+ # Examples:
#
# t = Time.zone.now # => Sun, 18 May 2008 13:27:25 EDT -04:00
# t.hour # => 13
@@ -113,8 +114,8 @@ module ActiveSupport
end
alias_method :iso8601, :xmlschema
- # Coerces the date to a string for JSON encoding. The default format is ISO 8601. You can get
- # %Y/%m/%d %H:%M:%S +offset style by setting ActiveSupport::JSON::Encoding.use_standard_json_time_format
+ # Coerces time to a string for JSON encoding. The default format is ISO 8601. You can get
+ # %Y/%m/%d %H:%M:%S +offset style by setting <tt>ActiveSupport::JSON::Encoding.use_standard_json_time_format</tt>
# to false.
#
# ==== Examples
diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb
index 49dd8a1b99..abd585b64f 100644
--- a/activesupport/lib/active_support/values/time_zone.rb
+++ b/activesupport/lib/active_support/values/time_zone.rb
@@ -8,10 +8,10 @@ require 'active_support/core_ext/object/try'
# * Lazily load TZInfo::Timezone instances only when they're needed.
# * Create ActiveSupport::TimeWithZone instances via TimeZone's +local+, +parse+, +at+ and +now+ methods.
#
-# If you set <tt>config.time_zone</tt> in the Rails Initializer, you can access this TimeZone object via <tt>Time.zone</tt>:
+# If you set <tt>config.time_zone</tt> in the Rails Application, you can access this TimeZone object via <tt>Time.zone</tt>:
#
-# # environment.rb:
-# Rails::Initializer.run do |config|
+# # application.rb:
+# class Application < Rails::Application
# config.time_zone = "Eastern Time (US & Canada)"
# end
#
diff --git a/activesupport/lib/active_support/version.rb b/activesupport/lib/active_support/version.rb
index 52612c27cb..9d2cf13260 100644
--- a/activesupport/lib/active_support/version.rb
+++ b/activesupport/lib/active_support/version.rb
@@ -3,7 +3,7 @@ module ActiveSupport
MAJOR = 3
MINOR = 0
TINY = 0
- BUILD = "beta4"
+ BUILD = "rc"
STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
end
diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb
index 7594d7b68b..352172027b 100644
--- a/activesupport/lib/active_support/xml_mini.rb
+++ b/activesupport/lib/active_support/xml_mini.rb
@@ -9,7 +9,7 @@ module ActiveSupport
module XmlMini
extend self
- # This module exists to decorate files deserialized using Hash.from_xml with
+ # This module decorates files deserialized using Hash.from_xml with
# the <tt>original_filename</tt> and <tt>content_type</tt> methods.
module FileLike #:nodoc:
attr_writer :original_filename, :content_type
@@ -129,12 +129,16 @@ module ActiveSupport
camelize = options.has_key?(:camelize) && options[:camelize]
dasherize = !options.has_key?(:dasherize) || options[:dasherize]
key = key.camelize if camelize
- key = key.dasherize if dasherize
+ key = _dasherize(key) if dasherize
key
end
protected
+ def _dasherize(key)
+ key.gsub(/(?!^[_]*)_(?![_]*$)/, '-')
+ end
+
# TODO: Add support for other encodings
def _parse_binary(bin, entity) #:nodoc:
case entity['encoding']
diff --git a/activesupport/lib/active_support/xml_mini/libxml.rb b/activesupport/lib/active_support/xml_mini/libxml.rb
index 9cf187302f..7fdcb11465 100644
--- a/activesupport/lib/active_support/xml_mini/libxml.rb
+++ b/activesupport/lib/active_support/xml_mini/libxml.rb
@@ -1,5 +1,4 @@
require 'libxml'
-require 'active_support/core_ext/object/returning'
require 'active_support/core_ext/object/blank'
# = XmlMini LibXML implementation
diff --git a/activesupport/lib/active_support/xml_mini/nokogiri.rb b/activesupport/lib/active_support/xml_mini/nokogiri.rb
index eb61a7fc22..e03a744257 100644
--- a/activesupport/lib/active_support/xml_mini/nokogiri.rb
+++ b/activesupport/lib/active_support/xml_mini/nokogiri.rb
@@ -1,4 +1,9 @@
-require 'nokogiri'
+begin
+ require 'nokogiri'
+rescue LoadError => e
+ $stderr.puts "You don't have nokogiri installed in your application. Please add it to your Gemfile and run bundle install"
+ raise e
+end
require 'active_support/core_ext/object/blank'
# = XmlMini Nokogiri implementation
diff --git a/activesupport/lib/active_support/xml_mini/nokogirisax.rb b/activesupport/lib/active_support/xml_mini/nokogirisax.rb
index 8af7b5e565..38c8685390 100644
--- a/activesupport/lib/active_support/xml_mini/nokogirisax.rb
+++ b/activesupport/lib/active_support/xml_mini/nokogirisax.rb
@@ -1,4 +1,9 @@
-require 'nokogiri'
+begin
+ require 'nokogiri'
+rescue LoadError => e
+ $stderr.puts "You don't have nokogiri installed in your application. Please add it to your Gemfile and run bundle install"
+ raise e
+end
require 'active_support/core_ext/object/blank'
# = XmlMini Nokogiri implementation using a SAX-based parser
@@ -80,4 +85,4 @@ module ActiveSupport
end
end
end
-end \ No newline at end of file
+end
diff --git a/activesupport/test/autoloading_fixtures/load_path/loaded_constant.rb b/activesupport/test/autoloading_fixtures/load_path/loaded_constant.rb
new file mode 100644
index 0000000000..e3d1218c96
--- /dev/null
+++ b/activesupport/test/autoloading_fixtures/load_path/loaded_constant.rb
@@ -0,0 +1,3 @@
+module LoadedConstant
+end
+
diff --git a/activesupport/test/autoloading_fixtures/loads_constant.rb b/activesupport/test/autoloading_fixtures/loads_constant.rb
new file mode 100644
index 0000000000..0b30dc8bca
--- /dev/null
+++ b/activesupport/test/autoloading_fixtures/loads_constant.rb
@@ -0,0 +1,5 @@
+module LoadsConstant
+end
+
+# The _ = assignment is to prevent warnings
+_ = RequiresConstant
diff --git a/activesupport/test/autoloading_fixtures/requires_constant.rb b/activesupport/test/autoloading_fixtures/requires_constant.rb
new file mode 100644
index 0000000000..14804a0de0
--- /dev/null
+++ b/activesupport/test/autoloading_fixtures/requires_constant.rb
@@ -0,0 +1,5 @@
+require "loaded_constant"
+
+module RequiresConstant
+end
+
diff --git a/activesupport/test/buffered_logger_test.rb b/activesupport/test/buffered_logger_test.rb
index 850febb959..97c0ef14db 100644
--- a/activesupport/test/buffered_logger_test.rb
+++ b/activesupport/test/buffered_logger_test.rb
@@ -1,9 +1,12 @@
require 'abstract_unit'
+require 'multibyte_test_helpers'
require 'stringio'
require 'fileutils'
require 'active_support/buffered_logger'
class BufferedLoggerTest < Test::Unit::TestCase
+ include MultibyteTestHelpers
+
Logger = ActiveSupport::BufferedLogger
def setup
@@ -146,4 +149,16 @@ class BufferedLoggerTest < Test::Unit::TestCase
@logger.expects :clear_buffer
@logger.flush
end
+
+ def test_buffer_multibyte
+ @logger.auto_flushing = 2
+ @logger.info(UNICODE_STRING)
+ @logger.info(BYTE_STRING)
+ assert @output.string.include?(UNICODE_STRING)
+ byte_string = @output.string.dup
+ if byte_string.respond_to?(:force_encoding)
+ byte_string.force_encoding("ASCII-8BIT")
+ end
+ assert byte_string.include?(BYTE_STRING)
+ end
end
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index 3e14c754b7..b79a7bbaec 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -7,6 +7,49 @@ class CacheKeyTest < ActiveSupport::TestCase
assert_equal '1/2/true', ActiveSupport::Cache.expand_cache_key([1, '2', true])
assert_equal 'name/1/2/true', ActiveSupport::Cache.expand_cache_key([1, '2', true], :name)
end
+
+ def test_expand_cache_key_with_rails_cache_id
+ begin
+ ENV['RAILS_CACHE_ID'] = 'c99'
+ assert_equal 'c99/foo', ActiveSupport::Cache.expand_cache_key(:foo)
+ assert_equal 'c99/foo', ActiveSupport::Cache.expand_cache_key([:foo])
+ assert_equal 'c99/c99/foo/c99/bar', ActiveSupport::Cache.expand_cache_key([:foo, :bar])
+ assert_equal 'nm/c99/foo', ActiveSupport::Cache.expand_cache_key(:foo, :nm)
+ assert_equal 'nm/c99/foo', ActiveSupport::Cache.expand_cache_key([:foo], :nm)
+ assert_equal 'nm/c99/c99/foo/c99/bar', ActiveSupport::Cache.expand_cache_key([:foo, :bar], :nm)
+ ensure
+ ENV['RAILS_CACHE_ID'] = nil
+ end
+ end
+
+ def test_expand_cache_key_with_rails_app_version
+ begin
+ ENV['RAILS_APP_VERSION'] = 'rails3'
+ assert_equal 'rails3/foo', ActiveSupport::Cache.expand_cache_key(:foo)
+ ensure
+ ENV['RAILS_APP_VERSION'] = nil
+ end
+ end
+
+ def test_expand_cache_key_rails_cache_id_should_win_over_rails_app_version
+ begin
+ ENV['RAILS_CACHE_ID'] = 'c99'
+ ENV['RAILS_APP_VERSION'] = 'rails3'
+ assert_equal 'c99/foo', ActiveSupport::Cache.expand_cache_key(:foo)
+ ensure
+ ENV['RAILS_CACHE_ID'] = nil
+ ENV['RAILS_APP_VERSION'] = nil
+ end
+ end
+
+ def test_respond_to_cache_key
+ key = 'foo'
+ def key.cache_key
+ :foo_key
+ end
+ assert_equal 'foo_key', ActiveSupport::Cache.expand_cache_key(key)
+ end
+
end
class CacheStoreSettingTest < ActiveSupport::TestCase
@@ -279,7 +322,7 @@ module CacheStoreBehavior
assert_equal 'bar', @cache.read('foo')
raise ArgumentError.new
end
- rescue ArgumentError => e
+ rescue ArgumentError
end
assert_equal "bar", @cache.read('foo')
Time.stubs(:now).returns(time + 71)
diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb
index 54376deee5..009a254c64 100644
--- a/activesupport/test/core_ext/array_ext_test.rb
+++ b/activesupport/test/core_ext/array_ext_test.rb
@@ -398,6 +398,18 @@ class ArrayWrapperTests < Test::Unit::TestCase
def method_missing(*a) @target.send(*a) end
end
+ class DoubtfulToAry
+ def to_ary
+ :not_an_array
+ end
+ end
+
+ class NilToAry
+ def to_ary
+ nil
+ end
+ end
+
def test_array
ary = %w(foo bar)
assert_same ary, Array.wrap(ary)
@@ -438,4 +450,12 @@ class ArrayWrapperTests < Test::Unit::TestCase
o = Struct.new(:foo).new(123)
assert_equal [o], Array.wrap(o)
end
+
+ def test_wrap_returns_nil_if_to_ary_returns_nil
+ assert_nil Array.wrap(NilToAry.new)
+ end
+
+ def test_wrap_does_not_complain_if_to_ary_does_not_return_an_array
+ assert_equal DoubtfulToAry.new.to_ary, Array.wrap(DoubtfulToAry.new)
+ end
end
diff --git a/activesupport/test/core_ext/class_test.rb b/activesupport/test/core_ext/class_test.rb
index 08bb13dd35..60ba3b8f88 100644
--- a/activesupport/test/core_ext/class_test.rb
+++ b/activesupport/test/core_ext/class_test.rb
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'active_support/core_ext/class'
+require 'set'
class ClassTest < Test::Unit::TestCase
class Parent; end
@@ -12,16 +13,16 @@ class ClassTest < Test::Unit::TestCase
class C < B; end
def test_descendants
- assert_equal [Foo, Bar, Baz, A, B, C], Parent.descendants
- assert_equal [Bar, Baz], Foo.descendants
+ assert_equal [Foo, Bar, Baz, A, B, C].to_set, Parent.descendants.to_set
+ assert_equal [Bar, Baz].to_set, Foo.descendants.to_set
assert_equal [Baz], Bar.descendants
assert_equal [], Baz.descendants
end
def test_subclasses
- assert_equal [Foo, A], Parent.subclasses
+ assert_equal [Foo, A].to_set, Parent.subclasses.to_set
assert_equal [Bar], Foo.subclasses
assert_equal [Baz], Bar.subclasses
assert_equal [], Baz.subclasses
end
-end \ No newline at end of file
+end
diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb
index 19d7935211..e8506f5222 100644
--- a/activesupport/test/core_ext/date_time_ext_test.rb
+++ b/activesupport/test/core_ext/date_time_ext_test.rb
@@ -171,22 +171,29 @@ class DateTimeExtCalculationsTest < Test::Unit::TestCase
end
def test_advance
- assert_equal DateTime.civil(2006,2,28,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:years => 1)
- assert_equal DateTime.civil(2005,6,28,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:months => 4)
- assert_equal DateTime.civil(2005,3,21,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:weeks => 3)
- assert_equal DateTime.civil(2005,3,5,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:days => 5)
- assert_equal DateTime.civil(2012,9,28,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:years => 7, :months => 7)
- assert_equal DateTime.civil(2013,10,3,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :days => 5)
+ assert_equal DateTime.civil(2006,2,28,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:years => 1)
+ assert_equal DateTime.civil(2005,6,28,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:months => 4)
+ assert_equal DateTime.civil(2005,3,21,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:weeks => 3)
+ assert_equal DateTime.civil(2005,3,5,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:days => 5)
+ assert_equal DateTime.civil(2012,9,28,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:years => 7, :months => 7)
+ assert_equal DateTime.civil(2013,10,3,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :days => 5)
assert_equal DateTime.civil(2013,10,17,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :weeks => 2, :days => 5)
assert_equal DateTime.civil(2001,12,27,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:years => -3, :months => -2, :days => -1)
- assert_equal DateTime.civil(2005,2,28,15,15,10), DateTime.civil(2004,2,29,15,15,10).advance(:years => 1) #leap day plus one year
- assert_equal DateTime.civil(2005,2,28,20,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:hours => 5)
- assert_equal DateTime.civil(2005,2,28,15,22,10), DateTime.civil(2005,2,28,15,15,10).advance(:minutes => 7)
- assert_equal DateTime.civil(2005,2,28,15,15,19), DateTime.civil(2005,2,28,15,15,10).advance(:seconds => 9)
- assert_equal DateTime.civil(2005,2,28,20,22,19), DateTime.civil(2005,2,28,15,15,10).advance(:hours => 5, :minutes => 7, :seconds => 9)
- assert_equal DateTime.civil(2005,2,28,10,8,1), DateTime.civil(2005,2,28,15,15,10).advance(:hours => -5, :minutes => -7, :seconds => -9)
+ assert_equal DateTime.civil(2005,2,28,15,15,10), DateTime.civil(2004,2,29,15,15,10).advance(:years => 1) #leap day plus one year
+ assert_equal DateTime.civil(2005,2,28,20,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:hours => 5)
+ assert_equal DateTime.civil(2005,2,28,15,22,10), DateTime.civil(2005,2,28,15,15,10).advance(:minutes => 7)
+ assert_equal DateTime.civil(2005,2,28,15,15,19), DateTime.civil(2005,2,28,15,15,10).advance(:seconds => 9)
+ assert_equal DateTime.civil(2005,2,28,20,22,19), DateTime.civil(2005,2,28,15,15,10).advance(:hours => 5, :minutes => 7, :seconds => 9)
+ assert_equal DateTime.civil(2005,2,28,10,8,1), DateTime.civil(2005,2,28,15,15,10).advance(:hours => -5, :minutes => -7, :seconds => -9)
assert_equal DateTime.civil(2013,10,17,20,22,19), DateTime.civil(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :weeks => 2, :days => 5, :hours => 5, :minutes => 7, :seconds => 9)
+ end
+ def test_advanced_processes_first_the_date_deltas_and_then_the_time_deltas
+ # If the time deltas were processed first, the following datetimes would be advanced to 2010/04/01 instead.
+ assert_equal DateTime.civil(2010, 3, 29), DateTime.civil(2010, 2, 28, 23, 59, 59).advance(:months => 1, :seconds => 1)
+ assert_equal DateTime.civil(2010, 3, 29), DateTime.civil(2010, 2, 28, 23, 59).advance(:months => 1, :minutes => 1)
+ assert_equal DateTime.civil(2010, 3, 29), DateTime.civil(2010, 2, 28, 23).advance(:months => 1, :hours => 1)
+ assert_equal DateTime.civil(2010, 3, 29), DateTime.civil(2010, 2, 28, 22, 58, 59).advance(:months => 1, :hours => 1, :minutes => 1, :seconds => 1)
end
def test_next_week
diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb
index 7b2c10908f..5d9846a216 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -2,6 +2,8 @@ require 'abstract_unit'
require 'active_support/core_ext/hash'
require 'bigdecimal'
require 'active_support/core_ext/string/access'
+require 'active_support/ordered_hash'
+require 'active_support/core_ext/object/conversions'
class HashExtTest < Test::Unit::TestCase
def setup
@@ -449,6 +451,33 @@ class IWriteMyOwnXML
end
end
+class HashExtToParamTests < Test::Unit::TestCase
+ class ToParam < String
+ def to_param
+ "#{self}-1"
+ end
+ end
+
+ def test_string_hash
+ assert_equal '', {}.to_param
+ assert_equal 'hello=world', { :hello => "world" }.to_param
+ assert_equal 'hello=10', { "hello" => 10 }.to_param
+ assert_equal 'hello=world&say_bye=true', ActiveSupport::OrderedHash[:hello, "world", "say_bye", true].to_param
+ end
+
+ def test_number_hash
+ assert_equal '10=20&30=40&50=60', ActiveSupport::OrderedHash[10, 20, 30, 40, 50, 60].to_param
+ end
+
+ def test_to_param_hash
+ assert_equal 'custom=param-1&custom2=param2-1', ActiveSupport::OrderedHash[ToParam.new('custom'), ToParam.new('param'), ToParam.new('custom2'), ToParam.new('param2')].to_param
+ end
+
+ def test_to_param_hash_escapes_its_keys_and_values
+ assert_equal 'param+1=A+string+with+%2F+characters+%26+that+should+be+%3F+escaped', { 'param 1' => 'A string with / characters & that should be ? escaped' }.to_param
+ end
+end
+
class HashToXmlTest < Test::Unit::TestCase
def setup
@xml_options = { :root => :person, :skip_instruct => true, :indent => 0 }
diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb
index 39ee0ac748..5d9cdf22c2 100644
--- a/activesupport/test/core_ext/module_test.rb
+++ b/activesupport/test/core_ext/module_test.rb
@@ -147,7 +147,7 @@ class ModuleTest < Test::Unit::TestCase
end
assert_nothing_raised do
- child = Class.new(parent) do
+ Class.new(parent) do
class << self
delegate :parent_method, :to => :superclass
end
diff --git a/activesupport/test/core_ext/object/to_query_test.rb b/activesupport/test/core_ext/object/to_query_test.rb
index 4d655913cc..e28b4cd493 100644
--- a/activesupport/test/core_ext/object/to_query_test.rb
+++ b/activesupport/test/core_ext/object/to_query_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/ordered_hash'
require 'active_support/core_ext/object/to_query'
class ToQueryTest < Test::Unit::TestCase
@@ -18,12 +19,12 @@ class ToQueryTest < Test::Unit::TestCase
def test_nested_conversion
assert_query_equal 'person[login]=seckar&person[name]=Nicholas',
- :person => {:name => 'Nicholas', :login => 'seckar'}
+ :person => ActiveSupport::OrderedHash[:login, 'seckar', :name, 'Nicholas']
end
def test_multiple_nested
assert_query_equal 'account[person][id]=20&person[id]=10',
- :person => {:id => 10}, :account => {:person => {:id => 20}}
+ ActiveSupport::OrderedHash[:account, {:person => {:id => 20}}, :person, {:id => 10}]
end
def test_array_values
diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb
index c7088638c7..f98d823f00 100644
--- a/activesupport/test/dependencies_test.rb
+++ b/activesupport/test/dependencies_test.rb
@@ -117,6 +117,7 @@ class DependenciesTest < Test::Unit::TestCase
assert_equal true, $checked_verbose, 'After first load warnings should be left alone.'
assert ActiveSupport::Dependencies.loaded.include?(expanded)
+ ActiveSupport::Dependencies.warnings_on_first_load = old_warnings
end
end
@@ -212,6 +213,50 @@ class DependenciesTest < Test::Unit::TestCase
end
end
+ def test_doesnt_break_normal_require
+ path = File.expand_path("../autoloading_fixtures/load_path", __FILE__)
+ original_path = $:.dup
+ original_features = $".dup
+ $:.push(path)
+
+ with_autoloading_fixtures do
+ # The _ = assignments are to prevent warnings
+ _ = RequiresConstant
+ assert defined?(RequiresConstant)
+ assert defined?(LoadedConstant)
+ ActiveSupport::Dependencies.clear
+ _ = RequiresConstant
+ assert defined?(RequiresConstant)
+ assert defined?(LoadedConstant)
+ end
+ ensure
+ remove_constants(:RequiresConstant, :LoadedConstant, :LoadsConstant)
+ $".replace(original_features)
+ $:.replace(original_path)
+ end
+
+ def test_doesnt_break_normal_require_nested
+ path = File.expand_path("../autoloading_fixtures/load_path", __FILE__)
+ original_path = $:.dup
+ original_features = $".dup
+ $:.push(path)
+
+ with_autoloading_fixtures do
+ # The _ = assignments are to prevent warnings
+ _ = LoadsConstant
+ assert defined?(LoadsConstant)
+ assert defined?(LoadedConstant)
+ ActiveSupport::Dependencies.clear
+ _ = LoadsConstant
+ assert defined?(LoadsConstant)
+ assert defined?(LoadedConstant)
+ end
+ ensure
+ remove_constants(:RequiresConstant, :LoadedConstant, :LoadsConstant)
+ $".replace(original_features)
+ $:.replace(original_path)
+ end
+
def failing_test_access_thru_and_upwards_fails
with_autoloading_fixtures do
assert ! defined?(ModuleFolder)
@@ -418,7 +463,6 @@ class DependenciesTest < Test::Unit::TestCase
def test_removal_from_tree_should_be_detected
with_loading 'dependencies' do
- root = ActiveSupport::Dependencies.autoload_paths.first
c = ServiceOne
ActiveSupport::Dependencies.clear
assert ! defined?(ServiceOne)
@@ -433,7 +477,6 @@ class DependenciesTest < Test::Unit::TestCase
def test_references_should_work
with_loading 'dependencies' do
- root = ActiveSupport::Dependencies.autoload_paths.first
c = ActiveSupport::Dependencies.ref("ServiceOne")
service_one_first = ServiceOne
assert_equal service_one_first, c.get
@@ -798,4 +841,11 @@ class DependenciesTest < Test::Unit::TestCase
ensure
ActiveSupport::Dependencies.hook!
end
+
+private
+ def remove_constants(*constants)
+ constants.each do |constant|
+ Object.send(:remove_const, constant) if Object.const_defined?(constant)
+ end
+ end
end
diff --git a/activesupport/test/deprecation/proxy_wrappers_test.rb b/activesupport/test/deprecation/proxy_wrappers_test.rb
new file mode 100644
index 0000000000..aa887f274d
--- /dev/null
+++ b/activesupport/test/deprecation/proxy_wrappers_test.rb
@@ -0,0 +1,22 @@
+require 'abstract_unit'
+require 'active_support/deprecation'
+
+class ProxyWrappersTest < Test::Unit::TestCase
+ Waffles = false
+ NewWaffles = :hamburgers
+
+ def test_deprecated_object_proxy_doesnt_wrap_falsy_objects
+ proxy = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(nil, "message")
+ assert !proxy
+ end
+
+ def test_deprecated_instance_variable_proxy_doesnt_wrap_falsy_objects
+ proxy = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(nil, :waffles)
+ assert !proxy
+ end
+
+ def test_deprecated_constant_proxy_doesnt_wrap_falsy_objects
+ proxy = ActiveSupport::Deprecation::DeprecatedConstantProxy.new(Waffles, NewWaffles)
+ assert !proxy
+ end
+end
diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb
index a679efb41e..1527d02d16 100644
--- a/activesupport/test/json/encoding_test.rb
+++ b/activesupport/test/json/encoding_test.rb
@@ -148,7 +148,7 @@ class TestJSONEncoding < Test::Unit::TestCase
:latitude => 123.234
}
}
- result = ActiveSupport::JSON.encode(hash)
+ ActiveSupport::JSON.encode(hash)
end
end
diff --git a/activesupport/test/load_paths_test.rb b/activesupport/test/load_paths_test.rb
index 9c83d6f061..36e3726a02 100644
--- a/activesupport/test/load_paths_test.rb
+++ b/activesupport/test/load_paths_test.rb
@@ -8,8 +8,8 @@ class LoadPathsTest < Test::Unit::TestCase
paths[expanded_path] += 1
paths
}
+ load_paths_count[File.expand_path('../../lib', __FILE__)] -= 1
- # CI has a bunch of duplicate load paths
- # assert_equal [], load_paths_count.select { |k, v| v > 1 }, $LOAD_PATH.inspect
+ assert load_paths_count.select { |k, v| v > 1 }.empty?, $LOAD_PATH.inspect
end
end
diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb
index 195e3eaa42..b11fa8d346 100644
--- a/activesupport/test/memoizable_test.rb
+++ b/activesupport/test/memoizable_test.rb
@@ -134,7 +134,6 @@ class MemoizableTest < ActiveSupport::TestCase
end
def test_reloadable
- counter = @calculator.counter
assert_equal 1, @calculator.counter
assert_equal 2, @calculator.counter(:reload)
assert_equal 2, @calculator.counter
diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb
index 78232d8eb5..6ebbfdf334 100644
--- a/activesupport/test/multibyte_chars_test.rb
+++ b/activesupport/test/multibyte_chars_test.rb
@@ -234,7 +234,7 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase
def test_include_raises_when_nil_is_passed
@chars.include?(nil)
flunk "Expected chars.include?(nil) to raise TypeError or NoMethodError"
- rescue Exception => e
+ rescue Exception
end
def test_index_should_return_character_offset
diff --git a/activesupport/test/multibyte_test_helpers.rb b/activesupport/test/multibyte_test_helpers.rb
index 597f949059..8839b75601 100644
--- a/activesupport/test/multibyte_test_helpers.rb
+++ b/activesupport/test/multibyte_test_helpers.rb
@@ -4,6 +4,9 @@ module MultibyteTestHelpers
UNICODE_STRING = 'こにちわ'
ASCII_STRING = 'ohayo'
BYTE_STRING = "\270\236\010\210\245"
+ if BYTE_STRING.respond_to?(:force_encoding)
+ BYTE_STRING.force_encoding("ASCII-8BIT")
+ end
def chars(str)
ActiveSupport::Multibyte::Chars.new(str)
@@ -16,4 +19,4 @@ module MultibyteTestHelpers
def assert_equal_codepoints(expected, actual, message=nil)
assert_equal(inspect_codepoints(expected), inspect_codepoints(actual), message)
end
-end \ No newline at end of file
+end
diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb
index e11de5f67a..9faa11efbc 100644
--- a/activesupport/test/notifications_test.rb
+++ b/activesupport/test/notifications_test.rb
@@ -11,14 +11,11 @@ module Notifications
@named_subscription = @notifier.subscribe("named.subscription") { |*args| @named_events << event(*args) }
end
- private
- def event(*args)
- ActiveSupport::Notifications::Event.new(*args)
- end
+ private
- def drain
- @notifier.wait
- end
+ def event(*args)
+ ActiveSupport::Notifications::Event.new(*args)
+ end
end
class UnsubscribeTest < TestCase
@@ -132,13 +129,10 @@ module Notifications
def test_instrument_returns_block_result
assert_equal 2, instrument(:awesome) { 1 + 1 }
- drain
end
def test_instrument_yields_the_paylod_for_further_modification
assert_equal 2, instrument(:awesome) { |p| p[:result] = 1 + 1 }
- drain
-
assert_equal 1, @events.size
assert_equal :awesome, @events.first.name
assert_equal Hash[:result => 2], @events.first.payload
@@ -154,15 +148,11 @@ module Notifications
1 + 1
end
- drain
-
assert_equal 1, @events.size
assert_equal :wot, @events.first.name
assert_equal Hash[:payload => "child"], @events.first.payload
end
- drain
-
assert_equal 2, @events.size
assert_equal :awesome, @events.last.name
assert_equal Hash[:payload => "notifications"], @events.last.payload
@@ -177,7 +167,6 @@ module Notifications
assert_equal "FAIL", e.message
end
- drain
assert_equal 1, @events.size
assert_equal Hash[:payload => "notifications",
:exception => ["RuntimeError", "FAIL"]], @events.last.payload
@@ -185,8 +174,6 @@ module Notifications
def test_event_is_pushed_even_without_block
instrument(:awesome, :payload => "notifications")
- drain
-
assert_equal 1, @events.size
assert_equal :awesome, @events.last.name
assert_equal Hash[:payload => "notifications"], @events.last.payload
@@ -198,9 +185,9 @@ module Notifications
time = Time.now
event = event(:foo, time, time + 0.01, random_id, {})
- assert_equal :foo, event.name
- assert_equal time, event.time
- assert_equal 10.0, event.duration
+ assert_equal :foo, event.name
+ assert_equal time, event.time
+ assert_in_delta 10.0, event.duration, 0.00001
end
def test_events_consumes_information_given_as_payload
diff --git a/activesupport/test/option_merger_test.rb b/activesupport/test/option_merger_test.rb
index b898292c9c..33e3e69666 100644
--- a/activesupport/test/option_merger_test.rb
+++ b/activesupport/test/option_merger_test.rb
@@ -1,5 +1,5 @@
require 'abstract_unit'
-require 'active_support/core_ext/object/misc'
+require 'active_support/core_ext/object/with_options'
class OptionMergerTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb
index d340bed444..f47e896487 100644
--- a/activesupport/test/ordered_hash_test.rb
+++ b/activesupport/test/ordered_hash_test.rb
@@ -214,7 +214,7 @@ class OrderedHashTest < Test::Unit::TestCase
def test_alternate_initialization_raises_exception_on_odd_length_args
begin
- alternate = ActiveSupport::OrderedHash[1,2,3,4,5]
+ ActiveSupport::OrderedHash[1,2,3,4,5]
flunk "Hash::[] should have raised an exception on initialization " +
"with an odd number of parameters"
rescue
diff --git a/activesupport/test/rescuable_test.rb b/activesupport/test/rescuable_test.rb
index ff77e16edd..1c74ce8b2a 100644
--- a/activesupport/test/rescuable_test.rb
+++ b/activesupport/test/rescuable_test.rb
@@ -9,11 +9,16 @@ end
class MadRonon < StandardError
end
+class CoolError < StandardError
+end
+
class Stargate
attr_accessor :result
include ActiveSupport::Rescuable
+ rescue_from WraithAttack, :with => :sos_first
+
rescue_from WraithAttack, :with => :sos
rescue_from NuclearExplosion do
@@ -45,11 +50,30 @@ class Stargate
def sos
@result = 'killed'
end
+
+ def sos_first
+ @result = 'sos_first'
+ end
+
+end
+
+class CoolStargate < Stargate
+ attr_accessor :result
+
+ include ActiveSupport::Rescuable
+
+ rescue_from CoolError, :with => :sos_cool_error
+
+ def sos_cool_error
+ @result = 'sos_cool_error'
+ end
end
+
class RescueableTest < Test::Unit::TestCase
def setup
@stargate = Stargate.new
+ @cool_stargate = CoolStargate.new
end
def test_rescue_from_with_method
@@ -66,4 +90,17 @@ class RescueableTest < Test::Unit::TestCase
@stargate.dispatch :ronanize
assert_equal 'dex', @stargate.result
end
+
+ def test_rescues_defined_later_are_added_at_end_of_the_rescue_handlers_array
+ expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon"]
+ result = @stargate.send(:rescue_handlers).collect {|e| e.first}
+ assert_equal expected, result
+ end
+
+ def test_children_should_inherit_rescue_defintions_from_parents_and_child_rescue_should_be_appended
+ expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon", "CoolError"]
+ result = @cool_stargate.send(:rescue_handlers).collect {|e| e.first}
+ assert_equal expected, result
+ end
+
end
diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb
index 3092fe01ae..633d3b212b 100644
--- a/activesupport/test/test_test.rb
+++ b/activesupport/test/test_test.rb
@@ -49,8 +49,8 @@ class AssertDifferenceTest < ActiveSupport::TestCase
end
def test_expression_is_evaluated_in_the_appropriate_scope
- local_scope = 'foo'
silence_warnings do
+ local_scope = 'foo'
assert_difference('local_scope; @object.num') { @object.increment }
end
end
diff --git a/activesupport/test/test_xml_mini.rb b/activesupport/test/test_xml_mini.rb
new file mode 100644
index 0000000000..585eb15c6e
--- /dev/null
+++ b/activesupport/test/test_xml_mini.rb
@@ -0,0 +1,49 @@
+require 'abstract_unit'
+require 'active_support/xml_mini'
+
+class XmlMiniTest < Test::Unit::TestCase
+ def test_rename_key_dasherizes_by_default
+ assert_equal "my-key", ActiveSupport::XmlMini.rename_key("my_key")
+ end
+
+ def test_rename_key_does_nothing_with_dasherize_true
+ assert_equal "my-key", ActiveSupport::XmlMini.rename_key("my_key", :dasherize => true)
+ end
+
+ def test_rename_key_does_nothing_with_dasherize_false
+ assert_equal "my_key", ActiveSupport::XmlMini.rename_key("my_key", :dasherize => false)
+ end
+
+ def test_rename_key_camelizes_with_camelize_true
+ assert_equal "MyKey", ActiveSupport::XmlMini.rename_key("my_key", :camelize => true)
+ end
+
+ def test_rename_key_camelizes_with_camelize_true
+ assert_equal "MyKey", ActiveSupport::XmlMini.rename_key("my_key", :camelize => true)
+ end
+
+ def test_rename_key_does_not_dasherize_leading_underscores
+ assert_equal "_id", ActiveSupport::XmlMini.rename_key("_id")
+ end
+
+ def test_rename_key_with_leading_underscore_dasherizes_interior_underscores
+ assert_equal "_my-key", ActiveSupport::XmlMini.rename_key("_my_key")
+ end
+
+ def test_rename_key_does_not_dasherize_trailing_underscores
+ assert_equal "id_", ActiveSupport::XmlMini.rename_key("id_")
+ end
+
+ def test_rename_key_with_trailing_underscore_dasherizes_interior_underscores
+ assert_equal "my-key_", ActiveSupport::XmlMini.rename_key("my_key_")
+ end
+
+ def test_rename_key_does_not_dasherize_multiple_leading_underscores
+ assert_equal "__id", ActiveSupport::XmlMini.rename_key("__id")
+ end
+
+ def test_rename_key_does_not_dasherize_multiple_leading_underscores
+ assert_equal "id__", ActiveSupport::XmlMini.rename_key("id__")
+ end
+
+end