aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG2
-rw-r--r--activesupport/activesupport.gemspec2
-rw-r--r--activesupport/lib/active_support.rb1
-rw-r--r--activesupport/lib/active_support/buffered_logger.rb13
-rw-r--r--activesupport/lib/active_support/cache/file_store.rb2
-rw-r--r--activesupport/lib/active_support/cache/mem_cache_store.rb10
-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/hash/conversions.rb3
-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.rb6
-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/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/inflector/inflections.rb2
-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.rb113
-rw-r--r--activesupport/lib/active_support/json/decoding.rb60
-rw-r--r--activesupport/lib/active_support/json/encoding.rb4
-rw-r--r--activesupport/lib/active_support/log_subscriber.rb2
-rw-r--r--activesupport/lib/active_support/notifications/fanout.rb6
-rw-r--r--activesupport/lib/active_support/testing/assertions.rb23
-rw-r--r--activesupport/lib/active_support/testing/performance.rb131
-rw-r--r--activesupport/lib/active_support/version.rb2
-rw-r--r--activesupport/lib/active_support/whiny_nil.rb2
-rw-r--r--activesupport/test/caching_test.rb38
-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.rb10
-rw-r--r--activesupport/test/core_ext/object/inclusion_test.rb4
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb6
-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/json/decoding_test.rb9
-rw-r--r--activesupport/test/json/encoding_test.rb33
-rw-r--r--activesupport/test/multibyte_chars_test.rb1
47 files changed, 501 insertions, 633 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 163f1c932c..69e9cbfd42 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*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
diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec
index eaecb30090..c5b5b57dec 100644
--- a/activesupport/activesupport.gemspec
+++ b/activesupport/activesupport.gemspec
@@ -16,4 +16,6 @@ Gem::Specification.new do |s|
s.files = Dir['CHANGELOG', 'README.rdoc', 'lib/**/*']
s.require_path = 'lib'
+
+ s.add_dependency('multi_json', '~> 1.0')
end
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 6b662ac660..6b87774978 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -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..88b50fc506 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
@@ -100,13 +100,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 +122,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 9936b33e22..a1376ae52a 100644
--- a/activesupport/lib/active_support/cache/file_store.rb
+++ b/activesupport/lib/active_support/cache/file_store.rb
@@ -121,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
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/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/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index 61a1d88b0e..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['type'] == 'file' || value["__content__"].present?
+ 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/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
index cc7edc0f17..b5671f66d0 100644
--- a/activesupport/lib/active_support/core_ext/object/inclusion.rb
+++ b/activesupport/lib/active_support/core_ext/object/inclusion.rb
@@ -1,11 +1,15 @@
class Object
# Returns true if this object is included in the argument. Argument must be
- # any object which respond to +#include?+. Usage:
+ # 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/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/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/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 e25e29d36b..0000000000
--- a/activesupport/lib/active_support/json/backends/yaml.rb
+++ /dev/null
@@ -1,113 +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)
- if ActiveSupport.parse_json_times
- # 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
- 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..1fafc36ee8 100644
--- a/activesupport/lib/active_support/json/encoding.rb
+++ b/activesupport/lib/active_support/json/encoding.rb
@@ -205,7 +205,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/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/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/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/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/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/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 012b956d7f..3ef080e1cb 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -897,7 +897,13 @@ class HashToXmlTest < Test::Unit::TestCase
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>
@@ -940,7 +946,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
index 382271d42d..1de857d678 100644
--- a/activesupport/test/core_ext/object/inclusion_test.rb
+++ b/activesupport/test/core_ext/object/inclusion_test.rb
@@ -43,4 +43,8 @@ class InTest < Test::Unit::TestCase
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 38b344b885..54ef68c59b 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/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/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb
index 88cf97de7e..6ccffa59b1 100644
--- a/activesupport/test/json/decoding_test.rb
+++ b/activesupport/test/json/decoding_test.rb
@@ -56,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|
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