aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG36
-rw-r--r--activesupport/README.rdoc2
-rw-r--r--activesupport/activesupport.gemspec2
-rw-r--r--activesupport/lib/active_support.rb3
-rw-r--r--activesupport/lib/active_support/buffered_logger.rb15
-rw-r--r--activesupport/lib/active_support/cache/file_store.rb7
-rw-r--r--activesupport/lib/active_support/cache/mem_cache_store.rb10
-rw-r--r--activesupport/lib/active_support/callbacks.rb3
-rw-r--r--activesupport/lib/active_support/configurable.rb15
-rw-r--r--activesupport/lib/active_support/core_ext/array/access.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/array/random_access.rb13
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/date/conversions.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/zones.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/hash/conversions.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/hash/indifferent_access.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/object.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/object/blank.rb49
-rw-r--r--activesupport/lib/active_support/core_ext/object/duplicable.rb57
-rw-r--r--activesupport/lib/active_support/core_ext/object/inclusion.rb15
-rw-r--r--activesupport/lib/active_support/core_ext/object/try.rb18
-rw-r--r--activesupport/lib/active_support/core_ext/string.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/string/inquiry.rb13
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/time/marshal.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/time/zones.rb41
-rw-r--r--activesupport/lib/active_support/deprecation.rb2
-rw-r--r--activesupport/lib/active_support/deprecation/reporting.rb4
-rw-r--r--activesupport/lib/active_support/descendants_tracker.rb16
-rw-r--r--activesupport/lib/active_support/hash_with_indifferent_access.rb4
-rw-r--r--activesupport/lib/active_support/inflector/inflections.rb2
-rw-r--r--activesupport/lib/active_support/inflector/methods.rb8
-rw-r--r--activesupport/lib/active_support/json/backends/jsongem.rb47
-rw-r--r--activesupport/lib/active_support/json/backends/yajl.rb44
-rw-r--r--activesupport/lib/active_support/json/backends/yaml.rb111
-rw-r--r--activesupport/lib/active_support/json/decoding.rb60
-rw-r--r--activesupport/lib/active_support/json/encoding.rb5
-rw-r--r--activesupport/lib/active_support/log_subscriber.rb2
-rw-r--r--activesupport/lib/active_support/log_subscriber/test_helper.rb1
-rw-r--r--activesupport/lib/active_support/notifications/fanout.rb6
-rw-r--r--activesupport/lib/active_support/ordered_hash.rb4
-rw-r--r--activesupport/lib/active_support/railtie.rb2
-rw-r--r--activesupport/lib/active_support/test_case.rb9
-rw-r--r--activesupport/lib/active_support/testing/assertions.rb23
-rw-r--r--activesupport/lib/active_support/testing/mochaing.rb7
-rw-r--r--activesupport/lib/active_support/testing/pending.rb46
-rw-r--r--activesupport/lib/active_support/testing/performance.rb131
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb5
-rw-r--r--activesupport/lib/active_support/version.rb2
-rw-r--r--activesupport/lib/active_support/whiny_nil.rb2
-rw-r--r--activesupport/lib/active_support/xml_mini.rb5
-rw-r--r--activesupport/test/buffered_logger_test.rb39
-rw-r--r--activesupport/test/caching_test.rb38
-rw-r--r--activesupport/test/class_cache_test.rb2
-rw-r--r--activesupport/test/configurable_test.rb7
-rw-r--r--activesupport/test/core_ext/array_ext_test.rb2
-rw-r--r--activesupport/test/core_ext/duration_test.rb1
-rw-r--r--activesupport/test/core_ext/hash_ext_test.rb32
-rw-r--r--activesupport/test/core_ext/object/inclusion_test.rb50
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb6
-rw-r--r--activesupport/test/core_ext/time_ext_test.rb7
-rw-r--r--activesupport/test/core_ext/time_with_zone_test.rb47
-rw-r--r--activesupport/test/descendants_tracker_test_cases.rb (renamed from activesupport/test/descendants_tracker_test.rb)36
-rw-r--r--activesupport/test/descendants_tracker_with_autoloading_test.rb35
-rw-r--r--activesupport/test/descendants_tracker_without_autoloading_test.rb8
-rw-r--r--activesupport/test/file_watcher_test.rb233
-rw-r--r--activesupport/test/inflector_test.rb42
-rw-r--r--activesupport/test/inflector_test_cases.rb30
-rw-r--r--activesupport/test/json/decoding_test.rb17
-rw-r--r--activesupport/test/json/encoding_test.rb33
-rw-r--r--activesupport/test/multibyte_chars_test.rb1
-rw-r--r--activesupport/test/ordered_hash_test.rb6
-rw-r--r--activesupport/test/ordered_options_test.rb26
-rw-r--r--activesupport/test/transliterate_test.rb3
-rw-r--r--activesupport/test/xml_mini_test.rb (renamed from activesupport/test/test_xml_mini.rb)20
75 files changed, 884 insertions, 717 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 373236ce9a..b5b0af8e85 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,9 @@
*Rails 3.1.0 (unreleased)*
+* Add String#inquiry as a convenience method for turning a string into a StringInquirer object [DHH]
+
+* Add Object#in? to test if an object is included in another object [Prem Sichanugrist, Brian Morearty, John Reitano]
+
* LocalCache strategy is now a real middleware class, not an anonymous class
posing for pictures.
@@ -15,14 +19,44 @@ advantage of the new ClassCache.
* Added before_remove_const callback to ActiveSupport::Dependencies.remove_unloadable_constants! [Andrew White]
-*Rails 3.0.2 (unreleased)*
+* JSON decoding now uses the multi_json gem which also vendors a json engine called OkJson. The yaml backend has been removed in favor of OkJson as a default engine for 1.8.x, while the built in 1.9.x json implementation will be used by default. [Josh Kalderimis]
+
+
+*Rails 3.0.7 (April 18, 2011)*
+
+* Hash.from_xml no longer loses attributes on tags containing only whitespace [André Arko]
+
+
+*Rails 3.0.6 (April 5, 2011)
+
+* No changes.
+
+
+*Rails 3.0.5 (February 26, 2011)*
+
+* No changes.
+
+
+*Rails 3.0.4 (February 8, 2011)*
+
+* No changes.
+
+
+*Rails 3.0.3 (November 16, 2010)*
+
+* No changes.
+
+
+*Rails 3.0.2 (November 15, 2010)*
* Added before_remove_const callback to ActiveSupport::Dependencies.remove_unloadable_constants! [Andrew White]
+
*Rails 3.0.1 (October 15, 2010)*
* No Changes, just a version bump.
+
*Rails 3.0.0 (August 29, 2010)*
* Implemented String#strip_heredoc. [fxn]
diff --git a/activesupport/README.rdoc b/activesupport/README.rdoc
index 13ca4b3bf1..8bb15e849a 100644
--- a/activesupport/README.rdoc
+++ b/activesupport/README.rdoc
@@ -30,4 +30,4 @@ API documentation is at
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
+* https://github.com/rails/rails/issues
diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec
index df7f68fecf..c5b5b57dec 100644
--- a/activesupport/activesupport.gemspec
+++ b/activesupport/activesupport.gemspec
@@ -17,5 +17,5 @@ Gem::Specification.new do |s|
s.files = Dir['CHANGELOG', 'README.rdoc', 'lib/**/*']
s.require_path = 'lib'
- s.has_rdoc = true
+ s.add_dependency('multi_json', '~> 1.0')
end
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 6b662ac660..a846f81c12 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2005 David Heinemeier Hansson
+# Copyright (c) 2005-2011 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -42,7 +42,6 @@ module ActiveSupport
autoload :DescendantsTracker
autoload :FileUpdateChecker
- autoload :FileWatcher
autoload :LogSubscriber
autoload :Notifications
diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb
index e41731f3e7..a14f008be5 100644
--- a/activesupport/lib/active_support/buffered_logger.rb
+++ b/activesupport/lib/active_support/buffered_logger.rb
@@ -41,7 +41,7 @@ module ActiveSupport
def initialize(log, level = DEBUG)
@level = level
- @buffer = {}
+ @buffer = Hash.new { |h,k| h[k] = [] }
@auto_flushing = 1
@guard = Mutex.new
@@ -49,10 +49,12 @@ module ActiveSupport
@log = log
elsif File.exist?(log)
@log = open(log, (File::WRONLY | File::APPEND))
+ @log.binmode
@log.sync = true
else
FileUtils.mkdir_p(File.dirname(log))
@log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
+ @log.binmode
@log.sync = true
end
end
@@ -100,13 +102,8 @@ module ActiveSupport
def flush
@guard.synchronize do
- unless buffer.empty?
- old_buffer = buffer
- all_content = StringIO.new
- old_buffer.each do |content|
- all_content << content
- end
- @log.write(all_content.string)
+ buffer.each do |content|
+ @log.write(content)
end
# Important to do this even if buffer was empty or else @buffer will
@@ -127,7 +124,7 @@ module ActiveSupport
end
def buffer
- @buffer[Thread.current] ||= []
+ @buffer[Thread.current]
end
def clear_buffer
diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb
index 18182bbb40..a1376ae52a 100644
--- a/activesupport/lib/active_support/cache/file_store.rb
+++ b/activesupport/lib/active_support/cache/file_store.rb
@@ -1,5 +1,6 @@
require 'active_support/core_ext/file/atomic'
require 'active_support/core_ext/string/conversions'
+require 'active_support/core_ext/object/inclusion'
require 'rack/utils'
module ActiveSupport
@@ -20,7 +21,7 @@ module ActiveSupport
end
def clear(options = nil)
- root_dirs = Dir.entries(cache_path).reject{|f| ['.', '..'].include?(f)}
+ root_dirs = Dir.entries(cache_path).reject{|f| f.in?(['.', '..'])}
FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)})
end
@@ -120,7 +121,7 @@ module ActiveSupport
# Lock a file for a block so only one process can modify it at a time.
def lock_file(file_name, &block) # :nodoc:
if File.exist?(file_name)
- File.open(file_name, 'r') do |f|
+ File.open(file_name, 'r+') do |f|
begin
f.flock File::LOCK_EX
yield
@@ -161,7 +162,7 @@ module ActiveSupport
# Delete empty directories in the cache.
def delete_empty_directories(dir)
return if dir == cache_path
- if Dir.entries(dir).reject{|f| ['.', '..'].include?(f)}.empty?
+ if Dir.entries(dir).reject{|f| f.in?(['.', '..'])}.empty?
File.delete(dir) rescue nil
delete_empty_directories(File.dirname(dir))
end
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index 45263d482f..7ef1497ac2 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -4,7 +4,9 @@ rescue LoadError => e
$stderr.puts "You don't have memcache-client installed in your application. Please add it to your Gemfile and run bundle install"
raise e
end
+
require 'digest/md5'
+require 'active_support/core_ext/string/encoding'
module ActiveSupport
module Cache
@@ -157,8 +159,14 @@ module ActiveSupport
end
private
+
+ # Memcache keys are binaries. So we need to force their encoding to binary
+ # before applying the regular expression to ensure we are escaping all
+ # characters properly.
def escape_key(key)
- key = key.to_s.gsub(ESCAPE_KEY_CHARS){|match| "%#{match.getbyte(0).to_s(16).upcase}"}
+ key = key.to_s.dup
+ key = key.force_encoding("BINARY") if key.encoding_aware?
+ key = key.gsub(ESCAPE_KEY_CHARS){ |match| "%#{match.getbyte(0).to_s(16).upcase}" }
key = "#{key[0, 213]}:md5:#{Digest::MD5.hexdigest(key)}" if key.size > 250
key
end
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 418102352f..656cba625c 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -4,6 +4,7 @@ require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/class/attribute'
require 'active_support/core_ext/kernel/reporting'
require 'active_support/core_ext/kernel/singleton_class'
+require 'active_support/core_ext/object/inclusion'
module ActiveSupport
# \Callbacks are code hooks that are run at key points in an object's lifecycle.
@@ -412,7 +413,7 @@ module ActiveSupport
# CallbackChain.
#
def __update_callbacks(name, filters = [], block = nil) #:nodoc:
- type = [:before, :after, :around].include?(filters.first) ? filters.shift : :before
+ type = filters.first.in?([:before, :after, :around]) ? filters.shift : :before
options = filters.last.is_a?(Hash) ? filters.pop : {}
filters.unshift(block) if block
diff --git a/activesupport/lib/active_support/configurable.rb b/activesupport/lib/active_support/configurable.rb
index 8c56a21ef7..a94446acde 100644
--- a/activesupport/lib/active_support/configurable.rb
+++ b/activesupport/lib/active_support/configurable.rb
@@ -2,6 +2,7 @@ require 'active_support/concern'
require 'active_support/ordered_options'
require 'active_support/core_ext/kernel/singleton_class'
require 'active_support/core_ext/module/delegation'
+require 'active_support/core_ext/array/extract_options'
module ActiveSupport
# Configurable provides a <tt>config</tt> method to store and retrieve
@@ -51,14 +52,16 @@ module ActiveSupport
# user.allowed_access # => true
#
def config_accessor(*names)
+ options = names.extract_options!
+
names.each do |name|
- code, line = <<-RUBY, __LINE__ + 1
- def #{name}; config.#{name}; end
- def #{name}=(value); config.#{name} = value; end
- RUBY
+ reader, line = "def #{name}; config.#{name}; end", __LINE__
+ writer, line = "def #{name}=(value); config.#{name} = value; end", __LINE__
- singleton_class.class_eval code, __FILE__, line
- class_eval code, __FILE__, line
+ singleton_class.class_eval reader, __FILE__, line
+ singleton_class.class_eval writer, __FILE__, line
+ class_eval reader, __FILE__, line unless options[:instance_reader] == false
+ class_eval writer, __FILE__, line unless options[:instance_writer] == false
end
end
end
diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb
index c69a015f12..2df4fd1da1 100644
--- a/activesupport/lib/active_support/core_ext/array/access.rb
+++ b/activesupport/lib/active_support/core_ext/array/access.rb
@@ -3,10 +3,10 @@ class Array
#
# %w( a b c d ).from(0) # => %w( a b c d )
# %w( a b c d ).from(2) # => %w( c d )
- # %w( a b c d ).from(10) # => nil
+ # %w( a b c d ).from(10) # => %w()
# %w().from(0) # => %w()
def from(position)
- self[position..-1]
+ self[position, length] || []
end
# Returns the beginning of the array up to +position+.
diff --git a/activesupport/lib/active_support/core_ext/array/random_access.rb b/activesupport/lib/active_support/core_ext/array/random_access.rb
index ab1fa7cd5b..9eba4642b8 100644
--- a/activesupport/lib/active_support/core_ext/array/random_access.rb
+++ b/activesupport/lib/active_support/core_ext/array/random_access.rb
@@ -1,12 +1,15 @@
class Array
# Backport of Array#sample based on Marc-Andre Lafortune's https://github.com/marcandre/backports/
# Returns a random element or +n+ random elements from the array.
- # If the array is empty and +n+ is nil, returns <tt>nil</tt>. if +n+ is passed, returns <tt>[]</tt>.
+ # If the array is empty and +n+ is nil, returns <tt>nil</tt>.
+ # If +n+ is passed and its value is less than 0, it raises an +ArgumentError+ exception.
+ # If the value of +n+ is equal or greater than 0 it returns <tt>[]</tt>.
#
- # [1,2,3,4,5,6].sample # => 4
- # [1,2,3,4,5,6].sample(3) # => [2, 4, 5]
- # [].sample # => nil
- # [].sample(3) # => []
+ # [1,2,3,4,5,6].sample # => 4
+ # [1,2,3,4,5,6].sample(3) # => [2, 4, 5]
+ # [1,2,3,4,5,6].sample(-3) # => ArgumentError: negative sample number
+ # [].sample # => nil
+ # [].sample(3) # => []
def sample(n=nil)
return self[Kernel.rand(size)] if n.nil?
n = n.to_int
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
index 5414b3a18f..7baba75ad3 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -84,7 +84,7 @@ class Class
val
end
- remove_method :#{name} if method_defined?(:#{name})
+ remove_possible_method :#{name}
def #{name}
defined?(@#{name}) ? @#{name} : self.class.#{name}
end
diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb
index 769ead9544..338104fd05 100644
--- a/activesupport/lib/active_support/core_ext/date/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date/conversions.rb
@@ -1,6 +1,7 @@
require 'date'
require 'active_support/inflector/methods'
require 'active_support/core_ext/date/zones'
+require 'active_support/core_ext/module/remove_method'
class Date
DATE_FORMATS = {
@@ -13,10 +14,10 @@ class Date
}
# Ruby 1.9 has Date#to_time which converts to localtime only.
- remove_method :to_time if method_defined?(:to_time)
+ remove_possible_method :to_time
# Ruby 1.9 has Date#xmlschema which converts to a string without the time component.
- remove_method :xmlschema if method_defined?(:xmlschema)
+ remove_possible_method :xmlschema
# Convert to a formatted string. See DATE_FORMATS for predefined formats.
#
diff --git a/activesupport/lib/active_support/core_ext/date_time/zones.rb b/activesupport/lib/active_support/core_ext/date_time/zones.rb
index 82a4f7ac5a..6fa55a9255 100644
--- a/activesupport/lib/active_support/core_ext/date_time/zones.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/zones.rb
@@ -16,6 +16,6 @@ class DateTime
def in_time_zone(zone = ::Time.zone)
return self unless zone
- ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone))
+ ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
end
end
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index 3005fef44c..102378a029 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -108,7 +108,8 @@ class Hash
raise "can't typecast #{entries.inspect}"
end
end
- elsif value.has_key?("__content__")
+ elsif value['type'] == 'file' ||
+ (value["__content__"] && (value.keys.size == 1 || value["__content__"].present?))
content = value["__content__"]
if parser = ActiveSupport::XmlMini::PARSING[value["type"]]
parser.arity == 1 ? parser.call(content) : parser.call(content, value)
diff --git a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
index aad4b61e16..c2a6476604 100644
--- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
+++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
@@ -9,4 +9,16 @@ class Hash
def with_indifferent_access
ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default(self)
end
+
+ # Called when object is nested under an object that receives
+ # #with_indifferent_access. This method with be called on the current object
+ # by the enclosing object and is aliased to #with_indifferent_access by
+ # default. Subclasses of Hash may overwrite this method to return +self+ if
+ # converting to an +ActiveSupport::HashWithIndifferentAccess+ would not be
+ # desirable.
+ #
+ # b = {:b => 1}
+ # {:a => b}.with_indifferent_access["a"] # calls b.nested_under_indifferent_access
+ #
+ alias nested_under_indifferent_access with_indifferent_access
end
diff --git a/activesupport/lib/active_support/core_ext/object.rb b/activesupport/lib/active_support/core_ext/object.rb
index 790a26f5c1..9ad1e12699 100644
--- a/activesupport/lib/active_support/core_ext/object.rb
+++ b/activesupport/lib/active_support/core_ext/object.rb
@@ -2,6 +2,7 @@ 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/inclusion'
require 'active_support/core_ext/object/conversions'
require 'active_support/core_ext/object/instance_variables'
diff --git a/activesupport/lib/active_support/core_ext/object/blank.rb b/activesupport/lib/active_support/core_ext/object/blank.rb
index d0c1ea8326..20085c4fb3 100644
--- a/activesupport/lib/active_support/core_ext/object/blank.rb
+++ b/activesupport/lib/active_support/core_ext/object/blank.rb
@@ -18,8 +18,8 @@ class Object
!blank?
end
- # Returns object if it's #present? otherwise returns nil.
- # object.presence is equivalent to object.present? ? object : nil.
+ # Returns object if it's <tt>present?</tt> otherwise returns +nil+.
+ # <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>.
#
# This is handy for any representation of objects where blank is the same
# as not present at all. For example, this simplifies a common check for
@@ -37,39 +37,72 @@ class Object
end
end
-class NilClass #:nodoc:
+class NilClass
+ # +nil+ is blank:
+ #
+ # nil.blank? # => true
+ #
def blank?
true
end
end
-class FalseClass #:nodoc:
+class FalseClass
+ # +false+ is blank:
+ #
+ # false.blank? # => true
+ #
def blank?
true
end
end
-class TrueClass #:nodoc:
+class TrueClass
+ # +true+ is not blank:
+ #
+ # true.blank? # => false
+ #
def blank?
false
end
end
-class Array #:nodoc:
+class Array
+ # An array is blank if it's empty:
+ #
+ # [].blank? # => true
+ # [1,2,3].blank? # => false
+ #
alias_method :blank?, :empty?
end
-class Hash #:nodoc:
+class Hash
+ # A hash is blank if it's empty:
+ #
+ # {}.blank? # => true
+ # {:key => 'value'}.blank? # => false
+ #
alias_method :blank?, :empty?
end
-class String #:nodoc:
+class String
+ # A string is blank if it's empty or contains whitespaces only:
+ #
+ # "".blank? # => true
+ # " ".blank? # => true
+ # " something here ".blank? # => false
+ #
def blank?
self !~ /\S/
end
end
class Numeric #:nodoc:
+ # No number is blank:
+ #
+ # 1.blank? # => false
+ # 0.blank? # => false
+ #
def blank?
false
end
diff --git a/activesupport/lib/active_support/core_ext/object/duplicable.rb b/activesupport/lib/active_support/core_ext/object/duplicable.rb
index b05325790c..02cb5dfee7 100644
--- a/activesupport/lib/active_support/core_ext/object/duplicable.rb
+++ b/activesupport/lib/active_support/core_ext/object/duplicable.rb
@@ -15,50 +15,89 @@
# That's why we hardcode the following cases and check duplicable? instead of
# using that rescue idiom.
class Object
- # Can you safely .dup this object?
- # False for nil, false, true, symbols, numbers, class and module objects; true otherwise.
+ # Can you safely dup this object?
+ #
+ # False for +nil+, +false+, +true+, symbols, numbers, class and module objects;
+ # true otherwise.
def duplicable?
true
end
end
-class NilClass #:nodoc:
+class NilClass
+ # +nil+ is not duplicable:
+ #
+ # nil.duplicable? # => false
+ # nil.dup # => TypeError: can't dup NilClass
+ #
def duplicable?
false
end
end
-class FalseClass #:nodoc:
+class FalseClass
+ # +false+ is not duplicable:
+ #
+ # false.duplicable? # => false
+ # false.dup # => TypeError: can't dup FalseClass
+ #
def duplicable?
false
end
end
-class TrueClass #:nodoc:
+class TrueClass
+ # +true+ is not duplicable:
+ #
+ # true.duplicable? # => false
+ # true.dup # => TypeError: can't dup TrueClass
+ #
def duplicable?
false
end
end
-class Symbol #:nodoc:
+class Symbol
+ # Symbols are not duplicable:
+ #
+ # :my_symbol.duplicable? # => false
+ # :my_symbol.dup # => TypeError: can't dup Symbol
+ #
def duplicable?
false
end
end
-class Numeric #:nodoc:
+class Numeric
+ # Numbers are not duplicable:
+ #
+ # 3.duplicable? # => false
+ # 3.dup # => TypeError: can't dup Fixnum
+ #
def duplicable?
false
end
end
-class Class #:nodoc:
+class Class
+ # Classes are not duplicable:
+ #
+ # c = Class.new # => #<Class:0x10328fd80>
+ # c.dup # => #<Class:0x10328fd80>
+ #
+ # Note +dup+ returned the same class object.
def duplicable?
false
end
end
-class Module #:nodoc:
+class Module
+ # Modules are not duplicable:
+ #
+ # m = Module.new # => #<Module:0x10328b6e0>
+ # m.dup # => #<Module:0x10328b6e0>
+ #
+ # Note +dup+ returned the same module object.
def duplicable?
false
end
diff --git a/activesupport/lib/active_support/core_ext/object/inclusion.rb b/activesupport/lib/active_support/core_ext/object/inclusion.rb
new file mode 100644
index 0000000000..b5671f66d0
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/object/inclusion.rb
@@ -0,0 +1,15 @@
+class Object
+ # Returns true if this object is included in the argument. Argument must be
+ # any object which responds to +#include?+. Usage:
+ #
+ # characters = ["Konata", "Kagami", "Tsukasa"]
+ # "Konata".in?(characters) # => true
+ #
+ # This will throw an ArgumentError if the argument doesn't respond
+ # to +#include?+.
+ def in?(another_object)
+ another_object.include?(self)
+ rescue NoMethodError
+ raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/object/try.rb b/activesupport/lib/active_support/core_ext/object/try.rb
index 04619124a1..e77a9da0ec 100644
--- a/activesupport/lib/active_support/core_ext/object/try.rb
+++ b/activesupport/lib/active_support/core_ext/object/try.rb
@@ -9,12 +9,12 @@ class Object
#
# ==== Examples
#
- # Without try
+ # Without +try+
# @person && @person.name
# or
# @person ? @person.name : nil
#
- # With try
+ # With +try+
# @person.try(:name)
#
# +try+ also accepts arguments and/or a block, for the method it is trying
@@ -34,7 +34,19 @@ class Object
end
end
-class NilClass #:nodoc:
+class NilClass
+ # Calling +try+ on +nil+ always returns +nil+.
+ # It becomes specially helpful when navigating through associations that may return +nil+.
+ #
+ # === Examples
+ #
+ # nil.try(:name) # => nil
+ #
+ # Without +try+
+ # @person && !@person.children.blank? && @person.children.first.name
+ #
+ # With +try+
+ # @person.try(:children).try(:first).try(:name)
def try(*args)
nil
end
diff --git a/activesupport/lib/active_support/core_ext/string.rb b/activesupport/lib/active_support/core_ext/string.rb
index 8fb8c31ade..72522d395c 100644
--- a/activesupport/lib/active_support/core_ext/string.rb
+++ b/activesupport/lib/active_support/core_ext/string.rb
@@ -11,3 +11,4 @@ require 'active_support/core_ext/string/output_safety'
require 'active_support/core_ext/string/exclude'
require 'active_support/core_ext/string/encoding'
require 'active_support/core_ext/string/strip'
+require 'active_support/core_ext/string/inquiry'
diff --git a/activesupport/lib/active_support/core_ext/string/inquiry.rb b/activesupport/lib/active_support/core_ext/string/inquiry.rb
new file mode 100644
index 0000000000..604f3bf4dc
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/string/inquiry.rb
@@ -0,0 +1,13 @@
+require 'active_support/string_inquirer'
+
+class String
+ # Wraps the current string in the ActiveSupport::StringInquirer class,
+ # which gives you a prettier way to test for equality. Example:
+ #
+ # env = "production".inquiry
+ # env.production? # => true
+ # env.development? # => false
+ def inquiry
+ ActiveSupport::StringInquirer.new(self)
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb
index addd4dab95..c27cbc37c5 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -9,7 +9,7 @@ class ERB
# A utility method for escaping HTML tag characters.
# This method is also aliased as <tt>h</tt>.
#
- # In your ERb templates, use this method to escape any unsafe content. For example:
+ # In your ERB templates, use this method to escape any unsafe content. For example:
# <%=h @person.name %>
#
# ==== Example:
diff --git a/activesupport/lib/active_support/core_ext/time/marshal.rb b/activesupport/lib/active_support/core_ext/time/marshal.rb
index 1a4d918ce7..457d3f5b62 100644
--- a/activesupport/lib/active_support/core_ext/time/marshal.rb
+++ b/activesupport/lib/active_support/core_ext/time/marshal.rb
@@ -37,6 +37,7 @@ if Time.local(2010).zone != Marshal.load(Marshal.dump(Time.local(2010))).zone
time.instance_eval do
if zone = defined?(@_zone) && remove_instance_variable('@_zone')
ary = to_a
+ ary[0] += subsec if ary[0] == sec
ary[-1] = zone
utc? ? Time.utc(*ary) : Time.local(*ary)
else
diff --git a/activesupport/lib/active_support/core_ext/time/zones.rb b/activesupport/lib/active_support/core_ext/time/zones.rb
index ff90d7ca58..0c5962858e 100644
--- a/activesupport/lib/active_support/core_ext/time/zones.rb
+++ b/activesupport/lib/active_support/core_ext/time/zones.rb
@@ -34,29 +34,36 @@ class Time
# end
# end
def zone=(time_zone)
- Thread.current[:time_zone] = get_zone(time_zone)
+ Thread.current[:time_zone] = find_zone!(time_zone)
end
# Allows override of <tt>Time.zone</tt> locally inside supplied block; resets <tt>Time.zone</tt> to existing value when done.
def use_zone(time_zone)
- old_zone, ::Time.zone = ::Time.zone, get_zone(time_zone)
- yield
- ensure
- ::Time.zone = old_zone
+ new_zone = find_zone!(time_zone)
+ begin
+ old_zone, ::Time.zone = ::Time.zone, new_zone
+ yield
+ ensure
+ ::Time.zone = old_zone
+ end
end
- private
- def get_zone(time_zone)
- return time_zone if time_zone.nil? || time_zone.is_a?(ActiveSupport::TimeZone)
- # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
- unless time_zone.respond_to?(:period_for_local)
- time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone) rescue nil
- end
- # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
- if time_zone
- time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
- end
+ # Returns a TimeZone instance or nil, or raises an ArgumentError for invalid timezones.
+ def find_zone!(time_zone)
+ return time_zone if time_zone.nil? || time_zone.is_a?(ActiveSupport::TimeZone)
+ # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
+ unless time_zone.respond_to?(:period_for_local)
+ time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
end
+ # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
+ time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
+ rescue TZInfo::InvalidTimezoneIdentifier
+ raise ArgumentError, "Invalid Timezone: #{time_zone}"
+ end
+
+ def find_zone(time_zone)
+ find_zone!(time_zone) rescue nil
+ end
end
# Returns the simultaneous time in <tt>Time.zone</tt>.
@@ -74,6 +81,6 @@ class Time
def in_time_zone(zone = ::Time.zone)
return self unless zone
- ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone))
+ ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
end
end
diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb
index ce0775a690..45b9dda5ca 100644
--- a/activesupport/lib/active_support/deprecation.rb
+++ b/activesupport/lib/active_support/deprecation.rb
@@ -9,7 +9,7 @@ module ActiveSupport
# The version the deprecated behavior will be removed, by default.
attr_accessor :deprecation_horizon
end
- self.deprecation_horizon = '3.1'
+ self.deprecation_horizon = '3.2'
# By default, warnings are not silenced and debugging is off.
self.silenced = false
diff --git a/activesupport/lib/active_support/deprecation/reporting.rb b/activesupport/lib/active_support/deprecation/reporting.rb
index ced08b8783..5d7e241d1a 100644
--- a/activesupport/lib/active_support/deprecation/reporting.rb
+++ b/activesupport/lib/active_support/deprecation/reporting.rb
@@ -5,10 +5,8 @@ module ActiveSupport
# Outputs a deprecation warning to the output configured by <tt>ActiveSupport::Deprecation.behavior</tt>
#
- # Example:
- #
# ActiveSupport::Deprecation.warn("something broke!")
- # #=> "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"
+ # # => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"
def warn(message = nil, callstack = caller)
return if silenced
deprecation_message(callstack, message).tap do |m|
diff --git a/activesupport/lib/active_support/descendants_tracker.rb b/activesupport/lib/active_support/descendants_tracker.rb
index 4d1cfacc95..e2a8b4d4e3 100644
--- a/activesupport/lib/active_support/descendants_tracker.rb
+++ b/activesupport/lib/active_support/descendants_tracker.rb
@@ -1,5 +1,3 @@
-require 'active_support/dependencies'
-
module ActiveSupport
# This module provides an internal implementation to track descendants
# which is faster than iterating through ObjectSpace.
@@ -18,12 +16,16 @@ module ActiveSupport
end
def self.clear
- @@direct_descendants.each do |klass, descendants|
- if ActiveSupport::Dependencies.autoloaded?(klass)
- @@direct_descendants.delete(klass)
- else
- descendants.reject! { |v| ActiveSupport::Dependencies.autoloaded?(v) }
+ if defined? ActiveSupport::Dependencies
+ @@direct_descendants.each do |klass, descendants|
+ if ActiveSupport::Dependencies.autoloaded?(klass)
+ @@direct_descendants.delete(klass)
+ else
+ descendants.reject! { |v| ActiveSupport::Dependencies.autoloaded?(v) }
+ end
end
+ else
+ @@direct_descendants.clear
end
end
diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb
index 79a0de7940..8ec4f6e09a 100644
--- a/activesupport/lib/active_support/hash_with_indifferent_access.rb
+++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb
@@ -140,8 +140,8 @@ module ActiveSupport
end
def convert_value(value)
- if value.class == Hash
- self.class.new_from_hash_copying_default(value)
+ if value.is_a? Hash
+ value.nested_under_indifferent_access
elsif value.is_a?(Array)
value.dup.replace(value.map { |e| convert_value(e) })
else
diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb
index e136e4c5b3..d5d55b7207 100644
--- a/activesupport/lib/active_support/inflector/inflections.rb
+++ b/activesupport/lib/active_support/inflector/inflections.rb
@@ -96,7 +96,7 @@ module ActiveSupport
def clear(scope = :all)
case scope
when :all
- @plurals, @singulars, @uncountables = [], [], []
+ @plurals, @singulars, @uncountables, @humans = [], [], [], []
else
instance_variable_set "@#{scope}", []
end
diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb
index de49750083..a2c4f7bfda 100644
--- a/activesupport/lib/active_support/inflector/methods.rb
+++ b/activesupport/lib/active_support/inflector/methods.rb
@@ -135,11 +135,13 @@ module ActiveSupport
# ordinalize(2) # => "2nd"
# ordinalize(1002) # => "1002nd"
# ordinalize(1003) # => "1003rd"
+ # ordinalize(-11) # => "-11th"
+ # ordinalize(-1021) # => "-1021st"
def ordinalize(number)
- if (11..13).include?(number.to_i % 100)
+ if (11..13).include?(number.to_i.abs % 100)
"#{number}th"
else
- case number.to_i % 10
+ case number.to_i.abs % 10
when 1; "#{number}st"
when 2; "#{number}nd"
when 3; "#{number}rd"
@@ -148,4 +150,4 @@ module ActiveSupport
end
end
end
-end \ No newline at end of file
+end
diff --git a/activesupport/lib/active_support/json/backends/jsongem.rb b/activesupport/lib/active_support/json/backends/jsongem.rb
deleted file mode 100644
index 533ba25da3..0000000000
--- a/activesupport/lib/active_support/json/backends/jsongem.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-require 'json' unless defined?(JSON)
-
-module ActiveSupport
- module JSON
- module Backends
- module JSONGem
- ParseError = ::JSON::ParserError
- extend self
-
- # Parses a JSON string or IO and convert it into an object
- def decode(json)
- if json.respond_to?(:read)
- json = json.read
- end
- data = ::JSON.parse(json)
- if ActiveSupport.parse_json_times
- convert_dates_from(data)
- else
- data
- end
- end
-
- private
- def convert_dates_from(data)
- case data
- when nil
- nil
- when DATE_REGEX
- begin
- DateTime.parse(data)
- rescue ArgumentError
- data
- end
- when Array
- data.map! { |d| convert_dates_from(d) }
- when Hash
- data.each do |key, value|
- data[key] = convert_dates_from(value)
- end
- else
- data
- end
- end
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/json/backends/yajl.rb b/activesupport/lib/active_support/json/backends/yajl.rb
deleted file mode 100644
index 58818658c7..0000000000
--- a/activesupport/lib/active_support/json/backends/yajl.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-require 'yajl' unless defined?(Yajl)
-
-module ActiveSupport
- module JSON
- module Backends
- module Yajl
- ParseError = ::Yajl::ParseError
- extend self
-
- # Parses a JSON string or IO and convert it into an object
- def decode(json)
- data = ::Yajl::Parser.new.parse(json)
- if ActiveSupport.parse_json_times
- convert_dates_from(data)
- else
- data
- end
- end
-
- private
- def convert_dates_from(data)
- case data
- when nil
- nil
- when DATE_REGEX
- begin
- DateTime.parse(data)
- rescue ArgumentError
- data
- end
- when Array
- data.map! { |d| convert_dates_from(d) }
- when Hash
- data.each do |key, value|
- data[key] = convert_dates_from(value)
- end
- else
- data
- end
- end
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/json/backends/yaml.rb b/activesupport/lib/active_support/json/backends/yaml.rb
deleted file mode 100644
index 077eda548a..0000000000
--- a/activesupport/lib/active_support/json/backends/yaml.rb
+++ /dev/null
@@ -1,111 +0,0 @@
-require 'active_support/core_ext/string/starts_ends_with'
-
-module ActiveSupport
- module JSON
- module Backends
- module Yaml
- ParseError = ::StandardError
- extend self
-
- EXCEPTIONS = [::ArgumentError] # :nodoc:
- begin
- require 'psych'
- EXCEPTIONS << Psych::SyntaxError
- rescue LoadError
- end
-
- # Parses a JSON string or IO and converts it into an object
- def decode(json)
- if json.respond_to?(:read)
- json = json.read
- end
- YAML.load(convert_json_to_yaml(json))
- rescue *EXCEPTIONS => e
- raise ParseError, "Invalid JSON string: '%s'" % json
- end
-
- protected
- # Ensure that ":" and "," are always followed by a space
- def convert_json_to_yaml(json) #:nodoc:
- require 'strscan' unless defined? ::StringScanner
- scanner, quoting, marks, pos, times = ::StringScanner.new(json), false, [], nil, []
- while scanner.scan_until(/(\\['"]|['":,\\]|\\.)/)
- case char = scanner[1]
- when '"', "'"
- if !quoting
- quoting = char
- pos = scanner.pos
- elsif quoting == char
- if valid_date?(json[pos..scanner.pos-2])
- # found a date, track the exact positions of the quotes so we can
- # overwrite them with spaces later.
- times << pos
- end
- quoting = false
- end
- when ":",","
- marks << scanner.pos - 1 unless quoting
- when "\\"
- scanner.skip(/\\/)
- end
- end
-
- if marks.empty?
- json.gsub(/\\([\\\/]|u[[:xdigit:]]{4})/) do
- ustr = $1
- if ustr.start_with?('u')
- char = [ustr[1..-1].to_i(16)].pack("U")
- # "\n" needs extra escaping due to yaml formatting
- char == "\n" ? "\\n" : char
- elsif ustr == '\\'
- '\\\\'
- else
- ustr
- end
- end
- else
- left_pos = [-1].push(*marks)
- right_pos = marks << scanner.pos + scanner.rest_size
- output = []
- left_pos.each_with_index do |left, i|
- scanner.pos = left.succ
- chunk = scanner.peek(right_pos[i] - scanner.pos + 1)
- # overwrite the quotes found around the dates with spaces
- while times.size > 0 && times[0] <= right_pos[i]
- chunk.insert(times.shift - scanner.pos - 1, '! ')
- end
- chunk.gsub!(/\\([\\\/]|u[[:xdigit:]]{4})/) do
- ustr = $1
- if ustr.start_with?('u')
- char = [ustr[1..-1].to_i(16)].pack("U")
- # "\n" needs extra escaping due to yaml formatting
- char == "\n" ? "\\n" : char
- elsif ustr == '\\'
- '\\\\'
- else
- ustr
- end
- end
- output << chunk
- end
- output = output * " "
-
- output.gsub!(/\\\//, '/')
- output
- end
- end
-
- private
- def valid_date?(date_string)
- begin
- date_string =~ DATE_REGEX && DateTime.parse(date_string)
- rescue ArgumentError
- false
- end
- end
-
- end
- end
- end
-end
-
diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb
index c1f6330c6c..cbeb6c0a28 100644
--- a/activesupport/lib/active_support/json/decoding.rb
+++ b/activesupport/lib/active_support/json/decoding.rb
@@ -1,32 +1,31 @@
require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/core_ext/module/delegation'
+require 'multi_json'
module ActiveSupport
# Look for and parse json strings that look like ISO 8601 times.
mattr_accessor :parse_json_times
module JSON
- # Listed in order of preference.
- DECODERS = %w(Yajl Yaml)
-
class << self
- attr_reader :parse_error
- delegate :decode, :to => :backend
+ def decode(json, options ={})
+ data = MultiJson.decode(json, options)
+ if ActiveSupport.parse_json_times
+ convert_dates_from(data)
+ else
+ data
+ end
+ end
- def backend
- set_default_backend unless defined?(@backend)
- @backend
+ def engine
+ MultiJson.engine
end
+ alias :backend :engine
- def backend=(name)
- if name.is_a?(Module)
- @backend = name
- else
- require "active_support/json/backends/#{name.to_s.downcase}"
- @backend = ActiveSupport::JSON::Backends::const_get(name)
- end
- @parse_error = @backend::ParseError
+ def engine=(name)
+ MultiJson.engine = name
end
+ alias :backend= :engine=
def with_backend(name)
old_backend, self.backend = backend, name
@@ -35,15 +34,30 @@ module ActiveSupport
self.backend = old_backend
end
- def set_default_backend
- DECODERS.find do |name|
+ def parse_error
+ MultiJson::DecodeError
+ end
+
+ private
+
+ def convert_dates_from(data)
+ case data
+ when nil
+ nil
+ when DATE_REGEX
begin
- self.backend = name
- true
- rescue LoadError
- # Try next decoder.
- false
+ DateTime.parse(data)
+ rescue ArgumentError
+ data
end
+ when Array
+ data.map! { |d| convert_dates_from(d) }
+ when Hash
+ data.each do |key, value|
+ data[key] = convert_dates_from(value)
+ end
+ else
+ data
end
end
end
diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb
index 82b8a7e148..d22fe14b33 100644
--- a/activesupport/lib/active_support/json/encoding.rb
+++ b/activesupport/lib/active_support/json/encoding.rb
@@ -2,6 +2,7 @@ require 'active_support/core_ext/object/to_json'
require 'active_support/core_ext/module/delegation'
require 'active_support/deprecation'
require 'active_support/json/variable'
+require 'active_support/ordered_hash'
require 'bigdecimal'
require 'active_support/core_ext/big_decimal/conversions' # for #to_s
@@ -205,7 +206,9 @@ class Regexp
end
module Enumerable
- def as_json(options = nil) to_a end #:nodoc:
+ def as_json(options = nil) #:nodoc:
+ to_a.as_json(options)
+ end
end
class Array
diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb
index 10675edac5..1c4dd24227 100644
--- a/activesupport/lib/active_support/log_subscriber.rb
+++ b/activesupport/lib/active_support/log_subscriber.rb
@@ -81,7 +81,7 @@ module ActiveSupport
# Flush all log_subscribers' logger.
def flush_all!
- flushable_loggers.each(&:flush)
+ flushable_loggers.each { |log| log.flush }
end
end
diff --git a/activesupport/lib/active_support/log_subscriber/test_helper.rb b/activesupport/lib/active_support/log_subscriber/test_helper.rb
index 392e33edbc..3e54134c5c 100644
--- a/activesupport/lib/active_support/log_subscriber/test_helper.rb
+++ b/activesupport/lib/active_support/log_subscriber/test_helper.rb
@@ -1,5 +1,6 @@
require 'active_support/log_subscriber'
require 'active_support/buffered_logger'
+require 'active_support/notifications'
module ActiveSupport
class LogSubscriber
diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb
index adc34f3286..a9aa5464e9 100644
--- a/activesupport/lib/active_support/notifications/fanout.rb
+++ b/activesupport/lib/active_support/notifications/fanout.rb
@@ -1,7 +1,7 @@
module ActiveSupport
module Notifications
- # This is a default queue implementation that ships with Notifications. It
- # just pushes events to all registered log subscribers.
+ # This is a default queue implementation that ships with Notifications.
+ # It just pushes events to all registered log subscribers.
class Fanout
def initialize
@subscribers = []
@@ -33,7 +33,7 @@ module ActiveSupport
listeners_for(name).any?
end
- # This is a sync queue, so there is not waiting.
+ # This is a sync queue, so there is no waiting.
def wait
end
diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb
index fbc40d1b69..762a64a881 100644
--- a/activesupport/lib/active_support/ordered_hash.rb
+++ b/activesupport/lib/active_support/ordered_hash.rb
@@ -43,6 +43,10 @@ module ActiveSupport
end
end
+ def nested_under_indifferent_access
+ self
+ end
+
# Hash is ordered in Ruby 1.9!
if RUBY_VERSION < '1.9'
diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb
index c2deba3b1b..04df2ea562 100644
--- a/activesupport/lib/active_support/railtie.rb
+++ b/activesupport/lib/active_support/railtie.rb
@@ -46,7 +46,7 @@ module ActiveSupport
# If assigned value cannot be matched to a TimeZone, an exception will be raised.
initializer "active_support.initialize_time_zone" do |app|
require 'active_support/core_ext/time/zones'
- zone_default = Time.__send__(:get_zone, app.config.time_zone)
+ zone_default = Time.find_zone!(app.config.time_zone)
unless zone_default
raise \
diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb
index fb52fc7083..8d6c27e381 100644
--- a/activesupport/lib/active_support/test_case.rb
+++ b/activesupport/lib/active_support/test_case.rb
@@ -5,16 +5,9 @@ require 'active_support/testing/deprecation'
require 'active_support/testing/declarative'
require 'active_support/testing/pending'
require 'active_support/testing/isolation'
+require 'active_support/testing/mochaing'
require 'active_support/core_ext/kernel/reporting'
-begin
- silence_warnings { require 'mocha' }
-rescue LoadError
- # Fake Mocha::ExpectationError so we can rescue it in #run. Bleh.
- Object.const_set :Mocha, Module.new
- Mocha.const_set :ExpectationError, Class.new(StandardError)
-end
-
module ActiveSupport
class TestCase < ::Test::Unit::TestCase
if defined? MiniTest
diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb
index a4e0361a32..05da50e150 100644
--- a/activesupport/lib/active_support/testing/assertions.rb
+++ b/activesupport/lib/active_support/testing/assertions.rb
@@ -29,22 +29,33 @@ module ActiveSupport
# post :create, :article => {...}
# end
#
+ # A lambda or a list of lambdas can be passed in and evaluated:
+ #
+ # assert_difference lambda { Article.count }, 2 do
+ # post :create, :article => {...}
+ # end
+ #
+ # assert_difference [->{ Article.count }, ->{ Post.count }], 2 do
+ # post :create, :article => {...}
+ # end
+ #
# A error message can be specified.
#
# assert_difference 'Article.count', -1, "An Article should be destroyed" do
# post :delete, :id => ...
# end
def assert_difference(expression, difference = 1, message = nil, &block)
- b = block.send(:binding)
- exps = Array.wrap(expression)
- before = exps.map { |e| eval(e, b) }
+ exps = Array.wrap(expression).map { |e|
+ e.respond_to?(:call) ? e : lambda { eval(e, block.binding) }
+ }
+ before = exps.map { |e| e.call }
yield
exps.each_with_index do |e, i|
- error = "#{e.inspect} didn't change by #{difference}"
- error = "#{message}.\n#{error}" if message
- assert_equal(before[i] + difference, eval(e, b), error)
+ error = "#{e.inspect} didn't change by #{difference}"
+ error = "#{message}.\n#{error}" if message
+ assert_equal(before[i] + difference, e.call, error)
end
end
diff --git a/activesupport/lib/active_support/testing/mochaing.rb b/activesupport/lib/active_support/testing/mochaing.rb
new file mode 100644
index 0000000000..4ad75a6681
--- /dev/null
+++ b/activesupport/lib/active_support/testing/mochaing.rb
@@ -0,0 +1,7 @@
+begin
+ silence_warnings { require 'mocha' }
+rescue LoadError
+ # Fake Mocha::ExpectationError so we can rescue it in #run. Bleh.
+ Object.const_set :Mocha, Module.new
+ Mocha.const_set :ExpectationError, Class.new(StandardError)
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/testing/pending.rb b/activesupport/lib/active_support/testing/pending.rb
index 3d119e2fba..feac7bc347 100644
--- a/activesupport/lib/active_support/testing/pending.rb
+++ b/activesupport/lib/active_support/testing/pending.rb
@@ -11,32 +11,36 @@ module ActiveSupport
@@at_exit = false
def pending(description = "", &block)
- if description.is_a?(Symbol)
- is_pending = $tags[description]
- return block.call unless is_pending
- end
+ if defined?(::MiniTest)
+ skip(description.blank? ? nil : description)
+ else
+ if description.is_a?(Symbol)
+ is_pending = $tags[description]
+ return block.call unless is_pending
+ end
- if block_given?
- failed = false
+ if block_given?
+ failed = false
- begin
- block.call
- rescue Exception
- failed = true
- end
+ begin
+ block.call
+ rescue Exception
+ failed = true
+ end
- flunk("<#{description}> did not fail.") unless failed
- end
+ flunk("<#{description}> did not fail.") unless failed
+ end
- caller[0] =~ (/(.*):(.*):in `(.*)'/)
- @@pending_cases << "#{$3} at #{$1}, line #{$2}"
- print "P"
+ caller[0] =~ (/(.*):(.*):in `(.*)'/)
+ @@pending_cases << "#{$3} at #{$1}, line #{$2}"
+ print "P"
- @@at_exit ||= begin
- at_exit do
- puts "\nPending Cases:"
- @@pending_cases.each do |test_case|
- puts test_case
+ @@at_exit ||= begin
+ at_exit do
+ puts "\nPending Cases:"
+ @@pending_cases.each do |test_case|
+ puts test_case
+ end
end
end
end
diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb
index 8c91a061fb..7cd9bfa947 100644
--- a/activesupport/lib/active_support/testing/performance.rb
+++ b/activesupport/lib/active_support/testing/performance.rb
@@ -3,12 +3,100 @@ begin
require 'fileutils'
require 'rails/version'
+ require 'active_support/concern'
require 'active_support/core_ext/class/delegating_attributes'
require 'active_support/core_ext/string/inflections'
module ActiveSupport
module Testing
module Performance
+ extend ActiveSupport::Concern
+
+ included do
+ superclass_delegating_accessor :profile_options
+ self.profile_options = DEFAULTS
+
+ if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions
+ include ForMiniTest
+ else
+ include ForClassicTestUnit
+ end
+ end
+
+ module ForMiniTest
+ def run(runner)
+ @runner = runner
+
+ run_warmup
+ if profile_options && metrics = profile_options[:metrics]
+ metrics.each do |metric_name|
+ if klass = Metrics[metric_name.to_sym]
+ run_profile(klass.new)
+ end
+ end
+ end
+ end
+
+ def run_test(metric, mode)
+ result = '.'
+ begin
+ run_callbacks :setup
+ setup
+ metric.send(mode) { __send__ method_name }
+ rescue Exception => e
+ result = @runner.puke(self.class, method_name, e)
+ ensure
+ begin
+ teardown
+ run_callbacks :teardown, :enumerator => :reverse_each
+ rescue Exception => e
+ result = @runner.puke(self.class, method_name, e)
+ end
+ end
+ result
+ end
+ end
+
+ module ForClassicTestUnit
+ def run(result)
+ return if method_name =~ /^default_test$/
+
+ yield(self.class::STARTED, name)
+ @_result = result
+
+ run_warmup
+ if profile_options && metrics = profile_options[:metrics]
+ metrics.each do |metric_name|
+ if klass = Metrics[metric_name.to_sym]
+ run_profile(klass.new)
+ result.add_run
+ end
+ end
+ end
+
+ yield(self.class::FINISHED, name)
+ end
+
+ def run_test(metric, mode)
+ run_callbacks :setup
+ setup
+ metric.send(mode) { __send__ @method_name }
+ rescue ::Test::Unit::AssertionFailedError => e
+ add_failure(e.message, e.backtrace)
+ rescue StandardError, ScriptError => e
+ add_error(e)
+ ensure
+ begin
+ teardown
+ run_callbacks :teardown, :enumerator => :reverse_each
+ rescue ::Test::Unit::AssertionFailedError => e
+ add_failure(e.message, e.backtrace)
+ rescue StandardError, ScriptError => e
+ add_error(e)
+ end
+ end
+ end
+
DEFAULTS =
if benchmark = ARGV.include?('--benchmark') # HAX for rake test
{ :benchmark => true,
@@ -24,53 +112,10 @@ begin
:output => 'tmp/performance' }
end.freeze
- def self.included(base)
- base.superclass_delegating_accessor :profile_options
- base.profile_options = DEFAULTS
- end
-
def full_test_name
"#{self.class.name}##{method_name}"
end
- def run(result)
- return if method_name =~ /^default_test$/
-
- yield(self.class::STARTED, name)
- @_result = result
-
- run_warmup
- if profile_options && metrics = profile_options[:metrics]
- metrics.each do |metric_name|
- if klass = Metrics[metric_name.to_sym]
- run_profile(klass.new)
- result.add_run
- end
- end
- end
-
- yield(self.class::FINISHED, name)
- end
-
- def run_test(metric, mode)
- run_callbacks :setup
- setup
- metric.send(mode) { __send__ @method_name }
- rescue ::Test::Unit::AssertionFailedError => e
- add_failure(e.message, e.backtrace)
- rescue StandardError, ScriptError => e
- add_error(e)
- ensure
- begin
- teardown
- run_callbacks :teardown, :enumerator => :reverse_each
- rescue ::Test::Unit::AssertionFailedError => e
- add_failure(e.message, e.backtrace)
- rescue StandardError, ScriptError => e
- add_error(e)
- end
- end
-
protected
def run_warmup
GC.start
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index c66aa78ce8..3d092529d6 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -1,5 +1,6 @@
require "active_support/values/time_zone"
require 'active_support/core_ext/object/acts_like'
+require 'active_support/core_ext/object/inclusion'
module ActiveSupport
# A Time-like class that can represent a time in any time zone. Necessary because standard Ruby Time instances are
@@ -309,7 +310,7 @@ module ActiveSupport
end
def marshal_load(variables)
- initialize(variables[0].utc, ::Time.__send__(:get_zone, variables[1]), variables[2].utc)
+ initialize(variables[0].utc, ::Time.find_zone(variables[1]), variables[2].utc)
end
# Ensure proxy class responds to all methods that underlying time instance responds to.
@@ -344,7 +345,7 @@ module ActiveSupport
end
def duration_of_variable_length?(obj)
- ActiveSupport::Duration === obj && obj.parts.any? {|p| [:years, :months, :days].include? p[0] }
+ ActiveSupport::Duration === obj && obj.parts.any? {|p| p[0].in?([:years, :months, :days]) }
end
end
end
diff --git a/activesupport/lib/active_support/version.rb b/activesupport/lib/active_support/version.rb
index 690fc7f0fc..c2cf39e391 100644
--- a/activesupport/lib/active_support/version.rb
+++ b/activesupport/lib/active_support/version.rb
@@ -3,7 +3,7 @@ module ActiveSupport
MAJOR = 3
MINOR = 1
TINY = 0
- PRE = "beta"
+ PRE = "beta1"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
diff --git a/activesupport/lib/active_support/whiny_nil.rb b/activesupport/lib/active_support/whiny_nil.rb
index bcedbfd57a..577db5018e 100644
--- a/activesupport/lib/active_support/whiny_nil.rb
+++ b/activesupport/lib/active_support/whiny_nil.rb
@@ -41,7 +41,7 @@ class NilClass
end
private
- def method_missing(method, *args, &block)
+ def method_missing(method, *args)
if klass = METHOD_CLASS_MAP[method]
raise_nil_warning_for klass, method, caller
else
diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb
index cddfcddb57..6e12404ad4 100644
--- a/activesupport/lib/active_support/xml_mini.rb
+++ b/activesupport/lib/active_support/xml_mini.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/module/delegation'
+require 'active_support/core_ext/string/inflections'
module ActiveSupport
# = XmlMini
@@ -138,7 +139,9 @@ module ActiveSupport
protected
def _dasherize(key)
- key.gsub(/(?!^[_]*)_(?![_]*$)/, '-')
+ # $2 must be a non-greedy regex for this to work
+ left, middle, right = /\A(_*)(.*?)(_*)\Z/.match(key.strip)[1,3]
+ "#{left}#{middle.tr('_ ', '--')}#{right}"
end
# TODO: Add support for other encodings
diff --git a/activesupport/test/buffered_logger_test.rb b/activesupport/test/buffered_logger_test.rb
index 8d1b1c02c6..21049d685b 100644
--- a/activesupport/test/buffered_logger_test.rb
+++ b/activesupport/test/buffered_logger_test.rb
@@ -2,6 +2,7 @@ require 'abstract_unit'
require 'multibyte_test_helpers'
require 'stringio'
require 'fileutils'
+require 'tempfile'
require 'active_support/buffered_logger'
class BufferedLoggerTest < Test::Unit::TestCase
@@ -16,6 +17,44 @@ class BufferedLoggerTest < Test::Unit::TestCase
@logger = Logger.new(@output)
end
+ def test_write_binary_data_to_existing_file
+ t = Tempfile.new ['development', 'log']
+ t.binmode
+ t.write 'hi mom!'
+ t.close
+
+ logger = Logger.new t.path
+ logger.level = Logger::DEBUG
+
+ str = "\x80"
+ if str.respond_to?(:force_encoding)
+ str.force_encoding("ASCII-8BIT")
+ end
+
+ logger.add Logger::DEBUG, str
+ logger.flush
+ ensure
+ logger.close
+ t.close true
+ end
+
+ def test_write_binary_data_create_file
+ fname = File.join Dir.tmpdir, 'lol', 'rofl.log'
+ logger = Logger.new fname
+ logger.level = Logger::DEBUG
+
+ str = "\x80"
+ if str.respond_to?(:force_encoding)
+ str.force_encoding("ASCII-8BIT")
+ end
+
+ logger.add Logger::DEBUG, str
+ logger.flush
+ ensure
+ logger.close
+ File.unlink fname
+ end
+
def test_should_log_debugging_message_when_debugging
@logger.level = Logger::DEBUG
@logger.add(Logger::DEBUG, @message)
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index e5668e29d7..476d55fffd 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -352,6 +352,43 @@ module CacheStoreBehavior
end
end
+# https://rails.lighthouseapp.com/projects/8994/tickets/6225-memcachestore-cant-deal-with-umlauts-and-special-characters
+# The error is caused by charcter encodings that can't be compared with ASCII-8BIT regular expressions and by special
+# characters like the umlaut in UTF-8.
+module EncodedKeyCacheBehavior
+ if defined?(Encoding)
+ Encoding.list.each do |encoding|
+ define_method "test_#{encoding.name.underscore}_encoded_values" do
+ key = "foo".force_encoding(encoding)
+ assert_equal true, @cache.write(key, "1", :raw => true)
+ assert_equal "1", @cache.read(key)
+ assert_equal "1", @cache.fetch(key)
+ assert_equal true, @cache.delete(key)
+ assert_equal "2", @cache.fetch(key, :raw => true) { "2" }
+ assert_equal 3, @cache.increment(key)
+ assert_equal 2, @cache.decrement(key)
+ end
+ end
+
+ def test_common_utf8_values
+ key = "\xC3\xBCmlaut".force_encoding(Encoding::UTF_8)
+ assert_equal true, @cache.write(key, "1", :raw => true)
+ assert_equal "1", @cache.read(key)
+ assert_equal "1", @cache.fetch(key)
+ assert_equal true, @cache.delete(key)
+ assert_equal "2", @cache.fetch(key, :raw => true) { "2" }
+ assert_equal 3, @cache.increment(key)
+ assert_equal 2, @cache.decrement(key)
+ end
+
+ def test_retains_encoding
+ key = "\xC3\xBCmlaut".force_encoding(Encoding::UTF_8)
+ assert_equal true, @cache.write(key, "1", :raw => true)
+ assert_equal Encoding::UTF_8, key.encoding
+ end
+ end
+end
+
module CacheDeleteMatchedBehavior
def test_delete_matched
@cache.write("foo", "bar")
@@ -617,6 +654,7 @@ uses_memcached 'memcached backed store' do
include CacheStoreBehavior
include LocalCacheBehavior
include CacheIncrementDecrementBehavior
+ include EncodedKeyCacheBehavior
def test_raw_values
cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, :raw => true)
diff --git a/activesupport/test/class_cache_test.rb b/activesupport/test/class_cache_test.rb
index 8445af8d25..fc2d54515d 100644
--- a/activesupport/test/class_cache_test.rb
+++ b/activesupport/test/class_cache_test.rb
@@ -58,7 +58,7 @@ module ActiveSupport
assert @cache.key?(ClassCacheTest.name)
end
- def test_new_rejects_strings
+ def test_new_rejects_strings_when_called_on_a_new_string
assert_deprecated do
@cache.new ClassCacheTest.name
end
diff --git a/activesupport/test/configurable_test.rb b/activesupport/test/configurable_test.rb
index 2b28e61815..c6d8191298 100644
--- a/activesupport/test/configurable_test.rb
+++ b/activesupport/test/configurable_test.rb
@@ -5,6 +5,7 @@ class ConfigurableActiveSupport < ActiveSupport::TestCase
class Parent
include ActiveSupport::Configurable
config_accessor :foo
+ config_accessor :bar, :instance_reader => false, :instance_writer => false
end
class Child < Parent
@@ -36,6 +37,12 @@ class ConfigurableActiveSupport < ActiveSupport::TestCase
assert_equal :bar, Parent.config.foo
end
+ test "configuration accessors is not available on instance" do
+ instance = Parent.new
+ assert !instance.respond_to?(:bar)
+ assert !instance.respond_to?(:bar=)
+ end
+
test "configuration hash is available on instance" do
instance = Parent.new
assert_equal :bar, instance.config.foo
diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb
index d7ab3ce605..0e5407bc35 100644
--- a/activesupport/test/core_ext/array_ext_test.rb
+++ b/activesupport/test/core_ext/array_ext_test.rb
@@ -10,7 +10,7 @@ class ArrayExtAccessTests < Test::Unit::TestCase
def test_from
assert_equal %w( a b c d ), %w( a b c d ).from(0)
assert_equal %w( c d ), %w( a b c d ).from(2)
- assert_nil %w( a b c d ).from(10)
+ assert_equal %w(), %w( a b c d ).from(10)
end
def test_to
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index c0b529d9f8..c8312aa653 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/inflector'
require 'active_support/time'
require 'active_support/json'
diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb
index a0479d45ac..4557a10688 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -16,6 +16,12 @@ class HashExtTest < Test::Unit::TestCase
class SubclassingHash < Hash
end
+ class NonIndifferentHash < Hash
+ def nested_under_indifferent_access
+ self
+ end
+ end
+
def setup
@strings = { 'a' => 1, 'b' => 2 }
@symbols = { :a => 1, :b => 2 }
@@ -109,9 +115,12 @@ class HashExtTest < Test::Unit::TestCase
assert_equal @strings, @mixed.with_indifferent_access.dup.stringify_keys!
end
- def test_hash_subclass
- flash = { "foo" => SubclassingHash.new.tap { |h| h["bar"] = "baz" } }.with_indifferent_access
- assert_kind_of SubclassingHash, flash["foo"]
+ def test_nested_under_indifferent_access
+ foo = { "foo" => SubclassingHash.new.tap { |h| h["bar"] = "baz" } }.with_indifferent_access
+ assert_kind_of ActiveSupport::HashWithIndifferentAccess, foo["foo"]
+
+ foo = { "foo" => NonIndifferentHash.new.tap { |h| h["bar"] = "baz" } }.with_indifferent_access
+ assert_kind_of NonIndifferentHash, foo["foo"]
end
def test_indifferent_assorted
@@ -889,6 +898,21 @@ class HashToXmlTest < Test::Unit::TestCase
assert_equal 'application/octet-stream', file.content_type
end
+ def test_tag_with_attrs_and_whitespace
+ xml = <<-XML
+ <blog name="bacon is the best">
+ </blog>
+ XML
+ hash = Hash.from_xml(xml)
+ assert_equal "bacon is the best", hash['blog']['name']
+ end
+
+ def test_empty_cdata_from_xml
+ xml = "<data><![CDATA[]]></data>"
+
+ assert_equal "", Hash.from_xml(xml)["data"]
+ end
+
def test_xsd_like_types_from_xml
bacon_xml = <<-EOT
<bacon>
@@ -931,7 +955,7 @@ class HashToXmlTest < Test::Unit::TestCase
assert_equal expected_product_hash, Hash.from_xml(product_xml)["product"]
end
-
+
def test_should_use_default_value_for_unknown_key
hash_wia = HashWithIndifferentAccess.new(3)
assert_equal 3, hash_wia[:new_key]
diff --git a/activesupport/test/core_ext/object/inclusion_test.rb b/activesupport/test/core_ext/object/inclusion_test.rb
new file mode 100644
index 0000000000..1de857d678
--- /dev/null
+++ b/activesupport/test/core_ext/object/inclusion_test.rb
@@ -0,0 +1,50 @@
+require 'abstract_unit'
+require 'active_support/core_ext/object/inclusion'
+
+class InTest < Test::Unit::TestCase
+ def test_in_array
+ assert 1.in?([1,2])
+ assert !3.in?([1,2])
+ end
+
+ def test_in_hash
+ h = { "a" => 100, "b" => 200 }
+ assert "a".in?(h)
+ assert !"z".in?(h)
+ end
+
+ def test_in_string
+ assert "lo".in?("hello")
+ assert !"ol".in?("hello")
+ assert ?h.in?("hello")
+ end
+
+ def test_in_range
+ assert 25.in?(1..50)
+ assert !75.in?(1..50)
+ end
+
+ def test_in_set
+ s = Set.new([1,2])
+ assert 1.in?(s)
+ assert !3.in?(s)
+ end
+
+ module A
+ end
+ class B
+ include A
+ end
+ class C < B
+ end
+
+ def test_in_module
+ assert A.in?(B)
+ assert A.in?(C)
+ assert !A.in?(A)
+ end
+
+ def test_no_method_catching
+ assert_raise(ArgumentError) { 1.in?(1) }
+ end
+end
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index bb865cae91..32675c884a 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -3,6 +3,7 @@ require 'date'
require 'abstract_unit'
require 'inflector_test_cases'
+require 'active_support/inflector'
require 'active_support/core_ext/string'
require 'active_support/time'
require 'active_support/core_ext/kernel/reporting'
@@ -250,6 +251,11 @@ class StringInflectionsTest < Test::Unit::TestCase
# And changes the original string:
assert_equal original, expected
end
+
+ def test_string_inquiry
+ assert "production".inquiry.production?
+ assert !"production".inquiry.development?
+ end
def test_truncate
assert_equal "Hello World!", "Hello World!".truncate(12)
diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb
index 53d497013a..44e02109b1 100644
--- a/activesupport/test/core_ext/time_ext_test.rb
+++ b/activesupport/test/core_ext/time_ext_test.rb
@@ -808,4 +808,11 @@ class TimeExtMarshalingTest < Test::Unit::TestCase
assert_equal t.zone, unmarshaled.zone
assert_equal t, unmarshaled
end
+
+ def test_marshalling_preserves_fractional_seconds
+ t = Time.parse('00:00:00.500')
+ unmarshaled = Marshal.load(Marshal.dump(t))
+ assert_equal t.to_f, unmarshaled.to_f
+ assert_equal t, unmarshaled
+ end
end
diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb
index bafa335a09..72b55183ba 100644
--- a/activesupport/test/core_ext/time_with_zone_test.rb
+++ b/activesupport/test/core_ext/time_with_zone_test.rb
@@ -36,6 +36,12 @@ class TimeWithZoneTest < Test::Unit::TestCase
assert_equal @twz.object_id, @twz.in_time_zone(ActiveSupport::TimeZone['Eastern Time (US & Canada)']).object_id
end
+ def test_in_time_zone_with_bad_argument
+ assert_raise(ArgumentError) { @twz.in_time_zone('No such timezone exists') }
+ assert_raise(ArgumentError) { @twz.in_time_zone(-15.hours) }
+ assert_raise(ArgumentError) { @twz.in_time_zone(Object.new) }
+ end
+
def test_localtime
assert_equal @twz.localtime, @twz.utc.getlocal
end
@@ -760,6 +766,15 @@ class TimeWithZoneMethodsForTimeAndDateTimeTest < Test::Unit::TestCase
end
end
+ def test_in_time_zone_with_invalid_argument
+ assert_raise(ArgumentError) { @t.in_time_zone("No such timezone exists") }
+ assert_raise(ArgumentError) { @dt.in_time_zone("No such timezone exists") }
+ assert_raise(ArgumentError) { @t.in_time_zone(-15.hours) }
+ assert_raise(ArgumentError) { @dt.in_time_zone(-15.hours) }
+ assert_raise(ArgumentError) { @t.in_time_zone(Object.new) }
+ assert_raise(ArgumentError) { @dt.in_time_zone(Object.new) }
+ end
+
def test_in_time_zone_with_time_local_instance
with_env_tz 'US/Eastern' do
time = Time.local(1999, 12, 31, 19) # == Time.utc(2000)
@@ -790,6 +805,14 @@ class TimeWithZoneMethodsForTimeAndDateTimeTest < Test::Unit::TestCase
assert_equal ActiveSupport::TimeZone['Alaska'], Time.zone
end
+ def test_use_zone_raises_on_invalid_timezone
+ Time.zone = 'Alaska'
+ assert_raise ArgumentError do
+ Time.use_zone("No such timezone exists") { }
+ end
+ assert_equal ActiveSupport::TimeZone['Alaska'], Time.zone
+ end
+
def test_time_zone_getter_and_setter
Time.zone = ActiveSupport::TimeZone['Alaska']
assert_equal ActiveSupport::TimeZone['Alaska'], Time.zone
@@ -843,11 +866,27 @@ class TimeWithZoneMethodsForTimeAndDateTimeTest < Test::Unit::TestCase
end
def test_time_zone_setter_with_invalid_zone
- Time.zone = 'foo'
- assert_nil Time.zone
+ assert_raise(ArgumentError){ Time.zone = "No such timezone exists" }
+ assert_raise(ArgumentError){ Time.zone = -15.hours }
+ assert_raise(ArgumentError){ Time.zone = Object.new }
+ end
+
+ def test_find_zone_without_bang_returns_nil_if_time_zone_can_not_be_found
+ assert_nil Time.find_zone('No such timezone exists')
+ assert_nil Time.find_zone(-15.hours)
+ assert_nil Time.find_zone(Object.new)
+ end
+
+ def test_find_zone_with_bang_raises_if_time_zone_can_not_be_found
+ assert_raise(ArgumentError) { Time.find_zone!('No such timezone exists') }
+ assert_raise(ArgumentError) { Time.find_zone!(-15.hours) }
+ assert_raise(ArgumentError) { Time.find_zone!(Object.new) }
+ end
- Time.zone = -15.hours
- assert_nil Time.zone
+ def test_time_zone_setter_with_find_zone_without_bang
+ assert_nil Time.zone = Time.find_zone('No such timezone exists')
+ assert_nil Time.zone = Time.find_zone(-15.hours)
+ assert_nil Time.zone = Time.find_zone(Object.new)
end
def test_current_returns_time_now_when_zone_not_set
diff --git a/activesupport/test/descendants_tracker_test.rb b/activesupport/test/descendants_tracker_test_cases.rb
index 79fb893592..066ec8549b 100644
--- a/activesupport/test/descendants_tracker_test.rb
+++ b/activesupport/test/descendants_tracker_test_cases.rb
@@ -1,9 +1,4 @@
-require 'abstract_unit'
-require 'test/unit'
-require 'active_support'
-require 'active_support/core_ext/hash/slice'
-
-class DescendantsTrackerTest < Test::Unit::TestCase
+module DescendantsTrackerTestCases
class Parent
extend ActiveSupport::DescendantsTracker
end
@@ -34,7 +29,7 @@ class DescendantsTrackerTest < Test::Unit::TestCase
assert_equal [], Child2.direct_descendants
end
- def test_clear_with_autoloaded_parent_children_and_granchildren
+ def test_clear
mark_as_autoloaded(*ALL) do
ActiveSupport::DescendantsTracker.clear
ALL.each do |k|
@@ -43,35 +38,22 @@ class DescendantsTrackerTest < Test::Unit::TestCase
end
end
- def test_clear_with_autoloaded_children_and_granchildren
- mark_as_autoloaded Child1, Grandchild1, Grandchild2 do
- ActiveSupport::DescendantsTracker.clear
- assert_equal [Child2], Parent.descendants
- assert_equal [], Child2.descendants
- end
- end
-
- def test_clear_with_autoloaded_granchildren
- mark_as_autoloaded Grandchild1, Grandchild2 do
- ActiveSupport::DescendantsTracker.clear
- assert_equal [Child1, Child2], Parent.descendants
- assert_equal [], Child1.descendants
- assert_equal [], Child2.descendants
- end
- end
-
protected
def mark_as_autoloaded(*klasses)
- old_autoloaded = ActiveSupport::Dependencies.autoloaded_constants.dup
- ActiveSupport::Dependencies.autoloaded_constants = klasses.map(&:name)
+ # If ActiveSupport::Dependencies is not loaded, forget about autoloading.
+ # This allows using AS::DescendantsTracker without AS::Dependencies.
+ if defined? ActiveSupport::Dependencies
+ old_autoloaded = ActiveSupport::Dependencies.autoloaded_constants.dup
+ ActiveSupport::Dependencies.autoloaded_constants = klasses.map(&:name)
+ end
old_descendants = ActiveSupport::DescendantsTracker.class_eval("@@direct_descendants").dup
old_descendants.each { |k, v| old_descendants[k] = v.dup }
yield
ensure
- ActiveSupport::Dependencies.autoloaded_constants = old_autoloaded
+ ActiveSupport::Dependencies.autoloaded_constants = old_autoloaded if defined? ActiveSupport::Dependencies
ActiveSupport::DescendantsTracker.class_eval("@@direct_descendants").replace(old_descendants)
end
end \ No newline at end of file
diff --git a/activesupport/test/descendants_tracker_with_autoloading_test.rb b/activesupport/test/descendants_tracker_with_autoloading_test.rb
new file mode 100644
index 0000000000..ae18a56f44
--- /dev/null
+++ b/activesupport/test/descendants_tracker_with_autoloading_test.rb
@@ -0,0 +1,35 @@
+require 'abstract_unit'
+require 'test/unit'
+require 'active_support/descendants_tracker'
+require 'active_support/dependencies'
+require 'descendants_tracker_test_cases'
+
+class DescendantsTrackerWithAutoloadingTest < Test::Unit::TestCase
+ include DescendantsTrackerTestCases
+
+ def test_clear_with_autoloaded_parent_children_and_granchildren
+ mark_as_autoloaded(*ALL) do
+ ActiveSupport::DescendantsTracker.clear
+ ALL.each do |k|
+ assert ActiveSupport::DescendantsTracker.descendants(k).empty?
+ end
+ end
+ end
+
+ def test_clear_with_autoloaded_children_and_granchildren
+ mark_as_autoloaded Child1, Grandchild1, Grandchild2 do
+ ActiveSupport::DescendantsTracker.clear
+ assert_equal [Child2], Parent.descendants
+ assert_equal [], Child2.descendants
+ end
+ end
+
+ def test_clear_with_autoloaded_granchildren
+ mark_as_autoloaded Grandchild1, Grandchild2 do
+ ActiveSupport::DescendantsTracker.clear
+ assert_equal [Child1, Child2], Parent.descendants
+ assert_equal [], Child1.descendants
+ assert_equal [], Child2.descendants
+ end
+ end
+end \ No newline at end of file
diff --git a/activesupport/test/descendants_tracker_without_autoloading_test.rb b/activesupport/test/descendants_tracker_without_autoloading_test.rb
new file mode 100644
index 0000000000..1f0c32dc3f
--- /dev/null
+++ b/activesupport/test/descendants_tracker_without_autoloading_test.rb
@@ -0,0 +1,8 @@
+require 'abstract_unit'
+require 'test/unit'
+require 'active_support/descendants_tracker'
+require 'descendants_tracker_test_cases'
+
+class DescendantsTrackerWithoutAutoloadingTest < Test::Unit::TestCase
+ include DescendantsTrackerTestCases
+end \ No newline at end of file
diff --git a/activesupport/test/file_watcher_test.rb b/activesupport/test/file_watcher_test.rb
deleted file mode 100644
index 7b4d4be24f..0000000000
--- a/activesupport/test/file_watcher_test.rb
+++ /dev/null
@@ -1,233 +0,0 @@
-require 'abstract_unit'
-require 'fssm'
-require "fileutils"
-require "timeout"
-
-
-class FileWatcherTest < ActiveSupport::TestCase
- class DumbBackend < ActiveSupport::FileWatcher::Backend
- end
-
- def setup
- @watcher = ActiveSupport::FileWatcher.new
-
- # In real life, the backend would take the path and use it to observe the file
- # system. In our case, we will manually trigger the events for unit testing,
- # so we can pass any path.
- @backend = DumbBackend.new("RAILS_WOOT", @watcher)
-
- @payload = []
- @watcher.watch %r{^app/assets/.*\.scss$} do |pay|
- pay.each do |status, files|
- files.sort!
- end
- @payload << pay
- end
- end
-
- def test_use_triple_equals
- fw = ActiveSupport::FileWatcher.new
- called = []
- fw.watch("some_arbitrary_file.rb") do |file|
- called << "omg"
- end
- fw.trigger(%w{ some_arbitrary_file.rb })
- assert_equal ['omg'], called
- end
-
- def test_one_change
- @backend.trigger("app/assets/main.scss" => :changed)
- assert_equal({:changed => ["app/assets/main.scss"]}, @payload.first)
- end
-
- def test_multiple_changes
- @backend.trigger("app/assets/main.scss" => :changed, "app/assets/javascripts/foo.coffee" => :changed)
- assert_equal([{:changed => ["app/assets/main.scss"]}], @payload)
- end
-
- def test_multiple_changes_match
- @backend.trigger("app/assets/main.scss" => :changed, "app/assets/print.scss" => :changed, "app/assets/javascripts/foo.coffee" => :changed)
- assert_equal([{:changed => ["app/assets/main.scss", "app/assets/print.scss"]}], @payload)
- end
-
- def test_multiple_state_changes
- @backend.trigger("app/assets/main.scss" => :created, "app/assets/print.scss" => :changed)
- assert_equal([{:changed => ["app/assets/print.scss"], :created => ["app/assets/main.scss"]}], @payload)
- end
-
- def test_more_blocks
- payload = []
- @watcher.watch %r{^config/routes\.rb$} do |pay|
- payload << pay
- end
-
- @backend.trigger "config/routes.rb" => :changed
- assert_equal [:changed => ["config/routes.rb"]], payload
- assert_equal [], @payload
- end
-
- def test_overlapping_watchers
- payload = []
- @watcher.watch %r{^app/assets/main\.scss$} do |pay|
- payload << pay
- end
-
- @backend.trigger "app/assets/print.scss" => :changed, "app/assets/main.scss" => :changed
- assert_equal [:changed => ["app/assets/main.scss"]], payload
- assert_equal [:changed => ["app/assets/main.scss", "app/assets/print.scss"]], @payload
- end
-end
-
-module FSSM::Backends
- class Polling
- def initialize_with_low_latency(options={})
- initialize_without_low_latency(options.merge(:latency => 0.1))
- end
- alias_method_chain :initialize, :low_latency
- end
-end
-
-class FSSMFileWatcherTest < ActiveSupport::TestCase
- class FSSMBackend < ActiveSupport::FileWatcher::Backend
- def initialize(path, watcher)
- super
-
- monitor = FSSM::Monitor.new
- monitor.path(path, '**/*') do |p|
- p.update { |base, relative| trigger relative => :changed }
- p.delete { |base, relative| trigger relative => :deleted }
- p.create { |base, relative| trigger relative => :created }
- end
-
- @thread = Thread.new do
- monitor.run
- end
- end
-
- def stop
- @thread.kill
- end
- end
-
- def setup
- Thread.abort_on_exception = true
-
- @payload = []
- @triggered = false
-
- @watcher = ActiveSupport::FileWatcher.new
-
- @path = path = File.expand_path("../tmp", __FILE__)
- FileUtils.rm_rf path
-
- create "app/assets/main.scss", true
- create "app/assets/javascripts/foo.coffee", true
- create "app/assets/print.scss", true
- create "app/assets/videos.scss", true
-
- @backend = FSSMBackend.new(path, @watcher)
-
- @watcher.watch %r{^app/assets/.*\.scss$} do |pay|
- pay.each do |status, files|
- files.sort!
- end
- @payload << pay
- trigger
- end
- end
-
- def teardown
- @backend.stop
- Thread.abort_on_exception = false
- end
-
- def create(path, past = false)
- wait(past) do
- path = File.join(@path, path)
- FileUtils.mkdir_p(File.dirname(path))
-
- FileUtils.touch(path)
- File.utime(Time.now - 100, Time.now - 100, path) if past
- end
- end
-
- def change(path)
- wait do
- FileUtils.touch(File.join(@path, path))
- end
- end
-
- def delete(path)
- wait do
- FileUtils.rm(File.join(@path, path))
- end
- end
-
- def wait(past = false)
- yield
- return if past
-
- begin
- Timeout.timeout(1) do
- sleep 0.05 until @triggered
- end
- rescue Timeout::Error
- end
-
- @triggered = false
- end
-
- def trigger
- @triggered = true
- end
-
- def test_one_change
- change "app/assets/main.scss"
- assert_equal({:changed => ["app/assets/main.scss"]}, @payload.first)
- end
-
- def test_multiple_changes
- change "app/assets/main.scss"
- change "app/assets/javascripts/foo.coffee"
- assert_equal([{:changed => ["app/assets/main.scss"]}], @payload)
- end
-
- def test_multiple_changes_match
- change "app/assets/main.scss"
- change "app/assets/print.scss"
- change "app/assets/javascripts/foo.coffee"
- assert_equal([{:changed => ["app/assets/main.scss"]}, {:changed => ["app/assets/print.scss"]}], @payload)
- end
-
- def test_multiple_state_changes
- create "app/assets/new.scss"
- change "app/assets/print.scss"
- delete "app/assets/videos.scss"
- assert_equal([{:created => ["app/assets/new.scss"]}, {:changed => ["app/assets/print.scss"]}, {:deleted => ["app/assets/videos.scss"]}], @payload)
- end
-
- def test_more_blocks
- payload = []
- @watcher.watch %r{^config/routes\.rb$} do |pay|
- payload << pay
- trigger
- end
-
- create "config/routes.rb"
- assert_equal [{:created => ["config/routes.rb"]}], payload
- assert_equal [], @payload
- end
-
- def test_overlapping_watchers
- payload = []
- @watcher.watch %r{^app/assets/main\.scss$} do |pay|
- payload << pay
- trigger
- end
-
- change "app/assets/main.scss"
- change "app/assets/print.scss"
- assert_equal [{:changed => ["app/assets/main.scss"]}], payload
- assert_equal [{:changed => ["app/assets/main.scss"]}, {:changed => ["app/assets/print.scss"]}], @payload
- end
-end
diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb
index 1670d9ee7d..95f18126d4 100644
--- a/activesupport/test/inflector_test.rb
+++ b/activesupport/test/inflector_test.rb
@@ -255,12 +255,21 @@ class InflectorTest < Test::Unit::TestCase
end
def test_clear_all
- cached_values = ActiveSupport::Inflector.inflections.plurals, ActiveSupport::Inflector.inflections.singulars, ActiveSupport::Inflector.inflections.uncountables, ActiveSupport::Inflector.inflections.humans
- ActiveSupport::Inflector.inflections.clear :all
- assert ActiveSupport::Inflector.inflections.plurals.empty?
- assert ActiveSupport::Inflector.inflections.singulars.empty?
- assert ActiveSupport::Inflector.inflections.uncountables.empty?
- assert ActiveSupport::Inflector.inflections.humans.empty?
+ cached_values = ActiveSupport::Inflector.inflections.plurals.dup, ActiveSupport::Inflector.inflections.singulars.dup, ActiveSupport::Inflector.inflections.uncountables.dup, ActiveSupport::Inflector.inflections.humans.dup
+ ActiveSupport::Inflector.inflections do |inflect|
+ # ensure any data is present
+ inflect.plural(/(quiz)$/i, '\1zes')
+ inflect.singular(/(database)s$/i, '\1')
+ inflect.uncountable('series')
+ inflect.human("col_rpted_bugs", "Reported bugs")
+
+ inflect.clear :all
+
+ assert inflect.plurals.empty?
+ assert inflect.singulars.empty?
+ assert inflect.uncountables.empty?
+ assert inflect.humans.empty?
+ end
ActiveSupport::Inflector.inflections.instance_variable_set :@plurals, cached_values[0]
ActiveSupport::Inflector.inflections.instance_variable_set :@singulars, cached_values[1]
ActiveSupport::Inflector.inflections.instance_variable_set :@uncountables, cached_values[2]
@@ -268,12 +277,21 @@ class InflectorTest < Test::Unit::TestCase
end
def test_clear_with_default
- cached_values = ActiveSupport::Inflector.inflections.plurals, ActiveSupport::Inflector.inflections.singulars, ActiveSupport::Inflector.inflections.uncountables, ActiveSupport::Inflector.inflections.humans
- ActiveSupport::Inflector.inflections.clear
- assert ActiveSupport::Inflector.inflections.plurals.empty?
- assert ActiveSupport::Inflector.inflections.singulars.empty?
- assert ActiveSupport::Inflector.inflections.uncountables.empty?
- assert ActiveSupport::Inflector.inflections.humans.empty?
+ cached_values = ActiveSupport::Inflector.inflections.plurals.dup, ActiveSupport::Inflector.inflections.singulars.dup, ActiveSupport::Inflector.inflections.uncountables.dup, ActiveSupport::Inflector.inflections.humans.dup
+ ActiveSupport::Inflector.inflections do |inflect|
+ # ensure any data is present
+ inflect.plural(/(quiz)$/i, '\1zes')
+ inflect.singular(/(database)s$/i, '\1')
+ inflect.uncountable('series')
+ inflect.human("col_rpted_bugs", "Reported bugs")
+
+ inflect.clear
+
+ assert inflect.plurals.empty?
+ assert inflect.singulars.empty?
+ assert inflect.uncountables.empty?
+ assert inflect.humans.empty?
+ end
ActiveSupport::Inflector.inflections.instance_variable_set :@plurals, cached_values[0]
ActiveSupport::Inflector.inflections.instance_variable_set :@singulars, cached_values[1]
ActiveSupport::Inflector.inflections.instance_variable_set :@uncountables, cached_values[2]
diff --git a/activesupport/test/inflector_test_cases.rb b/activesupport/test/inflector_test_cases.rb
index 2b144e5931..ec9d92794c 100644
--- a/activesupport/test/inflector_test_cases.rb
+++ b/activesupport/test/inflector_test_cases.rb
@@ -215,6 +215,36 @@ module InflectorTestCases
}
OrdinalNumbers = {
+ "-1" => "-1st",
+ "-2" => "-2nd",
+ "-3" => "-3rd",
+ "-4" => "-4th",
+ "-5" => "-5th",
+ "-6" => "-6th",
+ "-7" => "-7th",
+ "-8" => "-8th",
+ "-9" => "-9th",
+ "-10" => "-10th",
+ "-11" => "-11th",
+ "-12" => "-12th",
+ "-13" => "-13th",
+ "-14" => "-14th",
+ "-20" => "-20th",
+ "-21" => "-21st",
+ "-22" => "-22nd",
+ "-23" => "-23rd",
+ "-24" => "-24th",
+ "-100" => "-100th",
+ "-101" => "-101st",
+ "-102" => "-102nd",
+ "-103" => "-103rd",
+ "-104" => "-104th",
+ "-110" => "-110th",
+ "-111" => "-111th",
+ "-112" => "-112th",
+ "-113" => "-113th",
+ "-1000" => "-1000th",
+ "-1001" => "-1001st",
"0" => "0th",
"1" => "1st",
"2" => "2nd",
diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb
index 24d9f88c09..6ccffa59b1 100644
--- a/activesupport/test/json/decoding_test.rb
+++ b/activesupport/test/json/decoding_test.rb
@@ -17,6 +17,8 @@ class TestJSONDecoding < ActiveSupport::TestCase
%({"matzue": "松江", "asakusa": "浅草"}) => {"matzue" => "松江", "asakusa" => "浅草"},
%({"a": "2007-01-01"}) => {'a' => Date.new(2007, 1, 1)},
%({"a": "2007-01-01 01:12:34 Z"}) => {'a' => Time.utc(2007, 1, 1, 1, 12, 34)},
+ %(["2007-01-01 01:12:34 Z"]) => [Time.utc(2007, 1, 1, 1, 12, 34)],
+ %(["2007-01-01 01:12:34 Z", "2007-01-01 01:12:35 Z"]) => [Time.utc(2007, 1, 1, 1, 12, 34), Time.utc(2007, 1, 1, 1, 12, 35)],
# no time zone
%({"a": "2007-01-01 01:12:34"}) => {'a' => "2007-01-01 01:12:34"},
# invalid date
@@ -54,12 +56,9 @@ class TestJSONDecoding < ActiveSupport::TestCase
%q({"a":"Line1\u000aLine2"}) => {"a"=>"Line1\nLine2"}
}
- # load the default JSON backend
- ActiveSupport::JSON.backend = 'Yaml'
-
- backends = %w(Yaml)
- backends << "JSONGem" if defined?(::JSON)
- backends << "Yajl" if defined?(::Yajl)
+ backends = [:ok_json]
+ backends << :json_gem if defined?(::JSON)
+ backends << :yajl if defined?(::Yajl)
backends.each do |backend|
TESTS.each do |json, expected|
@@ -72,13 +71,11 @@ class TestJSONDecoding < ActiveSupport::TestCase
end
end
end
- end
- if backends.include?("JSONGem")
- test "json decodes time json with time parsing disabled" do
+ test "json decodes time json with time parsing disabled with the #{backend} backend" do
ActiveSupport.parse_json_times = false
expected = {"a" => "2007-01-01 01:12:34 Z"}
- ActiveSupport::JSON.with_backend "JSONGem" do
+ ActiveSupport::JSON.with_backend backend do
assert_equal expected, ActiveSupport::JSON.decode(%({"a": "2007-01-01 01:12:34 Z"}))
end
end
diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb
index d5fcbf15b7..8cf1a54a99 100644
--- a/activesupport/test/json/encoding_test.rb
+++ b/activesupport/test/json/encoding_test.rb
@@ -215,6 +215,30 @@ class TestJSONEncoding < Test::Unit::TestCase
assert_equal(%([{"address":{"city":"London"}},{"address":{"city":"Paris"}}]), json)
end
+ def test_enumerable_should_pass_encoding_options_to_children_in_as_json
+ people = [
+ { :name => 'John', :address => { :city => 'London', :country => 'UK' }},
+ { :name => 'Jean', :address => { :city => 'Paris' , :country => 'France' }}
+ ]
+ json = people.each.as_json :only => [:address, :city]
+ expected = [
+ { 'address' => { 'city' => 'London' }},
+ { 'address' => { 'city' => 'Paris' }}
+ ]
+
+ assert_equal(expected, json)
+ end
+
+ def test_enumerable_should_pass_encoding_options_to_children_in_to_json
+ people = [
+ { :name => 'John', :address => { :city => 'London', :country => 'UK' }},
+ { :name => 'Jean', :address => { :city => 'Paris' , :country => 'France' }}
+ ]
+ json = people.each.to_json :only => [:address, :city]
+
+ assert_equal(%([{"address":{"city":"London"}},{"address":{"city":"Paris"}}]), json)
+ end
+
def test_struct_encoding
Struct.new('UserNameAndEmail', :name, :email)
Struct.new('UserNameAndDate', :name, :date)
@@ -259,12 +283,3 @@ class TestJSONEncoding < Test::Unit::TestCase
old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
end
end
-
-class JsonOptionsTests < Test::Unit::TestCase
- def test_enumerable_should_passthrough_options_to_elements
- value, options = Object.new, Object.new
- def value.as_json(options) options end
- def options.encode_json(encoder) self end
- assert_equal options, ActiveSupport::JSON.encode(value, options)
- end
-end
diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb
index 6ebbfdf334..bfff10fff2 100644
--- a/activesupport/test/multibyte_chars_test.rb
+++ b/activesupport/test/multibyte_chars_test.rb
@@ -1,6 +1,7 @@
# encoding: utf-8
require 'abstract_unit'
require 'multibyte_test_helpers'
+require 'active_support/core_ext/string/multibyte'
class String
def __method_for_multibyte_testing_with_integer_result; 1; end
diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb
index 50168fa78f..f3dcd7b068 100644
--- a/activesupport/test/ordered_hash_test.rb
+++ b/activesupport/test/ordered_hash_test.rb
@@ -1,6 +1,7 @@
require 'abstract_unit'
require 'active_support/json'
require 'active_support/core_ext/object/to_json'
+require 'active_support/core_ext/hash/indifferent_access'
class OrderedHashTest < Test::Unit::TestCase
def setup
@@ -243,6 +244,11 @@ class OrderedHashTest < Test::Unit::TestCase
assert_equal @other_ordered_hash.keys, @ordered_hash.keys
end
+ def test_nested_under_indifferent_access
+ flash = {:a => ActiveSupport::OrderedHash[:b, 1, :c, 2]}.with_indifferent_access
+ assert_kind_of ActiveSupport::OrderedHash, flash[:a]
+ end
+
def test_each_after_yaml_serialization
values = []
@deserialized_ordered_hash = YAML.load(YAML.dump(@ordered_hash))
diff --git a/activesupport/test/ordered_options_test.rb b/activesupport/test/ordered_options_test.rb
index e48425ca25..b215b60df3 100644
--- a/activesupport/test/ordered_options_test.rb
+++ b/activesupport/test/ordered_options_test.rb
@@ -50,4 +50,30 @@ class OrderedOptionsTest < Test::Unit::TestCase
assert_equal 2, a.size
assert_equal 56, a.else_where
end
+
+ def test_inheritable_options_continues_lookup_in_parent
+ parent = ActiveSupport::OrderedOptions.new
+ parent[:foo] = true
+
+ child = ActiveSupport::InheritableOptions.new(parent)
+ assert child.foo
+ end
+
+ def test_inheritable_options_can_override_parent
+ parent = ActiveSupport::OrderedOptions.new
+ parent[:foo] = :bar
+
+ child = ActiveSupport::InheritableOptions.new(parent)
+ child[:foo] = :baz
+
+ assert_equal :baz, child.foo
+ end
+
+ def test_inheritable_options_inheritable_copy
+ original = ActiveSupport::InheritableOptions.new
+ copy = original.inheritable_copy
+
+ assert copy.kind_of?(original.class)
+ assert_not_equal copy.object_id, original.object_id
+ end
end
diff --git a/activesupport/test/transliterate_test.rb b/activesupport/test/transliterate_test.rb
index b054855d08..08e11d4f38 100644
--- a/activesupport/test/transliterate_test.rb
+++ b/activesupport/test/transliterate_test.rb
@@ -1,6 +1,7 @@
# encoding: utf-8
require 'abstract_unit'
require 'active_support/inflector/transliterate'
+require 'active_support/core_ext/object/inclusion'
class TransliterateTest < Test::Unit::TestCase
@@ -15,7 +16,7 @@ class TransliterateTest < Test::Unit::TestCase
# create string with range of Unicode"s western characters with
# diacritics, excluding the division and multiplication signs which for
# some reason or other are floating in the middle of all the letters.
- string = (0xC0..0x17E).to_a.reject {|c| [0xD7, 0xF7].include? c}.pack("U*")
+ string = (0xC0..0x17E).to_a.reject {|c| c.in?([0xD7, 0xF7])}.pack("U*")
string.each_char do |char|
assert_match %r{^[a-zA-Z']*$}, ActiveSupport::Inflector.transliterate(string)
end
diff --git a/activesupport/test/test_xml_mini.rb b/activesupport/test/xml_mini_test.rb
index 6dbcd1f40b..e2b90ae16e 100644
--- a/activesupport/test/test_xml_mini.rb
+++ b/activesupport/test/xml_mini_test.rb
@@ -16,14 +16,6 @@ module XmlMiniTest
assert_equal "my_key", ActiveSupport::XmlMini.rename_key("my_key", :dasherize => false)
end
- def test_rename_key_camelizes_with_camelize_false
- assert_equal "my_key", ActiveSupport::XmlMini.rename_key("my_key", :camelize => false)
- end
-
- def test_rename_key_camelizes_with_camelize_nil
- assert_equal "my_key", ActiveSupport::XmlMini.rename_key("my_key", :camelize => nil)
- end
-
def test_rename_key_camelizes_with_camelize_true
assert_equal "MyKey", ActiveSupport::XmlMini.rename_key("my_key", :camelize => true)
end
@@ -56,7 +48,7 @@ module XmlMiniTest
assert_equal "__id", ActiveSupport::XmlMini.rename_key("__id")
end
- def test_rename_key_does_not_dasherize_multiple_leading_underscores
+ def test_rename_key_does_not_dasherize_multiple_trailing_underscores
assert_equal "id__", ActiveSupport::XmlMini.rename_key("id__")
end
end
@@ -95,6 +87,16 @@ module XmlMiniTest
@xml.to_tag(:b, "Howdy", @options)
assert_xml "<b>Howdy</b>"
end
+
+ test "#to_tag should dasherize the space when passed a string with spaces as a key" do
+ @xml.to_tag("New York", 33, @options)
+ assert_xml "<New---York type=\"integer\">33</New---York>"
+ end
+
+ test "#to_tag should dasherize the space when passed a symbol with spaces as a key" do
+ @xml.to_tag(:"New York", 33, @options)
+ assert_xml "<New---York type=\"integer\">33</New---York>"
+ end
# TODO: test the remaining functions hidden in #to_tag.
end
end