aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG4
-rwxr-xr-x[-rw-r--r--]activesupport/Rakefile0
-rw-r--r--activesupport/lib/active_support/cache.rb6
-rw-r--r--activesupport/lib/active_support/cache/file_store.rb7
-rw-r--r--activesupport/lib/active_support/callbacks.rb118
-rw-r--r--activesupport/lib/active_support/concern.rb2
-rw-r--r--activesupport/lib/active_support/configurable.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/big_decimal/conversions.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/cgi.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb19
-rw-r--r--activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb92
-rw-r--r--activesupport/lib/active_support/core_ext/class/subclasses.rb54
-rw-r--r--activesupport/lib/active_support/core_ext/date/conversions.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/conversions.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/hash.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/hash/conversions.rb16
-rw-r--r--activesupport/lib/active_support/core_ext/hash/deep_dup.rb11
-rw-r--r--activesupport/lib/active_support/core_ext/module/synchronization.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/object/instance_variables.rb31
-rw-r--r--activesupport/lib/active_support/core_ext/object/to_param.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/object/to_query.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/object/try.rb17
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb22
-rw-r--r--activesupport/lib/active_support/core_ext/time/conversions.rb2
-rw-r--r--activesupport/lib/active_support/dependencies.rb2
-rw-r--r--activesupport/lib/active_support/deprecation.rb4
-rw-r--r--activesupport/lib/active_support/deprecation/behaviors.rb7
-rw-r--r--activesupport/lib/active_support/deprecation/proxy_wrappers.rb2
-rw-r--r--activesupport/lib/active_support/deprecation/reporting.rb6
-rw-r--r--activesupport/lib/active_support/duration.rb4
-rw-r--r--activesupport/lib/active_support/file_update_checker.rb2
-rw-r--r--activesupport/lib/active_support/hash_with_indifferent_access.rb13
-rw-r--r--activesupport/lib/active_support/i18n.rb1
-rw-r--r--activesupport/lib/active_support/i18n_railtie.rb2
-rw-r--r--activesupport/lib/active_support/inflector/inflections.rb2
-rw-r--r--activesupport/lib/active_support/json/backends/yaml.rb9
-rw-r--r--activesupport/lib/active_support/json/encoding.rb6
-rw-r--r--activesupport/lib/active_support/ordered_hash.rb12
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb8
-rw-r--r--activesupport/lib/active_support/version.rb4
-rw-r--r--activesupport/lib/active_support/xml_mini.rb6
-rw-r--r--activesupport/lib/active_support/xml_mini/nokogirisax.rb3
-rw-r--r--activesupport/test/caching_test.rb9
-rw-r--r--activesupport/test/callbacks_test.rb31
-rw-r--r--activesupport/test/core_ext/bigdecimal_test.rb (renamed from activesupport/test/core_ext/bigdecimal.rb)13
-rw-r--r--activesupport/test/core_ext/cgi_ext_test.rb15
-rw-r--r--activesupport/test/core_ext/class/class_inheritable_attributes_test.rb5
-rw-r--r--activesupport/test/core_ext/duration_test.rb5
-rw-r--r--activesupport/test/core_ext/hash_ext_test.rb65
-rw-r--r--activesupport/test/core_ext/module/synchronization_test.rb1
-rw-r--r--activesupport/test/core_ext/object/to_query_test.rb8
-rw-r--r--activesupport/test/core_ext/object_and_class_ext_test.rb53
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb69
-rw-r--r--activesupport/test/core_ext/time_with_zone_test.rb13
-rw-r--r--activesupport/test/inflector_test.rb28
-rw-r--r--activesupport/test/json/encoding_test.rb31
-rw-r--r--activesupport/test/ordered_hash_test.rb36
-rw-r--r--activesupport/test/test_xml_mini.rb117
58 files changed, 565 insertions, 459 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 3b6a29f7d6..6e8cce0d27 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -4,6 +4,10 @@
* Added before_remove_const callback to ActiveSupport::Dependencies.remove_unloadable_constants! [Andrew White]
+*Rails 3.0.2 (unreleased)*
+
+* 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.
diff --git a/activesupport/Rakefile b/activesupport/Rakefile
index d117ca6356..d117ca6356 100644..100755
--- a/activesupport/Rakefile
+++ b/activesupport/Rakefile
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index 9098ffbfec..b4f0c42e37 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -210,11 +210,11 @@ module ActiveSupport
# be specified as an option to the construction in which call all entries will be
# affected. Or it can be supplied to the +fetch+ or +write+ method for just one entry.
#
- # cache = ActiveSupport::Cache::MemoryStore.new(:expire_in => 5.minutes)
- # cache.write(key, value, :expire_in => 1.minute) # Set a lower value for one entry
+ # cache = ActiveSupport::Cache::MemoryStore.new(:expires_in => 5.minutes)
+ # cache.write(key, value, :expires_in => 1.minute) # Set a lower value for one entry
#
# Setting <tt>:race_condition_ttl</tt> is very useful in situations where a cache entry
- # is used very frequently unver heavy load. If a cache expires and due to heavy load
+ # is used very frequently and is under heavy load. If a cache expires and due to heavy load
# seven different processes will try to read data natively and then they all will try to
# write to cache. To avoid that case the first process to find an expired cache entry will
# bump the cache expiration time by the value set in <tt>:race_condition_ttl</tt>. Yes
diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb
index 84f6f29572..18182bbb40 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 'rack/utils'
module ActiveSupport
module Cache
@@ -11,8 +12,6 @@ module ActiveSupport
attr_reader :cache_path
DIR_FORMATTER = "%03X"
- ESCAPE_FILENAME_CHARS = /[^a-z0-9_.-]/i
- UNESCAPE_FILENAME_CHARS = /%[0-9A-F]{2}/
def initialize(cache_path, options = nil)
super(options)
@@ -136,7 +135,7 @@ module ActiveSupport
# Translate a key into a file path.
def key_file_path(key)
- fname = key.to_s.gsub(ESCAPE_FILENAME_CHARS){|match| "%#{match.ord.to_s(16).upcase}"}
+ fname = Rack::Utils.escape(key)
hash = Zlib.adler32(fname)
hash, dir_1 = hash.divmod(0x1000)
dir_2 = hash.modulo(0x1000)
@@ -156,7 +155,7 @@ module ActiveSupport
# Translate a file path into a key.
def file_path_key(path)
fname = path[cache_path.size, path.size].split(File::SEPARATOR, 4).last
- fname.gsub(UNESCAPE_FILENAME_CHARS){|match| $1.ord.to_s(16)}
+ Rack::Utils.unescape(fname)
end
# Delete empty directories in the cache.
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 8f8def5922..32ebea8571 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -1,6 +1,6 @@
require 'active_support/descendants_tracker'
require 'active_support/core_ext/array/wrap'
-require 'active_support/core_ext/class/inheritable_attributes'
+require 'active_support/core_ext/class/attribute'
require 'active_support/core_ext/kernel/reporting'
require 'active_support/core_ext/kernel/singleton_class'
@@ -178,49 +178,48 @@ module ActiveSupport
# options[0] is the compiled form of supplied conditions
# options[1] is the "end" for the conditional
#
- if @kind == :before || @kind == :around
- if @kind == :before
- # if condition # before_save :filter_name, :if => :condition
- # filter_name
- # end
- filter = <<-RUBY_EVAL
- unless halted
- result = #{@filter}
- halted = (#{chain.config[:terminator]})
- end
- RUBY_EVAL
-
- [@compiled_options[0], filter, @compiled_options[1]].compact.join("\n")
- else
- # Compile around filters with conditions into proxy methods
- # that contain the conditions.
- #
- # For `around_save :filter_name, :if => :condition':
- #
- # def _conditional_callback_save_17
- # if condition
- # filter_name do
- # yield self
- # end
- # else
- # yield self
- # end
- # end
- #
- name = "_conditional_callback_#{@kind}_#{next_id}"
- @klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
- def #{name}(halted)
- #{@compiled_options[0] || "if true"} && !halted
- #{@filter} do
- yield self
- end
- else
+ case @kind
+ when :before
+ # if condition # before_save :filter_name, :if => :condition
+ # filter_name
+ # end
+ filter = <<-RUBY_EVAL
+ unless halted
+ result = #{@filter}
+ halted = (#{chain.config[:terminator]})
+ end
+ RUBY_EVAL
+
+ [@compiled_options[0], filter, @compiled_options[1]].compact.join("\n")
+ when :around
+ # Compile around filters with conditions into proxy methods
+ # that contain the conditions.
+ #
+ # For `around_save :filter_name, :if => :condition':
+ #
+ # def _conditional_callback_save_17
+ # if condition
+ # filter_name do
+ # yield self
+ # end
+ # else
+ # yield self
+ # end
+ # end
+ #
+ name = "_conditional_callback_#{@kind}_#{next_id}"
+ @klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
+ def #{name}(halted)
+ #{@compiled_options[0] || "if true"} && !halted
+ #{@filter} do
yield self
end
+ else
+ yield self
end
- RUBY_EVAL
- "#{name}(halted) do"
- end
+ end
+ RUBY_EVAL
+ "#{name}(halted) do"
end
end
@@ -229,15 +228,14 @@ module ActiveSupport
def end(key=nil, object=nil)
return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?")
- if @kind == :around || @kind == :after
+ case @kind
+ when :after
# if condition # after_save :filter_name, :if => :condition
# filter_name
# end
- if @kind == :after
- [@compiled_options[0], @filter, @compiled_options[1]].compact.join("\n")
- else
- "end"
- end
+ [@compiled_options[0], @filter, @compiled_options[1]].compact.join("\n")
+ when :around
+ "end"
end
end
@@ -388,7 +386,7 @@ module ActiveSupport
# key. See #define_callbacks for more information.
#
def __define_runner(symbol) #:nodoc:
- body = send("_#{symbol}_callbacks").compile(nil)
+ body = send("_#{symbol}_callbacks").compile
silence_warnings do
undef_method "_run_#{symbol}_callbacks" if method_defined?("_run_#{symbol}_callbacks")
@@ -437,7 +435,7 @@ module ActiveSupport
([self] + ActiveSupport::DescendantsTracker.descendants(self)).each do |target|
chain = target.send("_#{name}_callbacks")
- yield chain, type, filters, options
+ yield target, chain.dup, type, filters, options
target.__define_runner(name)
end
end
@@ -449,6 +447,10 @@ module ActiveSupport
# set_callback :save, :after, :after_meth, :if => :condition
# set_callback :save, :around, lambda { |r| stuff; yield; stuff }
#
+ # If the second argument is not :before, :after or :around then an implicit :before is assumed.
+ # It means the first example mentioned above can also be written as:
+ # set_callback :save, :before_meth
+ #
# Use skip_callback to skip any defined one.
#
# When creating or skipping callbacks, you can specify conditions that
@@ -473,7 +475,7 @@ module ActiveSupport
def set_callback(name, *filter_list, &block)
mapped = nil
- __update_callbacks(name, filter_list, block) do |chain, type, filters, options|
+ __update_callbacks(name, filter_list, block) do |target, chain, type, filters, options|
mapped ||= filters.map do |filter|
Callback.new(chain, filter, type, options.dup, self)
end
@@ -483,6 +485,8 @@ module ActiveSupport
end
options[:prepend] ? chain.unshift(*(mapped.reverse)) : chain.push(*mapped)
+
+ target.send("_#{name}_callbacks=", chain)
end
end
@@ -493,7 +497,7 @@ module ActiveSupport
# end
#
def skip_callback(name, *filter_list, &block)
- __update_callbacks(name, filter_list, block) do |chain, type, filters, options|
+ __update_callbacks(name, filter_list, block) do |target, chain, type, filters, options|
filters.each do |filter|
filter = chain.find {|c| c.matches?(type, filter) }
@@ -505,6 +509,7 @@ module ActiveSupport
chain.delete(filter)
end
+ target.send("_#{name}_callbacks=", chain)
end
end
@@ -514,12 +519,14 @@ module ActiveSupport
callbacks = send("_#{symbol}_callbacks")
ActiveSupport::DescendantsTracker.descendants(self).each do |target|
- chain = target.send("_#{symbol}_callbacks")
+ chain = target.send("_#{symbol}_callbacks").dup
callbacks.each { |c| chain.delete(c) }
+ target.send("_#{symbol}_callbacks=", chain)
target.__define_runner(symbol)
end
- callbacks.clear
+ self.send("_#{symbol}_callbacks=", callbacks.dup.clear)
+
__define_runner(symbol)
end
@@ -589,9 +596,8 @@ module ActiveSupport
def define_callbacks(*callbacks)
config = callbacks.last.is_a?(Hash) ? callbacks.pop : {}
callbacks.each do |callback|
- extlib_inheritable_reader("_#{callback}_callbacks") do
- CallbackChain.new(callback, config)
- end
+ class_attribute "_#{callback}_callbacks"
+ send("_#{callback}_callbacks=", CallbackChain.new(callback, config))
__define_runner(callback)
end
end
diff --git a/activesupport/lib/active_support/concern.rb b/activesupport/lib/active_support/concern.rb
index ac94d12e5e..81fb859334 100644
--- a/activesupport/lib/active_support/concern.rb
+++ b/activesupport/lib/active_support/concern.rb
@@ -3,7 +3,7 @@ module ActiveSupport
#
# module M
# def self.included(base)
- # base.extend, ClassMethods
+ # base.extend ClassMethods
# base.send(:include, InstanceMethods)
# scope :disabled, where(:disabled => true)
# end
diff --git a/activesupport/lib/active_support/configurable.rb b/activesupport/lib/active_support/configurable.rb
index 58ed37b018..644db0b205 100644
--- a/activesupport/lib/active_support/configurable.rb
+++ b/activesupport/lib/active_support/configurable.rb
@@ -38,6 +38,18 @@ module ActiveSupport
yield config
end
+ # Allows you to add shortcut so that you don't have to refer to attribute through config.
+ # Also look at the example for config to contrast.
+ #
+ # class User
+ # include ActiveSupport::Configurable
+ # config_accessor :allowed_access
+ # end
+ #
+ # user = User.new
+ # user.allowed_access = true
+ # user.allowed_access # => true
+ #
def config_accessor(*names)
names.each do |name|
code, line = <<-RUBY, __LINE__ + 1
diff --git a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb
index f7f03f4d95..3720dbb8b8 100644
--- a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb
@@ -18,6 +18,10 @@ class BigDecimal
end
end
+ def to_d
+ self
+ end
+
DEFAULT_STRING_FORMAT = 'F'
def to_formatted_s(format = DEFAULT_STRING_FORMAT)
_original_to_s(format)
diff --git a/activesupport/lib/active_support/core_ext/cgi.rb b/activesupport/lib/active_support/core_ext/cgi.rb
deleted file mode 100644
index 7279a3d4da..0000000000
--- a/activesupport/lib/active_support/core_ext/cgi.rb
+++ /dev/null
@@ -1 +0,0 @@
-require 'active_support/core_ext/cgi/escape_skipping_slashes'
diff --git a/activesupport/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb b/activesupport/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb
deleted file mode 100644
index d3c3575748..0000000000
--- a/activesupport/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-require 'cgi'
-
-class CGI #:nodoc:
- if RUBY_VERSION >= '1.9'
- def self.escape_skipping_slashes(str)
- str = str.join('/') if str.respond_to? :join
- str.gsub(/([^ \/a-zA-Z0-9_.-])/n) do
- "%#{$1.unpack('H2' * $1.bytesize).join('%').upcase}"
- end.tr(' ', '+')
- end
- else
- def self.escape_skipping_slashes(str)
- str = str.join('/') if str.respond_to? :join
- str.gsub(/([^ \/a-zA-Z0-9_.-])/n) do
- "%#{$1.unpack('H2').first.upcase}"
- end.tr(' ', '+')
- end
- end
-end
diff --git a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
index af30bfc13a..ca3db2349e 100644
--- a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
+++ b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
@@ -1,8 +1,10 @@
require 'active_support/core_ext/object/duplicable'
require 'active_support/core_ext/array/extract_options'
+require 'active_support/deprecation'
# Retained for backward compatibility. Methods are now included in Class.
module ClassInheritableAttributes # :nodoc:
+ DEPRECATION_WARNING_MESSAGE = "class_inheritable_attribute is deprecated, please use class_attribute method instead. Notice their behavior are slightly different, so refer to class_attribute documentation first"
end
# It is recommended to use <tt>class_attribute</tt> over methods defined in this file. Please
@@ -36,6 +38,7 @@ end
# Person.new.hair_colors # => NoMethodError
class Class # :nodoc:
def class_inheritable_reader(*syms)
+ ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
options = syms.extract_options!
syms.each do |sym|
next if sym.is_a?(Hash)
@@ -54,6 +57,7 @@ class Class # :nodoc:
end
def class_inheritable_writer(*syms)
+ ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
options = syms.extract_options!
syms.each do |sym|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
@@ -71,6 +75,7 @@ class Class # :nodoc:
end
def class_inheritable_array_writer(*syms)
+ ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
options = syms.extract_options!
syms.each do |sym|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
@@ -88,6 +93,7 @@ class Class # :nodoc:
end
def class_inheritable_hash_writer(*syms)
+ ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
options = syms.extract_options!
syms.each do |sym|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
@@ -124,6 +130,7 @@ class Class # :nodoc:
end
def write_inheritable_attribute(key, value)
+ ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
@inheritable_attributes = {}
end
@@ -141,10 +148,12 @@ class Class # :nodoc:
end
def read_inheritable_attribute(key)
+ ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
inheritable_attributes[key]
end
def reset_inheritable_attributes
+ ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE
@inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
end
@@ -169,86 +178,3 @@ class Class # :nodoc:
alias inherited_without_inheritable_attributes inherited
alias inherited inherited_with_inheritable_attributes
end
-
-class Class
- # Defines class-level inheritable attribute reader. Attributes are available to subclasses,
- # each subclass has a copy of parent's attribute.
- #
- # @param *syms<Array[#to_s]> Array of attributes to define inheritable reader for.
- # @return <Array[#to_s]> Array of attributes converted into inheritable_readers.
- #
- # @api public
- #
- # @todo Do we want to block instance_reader via :instance_reader => false
- # @todo It would be preferable that we do something with a Hash passed in
- # (error out or do the same as other methods above) instead of silently
- # moving on). In particular, this makes the return value of this function
- # less useful.
- def extlib_inheritable_reader(*ivars, &block)
- options = ivars.extract_options!
-
- ivars.each do |ivar|
- self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def self.#{ivar}
- return @#{ivar} if self.object_id == #{self.object_id} || defined?(@#{ivar})
- ivar = superclass.#{ivar}
- return nil if ivar.nil? && !#{self}.instance_variable_defined?("@#{ivar}")
- @#{ivar} = ivar.duplicable? ? ivar.dup : ivar
- end
- RUBY
- unless options[:instance_reader] == false
- self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def #{ivar}
- self.class.#{ivar}
- end
- RUBY
- end
- instance_variable_set(:"@#{ivar}", yield) if block_given?
- end
- end
-
- # Defines class-level inheritable attribute writer. Attributes are available to subclasses,
- # each subclass has a copy of parent's attribute.
- #
- # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
- # define inheritable writer for.
- # @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
- # @return <Array[#to_s]> An Array of the attributes that were made into inheritable writers.
- #
- # @api public
- #
- # @todo We need a style for class_eval <<-HEREDOC. I'd like to make it
- # class_eval(<<-RUBY, __FILE__, __LINE__), but we should codify it somewhere.
- def extlib_inheritable_writer(*ivars)
- options = ivars.extract_options!
-
- ivars.each do |ivar|
- self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def self.#{ivar}=(obj)
- @#{ivar} = obj
- end
- RUBY
- unless options[:instance_writer] == false
- self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def #{ivar}=(obj) self.class.#{ivar} = obj end
- RUBY
- end
-
- self.send("#{ivar}=", yield) if block_given?
- end
- end
-
- # Defines class-level inheritable attribute accessor. Attributes are available to subclasses,
- # each subclass has a copy of parent's attribute.
- #
- # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
- # define inheritable accessor for.
- # @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
- # @return <Array[#to_s]> An Array of attributes turned into inheritable accessors.
- #
- # @api public
- def extlib_inheritable_accessor(*syms, &block)
- extlib_inheritable_reader(*syms)
- extlib_inheritable_writer(*syms, &block)
- end
-end
diff --git a/activesupport/lib/active_support/core_ext/class/subclasses.rb b/activesupport/lib/active_support/core_ext/class/subclasses.rb
index 3e5d1a2a42..46e9daaa8f 100644
--- a/activesupport/lib/active_support/core_ext/class/subclasses.rb
+++ b/activesupport/lib/active_support/core_ext/class/subclasses.rb
@@ -2,49 +2,35 @@ require 'active_support/core_ext/module/anonymous'
require 'active_support/core_ext/module/reachable'
class Class #:nodoc:
- # Rubinius
- if defined?(Class.__subclasses__)
- alias :subclasses :__subclasses__
+ begin
+ ObjectSpace.each_object(Class.new) {}
def descendants
descendants = []
- __subclasses__.each do |k|
- descendants << k
- descendants.concat k.descendants
+ ObjectSpace.each_object(class << self; self; end) do |k|
+ descendants.unshift k unless k == self
end
descendants
end
- else # MRI
- begin
- ObjectSpace.each_object(Class.new) {}
-
- def descendants
- descendants = []
- ObjectSpace.each_object(class << self; self; end) do |k|
- descendants.unshift k unless k == self
- end
- descendants
- end
- rescue StandardError # JRuby
- def descendants
- descendants = []
- ObjectSpace.each_object(Class) do |k|
- descendants.unshift k if k < self
- end
- descendants.uniq!
- descendants
+ rescue StandardError # JRuby
+ def descendants
+ descendants = []
+ ObjectSpace.each_object(Class) do |k|
+ descendants.unshift k if k < self
end
+ descendants.uniq!
+ descendants
end
+ end
- # Returns an array with the direct children of +self+.
- #
- # Integer.subclasses # => [Bignum, Fixnum]
- def subclasses
- subclasses, chain = [], descendants
- chain.each do |k|
- subclasses << k unless chain.any? { |c| c > k }
- end
- subclasses
+ # Returns an array with the direct children of +self+.
+ #
+ # Integer.subclasses # => [Bignum, Fixnum]
+ def subclasses
+ subclasses, chain = [], descendants
+ chain.each do |k|
+ subclasses << k unless chain.any? { |c| c > k }
end
+ subclasses
end
end
diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb
index 092f936961..06d868a3b0 100644
--- a/activesupport/lib/active_support/core_ext/date/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date/conversions.rb
@@ -1,5 +1,5 @@
require 'date'
-require 'active_support/inflector'
+require 'active_support/inflector/methods'
require 'active_support/core_ext/date/zones'
class Date
diff --git a/activesupport/lib/active_support/core_ext/date_time/conversions.rb b/activesupport/lib/active_support/core_ext/date_time/conversions.rb
index 8e267c76c4..029b8c41b4 100644
--- a/activesupport/lib/active_support/core_ext/date_time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/conversions.rb
@@ -1,4 +1,4 @@
-require 'active_support/inflector'
+require 'active_support/inflector/methods'
require 'active_support/core_ext/time/conversions'
require 'active_support/core_ext/date_time/calculations'
require 'active_support/values/time_zone'
diff --git a/activesupport/lib/active_support/core_ext/hash.rb b/activesupport/lib/active_support/core_ext/hash.rb
index 501483498d..fd1cda991e 100644
--- a/activesupport/lib/active_support/core_ext/hash.rb
+++ b/activesupport/lib/active_support/core_ext/hash.rb
@@ -1,5 +1,6 @@
require 'active_support/core_ext/hash/conversions'
require 'active_support/core_ext/hash/deep_merge'
+require 'active_support/core_ext/hash/deep_dup'
require 'active_support/core_ext/hash/diff'
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/hash/indifferent_access'
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index 4e8ec5a3a8..3005fef44c 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -26,10 +26,22 @@ class Hash
#
# * If +value+ is a callable object it must expect one or two arguments. Depending
# on the arity, the callable is invoked with the +options+ hash as first argument
- # with +key+ as <tt>:root</tt>, and +key+ singularized as second argument. Its
- # return value becomes a new node.
+ # with +key+ as <tt>:root</tt>, and +key+ singularized as second argument. The
+ # callable can add nodes by using <tt>options[:builder]</tt>.
+ #
+ # "foo".to_xml(lambda { |options, key| options[:builder].b(key) })
+ # # => "<b>foo</b>"
#
# * If +value+ responds to +to_xml+ the method is invoked with +key+ as <tt>:root</tt>.
+ #
+ # class Foo
+ # def to_xml(options)
+ # options[:builder].bar "fooing!"
+ # end
+ # end
+ #
+ # {:foo => Foo.new}.to_xml(:skip_instruct => true)
+ # # => "<hash><bar>fooing!</bar></hash>"
#
# * Otherwise, a node with +key+ as tag is created with a string representation of
# +value+ as text node. If +value+ is +nil+ an attribute "nil" set to "true" is added.
diff --git a/activesupport/lib/active_support/core_ext/hash/deep_dup.rb b/activesupport/lib/active_support/core_ext/hash/deep_dup.rb
new file mode 100644
index 0000000000..447142605c
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/hash/deep_dup.rb
@@ -0,0 +1,11 @@
+class Hash
+ # Returns a deep copy of hash.
+ def deep_dup
+ duplicate = self.dup
+ duplicate.each_pair do |k,v|
+ tv = duplicate[k]
+ duplicate[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? tv.deep_dup : v
+ end
+ duplicate
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/module/synchronization.rb b/activesupport/lib/active_support/core_ext/module/synchronization.rb
index 38ce55f26e..ed16c2f71b 100644
--- a/activesupport/lib/active_support/core_ext/module/synchronization.rb
+++ b/activesupport/lib/active_support/core_ext/module/synchronization.rb
@@ -1,3 +1,4 @@
+require 'thread'
require 'active_support/core_ext/module/aliasing'
require 'active_support/core_ext/array/extract_options'
diff --git a/activesupport/lib/active_support/core_ext/object/instance_variables.rb b/activesupport/lib/active_support/core_ext/object/instance_variables.rb
index 77a3cfc21d..eda9694614 100644
--- a/activesupport/lib/active_support/core_ext/object/instance_variables.rb
+++ b/activesupport/lib/active_support/core_ext/object/instance_variables.rb
@@ -30,35 +30,4 @@ class Object
else
alias_method :instance_variable_names, :instance_variables
end
-
- # Copies the instance variables of +object+ into +self+.
- #
- # Instance variable names in the +exclude+ array are ignored. If +object+
- # responds to <tt>protected_instance_variables</tt> the ones returned are
- # also ignored. For example, Rails controllers implement that method.
- #
- # In both cases strings and symbols are understood, and they have to include
- # the at sign.
- #
- # class C
- # def initialize(x, y, z)
- # @x, @y, @z = x, y, z
- # end
- #
- # def protected_instance_variables
- # %w(@z)
- # end
- # end
- #
- # a = C.new(0, 1, 2)
- # b = C.new(3, 4, 5)
- #
- # a.copy_instance_variables_from(b, [:@y])
- # # a is now: @x = 3, @y = 1, @z = 2
- def copy_instance_variables_from(object, exclude = []) #:nodoc:
- exclude += object.protected_instance_variables if object.respond_to? :protected_instance_variables
-
- vars = object.instance_variables.map(&:to_s) - exclude.map(&:to_s)
- vars.each { |name| instance_variable_set(name, object.instance_variable_get(name)) }
- end
end
diff --git a/activesupport/lib/active_support/core_ext/object/to_param.rb b/activesupport/lib/active_support/core_ext/object/to_param.rb
index ecb2bca82c..593f376159 100644
--- a/activesupport/lib/active_support/core_ext/object/to_param.rb
+++ b/activesupport/lib/active_support/core_ext/object/to_param.rb
@@ -1,5 +1,3 @@
-
-
class Object
# Alias of <tt>to_s</tt>.
def to_param
@@ -41,7 +39,7 @@ class Hash
# ==== Examples
# { :name => 'David', :nationality => 'Danish' }.to_param # => "name=David&nationality=Danish"
#
- # { :name => 'David', :nationality => 'Danish' }.to_param('user') # => "user[name]=David&user[nationality]=Danish"
+ # { :name => 'David', :nationality => 'Danish' }.to_query('user') # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
def to_param(namespace = nil)
collect do |key, value|
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
diff --git a/activesupport/lib/active_support/core_ext/object/to_query.rb b/activesupport/lib/active_support/core_ext/object/to_query.rb
index c9981895b4..3f1540f685 100644
--- a/activesupport/lib/active_support/core_ext/object/to_query.rb
+++ b/activesupport/lib/active_support/core_ext/object/to_query.rb
@@ -7,7 +7,7 @@ class Object
# Note: This method is defined as a default implementation for all Objects for Hash#to_query to work.
def to_query(key)
require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
- "#{CGI.escape(key.to_s).gsub(/%(5B|5D)/n) { [$1].pack('H*') }}=#{CGI.escape(to_param.to_s)}"
+ "#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}"
end
end
@@ -15,7 +15,7 @@ class Array
# Converts an array into a string suitable for use as a URL query string,
# using the given +key+ as the param name.
#
- # ['Rails', 'coding'].to_query('hobbies') # => "hobbies[]=Rails&hobbies[]=coding"
+ # ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
def to_query(key)
prefix = "#{key}[]"
collect { |value| value.to_query(prefix) }.join '&'
diff --git a/activesupport/lib/active_support/core_ext/object/try.rb b/activesupport/lib/active_support/core_ext/object/try.rb
index 48e9d04787..ff812234e3 100644
--- a/activesupport/lib/active_support/core_ext/object/try.rb
+++ b/activesupport/lib/active_support/core_ext/object/try.rb
@@ -1,13 +1,12 @@
class Object
- ##
- # :method: try
- #
# Invokes the method identified by the symbol +method+, passing it any arguments
# and/or the block specified, just like the regular Ruby <tt>Object#send</tt> does.
#
# *Unlike* that method however, a +NoMethodError+ exception will *not* be raised
# and +nil+ will be returned instead, if the receiving object is a +nil+ object or NilClass.
#
+ # If try is called without a method to call, it will yield any given block with the object.
+ #
# ==== Examples
#
# Without try
@@ -21,10 +20,18 @@ class Object
# +try+ also accepts arguments and/or a block, for the method it is trying
# Person.try(:find, 1)
# @people.try(:collect) {|p| p.name}
+ #
+ # Without a method argument try will yield to the block unless the reciever is nil.
+ # @person.try { |p| "#{p.first_name} #{p.last_name}" }
#--
# +try+ behaves like +Object#send+, unless called on +NilClass+.
-
- alias_method :try, :__send__
+ def try(*a, &b)
+ if a.empty? && block_given?
+ yield self
+ else
+ __send__(*a, &b)
+ end
+ end
end
class NilClass #:nodoc:
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 37c206ea3c..bb0f747960 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -33,21 +33,23 @@ class ERB
singleton_class.send(:remove_method, :html_escape)
module_function :html_escape
- # A utility method for escaping HTML entities in JSON strings.
- # This method is also aliased as <tt>j</tt>.
+ # A utility method for escaping HTML entities in JSON strings
+ # using \uXXXX JavaScript escape sequences for string literals:
#
- # Note that after this operation is performed the output is not
- # a valid JSON.
+ # json_escape("is a > 0 & a < 10?")
+ # # => is a \u003E 0 \u0026 a \u003C 10?
#
- # In your ERb templates, use this method to escape any HTML entities:
- # <%=j @person.to_json %>
+ # Note that after this operation is performed the output is not
+ # valid JSON. In particular double quotes are removed:
#
- # ==== Example:
- # puts json_escape("{\"name\":\"john\",\"created_at\":\"2010-04-28T01:39:31Z\",\"id\":1}")
+ # json_escape('{"name":"john","created_at":"2010-04-28T01:39:31Z","id":1}')
# # => {name:john,created_at:2010-04-28T01:39:31Z,id:1}
#
- # puts json_escape("is a > 0 & a < 10?")
- # # => is a \u003E 0 \u0026 a \u003C 10?
+ # This method is also aliased as +j+, and available as a helper
+ # in Rails templates:
+ #
+ # <%=j @person.to_json %>
+ #
def json_escape(s)
s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
end
diff --git a/activesupport/lib/active_support/core_ext/time/conversions.rb b/activesupport/lib/active_support/core_ext/time/conversions.rb
index d4ae3131ec..49ac18d245 100644
--- a/activesupport/lib/active_support/core_ext/time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/time/conversions.rb
@@ -1,4 +1,4 @@
-require 'active_support/inflector'
+require 'active_support/inflector/methods'
require 'active_support/core_ext/time/publicize_conversion_methods'
require 'active_support/values/time_zone'
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 787437c49a..dab6fdbac6 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -331,7 +331,7 @@ module ActiveSupport #:nodoc:
if load?
log "loading #{file_name}"
- # Enable warnings iff this file has not been loaded before and
+ # Enable warnings if this file has not been loaded before and
# warnings_on_first_load is set.
load_args = ["#{file_name}.rb"]
load_args << const_path unless const_path.nil?
diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb
index e1b8211d68..ce0775a690 100644
--- a/activesupport/lib/active_support/deprecation.rb
+++ b/activesupport/lib/active_support/deprecation.rb
@@ -4,12 +4,12 @@ require 'active_support/deprecation/method_wrappers'
require 'active_support/deprecation/proxy_wrappers'
module ActiveSupport
- module Deprecation #:nodoc:
+ module Deprecation
class << self
# The version the deprecated behavior will be removed, by default.
attr_accessor :deprecation_horizon
end
- self.deprecation_horizon = '3.0'
+ self.deprecation_horizon = '3.1'
# By default, warnings are not silenced and debugging is off.
self.silenced = false
diff --git a/activesupport/lib/active_support/deprecation/behaviors.rb b/activesupport/lib/active_support/deprecation/behaviors.rb
index f54f65dcf0..da4af339fc 100644
--- a/activesupport/lib/active_support/deprecation/behaviors.rb
+++ b/activesupport/lib/active_support/deprecation/behaviors.rb
@@ -7,10 +7,17 @@ module ActiveSupport
# Whether to print a backtrace along with the warning.
attr_accessor :debug
+ # Returns the set behaviour or if one isn't set, defaults to +:stderr+
def behavior
@behavior ||= [DEFAULT_BEHAVIORS[:stderr]]
end
+ # Sets the behaviour to the specified value. Can be a single value or an array.
+ #
+ # Examples
+ #
+ # ActiveSupport::Deprecation.behavior = :stderr
+ # ActiveSupport::Deprecation.behavior = [:stderr, :log]
def behavior=(behavior)
@behavior = Array.wrap(behavior).map { |b| DEFAULT_BEHAVIORS[b] || b }
end
diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
index 970536a594..a65fcafb44 100644
--- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
@@ -1,4 +1,4 @@
-require 'active_support/inflector'
+require 'active_support/inflector/methods'
module ActiveSupport
module Deprecation
diff --git a/activesupport/lib/active_support/deprecation/reporting.rb b/activesupport/lib/active_support/deprecation/reporting.rb
index 6a7b11c7e0..ced08b8783 100644
--- a/activesupport/lib/active_support/deprecation/reporting.rb
+++ b/activesupport/lib/active_support/deprecation/reporting.rb
@@ -3,6 +3,12 @@ module ActiveSupport
class << self
attr_accessor :silenced
+ # 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)"
def warn(message = nil, callstack = caller)
return if silenced
deprecation_message(callstack, message).tap do |m|
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb
index de3ded1e1f..00c67a470d 100644
--- a/activesupport/lib/active_support/duration.rb
+++ b/activesupport/lib/active_support/duration.rb
@@ -80,6 +80,10 @@ module ActiveSupport
parts.to_sentence(:locale => :en)
end
+ def as_json(options = nil) #:nodoc:
+ to_i
+ end
+
protected
def sum(sign, time = ::Time.current) #:nodoc:
diff --git a/activesupport/lib/active_support/file_update_checker.rb b/activesupport/lib/active_support/file_update_checker.rb
index cd658fe173..a97e9d7daf 100644
--- a/activesupport/lib/active_support/file_update_checker.rb
+++ b/activesupport/lib/active_support/file_update_checker.rb
@@ -8,7 +8,7 @@ module ActiveSupport
# I18n.reload!
# end
#
- # ActionDispatch::Callbacks.to_prepare do
+ # ActionDispatch::Reloader.to_prepare do
# i18n_reloader.execute_if_updated
# end
#
diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb
index c406dd3c2e..6a344867ee 100644
--- a/activesupport/lib/active_support/hash_with_indifferent_access.rb
+++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb
@@ -28,7 +28,7 @@ module ActiveSupport
end
def self.new_from_hash_copying_default(hash)
- ActiveSupport::HashWithIndifferentAccess.new(hash).tap do |new_hash|
+ new(hash).tap do |new_hash|
new_hash.default = hash.default
end
end
@@ -97,7 +97,9 @@ module ActiveSupport
# Returns an exact copy of the hash.
def dup
- HashWithIndifferentAccess.new(self)
+ self.class.new(self).tap do |new_hash|
+ new_hash.default = default
+ end
end
# Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
@@ -138,11 +140,10 @@ module ActiveSupport
end
def convert_value(value)
- case value
- when Hash
+ if value.class == Hash
self.class.new_from_hash_copying_default(value)
- when Array
- value.collect { |e| e.is_a?(Hash) ? self.class.new_from_hash_copying_default(e) : e }
+ elsif value.is_a?(Array)
+ value.dup.replace(value.map { |e| convert_value(e) })
else
value
end
diff --git a/activesupport/lib/active_support/i18n.rb b/activesupport/lib/active_support/i18n.rb
index 4d33f597d9..00ea8813dd 100644
--- a/activesupport/lib/active_support/i18n.rb
+++ b/activesupport/lib/active_support/i18n.rb
@@ -7,4 +7,3 @@ rescue LoadError => e
end
I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml"
-ActiveSupport.run_load_hooks(:i18n)
diff --git a/activesupport/lib/active_support/i18n_railtie.rb b/activesupport/lib/active_support/i18n_railtie.rb
index f8a5616a76..282337d373 100644
--- a/activesupport/lib/active_support/i18n_railtie.rb
+++ b/activesupport/lib/active_support/i18n_railtie.rb
@@ -19,7 +19,7 @@ module I18n
# on to_prepare callbacks. This will only happen on the config.after_initialize
# callback below.
initializer "i18n.callbacks" do
- ActionDispatch::Callbacks.to_prepare do
+ ActionDispatch::Reloader.to_prepare do
I18n::Railtie.reloader.execute_if_updated
end
end
diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb
index 3caf78bc7d..e136e4c5b3 100644
--- a/activesupport/lib/active_support/inflector/inflections.rb
+++ b/activesupport/lib/active_support/inflector/inflections.rb
@@ -148,7 +148,7 @@ module ActiveSupport
def singularize(word)
result = word.to_s.dup
- if inflections.uncountables.any? { |inflection| result =~ /#{inflection}\Z/i }
+ if inflections.uncountables.any? { |inflection| result =~ /\b(#{inflection})\Z/i }
result
else
inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
diff --git a/activesupport/lib/active_support/json/backends/yaml.rb b/activesupport/lib/active_support/json/backends/yaml.rb
index 4cb9d01077..2e389b5c12 100644
--- a/activesupport/lib/active_support/json/backends/yaml.rb
+++ b/activesupport/lib/active_support/json/backends/yaml.rb
@@ -7,13 +7,20 @@ module ActiveSupport
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 ArgumentError
+ rescue *EXCEPTIONS
raise ParseError, "Invalid JSON string"
end
diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb
index c8cac52027..b2ea196003 100644
--- a/activesupport/lib/active_support/json/encoding.rb
+++ b/activesupport/lib/active_support/json/encoding.rb
@@ -153,6 +153,12 @@ class Object
end
end
+class Struct
+ def as_json(options = nil) #:nodoc:
+ Hash[members.zip(values)]
+ end
+end
+
class TrueClass
AS_JSON = ActiveSupport::JSON::Variable.new('true').freeze
def as_json(options = nil) AS_JSON end #:nodoc:
diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb
index 7f148dc853..5b8c342f4f 100644
--- a/activesupport/lib/active_support/ordered_hash.rb
+++ b/activesupport/lib/active_support/ordered_hash.rb
@@ -20,9 +20,17 @@ module ActiveSupport
"!tag:yaml.org,2002:omap"
end
+ def encode_with(coder)
+ coder.represent_seq '!omap', map { |k,v| { k => v } }
+ end
+
def to_yaml(opts = {})
+ if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck?
+ return super
+ end
+
YAML.quick_emit(self, opts) do |out|
- out.seq(taguri, to_yaml_style) do |seq|
+ out.seq(taguri) do |seq|
each do |k, v|
seq.add(k => v)
end
@@ -137,6 +145,8 @@ module ActiveSupport
alias_method :each_pair, :each
+ alias_method :select, :find_all
+
def clear
super
@keys.clear
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index 93f5d5a0cc..8137f8e17e 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -73,7 +73,7 @@ module ActiveSupport
# Returns a <tt>Time.local()</tt> instance of the simultaneous time in your system's <tt>ENV['TZ']</tt> zone
def localtime
- utc.getlocal
+ utc.respond_to?(:getlocal) ? utc.getlocal : utc.to_time.getlocal
end
alias_method :getlocal, :localtime
@@ -138,11 +138,7 @@ module ActiveSupport
end
def to_yaml(options = {})
- if options.kind_of?(YAML::Emitter)
- utc.to_yaml(options)
- else
- time.to_yaml(options).gsub('Z', formatted_offset(true, 'Z'))
- end
+ utc.to_yaml(options)
end
def httpdate
diff --git a/activesupport/lib/active_support/version.rb b/activesupport/lib/active_support/version.rb
index 9e8b3d7888..690fc7f0fc 100644
--- a/activesupport/lib/active_support/version.rb
+++ b/activesupport/lib/active_support/version.rb
@@ -3,8 +3,8 @@ module ActiveSupport
MAJOR = 3
MINOR = 1
TINY = 0
- BUILD = "beta"
+ PRE = "beta"
- STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
end
diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb
index b6a8cf3caf..cddfcddb57 100644
--- a/activesupport/lib/active_support/xml_mini.rb
+++ b/activesupport/lib/active_support/xml_mini.rb
@@ -126,9 +126,11 @@ module ActiveSupport
end
def rename_key(key, options = {})
- camelize = options.has_key?(:camelize) && options[:camelize]
+ camelize = options[:camelize]
dasherize = !options.has_key?(:dasherize) || options[:dasherize]
- key = key.camelize if camelize
+ if camelize
+ key = true == camelize ? key.camelize : key.camelize(camelize)
+ end
key = _dasherize(key) if dasherize
key
end
diff --git a/activesupport/lib/active_support/xml_mini/nokogirisax.rb b/activesupport/lib/active_support/xml_mini/nokogirisax.rb
index 38c8685390..25afbfcd1c 100644
--- a/activesupport/lib/active_support/xml_mini/nokogirisax.rb
+++ b/activesupport/lib/active_support/xml_mini/nokogirisax.rb
@@ -38,8 +38,7 @@ module ActiveSupport
end
def start_element(name, attrs = [])
- new_hash = { CONTENT_KEY => '' }
- new_hash[attrs.shift] = attrs.shift while attrs.length > 0
+ new_hash = { CONTENT_KEY => '' }.merge(Hash[attrs])
new_hash[HASH_SIZE_KEY] = new_hash.size + 1
case current_hash[name]
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index 28ef695a4b..579d5dad24 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -356,9 +356,13 @@ module CacheDeleteMatchedBehavior
def test_delete_matched
@cache.write("foo", "bar")
@cache.write("fu", "baz")
+ @cache.write("foo/bar", "baz")
+ @cache.write("fu/baz", "bar")
@cache.delete_matched(/oo/)
assert_equal false, @cache.exist?("foo")
assert_equal true, @cache.exist?("fu")
+ assert_equal false, @cache.exist?("foo/bar")
+ assert_equal true, @cache.exist?("fu/baz")
end
end
@@ -509,6 +513,11 @@ class FileStoreTest < ActiveSupport::TestCase
assert_nil old_cache.read('foo')
end
end
+
+ def test_key_transformation
+ key = @cache.send(:key_file_path, "views/index?id=1")
+ assert_equal "views/index?id=1", @cache.send(:file_path_key, key)
+ end
end
class MemoryStoreTest < ActiveSupport::TestCase
diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb
index 51b28b6a43..c89b03e243 100644
--- a/activesupport/test/callbacks_test.rb
+++ b/activesupport/test/callbacks_test.rb
@@ -3,6 +3,27 @@ require 'test/unit'
require 'active_support'
module CallbacksTest
+ class Phone
+ include ActiveSupport::Callbacks
+ define_callbacks :save, :rescuable => true
+
+ set_callback :save, :before, :before_save1
+ set_callback :save, :after, :after_save1
+
+ def before_save1; self.history << :before; end
+ def after_save1; self.history << :after; end
+
+ def save
+ self.send(:_run_save_callbacks) do
+ raise 'boom'
+ end
+ end
+
+ def history
+ @history ||= []
+ end
+ end
+
class Record
include ActiveSupport::Callbacks
@@ -338,6 +359,14 @@ module CallbacksTest
end
class CallbacksTest < Test::Unit::TestCase
+ def test_save_phone
+ phone = Phone.new
+ assert_raise RuntimeError do
+ phone.save
+ end
+ assert_equal [:before, :after], phone.history
+ end
+
def test_save_person
person = Person.new
assert_equal [], person.history
@@ -573,5 +602,5 @@ module CallbacksTest
], writer.history
end
end
-
+
end
diff --git a/activesupport/test/core_ext/bigdecimal.rb b/activesupport/test/core_ext/bigdecimal_test.rb
index 9faad9146f..d592973d7a 100644
--- a/activesupport/test/core_ext/bigdecimal.rb
+++ b/activesupport/test/core_ext/bigdecimal_test.rb
@@ -1,10 +1,17 @@
require 'abstract_unit'
+require 'bigdecimal'
+require 'active_support/core_ext/big_decimal'
class BigDecimalTest < Test::Unit::TestCase
def test_to_yaml
assert_equal("--- 100000.30020320320000000000000000000000000000001\n", BigDecimal.new('100000.30020320320000000000000000000000000000001').to_yaml)
- assert_equal("--- .Inf\n", BigDecimal.new('Infinity').to_yaml)
- assert_equal("--- .NaN\n", BigDecimal.new('NaN').to_yaml)
+ assert_equal("--- .Inf\n", BigDecimal.new('Infinity').to_yaml)
+ assert_equal("--- .NaN\n", BigDecimal.new('NaN').to_yaml)
assert_equal("--- -.Inf\n", BigDecimal.new('-Infinity').to_yaml)
end
-end \ No newline at end of file
+
+ def test_to_d
+ bd = BigDecimal.new '10'
+ assert_equal bd, bd.to_d
+ end
+end
diff --git a/activesupport/test/core_ext/cgi_ext_test.rb b/activesupport/test/core_ext/cgi_ext_test.rb
deleted file mode 100644
index c80362e382..0000000000
--- a/activesupport/test/core_ext/cgi_ext_test.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'abstract_unit'
-require 'active_support/core_ext/cgi'
-
-class EscapeSkippingSlashesTest < Test::Unit::TestCase
- def test_array
- assert_equal 'hello/world', CGI.escape_skipping_slashes(%w(hello world))
- assert_equal 'hello+world/how/are/you', CGI.escape_skipping_slashes(['hello world', 'how', 'are', 'you'])
- end
-
- def test_typical
- assert_equal 'hi', CGI.escape_skipping_slashes('hi')
- assert_equal 'hi/world', CGI.escape_skipping_slashes('hi/world')
- assert_equal 'hi/world+you+funky+thing', CGI.escape_skipping_slashes('hi/world you funky thing')
- end
-end
diff --git a/activesupport/test/core_ext/class/class_inheritable_attributes_test.rb b/activesupport/test/core_ext/class/class_inheritable_attributes_test.rb
index b284e5ee1c..020dfce56a 100644
--- a/activesupport/test/core_ext/class/class_inheritable_attributes_test.rb
+++ b/activesupport/test/core_ext/class/class_inheritable_attributes_test.rb
@@ -3,9 +3,14 @@ require 'active_support/core_ext/class/inheritable_attributes'
class ClassInheritableAttributesTest < Test::Unit::TestCase
def setup
+ ActiveSupport::Deprecation.silenced = true
@klass = Class.new
end
+ def teardown
+ ActiveSupport::Deprecation.silenced = false
+ end
+
def test_reader_declaration
assert_nothing_raised do
@klass.class_inheritable_reader :a
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index bb453b8d7f..6a01eeed6b 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'active_support/time'
+require 'active_support/json'
class DurationTest < ActiveSupport::TestCase
def test_is_a
@@ -138,6 +139,10 @@ class DurationTest < ActiveSupport::TestCase
assert_equal counter, 60
end
+ def test_to_json
+ assert_equal '172800', 2.days.to_json
+ end
+
protected
def with_env_tz(new_tz = 'US/Eastern')
old_tz, ENV['TZ'] = ENV['TZ'], new_tz
diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb
index 545fed2684..a0479d45ac 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -4,8 +4,18 @@ require 'bigdecimal'
require 'active_support/core_ext/string/access'
require 'active_support/ordered_hash'
require 'active_support/core_ext/object/conversions'
+require 'active_support/inflections'
class HashExtTest < Test::Unit::TestCase
+ class IndifferentHash < HashWithIndifferentAccess
+ end
+
+ class SubclassingArray < Array
+ end
+
+ class SubclassingHash < Hash
+ end
+
def setup
@strings = { 'a' => 1, 'b' => 2 }
@symbols = { :a => 1, :b => 2 }
@@ -99,6 +109,11 @@ 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"]
+ end
+
def test_indifferent_assorted
@strings = @strings.with_indifferent_access
@symbols = @symbols.with_indifferent_access
@@ -248,6 +263,20 @@ class HashExtTest < Test::Unit::TestCase
hash = { "urls" => { "url" => [ { "address" => "1" }, { "address" => "2" } ] }}.with_indifferent_access
assert_equal "1", hash[:urls][:url].first[:address]
end
+
+ def test_should_preserve_array_subclass_when_value_is_array
+ array = SubclassingArray.new
+ array << { "address" => "1" }
+ hash = { "urls" => { "url" => array }}.with_indifferent_access
+ assert_equal SubclassingArray, hash[:urls][:url].class
+ end
+
+ def test_should_preserve_array_class_when_hash_value_is_frozen_array
+ array = SubclassingArray.new
+ array << { "address" => "1" }
+ hash = { "urls" => { "url" => array.freeze }}.with_indifferent_access
+ assert_equal SubclassingArray, hash[:urls][:url].class
+ end
def test_stringify_and_symbolize_keys_on_indifferent_preserves_hash
h = HashWithIndifferentAccess.new
@@ -267,7 +296,6 @@ class HashExtTest < Test::Unit::TestCase
assert_equal 1, h['first']
end
-
def test_indifferent_subhashes
h = {'user' => {'id' => 5}}.with_indifferent_access
['user', :user].each {|user| [:id, 'id'].each {|id| assert_equal 5, h[user][id], "h[#{user.inspect}][#{id.inspect}] should be 5"}}
@@ -276,6 +304,17 @@ class HashExtTest < Test::Unit::TestCase
['user', :user].each {|user| [:id, 'id'].each {|id| assert_equal 5, h[user][id], "h[#{user.inspect}][#{id.inspect}] should be 5"}}
end
+ def test_indifferent_duplication
+ # Should preserve default value
+ h = HashWithIndifferentAccess.new
+ h.default = '1234'
+ assert_equal h.default, h.dup.default
+
+ # Should preserve class for subclasses
+ h = IndifferentHash.new
+ assert_equal h.class, h.dup.class
+ end
+
def test_assert_valid_keys
assert_nothing_raised do
{ :failure => "stuff", :funny => "business" }.assert_valid_keys([ :failure, :funny ])
@@ -316,6 +355,21 @@ class HashExtTest < Test::Unit::TestCase
assert_equal expected, hash_1
end
+ def test_deep_dup
+ hash = { :a => { :b => 'b' } }
+ dup = hash.deep_dup
+ dup[:a][:c] = 'c'
+ assert_equal nil, hash[:a][:c]
+ assert_equal 'c', dup[:a][:c]
+ end
+
+ def test_deep_dup_initialize
+ zero_hash = Hash.new 0
+ hash = { :a => zero_hash }
+ dup = hash.deep_dup
+ assert_equal 0, dup[:a][44]
+ end
+
def test_store_on_indifferent_access
hash = HashWithIndifferentAccess.new
hash.store(:test1, 1)
@@ -486,7 +540,7 @@ class HashExtToParamTests < Test::Unit::TestCase
def test_to_param_hash_escapes_its_keys_and_values
assert_equal 'param+1=A+string+with+%2F+characters+%26+that+should+be+%3F+escaped', { 'param 1' => 'A string with / characters & that should be ? escaped' }.to_param
end
-
+
def test_to_param_orders_by_key_in_ascending_order
assert_equal 'a=2&b=1&c=0', ActiveSupport::OrderedHash[*%w(b 1 c 0 a 2)].to_param
end
@@ -525,6 +579,13 @@ class HashToXmlTest < Test::Unit::TestCase
assert xml.include?(%(<Name>David</Name>))
end
+ def test_one_level_camelize_lower
+ xml = { :name => "David", :street_name => "Paulina" }.to_xml(@xml_options.merge(:camelize => :lower))
+ assert_equal "<person>", xml.first(8)
+ assert xml.include?(%(<streetName>Paulina</streetName>))
+ assert xml.include?(%(<name>David</name>))
+ end
+
def test_one_level_with_types
xml = { :name => "David", :street => "Paulina", :age => 26, :age_in_millis => 820497600000, :moved_on => Date.new(2005, 11, 15), :resident => :yes }.to_xml(@xml_options)
assert_equal "<person>", xml.first(8)
diff --git a/activesupport/test/core_ext/module/synchronization_test.rb b/activesupport/test/core_ext/module/synchronization_test.rb
index eb850893f0..6c407e2260 100644
--- a/activesupport/test/core_ext/module/synchronization_test.rb
+++ b/activesupport/test/core_ext/module/synchronization_test.rb
@@ -1,3 +1,4 @@
+require 'thread'
require 'abstract_unit'
require 'active_support/core_ext/class/attribute_accessors'
diff --git a/activesupport/test/core_ext/object/to_query_test.rb b/activesupport/test/core_ext/object/to_query_test.rb
index e28b4cd493..84da52f4bf 100644
--- a/activesupport/test/core_ext/object/to_query_test.rb
+++ b/activesupport/test/core_ext/object/to_query_test.rb
@@ -18,22 +18,22 @@ class ToQueryTest < Test::Unit::TestCase
end
def test_nested_conversion
- assert_query_equal 'person[login]=seckar&person[name]=Nicholas',
+ assert_query_equal 'person%5Blogin%5D=seckar&person%5Bname%5D=Nicholas',
:person => ActiveSupport::OrderedHash[:login, 'seckar', :name, 'Nicholas']
end
def test_multiple_nested
- assert_query_equal 'account[person][id]=20&person[id]=10',
+ assert_query_equal 'account%5Bperson%5D%5Bid%5D=20&person%5Bid%5D=10',
ActiveSupport::OrderedHash[:account, {:person => {:id => 20}}, :person, {:id => 10}]
end
def test_array_values
- assert_query_equal 'person[id][]=10&person[id][]=20',
+ assert_query_equal 'person%5Bid%5D%5B%5D=10&person%5Bid%5D%5B%5D=20',
:person => {:id => [10, 20]}
end
def test_array_values_are_not_sorted
- assert_query_equal 'person[id][]=20&person[id][]=10',
+ assert_query_equal 'person%5Bid%5D%5B%5D=20&person%5Bid%5D%5B%5D=10',
:person => {:id => [20, 10]}
end
diff --git a/activesupport/test/core_ext/object_and_class_ext_test.rb b/activesupport/test/core_ext/object_and_class_ext_test.rb
index 3ccf18f473..5d68b198f2 100644
--- a/activesupport/test/core_ext/object_and_class_ext_test.rb
+++ b/activesupport/test/core_ext/object_and_class_ext_test.rb
@@ -28,18 +28,6 @@ module Nested
end
end
-module Bar
- def bar; end
-end
-
-module Baz
- def baz; end
-end
-
-class Foo
- include Bar
-end
-
class ObjectTests < ActiveSupport::TestCase
class DuckTime
def acts_like_time?
@@ -82,37 +70,6 @@ class ObjectInstanceVariableTest < Test::Unit::TestCase
assert_equal %w(@bar @baz), @source.instance_variable_names.sort
end
- def test_copy_instance_variables_from_without_explicit_excludes
- assert_equal [], @dest.instance_variables
- @dest.copy_instance_variables_from(@source)
-
- assert_equal %w(@bar @baz), @dest.instance_variables.sort.map(&:to_s)
- %w(@bar @baz).each do |name|
- assert_equal @source.instance_variable_get(name).object_id,
- @dest.instance_variable_get(name).object_id
- end
- end
-
- def test_copy_instance_variables_from_with_explicit_excludes
- @dest.copy_instance_variables_from(@source, ['@baz'])
- assert !@dest.instance_variable_defined?('@baz')
- assert_equal 'bar', @dest.instance_variable_get('@bar')
- end
-
- def test_copy_instance_variables_automatically_excludes_protected_instance_variables
- @source.instance_variable_set(:@quux, 'quux')
- class << @source
- def protected_instance_variables
- ['@bar', :@quux]
- end
- end
-
- @dest.copy_instance_variables_from(@source)
- assert !@dest.instance_variable_defined?('@bar')
- assert !@dest.instance_variable_defined?('@quux')
- assert_equal 'baz', @dest.instance_variable_get('@baz')
- end
-
def test_instance_values
object = Object.new
object.instance_variable_set :@a, 1
@@ -165,4 +122,14 @@ class ObjectTryTest < Test::Unit::TestCase
def test_false_try
assert_equal 'false', false.try(:to_s)
end
+
+ def test_try_only_block
+ assert_equal @string.reverse, @string.try { |s| s.reverse }
+ end
+
+ def test_try_only_block_nil
+ ran = false
+ nil.try { ran = true }
+ assert_equal false, ran
+ end
end
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index 8be65c99f2..bb865cae91 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -321,75 +321,6 @@ class CoreExtStringMultibyteTest < ActiveSupport::TestCase
end
end
-=begin
- string.rb - Interpolation for String.
-
- Copyright (C) 2005-2009 Masao Mutoh
-
- You may redistribute it and/or modify it under the same
- license terms as Ruby.
-=end
-class TestGetTextString < Test::Unit::TestCase
- def test_sprintf
- assert_equal("foo is a number", "%{msg} is a number" % {:msg => "foo"})
- assert_equal("bar is a number", "%s is a number" % ["bar"])
- assert_equal("bar is a number", "%s is a number" % "bar")
- assert_equal("1, test", "%{num}, %{record}" % {:num => 1, :record => "test"})
- assert_equal("test, 1", "%{record}, %{num}" % {:num => 1, :record => "test"})
- assert_equal("1, test", "%d, %s" % [1, "test"])
- assert_equal("test, 1", "%2$s, %1$d" % [1, "test"])
- assert_raise(ArgumentError) { "%-%" % [1] }
- end
-
- def test_percent
- assert_equal("% 1", "%% %<num>d" % {:num => 1.0})
- assert_equal("%{num} %<num>d 1", "%%{num} %%<num>d %<num>d" % {:num => 1})
- end
-
- def test_sprintf_percent_in_replacement
- assert_equal("%<not_translated>s", "%{msg}" % { :msg => '%<not_translated>s', :not_translated => 'should not happen' })
- end
-
- def test_sprintf_lack_argument
- assert_raises(KeyError) { "%{num}, %{record}" % {:record => "test"} }
- assert_raises(KeyError) { "%{record}" % {:num => 1} }
- end
-
- def test_no_placeholder
- # Causes a "too many arguments for format string" warning
- # on 1.8.7 and 1.9 but we still want to make sure the behavior works
- silence_warnings do
- assert_equal("aaa", "aaa" % {:num => 1})
- assert_equal("bbb", "bbb" % [1])
- end
- end
-
- def test_sprintf_ruby19_style
- assert_equal("1", "%<num>d" % {:num => 1})
- assert_equal("0b1", "%<num>#b" % {:num => 1})
- assert_equal("foo", "%<msg>s" % {:msg => "foo"})
- assert_equal("1.000000", "%<num>f" % {:num => 1.0})
- assert_equal(" 1", "%<num>3.0f" % {:num => 1.0})
- assert_equal("100.00", "%<num>2.2f" % {:num => 100.0})
- assert_equal("0x64", "%<num>#x" % {:num => 100.0})
- assert_raise(ArgumentError) { "%<num>,d" % {:num => 100} }
- assert_raise(ArgumentError) { "%<num>/d" % {:num => 100} }
- end
-
- def test_sprintf_old_style
- assert_equal("foo 1.000000", "%s %f" % ["foo", 1.0])
- end
-
- def test_sprintf_mix_unformatted_and_formatted_named_placeholders
- assert_equal("foo 1.000000", "%{name} %<num>f" % {:name => "foo", :num => 1.0})
- end
-
- def test_string_interpolation_raises_an_argument_error_when_mixing_named_and_unnamed_placeholders
- assert_raises(ArgumentError) { "%{name} %f" % [1.0] }
- assert_raises(ArgumentError) { "%{name} %f" % [1.0, 2.0] }
- end
-end
-
class OutputSafetyTest < ActiveSupport::TestCase
def setup
@string = "hello"
diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb
index 0bb2c4a39e..2b86da67fa 100644
--- a/activesupport/test/core_ext/time_with_zone_test.rb
+++ b/activesupport/test/core_ext/time_with_zone_test.rb
@@ -36,6 +36,10 @@ 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_localtime
+ assert_equal @twz.localtime, @twz.utc.getlocal
+ end
+
def test_utc?
assert_equal false, @twz.utc?
assert_equal true, ActiveSupport::TimeWithZone.new(Time.utc(2000), ActiveSupport::TimeZone['UTC']).utc?
@@ -102,7 +106,7 @@ class TimeWithZoneTest < Test::Unit::TestCase
end
def test_to_yaml
- assert_equal "--- 1999-12-31 19:00:00 -05:00\n", @twz.to_yaml
+ assert_equal "--- 2000-01-01 00:00:00 Z\n", @twz.to_yaml
end
def test_ruby_to_yaml
@@ -763,6 +767,13 @@ class TimeWithZoneMethodsForTimeAndDateTimeTest < Test::Unit::TestCase
end
end
+ def test_localtime
+ Time.zone_default = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
+ assert_equal @dt.in_time_zone.localtime, @dt.in_time_zone.utc.to_time.getlocal
+ ensure
+ Time.zone_default = nil
+ end
+
def test_use_zone
Time.zone = 'Alaska'
Time.use_zone 'Hawaii' do
diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb
index 2990177bed..60714a152d 100644
--- a/activesupport/test/inflector_test.rb
+++ b/activesupport/test/inflector_test.rb
@@ -22,6 +22,34 @@ class InflectorTest < Test::Unit::TestCase
assert_equal "", ActiveSupport::Inflector.pluralize("")
end
+ ActiveSupport::Inflector.inflections.uncountable.each do |word|
+ define_method "test_uncountability_of_#{word}" do
+ assert_equal word, ActiveSupport::Inflector.singularize(word)
+ assert_equal word, ActiveSupport::Inflector.pluralize(word)
+ assert_equal ActiveSupport::Inflector.pluralize(word), ActiveSupport::Inflector.singularize(word)
+ end
+ end
+
+ def test_uncountable_word_is_not_greedy
+ uncountable_word = "ors"
+ countable_word = "sponsor"
+
+ cached_uncountables = ActiveSupport::Inflector.inflections.uncountables
+
+ ActiveSupport::Inflector.inflections.uncountable << uncountable_word
+
+ assert_equal uncountable_word, ActiveSupport::Inflector.singularize(uncountable_word)
+ assert_equal uncountable_word, ActiveSupport::Inflector.pluralize(uncountable_word)
+ assert_equal ActiveSupport::Inflector.pluralize(uncountable_word), ActiveSupport::Inflector.singularize(uncountable_word)
+
+ assert_equal "sponsor", ActiveSupport::Inflector.singularize(countable_word)
+ assert_equal "sponsors", ActiveSupport::Inflector.pluralize(countable_word)
+ assert_equal "sponsor", ActiveSupport::Inflector.singularize(ActiveSupport::Inflector.pluralize(countable_word))
+
+ ensure
+ ActiveSupport::Inflector.inflections.instance_variable_set :@uncountables, cached_uncountables
+ end
+
SingularToPlural.each do |singular, plural|
define_method "test_pluralize_#{singular}" do
assert_equal(plural, ActiveSupport::Inflector.pluralize(singular))
diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb
index e0494de6e4..d5fcbf15b7 100644
--- a/activesupport/test/json/encoding_test.rb
+++ b/activesupport/test/json/encoding_test.rb
@@ -1,5 +1,6 @@
# encoding: utf-8
require 'abstract_unit'
+require 'active_support/core_ext/string/inflections'
require 'active_support/json'
class TestJSONEncoding < Test::Unit::TestCase
@@ -214,6 +215,36 @@ class TestJSONEncoding < Test::Unit::TestCase
assert_equal(%([{"address":{"city":"London"}},{"address":{"city":"Paris"}}]), json)
end
+ def test_struct_encoding
+ Struct.new('UserNameAndEmail', :name, :email)
+ Struct.new('UserNameAndDate', :name, :date)
+ Struct.new('Custom', :name, :sub)
+ user_email = Struct::UserNameAndEmail.new 'David', 'sample@example.com'
+ user_birthday = Struct::UserNameAndDate.new 'David', Date.new(2010, 01, 01)
+ custom = Struct::Custom.new 'David', user_birthday
+
+
+ json_strings = ""
+ json_string_and_date = ""
+ json_custom = ""
+
+ assert_nothing_raised do
+ json_strings = user_email.to_json
+ json_string_and_date = user_birthday.to_json
+ json_custom = custom.to_json
+ end
+
+ assert_equal({"name" => "David",
+ "sub" => {
+ "name" => "David",
+ "date" => "2010/01/01" }}, JSON.parse(json_custom))
+
+ assert_equal({"name" => "David", "email" => "sample@example.com"},
+ JSON.parse(json_strings))
+
+ assert_equal({"name" => "David", "date" => "2010/01/01"},
+ JSON.parse(json_string_and_date))
+ end
protected
diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb
index 50778b5864..09203465c3 100644
--- a/activesupport/test/ordered_hash_test.rb
+++ b/activesupport/test/ordered_hash_test.rb
@@ -109,6 +109,14 @@ class OrderedHashTest < Test::Unit::TestCase
assert_equal @keys, keys
end
+ def test_find_all
+ assert_equal @keys, @ordered_hash.find_all { true }.map(&:first)
+ end
+
+ def test_select
+ assert_equal @keys, @ordered_hash.select { true }.map(&:first)
+ end
+
def test_delete_if
copy = @ordered_hash.dup
copy.delete('pink')
@@ -231,14 +239,14 @@ class OrderedHashTest < Test::Unit::TestCase
def test_each_after_yaml_serialization
values = []
- @deserialized_ordered_hash = YAML::load(YAML::dump(@ordered_hash))
+ @deserialized_ordered_hash = YAML.load(YAML.dump(@ordered_hash))
@deserialized_ordered_hash.each {|key, value| values << value}
assert_equal @values, values
end
def test_order_after_yaml_serialization
- @deserialized_ordered_hash = YAML::load(YAML::dump(@ordered_hash))
+ @deserialized_ordered_hash = YAML.load(YAML.dump(@ordered_hash))
assert_equal @keys, @deserialized_ordered_hash.keys
assert_equal @values, @deserialized_ordered_hash.values
@@ -247,12 +255,34 @@ class OrderedHashTest < Test::Unit::TestCase
def test_order_after_yaml_serialization_with_nested_arrays
@ordered_hash[:array] = %w(a b c)
- @deserialized_ordered_hash = YAML::load(YAML::dump(@ordered_hash))
+ @deserialized_ordered_hash = YAML.load(YAML.dump(@ordered_hash))
assert_equal @ordered_hash.keys, @deserialized_ordered_hash.keys
assert_equal @ordered_hash.values, @deserialized_ordered_hash.values
end
+ begin
+ require 'psych'
+
+ def test_psych_serialize
+ @deserialized_ordered_hash = Psych.load(Psych.dump(@ordered_hash))
+
+ values = @deserialized_ordered_hash.map { |_, value| value }
+ assert_equal @values, values
+ end
+
+ def test_psych_serialize_tag
+ yaml = Psych.dump(@ordered_hash)
+ assert_match '!omap', yaml
+ end
+ rescue LoadError
+ end
+
+ def test_has_yaml_tag
+ @ordered_hash[:array] = %w(a b c)
+ assert_match '!omap', YAML.dump(@ordered_hash)
+ end
+
def test_update_sets_keys
@updated_ordered_hash = ActiveSupport::OrderedHash.new
@updated_ordered_hash.update(:name => "Bob")
diff --git a/activesupport/test/test_xml_mini.rb b/activesupport/test/test_xml_mini.rb
index 585eb15c6e..6dbcd1f40b 100644
--- a/activesupport/test/test_xml_mini.rb
+++ b/activesupport/test/test_xml_mini.rb
@@ -1,49 +1,100 @@
require 'abstract_unit'
require 'active_support/xml_mini'
+require 'active_support/builder'
-class XmlMiniTest < Test::Unit::TestCase
- def test_rename_key_dasherizes_by_default
- assert_equal "my-key", ActiveSupport::XmlMini.rename_key("my_key")
- end
+module XmlMiniTest
+ class RenameKeyTest < Test::Unit::TestCase
+ def test_rename_key_dasherizes_by_default
+ assert_equal "my-key", ActiveSupport::XmlMini.rename_key("my_key")
+ end
- def test_rename_key_does_nothing_with_dasherize_true
- assert_equal "my-key", ActiveSupport::XmlMini.rename_key("my_key", :dasherize => true)
- end
+ def test_rename_key_does_nothing_with_dasherize_true
+ assert_equal "my-key", ActiveSupport::XmlMini.rename_key("my_key", :dasherize => true)
+ end
- def test_rename_key_does_nothing_with_dasherize_false
- assert_equal "my_key", ActiveSupport::XmlMini.rename_key("my_key", :dasherize => false)
- end
+ def test_rename_key_does_nothing_with_dasherize_false
+ assert_equal "my_key", ActiveSupport::XmlMini.rename_key("my_key", :dasherize => false)
+ end
- def test_rename_key_camelizes_with_camelize_true
- assert_equal "MyKey", ActiveSupport::XmlMini.rename_key("my_key", :camelize => true)
- end
+ def test_rename_key_camelizes_with_camelize_false
+ assert_equal "my_key", ActiveSupport::XmlMini.rename_key("my_key", :camelize => false)
+ end
- def test_rename_key_camelizes_with_camelize_true
- assert_equal "MyKey", ActiveSupport::XmlMini.rename_key("my_key", :camelize => true)
- end
+ def test_rename_key_camelizes_with_camelize_nil
+ assert_equal "my_key", ActiveSupport::XmlMini.rename_key("my_key", :camelize => nil)
+ end
- def test_rename_key_does_not_dasherize_leading_underscores
- assert_equal "_id", ActiveSupport::XmlMini.rename_key("_id")
- end
+ def test_rename_key_camelizes_with_camelize_true
+ assert_equal "MyKey", ActiveSupport::XmlMini.rename_key("my_key", :camelize => true)
+ end
- def test_rename_key_with_leading_underscore_dasherizes_interior_underscores
- assert_equal "_my-key", ActiveSupport::XmlMini.rename_key("_my_key")
- end
+ def test_rename_key_lower_camelizes_with_camelize_lower
+ assert_equal "myKey", ActiveSupport::XmlMini.rename_key("my_key", :camelize => :lower)
+ end
- def test_rename_key_does_not_dasherize_trailing_underscores
- assert_equal "id_", ActiveSupport::XmlMini.rename_key("id_")
- end
+ def test_rename_key_lower_camelizes_with_camelize_upper
+ assert_equal "MyKey", ActiveSupport::XmlMini.rename_key("my_key", :camelize => :upper)
+ end
- def test_rename_key_with_trailing_underscore_dasherizes_interior_underscores
- assert_equal "my-key_", ActiveSupport::XmlMini.rename_key("my_key_")
- end
+ def test_rename_key_does_not_dasherize_leading_underscores
+ assert_equal "_id", ActiveSupport::XmlMini.rename_key("_id")
+ end
- def test_rename_key_does_not_dasherize_multiple_leading_underscores
- assert_equal "__id", ActiveSupport::XmlMini.rename_key("__id")
- end
+ def test_rename_key_with_leading_underscore_dasherizes_interior_underscores
+ assert_equal "_my-key", ActiveSupport::XmlMini.rename_key("_my_key")
+ end
+
+ def test_rename_key_does_not_dasherize_trailing_underscores
+ assert_equal "id_", ActiveSupport::XmlMini.rename_key("id_")
+ end
- def test_rename_key_does_not_dasherize_multiple_leading_underscores
- assert_equal "id__", ActiveSupport::XmlMini.rename_key("id__")
+ def test_rename_key_with_trailing_underscore_dasherizes_interior_underscores
+ assert_equal "my-key_", ActiveSupport::XmlMini.rename_key("my_key_")
+ end
+
+ def test_rename_key_does_not_dasherize_multiple_leading_underscores
+ assert_equal "__id", ActiveSupport::XmlMini.rename_key("__id")
+ end
+
+ def test_rename_key_does_not_dasherize_multiple_leading_underscores
+ assert_equal "id__", ActiveSupport::XmlMini.rename_key("id__")
+ end
end
+ class ToTagTest < ActiveSupport::TestCase
+ def assert_xml(xml)
+ assert_equal xml, @options[:builder].target!
+ end
+
+ setup do
+ @xml = ActiveSupport::XmlMini
+ @options = {:skip_instruct => true, :builder => Builder::XmlMarkup.new}
+ end
+
+ test "#to_tag accepts a callable object and passes options with the builder" do
+ @xml.to_tag(:some_tag, lambda {|o| o[:builder].br }, @options)
+ assert_xml "<br/>"
+ end
+
+ test "#to_tag accepts a callable object and passes options and tag name" do
+ @xml.to_tag(:tag, lambda {|o, t| o[:builder].b(t) }, @options)
+ assert_xml "<b>tag</b>"
+ end
+
+ test "#to_tag accepts an object responding to #to_xml and passes the options, where :root is key" do
+ obj = Object.new
+ obj.instance_eval do
+ def to_xml(options) options[:builder].yo(options[:root].to_s) end
+ end
+
+ @xml.to_tag(:tag, obj, @options)
+ assert_xml "<yo>tag</yo>"
+ end
+
+ test "#to_tag accepts arbitrary objects responding to #to_str" do
+ @xml.to_tag(:b, "Howdy", @options)
+ assert_xml "<b>Howdy</b>"
+ end
+ # TODO: test the remaining functions hidden in #to_tag.
+ end
end