aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG10
-rw-r--r--activesupport/lib/active_support/backtrace_cleaner.rb27
-rw-r--r--activesupport/lib/active_support/benchmarkable.rb22
-rw-r--r--activesupport/lib/active_support/cache.rb50
-rw-r--r--activesupport/lib/active_support/configurable.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/array/wrap.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb24
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute_accessors.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/date/freeze.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/hash/indifferent_access.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/reporting.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/module/attribute_accessors.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/module/delegation.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/inflections.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb65
-rw-r--r--activesupport/lib/active_support/core_ext/time/calculations.rb27
-rw-r--r--activesupport/lib/active_support/dependencies.rb11
-rw-r--r--activesupport/lib/active_support/inflector/inflections.rb145
-rw-r--r--activesupport/lib/active_support/inflector/methods.rb105
-rw-r--r--activesupport/lib/active_support/log_subscriber.rb8
-rw-r--r--activesupport/lib/active_support/memoizable.rb13
-rw-r--r--activesupport/lib/active_support/ordered_options.rb4
-rw-r--r--activesupport/lib/active_support/testing/assertions.rb2
-rw-r--r--activesupport/lib/active_support/testing/performance.rb38
-rw-r--r--activesupport/lib/active_support/testing/performance/jruby.rb18
-rw-r--r--activesupport/lib/active_support/testing/performance/rubinius.rb22
-rw-r--r--activesupport/lib/active_support/testing/performance/ruby.rb6
-rw-r--r--activesupport/lib/active_support/testing/performance/ruby/mri.rb10
-rw-r--r--activesupport/lib/active_support/testing/performance/ruby/yarv.rb8
-rw-r--r--activesupport/lib/active_support/version.rb4
-rw-r--r--activesupport/test/configurable_test.rb22
-rw-r--r--activesupport/test/core_ext/array_ext_test.rb5
-rw-r--r--activesupport/test/core_ext/class/attribute_accessor_test.rb11
-rw-r--r--activesupport/test/core_ext/class/attribute_test.rb6
-rw-r--r--activesupport/test/core_ext/date_ext_test.rb6
-rw-r--r--activesupport/test/core_ext/module/attribute_accessor_test.rb7
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb12
-rw-r--r--activesupport/test/core_ext/time_ext_test.rb20
-rw-r--r--activesupport/test/flush_cache_on_private_memoization_test.rb4
-rw-r--r--activesupport/test/inflector_test.rb86
-rw-r--r--activesupport/test/inflector_test_cases.rb3
-rw-r--r--activesupport/test/memoizable_test.rb38
-rw-r--r--activesupport/test/safe_buffer_test.rb52
-rw-r--r--activesupport/test/test_test.rb2
-rw-r--r--activesupport/test/time_zone_test.rb8
45 files changed, 660 insertions, 279 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 6b7044aeae..034d03533f 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,6 +1,14 @@
*Rails 3.2.0 (unreleased)*
-* Removed ActiveSupport::SecureRandom in favour of SecureRandom from the standard library [Jon Leighton]
+* The inflector understands acronyms. [dlee]
+
+* Deprecated ActiveSupport::Memoizable in favor of Ruby memoization pattern [José Valim]
+
+* Added Time#all_day/week/quarter/year as a way of generating ranges (example: Event.where(created_at: Time.now.all_week)) [DHH]
+
+* Added instance_accessor: false as an option to Class#cattr_accessor and friends [DHH]
+
+* Removed ActiveSupport::SecureRandom in favor of SecureRandom from the standard library [Jon Leighton]
* ActiveSupport::OrderedHash now has different behavior for #each and
#each_pair when given a block accepting its parameters with a splat. [Andrew Radev]
diff --git a/activesupport/lib/active_support/backtrace_cleaner.rb b/activesupport/lib/active_support/backtrace_cleaner.rb
index 0e6bc30fa2..8f8deb9692 100644
--- a/activesupport/lib/active_support/backtrace_cleaner.rb
+++ b/activesupport/lib/active_support/backtrace_cleaner.rb
@@ -1,12 +1,12 @@
module ActiveSupport
- # Many backtraces include too much information that's not relevant for the context. This makes it hard to find the signal
- # in the backtrace and adds debugging time. With a BacktraceCleaner, you can setup filters and silencers for your particular
- # context, so only the relevant lines are included.
+ # Backtraces often include many lines that are not relevant for the context under review. This makes it hard to find the
+ # signal amongst the backtrace noise, and adds debugging time. With a BacktraceCleaner, filters and silencers are used to
+ # remove the noisy lines, so that only the most relevant lines remain.
#
- # If you need to reconfigure an existing BacktraceCleaner, like the one in Rails, to show as much as possible, you can always
- # call BacktraceCleaner#remove_silencers! Also, if you need to reconfigure an existing BacktraceCleaner so that it does not
- # filter or modify the paths of any lines of the backtrace, you can call BacktraceCleaner#remove_filters! These two methods
- # will give you a completely untouched backtrace.
+ # Filters are used to modify lines of data, while silencers are used to remove lines entirely. The typical filter use case
+ # is to remove lengthy path information from the start of each line, and view file paths relevant to the app directory
+ # instead of the file system root. The typical silencer use case is to exclude the output of a noisy library from the
+ # backtrace, so that you can focus on the rest.
#
# ==== Example:
#
@@ -15,13 +15,18 @@ module ActiveSupport
# bc.add_silencer { |line| line =~ /mongrel|rubygems/ }
# bc.clean(exception.backtrace) # will strip the Rails.root prefix and skip any lines from mongrel or rubygems
#
+ # To reconfigure an existing BacktraceCleaner (like the default one in Rails) and show as much data as possible, you can
+ # always call <tt>BacktraceCleaner#remove_silencers!</tt>, which will restore the backtrace to a pristine state. If you
+ # need to reconfigure an existing BacktraceCleaner so that it does not filter or modify the paths of any lines of the
+ # backtrace, you can call BacktraceCleaner#remove_filters! These two methods will give you a completely untouched backtrace.
+ #
# Inspired by the Quiet Backtrace gem by Thoughtbot.
class BacktraceCleaner
def initialize
@filters, @silencers = [], []
end
- # Returns the backtrace after all filters and silencers has been run against it. Filters run first, then silencers.
+ # Returns the backtrace after all filters and silencers have been run against it. Filters run first, then silencers.
def clean(backtrace, kind = :silent)
filtered = filter(backtrace)
@@ -45,8 +50,8 @@ module ActiveSupport
@filters << block
end
- # Adds a silencer from the block provided. If the silencer returns true for a given line, it'll be excluded from the
- # clean backtrace.
+ # Adds a silencer from the block provided. If the silencer returns true for a given line, it will be excluded from
+ # the clean backtrace.
#
# Example:
#
@@ -57,7 +62,7 @@ module ActiveSupport
end
# Will remove all silencers, but leave in the filters. This is useful if your context of debugging suddenly expands as
- # you suspect a bug in the libraries you use.
+ # you suspect a bug in one of the libraries you use.
def remove_silencers!
@silencers = []
end
diff --git a/activesupport/lib/active_support/benchmarkable.rb b/activesupport/lib/active_support/benchmarkable.rb
index e303eaa5ce..cc94041a1d 100644
--- a/activesupport/lib/active_support/benchmarkable.rb
+++ b/activesupport/lib/active_support/benchmarkable.rb
@@ -3,28 +3,28 @@ require 'active_support/core_ext/hash/keys'
module ActiveSupport
module Benchmarkable
- # Allows you to measure the execution time of a block
- # in a template and records the result to the log. Wrap this block around
- # expensive operations or possible bottlenecks to get a time reading
- # for the operation. For example, let's say you thought your file
- # processing method was taking too long; you could wrap it in a benchmark block.
+ # Allows you to measure the execution time of a block in a template and records the result to
+ # the log. Wrap this block around expensive operations or possible bottlenecks to get a time
+ # reading for the operation. For example, let's say you thought your file processing method
+ # was taking too long; you could wrap it in a benchmark block.
#
# <% benchmark "Process data files" do %>
# <%= expensive_files_operation %>
# <% end %>
#
- # That would add something like "Process data files (345.2ms)" to the log,
- # which you can then use to compare timings when optimizing your code.
+ # That would add something like "Process data files (345.2ms)" to the log, which you can then
+ # use to compare timings when optimizing your code.
#
- # You may give an optional logger level as the :level option.
- # (:debug, :info, :warn, :error); the default value is :info.
+ # You may give an optional logger level (:debug, :info, :warn, :error) as the :level option.
+ # The default logger level value is :info.
#
# <% benchmark "Low-level files", :level => :debug do %>
# <%= lowlevel_files_operation %>
# <% end %>
#
- # Finally, you can pass true as the third argument to silence all log activity
- # inside the block. This is great for boiling down a noisy block to just a single statement:
+ # Finally, you can pass true as the third argument to silence all log activity (other than the
+ # timing information) from inside the block. This is great for boiling down a noisy block to
+ # just a single statement that produces one log line:
#
# <% benchmark "Process data files", :level => :info, :silence => true do %>
# <%= expensive_and_chatty_files_operation %>
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index 10c457bb1d..85692428e3 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -116,31 +116,32 @@ module ActiveSupport
# cache.read("city") # => "Duckburgh"
#
# Keys are always translated into Strings and are case sensitive. When an
- # object is specified as a key, its +cache_key+ method will be called if it
- # is defined. Otherwise, the +to_param+ method will be called. Hashes and
- # Arrays can be used as keys. The elements will be delimited by slashes
- # and Hashes elements will be sorted by key so they are consistent.
+ # object is specified as a key and has a +cache_key+ method defined, this
+ # method will be called to define the key. Otherwise, the +to_param+
+ # method will be called. Hashes and Arrays can also be used as keys. The
+ # elements will be delimited by slashes, and the elements within a Hash
+ # will be sorted by key so they are consistent.
#
# cache.read("city") == cache.read(:city) # => true
#
# Nil values can be cached.
#
- # If your cache is on a shared infrastructure, you can define a namespace for
- # your cache entries. If a namespace is defined, it will be prefixed on to every
- # key. The namespace can be either a static value or a Proc. If it is a Proc, it
- # will be invoked when each key is evaluated so that you can use application logic
- # to invalidate keys.
+ # If your cache is on a shared infrastructure, you can define a namespace
+ # for your cache entries. If a namespace is defined, it will be prefixed on
+ # to every key. The namespace can be either a static value or a Proc. If it
+ # is a Proc, it will be invoked when each key is evaluated so that you can
+ # use application logic to invalidate keys.
#
# cache.namespace = lambda { @last_mod_time } # Set the namespace to a variable
# @last_mod_time = Time.now # Invalidate the entire cache by changing namespace
#
#
- # Caches can also store values in a compressed format to save space and reduce
- # time spent sending data. Since there is some overhead, values must be large
- # enough to warrant compression. To turn on compression either pass
- # <tt>:compress => true</tt> in the initializer or to +fetch+ or +write+.
- # To specify the threshold at which to compress values, set
- # <tt>:compress_threshold</tt>. The default threshold is 32K.
+ # Caches can also store values in a compressed format to save space and
+ # reduce time spent sending data. Since there is overhead, values must be
+ # large enough to warrant compression. To turn on compression either pass
+ # <tt>:compress => true</tt> in the initializer or as an option to +fetch+
+ # or +write+. To specify the threshold at which to compress values, set the
+ # <tt>:compress_threshold</tt> option. The default threshold is 32K.
class Store
cattr_accessor :logger, :instance_writer => true
@@ -180,11 +181,11 @@ module ActiveSupport
# Fetches data from the cache, using the given key. If there is data in
# the cache with the given key, then that data is returned.
#
- # If there is no such data in the cache (a cache miss occurred),
- # then nil will be returned. However, if a block has been passed, then
- # that block will be run in the event of a cache miss. The return value
- # of the block will be written to the cache under the given cache key,
- # and that return value will be returned.
+ # If there is no such data in the cache (a cache miss), then nil will be
+ # returned. However, if a block has been passed, that block will be run
+ # in the event of a cache miss. The return value of the block will be
+ # written to the cache under the given cache key, and that return value
+ # will be returned.
#
# cache.write("today", "Monday")
# cache.fetch("today") # => "Monday"
@@ -205,10 +206,11 @@ module ActiveSupport
# in a compressed format.
#
#
- # Setting <tt>:expires_in</tt> will set an expiration time on the cache. All caches
- # support auto expiring content after a specified number of seconds. This value can
- # be specified as an option to the construction in which call all entries will be
- # affected. Or it can be supplied to the +fetch+ or +write+ method for just one entry.
+ # Setting <tt>:expires_in</tt> will set an expiration time on the cache.
+ # All caches support auto-expiring content after a specified number of
+ # seconds. This value can be specified as an option to the constructor
+ # (in which case all entries will be affected), or it can be supplied to
+ # the +fetch+ or +write+ method to effect just 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
diff --git a/activesupport/lib/active_support/configurable.rb b/activesupport/lib/active_support/configurable.rb
index a94446acde..a2d2719de7 100644
--- a/activesupport/lib/active_support/configurable.rb
+++ b/activesupport/lib/active_support/configurable.rb
@@ -12,12 +12,12 @@ module ActiveSupport
class Configuration < ActiveSupport::InheritableOptions
def compile_methods!
- self.class.compile_methods!(keys.reject {|key| respond_to?(key)})
+ self.class.compile_methods!(keys)
end
# compiles reader methods so we don't have to go through method_missing
def self.compile_methods!(keys)
- keys.each do |key|
+ keys.reject { |m| method_defined?(m) }.each do |key|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{key}; _get(#{key.inspect}); end
RUBY
diff --git a/activesupport/lib/active_support/core_ext/array/wrap.rb b/activesupport/lib/active_support/core_ext/array/wrap.rb
index 7fabae3138..4834eca8b1 100644
--- a/activesupport/lib/active_support/core_ext/array/wrap.rb
+++ b/activesupport/lib/active_support/core_ext/array/wrap.rb
@@ -14,7 +14,7 @@ class Array
# This method is similar in purpose to <tt>Kernel#Array</tt>, but there are some differences:
#
# * If the argument responds to +to_ary+ the method is invoked. <tt>Kernel#Array</tt>
- # moves on to try +to_a+ if the returned value is +nil+, but <tt>Arraw.wrap</tt> returns
+ # moves on to try +to_a+ if the returned value is +nil+, but <tt>Array.wrap</tt> returns
# such a +nil+ right away.
# * If the returned value from +to_ary+ is neither +nil+ nor an +Array+ object, <tt>Kernel#Array</tt>
# raises an exception, while <tt>Array.wrap</tt> does not, it just returns the value.
@@ -40,7 +40,7 @@ class Array
if object.nil?
[]
elsif object.respond_to?(:to_ary)
- object.to_ary
+ object.to_ary || [object]
else
[object]
end
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
index 7baba75ad3..ca9b2c1b60 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -1,5 +1,6 @@
require 'active_support/core_ext/kernel/singleton_class'
require 'active_support/core_ext/module/remove_method'
+require 'active_support/core_ext/array/extract_options'
class Class
# Declare a class-level attribute whose value is inheritable by subclasses.
@@ -56,11 +57,18 @@ class Class
# object.setting # => false
# Base.setting # => true
#
+ # To opt out of the instance reader method, pass :instance_reader => false.
+ #
+ # object.setting # => NoMethodError
+ # object.setting? # => NoMethodError
+ #
# To opt out of the instance writer method, pass :instance_writer => false.
#
# object.setting = false # => NoMethodError
def class_attribute(*attrs)
- instance_writer = !attrs.last.is_a?(Hash) || attrs.pop[:instance_writer]
+ options = attrs.extract_options!
+ instance_reader = options.fetch(:instance_reader, true)
+ instance_writer = options.fetch(:instance_writer, true)
attrs.each do |name|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
@@ -84,13 +92,15 @@ class Class
val
end
- remove_possible_method :#{name}
- def #{name}
- defined?(@#{name}) ? @#{name} : self.class.#{name}
- end
+ if instance_reader
+ remove_possible_method :#{name}
+ def #{name}
+ defined?(@#{name}) ? @#{name} : self.class.#{name}
+ end
- def #{name}?
- !!#{name}
+ def #{name}?
+ !!#{name}
+ end
end
RUBY
diff --git a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
index a903735acf..268303aaf2 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
@@ -17,6 +17,7 @@ require 'active_support/core_ext/array/extract_options'
#
# To opt out of the instance writer method, pass :instance_writer => false.
# To opt out of the instance reader method, pass :instance_reader => false.
+# To opt out of both instance methods, pass :instance_accessor => false.
#
# class Person
# cattr_accessor :hair_colors, :instance_writer => false, :instance_reader => false
@@ -38,7 +39,7 @@ class Class
end
EOS
- unless options[:instance_reader] == false
+ unless options[:instance_reader] == false || options[:instance_accessor] == false
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}
@@#{sym}
@@ -61,7 +62,7 @@ class Class
end
EOS
- unless options[:instance_writer] == false
+ unless options[:instance_writer] == false || options[:instance_accessor] == false
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}=(obj)
@@#{sym} = obj
diff --git a/activesupport/lib/active_support/core_ext/date/freeze.rb b/activesupport/lib/active_support/core_ext/date/freeze.rb
index 4edd715ba2..a731f8345e 100644
--- a/activesupport/lib/active_support/core_ext/date/freeze.rb
+++ b/activesupport/lib/active_support/core_ext/date/freeze.rb
@@ -5,7 +5,7 @@
# first call will result in a frozen object error since the memo
# instance variable is uninitialized.
#
-# Work around by eagerly memoizing before freezing.
+# Work around by eagerly memoizing before the first freeze.
#
# Ruby 1.9 uses a preinitialized instance variable so it's unaffected.
# This hack is as close as we can get to feature detection:
@@ -17,9 +17,11 @@ if RUBY_VERSION < '1.9'
if frozen_object_error.message =~ /frozen/
class Date #:nodoc:
def freeze
- self.class.private_instance_methods(false).each do |m|
- if m.to_s =~ /\A__\d+__\Z/
- instance_variable_set(:"@#{m}", [send(m)])
+ unless frozen?
+ self.class.private_instance_methods(false).each do |m|
+ if m.to_s =~ /\A__\d+__\Z/
+ instance_variable_set(:"@#{m}", [send(m)])
+ end
end
end
diff --git a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
index c2a6476604..0b368fe7b7 100644
--- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
+++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
@@ -11,7 +11,7 @@ class Hash
end
# Called when object is nested under an object that receives
- # #with_indifferent_access. This method with be called on the current object
+ # #with_indifferent_access. This method will be called on the current object
# by the enclosing object and is aliased to #with_indifferent_access by
# default. Subclasses of Hash may overwrite this method to return +self+ if
# converting to an +ActiveSupport::HashWithIndifferentAccess+ would not be
diff --git a/activesupport/lib/active_support/core_ext/kernel/reporting.rb b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
index c6920098a8..526b8378a5 100644
--- a/activesupport/lib/active_support/core_ext/kernel/reporting.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
@@ -59,7 +59,7 @@ module Kernel
raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
end
end
-
+
# Captures the given stream and returns it:
#
# stream = capture(:stdout) { puts "Cool" }
diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
index 871f5cef3b..be94ae1565 100644
--- a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
@@ -12,7 +12,7 @@ class Module
end
EOS
- unless options[:instance_reader] == false
+ unless options[:instance_reader] == false || options[:instance_accessor] == false
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}
@@#{sym}
@@ -31,7 +31,7 @@ class Module
end
EOS
- unless options[:instance_writer] == false
+ unless options[:instance_writer] == false || options[:instance_accessor] == false
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}=(obj)
@@#{sym} = obj
@@ -53,6 +53,10 @@ class Module
# end
#
# AppConfiguration.google_api_key = "overriding the api key!"
+ #
+ # To opt out of the instance writer method, pass :instance_writer => false.
+ # To opt out of the instance reader method, pass :instance_reader => false.
+ # To opt out of both instance methods, pass :instance_accessor => false.
def mattr_accessor(*syms)
mattr_reader(*syms)
mattr_writer(*syms)
diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb
index 3a7652f5bf..1777a4b32d 100644
--- a/activesupport/lib/active_support/core_ext/module/delegation.rb
+++ b/activesupport/lib/active_support/core_ext/module/delegation.rb
@@ -113,7 +113,7 @@ class Module
raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
end
- prefix = options[:prefix] && "#{options[:prefix] == true ? to : options[:prefix]}_" || ''
+ prefix = options[:prefix] ? "#{options[:prefix] == true ? to : options[:prefix]}_" : ''
file, line = caller.first.split(':', 2)
line = line.to_i
diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb
index 2f0676f567..002688d6c0 100644
--- a/activesupport/lib/active_support/core_ext/string/inflections.rb
+++ b/activesupport/lib/active_support/core_ext/string/inflections.rb
@@ -1,5 +1,4 @@
require 'active_support/inflector/methods'
-require 'active_support/inflector/inflections'
require 'active_support/inflector/transliterate'
# String inflections define new methods on the String class to transform names for different purposes.
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 c27cbc37c5..3bf4edbdef 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -51,7 +51,8 @@ class ERB
# <%=j @person.to_json %>
#
def json_escape(s)
- s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
+ result = s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
+ s.html_safe? ? result.html_safe : result
end
alias j json_escape
@@ -66,7 +67,7 @@ class Object
end
end
-class Fixnum
+class Numeric
def html_safe?
true
end
@@ -74,10 +75,34 @@ end
module ActiveSupport #:nodoc:
class SafeBuffer < String
- alias safe_concat concat
+ UNSAFE_STRING_METHODS = ["capitalize", "chomp", "chop", "delete", "downcase", "gsub", "lstrip", "next", "reverse", "rstrip", "slice", "squeeze", "strip", "sub", "succ", "swapcase", "tr", "tr_s", "upcase"].freeze
+
+ alias_method :original_concat, :concat
+ private :original_concat
+
+ class SafeConcatError < StandardError
+ def initialize
+ super "Could not concatenate to the buffer because it is not html safe."
+ end
+ end
+
+ def safe_concat(value)
+ raise SafeConcatError if dirty?
+ original_concat(value)
+ end
+
+ def initialize(*)
+ @dirty = false
+ super
+ end
+
+ def initialize_copy(other)
+ super
+ @dirty = other.dirty?
+ end
def concat(value)
- if value.html_safe?
+ if dirty? || value.html_safe?
super(value)
else
super(ERB::Util.h(value))
@@ -90,15 +115,15 @@ module ActiveSupport #:nodoc:
end
def html_safe?
- true
+ !dirty?
end
- def html_safe
+ def to_s
self
end
- def to_s
- self
+ def to_param
+ to_str
end
def encode_with(coder)
@@ -107,17 +132,31 @@ module ActiveSupport #:nodoc:
def to_yaml(*args)
return super() if defined?(YAML::ENGINE) && !YAML::ENGINE.syck?
-
to_str.to_yaml(*args)
end
+
+ UNSAFE_STRING_METHODS.each do |unsafe_method|
+ class_eval <<-EOT, __FILE__, __LINE__
+ def #{unsafe_method}(*args, &block) # def gsub(*args, &block)
+ to_str.#{unsafe_method}(*args, &block) # to_str.gsub(*args, &block)
+ end # end
+
+ def #{unsafe_method}!(*args) # def gsub!(*args)
+ @dirty = true # @dirty = true
+ super # super
+ end # end
+ EOT
+ end
+
+ protected
+
+ def dirty?
+ @dirty
+ end
end
end
class String
- def html_safe!
- raise "You can't call html_safe! on a String"
- end
-
def html_safe
ActiveSupport::SafeBuffer.new(self)
end
diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb
index 00fda2b370..c5fbbcf890 100644
--- a/activesupport/lib/active_support/core_ext/time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/time/calculations.rb
@@ -226,7 +226,7 @@ class Time
end
alias :at_end_of_quarter :end_of_quarter
- # Returns a new Time representing the start of the year (1st of january, 0:00)
+ # Returns a new Time representing the start of the year (1st of january, 0:00)
def beginning_of_year
change(:month => 1, :day => 1, :hour => 0)
end
@@ -248,6 +248,31 @@ class Time
advance(:days => 1)
end
+ # Returns a Range representing the whole day of the current time.
+ def all_day
+ beginning_of_day..end_of_day
+ end
+
+ # Returns a Range representing the whole week of the current time.
+ def all_week
+ beginning_of_week..end_of_week
+ end
+
+ # Returns a Range representing the whole month of the current time.
+ def all_month
+ beginning_of_month..end_of_month
+ end
+
+ # Returns a Range representing the whole quarter of the current time.
+ def all_quarter
+ beginning_of_quarter..end_of_quarter
+ end
+
+ # Returns a Range representing the whole year of the current time.
+ def all_year
+ beginning_of_year..end_of_year
+ end
+
def plus_with_duration(other) #:nodoc:
if ActiveSupport::Duration === other
other.since(self)
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 26c5c157cb..d1543c4c58 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -628,17 +628,6 @@ module ActiveSupport #:nodoc:
return []
end
- class LoadingModule #:nodoc:
- # Old style environment.rb referenced this method directly. Please note, it doesn't
- # actually *do* anything any more.
- def self.root(*args)
- if defined?(Rails) && Rails.logger
- Rails.logger.warn "Your environment.rb uses the old syntax, it may not continue to work in future releases."
- Rails.logger.warn "For upgrade instructions please see: http://manuals.rubyonrails.com/read/book/19"
- end
- end
- end
-
# Convert the provided const desc to a qualified constant name (as a string).
# A module, class, symbol, or string may be provided.
def to_constant_name(desc) #:nodoc:
diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb
index d5d55b7207..90bb62f57b 100644
--- a/activesupport/lib/active_support/inflector/inflections.rb
+++ b/activesupport/lib/active_support/inflector/inflections.rb
@@ -20,10 +20,61 @@ module ActiveSupport
@__instance__ ||= new
end
- attr_reader :plurals, :singulars, :uncountables, :humans
+ attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms, :acronym_regex
def initialize
- @plurals, @singulars, @uncountables, @humans = [], [], [], []
+ @plurals, @singulars, @uncountables, @humans, @acronyms, @acronym_regex = [], [], [], [], {}, /(?=a)b/
+ end
+
+ # Specifies a new acronym. An acronym must be specified as it will appear in a camelized string. An underscore
+ # string that contains the acronym will retain the acronym when passed to `camelize`, `humanize`, or `titleize`.
+ # A camelized string that contains the acronym will maintain the acronym when titleized or humanized, and will
+ # convert the acronym into a non-delimited single lowercase word when passed to +underscore+.
+ #
+ # Examples:
+ # acronym 'HTML'
+ # titleize 'html' #=> 'HTML'
+ # camelize 'html' #=> 'HTML'
+ # underscore 'MyHTML' #=> 'my_html'
+ #
+ # The acronym, however, must occur as a delimited unit and not be part of another word for conversions to recognize it:
+ #
+ # acronym 'HTTP'
+ # camelize 'my_http_delimited' #=> 'MyHTTPDelimited'
+ # camelize 'https' #=> 'Https', not 'HTTPs'
+ # underscore 'HTTPS' #=> 'http_s', not 'https'
+ #
+ # acronym 'HTTPS'
+ # camelize 'https' #=> 'HTTPS'
+ # underscore 'HTTPS' #=> 'https'
+ #
+ # Note: Acronyms that are passed to `pluralize` will no longer be recognized, since the acronym will not occur as
+ # a delimited unit in the pluralized result. To work around this, you must specify the pluralized form as an
+ # acronym as well:
+ #
+ # acronym 'API'
+ # camelize(pluralize('api')) #=> 'Apis'
+ #
+ # acronym 'APIs'
+ # camelize(pluralize('api')) #=> 'APIs'
+ #
+ # `acronym` may be used to specify any word that contains an acronym or otherwise needs to maintain a non-standard
+ # capitalization. The only restriction is that the word must begin with a capital letter.
+ #
+ # Examples:
+ # acronym 'RESTful'
+ # underscore 'RESTful' #=> 'restful'
+ # underscore 'RESTfulController' #=> 'restful_controller'
+ # titleize 'RESTfulController' #=> 'RESTful Controller'
+ # camelize 'restful' #=> 'RESTful'
+ # camelize 'restful_controller' #=> 'RESTfulController'
+ #
+ # acronym 'McDonald'
+ # underscore 'McDonald' #=> 'mcdonald'
+ # camelize 'mcdonald' #=> 'McDonald'
+ def acronym(word)
+ @acronyms[word.downcase] = word
+ @acronym_regex = /#{@acronyms.values.join("|")}/
end
# Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
@@ -117,95 +168,5 @@ module ActiveSupport
Inflections.instance
end
end
-
- # Returns the plural form of the word in the string.
- #
- # Examples:
- # "post".pluralize # => "posts"
- # "octopus".pluralize # => "octopi"
- # "sheep".pluralize # => "sheep"
- # "words".pluralize # => "words"
- # "CamelOctopus".pluralize # => "CamelOctopi"
- def pluralize(word)
- result = word.to_s.dup
-
- if word.empty? || inflections.uncountables.include?(result.downcase)
- result
- else
- inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
- result
- end
- end
-
- # The reverse of +pluralize+, returns the singular form of a word in a string.
- #
- # Examples:
- # "posts".singularize # => "post"
- # "octopi".singularize # => "octopus"
- # "sheep".singularize # => "sheep"
- # "word".singularize # => "word"
- # "CamelOctopi".singularize # => "CamelOctopus"
- def singularize(word)
- result = word.to_s.dup
-
- if inflections.uncountables.any? { |inflection| result =~ /\b(#{inflection})\Z/i }
- result
- else
- inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
- result
- end
- end
-
- # Capitalizes the first word and turns underscores into spaces and strips a
- # trailing "_id", if any. Like +titleize+, this is meant for creating pretty output.
- #
- # Examples:
- # "employee_salary" # => "Employee salary"
- # "author_id" # => "Author"
- def humanize(lower_case_and_underscored_word)
- result = lower_case_and_underscored_word.to_s.dup
-
- inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
- result.gsub(/_id$/, "").gsub(/_/, " ").capitalize
- end
-
- # Capitalizes all the words and replaces some characters in the string to create
- # a nicer looking title. +titleize+ is meant for creating pretty output. It is not
- # used in the Rails internals.
- #
- # +titleize+ is also aliased as as +titlecase+.
- #
- # Examples:
- # "man from the boondocks".titleize # => "Man From The Boondocks"
- # "x-men: the last stand".titleize # => "X Men: The Last Stand"
- def titleize(word)
- humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize }
- end
-
- # Create the name of a table like Rails does for models to table names. This method
- # uses the +pluralize+ method on the last word in the string.
- #
- # Examples
- # "RawScaledScorer".tableize # => "raw_scaled_scorers"
- # "egg_and_ham".tableize # => "egg_and_hams"
- # "fancyCategory".tableize # => "fancy_categories"
- def tableize(class_name)
- pluralize(underscore(class_name))
- end
-
- # Create a class name from a plural table name like Rails does for table names to models.
- # Note that this returns a string and not a Class. (To convert to an actual class
- # follow +classify+ with +constantize+.)
- #
- # Examples:
- # "egg_and_hams".classify # => "EggAndHam"
- # "posts".classify # => "Post"
- #
- # Singular names are not handled correctly:
- # "business".classify # => "Busines"
- def classify(table_name)
- # strip out any leading schema name
- camelize(singularize(table_name.to_s.sub(/.*\./, '')))
- end
end
end
diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb
index a2c4f7bfda..3d28d33f40 100644
--- a/activesupport/lib/active_support/inflector/methods.rb
+++ b/activesupport/lib/active_support/inflector/methods.rb
@@ -1,3 +1,5 @@
+require 'active_support/inflector/inflections'
+
module ActiveSupport
# The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
# and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
@@ -10,6 +12,44 @@ module ActiveSupport
module Inflector
extend self
+ # Returns the plural form of the word in the string.
+ #
+ # Examples:
+ # "post".pluralize # => "posts"
+ # "octopus".pluralize # => "octopi"
+ # "sheep".pluralize # => "sheep"
+ # "words".pluralize # => "words"
+ # "CamelOctopus".pluralize # => "CamelOctopi"
+ def pluralize(word)
+ result = word.to_s.dup
+
+ if word.empty? || inflections.uncountables.include?(result.downcase)
+ result
+ else
+ inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
+ result
+ end
+ end
+
+ # The reverse of +pluralize+, returns the singular form of a word in a string.
+ #
+ # Examples:
+ # "posts".singularize # => "post"
+ # "octopi".singularize # => "octopus"
+ # "sheep".singularize # => "sheep"
+ # "word".singularize # => "word"
+ # "CamelOctopi".singularize # => "CamelOctopus"
+ def singularize(word)
+ result = word.to_s.dup
+
+ if inflections.uncountables.any? { |inflection| result =~ /\b(#{inflection})\Z/i }
+ result
+ else
+ inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
+ result
+ end
+ end
+
# By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+
# is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase.
#
@@ -25,12 +65,14 @@ module ActiveSupport
# though there are cases where that does not hold:
#
# "SSLError".underscore.camelize # => "SslError"
- def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
- if first_letter_in_uppercase
- lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
+ def camelize(term, uppercase_first_letter = true)
+ string = term.to_s
+ if uppercase_first_letter
+ string = string.sub(/^[a-z\d]*/) { inflections.acronyms[$&] || $&.capitalize }
else
- lower_case_and_underscored_word.to_s[0].chr.downcase + camelize(lower_case_and_underscored_word)[1..-1]
+ string = string.sub(/^(?:#{inflections.acronym_regex}(?=\b|[A-Z_])|\w)/) { $&.downcase }
end
+ string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }.gsub('/', '::')
end
# Makes an underscored, lowercase form from the expression in the string.
@@ -48,13 +90,66 @@ module ActiveSupport
def underscore(camel_cased_word)
word = camel_cased_word.to_s.dup
word.gsub!(/::/, '/')
- word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
+ word.gsub!(/(?:([A-Za-z\d])|^)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1}#{$1 && '_'}#{$2.downcase}" }
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
word.tr!("-", "_")
word.downcase!
word
end
+ # Capitalizes the first word and turns underscores into spaces and strips a
+ # trailing "_id", if any. Like +titleize+, this is meant for creating pretty output.
+ #
+ # Examples:
+ # "employee_salary" # => "Employee salary"
+ # "author_id" # => "Author"
+ def humanize(lower_case_and_underscored_word)
+ result = lower_case_and_underscored_word.to_s.dup
+ inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
+ result.gsub!(/_id$/, "")
+ result.gsub(/(_)?([a-z\d]*)/i) { "#{$1 && ' '}#{inflections.acronyms[$2] || $2.downcase}" }.gsub(/^\w/) { $&.upcase }
+ end
+
+ # Capitalizes all the words and replaces some characters in the string to create
+ # a nicer looking title. +titleize+ is meant for creating pretty output. It is not
+ # used in the Rails internals.
+ #
+ # +titleize+ is also aliased as as +titlecase+.
+ #
+ # Examples:
+ # "man from the boondocks".titleize # => "Man From The Boondocks"
+ # "x-men: the last stand".titleize # => "X Men: The Last Stand"
+ def titleize(word)
+ humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize }
+ end
+
+ # Create the name of a table like Rails does for models to table names. This method
+ # uses the +pluralize+ method on the last word in the string.
+ #
+ # Examples
+ # "RawScaledScorer".tableize # => "raw_scaled_scorers"
+ # "egg_and_ham".tableize # => "egg_and_hams"
+ # "fancyCategory".tableize # => "fancy_categories"
+ def tableize(class_name)
+ pluralize(underscore(class_name))
+ end
+
+ # Create a class name from a plural table name like Rails does for table names to models.
+ # Note that this returns a string and not a Class. (To convert to an actual class
+ # follow +classify+ with +constantize+.)
+ #
+ # Examples:
+ # "egg_and_hams".classify # => "EggAndHam"
+ # "posts".classify # => "Post"
+ #
+ # Singular names are not handled correctly:
+ # "business".classify # => "Busines"
+ def classify(table_name)
+ # strip out any leading schema name
+ camelize(singularize(table_name.to_s.sub(/.*\./, '')))
+ end
+
# Replaces underscores with dashes in the string.
#
# Example:
diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb
index 1c4dd24227..6296c1d4b8 100644
--- a/activesupport/lib/active_support/log_subscriber.rb
+++ b/activesupport/lib/active_support/log_subscriber.rb
@@ -3,8 +3,8 @@ require 'active_support/core_ext/class/attribute'
module ActiveSupport
# ActiveSupport::LogSubscriber is an object set to consume ActiveSupport::Notifications
- # with solely purpose of logging. The log subscriber dispatches notifications to a
- # registered object based on its given namespace.
+ # with the sole purpose of logging them. The log subscriber dispatches notifications to
+ # a registered object based on its given namespace.
#
# An example would be Active Record log subscriber responsible for logging queries:
#
@@ -109,8 +109,8 @@ module ActiveSupport
# Set color by using a string or one of the defined constants. If a third
# option is set to true, it also adds bold to the string. This is based
- # on Highline implementation and it automatically appends CLEAR to the end
- # of the returned String.
+ # on the Highline implementation and will automatically append CLEAR to the
+ # end of the returned String.
#
def color(text, color, bold=false)
return text unless colorize_logging
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb
index 0a7bcd5bb8..4c67676ad5 100644
--- a/activesupport/lib/active_support/memoizable.rb
+++ b/activesupport/lib/active_support/memoizable.rb
@@ -1,8 +1,15 @@
require 'active_support/core_ext/kernel/singleton_class'
require 'active_support/core_ext/module/aliasing'
+require 'active_support/deprecation'
module ActiveSupport
module Memoizable
+ def self.extended(base)
+ ActiveSupport::Deprecation.warn "ActiveSupport::Memoizable is deprecated and will be removed in future releases," \
+ "simply use Ruby memoization pattern instead.", caller
+ super
+ end
+
def self.memoized_ivar_for(symbol)
"@_memoized_#{symbol.to_s.sub(/\?\Z/, '_query').sub(/!\Z/, '_bang')}".to_sym
end
@@ -79,7 +86,11 @@ module ActiveSupport
else # else
def #{symbol}(*args) # def mime_type(*args)
#{memoized_ivar} ||= {} unless frozen? # @_memoized_mime_type ||= {} unless frozen?
- reload = args.pop if args.last == true || args.last == :reload # reload = args.pop if args.last == true || args.last == :reload
+ args_length = method(:#{original_method}).arity # args_length = method(:_unmemoized_mime_type).arity
+ if args.length == args_length + 1 && # if args.length == args_length + 1 &&
+ (args.last == true || args.last == :reload) # (args.last == true || args.last == :reload)
+ reload = args.pop # reload = args.pop
+ end # end
#
if defined?(#{memoized_ivar}) && #{memoized_ivar} # if defined?(@_memoized_mime_type) && @_memoized_mime_type
if !reload && #{memoized_ivar}.has_key?(args) # if !reload && @_memoized_mime_type.has_key?(args)
diff --git a/activesupport/lib/active_support/ordered_options.rb b/activesupport/lib/active_support/ordered_options.rb
index 8d8e6ebc58..bf81567d22 100644
--- a/activesupport/lib/active_support/ordered_options.rb
+++ b/activesupport/lib/active_support/ordered_options.rb
@@ -36,6 +36,10 @@ module ActiveSupport #:nodoc:
self[name]
end
end
+
+ def respond_to?(name)
+ true
+ end
end
class InheritableOptions < OrderedOptions
diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb
index 05da50e150..3864b1f5a6 100644
--- a/activesupport/lib/active_support/testing/assertions.rb
+++ b/activesupport/lib/active_support/testing/assertions.rb
@@ -68,7 +68,7 @@ module ActiveSupport
#
# A error message can be specified.
#
- # assert_no_difference 'Article.count', "An Article should not be destroyed" do
+ # assert_no_difference 'Article.count', "An Article should not be created" do
# post :create, :article => invalid_attributes
# end
def assert_no_difference(expression, message = nil, &block)
diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb
index 02c19448fd..dd23f8d82d 100644
--- a/activesupport/lib/active_support/testing/performance.rb
+++ b/activesupport/lib/active_support/testing/performance.rb
@@ -9,7 +9,7 @@ module ActiveSupport
module Testing
module Performance
extend ActiveSupport::Concern
-
+
included do
superclass_delegating_accessor :profile_options
self.profile_options = {}
@@ -20,7 +20,7 @@ module ActiveSupport
include ForClassicTestUnit
end
end
-
+
# each implementation should define metrics and freeze the defaults
DEFAULTS =
if ARGV.include?('--benchmark') # HAX for rake test
@@ -32,7 +32,7 @@ module ActiveSupport
:output => 'tmp/performance',
:benchmark => false }
end
-
+
def full_profile_options
DEFAULTS.merge(profile_options)
end
@@ -40,7 +40,7 @@ module ActiveSupport
def full_test_name
"#{self.class.name}##{method_name}"
end
-
+
module ForMiniTest
def run(runner)
@runner = runner
@@ -53,7 +53,7 @@ module ActiveSupport
end
end
end
-
+
return
end
@@ -122,7 +122,7 @@ module ActiveSupport
protected
# overridden by each implementation
def run_gc; end
-
+
def run_warmup
run_gc
@@ -132,7 +132,7 @@ module ActiveSupport
run_gc
end
-
+
def run_profile(metric)
klass = full_profile_options[:benchmark] ? Benchmarker : Profiler
performer = klass.new(self, metric)
@@ -163,7 +163,7 @@ module ActiveSupport
"#{full_profile_options[:output]}/#{full_test_name}_#{@metric.name}"
end
end
-
+
# overridden by each implementation
class Profiler < Performer
def time_with_block
@@ -171,7 +171,7 @@ module ActiveSupport
yield
Time.now - before
end
-
+
def run; end
def record; end
end
@@ -181,10 +181,10 @@ module ActiveSupport
super
@supported = @metric.respond_to?('measure')
end
-
+
def run
return unless @supported
-
+
full_profile_options[:runs].to_i.times { run_test(@metric, :benchmark) }
@total = @metric.total
end
@@ -237,7 +237,7 @@ module ActiveSupport
"#{super}.csv"
end
end
-
+
module Metrics
def self.[](name)
const_get(name.to_s.camelize)
@@ -247,7 +247,7 @@ module ActiveSupport
class Base
include ActionView::Helpers::NumberHelper
-
+
attr_reader :total
def initialize
@@ -265,15 +265,15 @@ module ActiveSupport
@total += (measure - before)
end
end
-
+
# overridden by each implementation
def profile; end
-
+
protected
# overridden by each implementation
def with_gc_stats; end
end
-
+
class Time < Base
def measure
::Time.now.to_f
@@ -287,19 +287,19 @@ module ActiveSupport
end
end
end
-
+
class Amount < Base
def format(measurement)
number_with_delimiter(measurement.floor)
end
end
-
+
class DigitalInformationUnit < Base
def format(measurement)
number_to_human_size(measurement, :precision => 2)
end
end
-
+
# each implementation provides its own metrics like ProcessTime, Memory or GcRuns
end
end
diff --git a/activesupport/lib/active_support/testing/performance/jruby.rb b/activesupport/lib/active_support/testing/performance/jruby.rb
index 326904bbac..b347539f13 100644
--- a/activesupport/lib/active_support/testing/performance/jruby.rb
+++ b/activesupport/lib/active_support/testing/performance/jruby.rb
@@ -1,5 +1,5 @@
require 'jruby/profiler'
-require 'java'
+require 'java'
java_import java.lang.management.ManagementFactory
module ActiveSupport
@@ -12,21 +12,21 @@ module ActiveSupport
{ :metrics => [:wall_time],
:formats => [:flat, :graph] }
end).freeze
-
+
protected
def run_gc
ManagementFactory.memory_mx_bean.gc
- end
+ end
class Profiler < Performer
def initialize(*args)
super
@supported = @metric.is_a?(Metrics::WallTime)
end
-
+
def run
return unless @supported
-
+
@total = time_with_block do
@data = JRuby::Profiler.profile do
full_profile_options[:runs].to_i.times { run_test(@metric, :profile) }
@@ -36,7 +36,7 @@ module ActiveSupport
def record
return unless @supported
-
+
klasses = full_profile_options[:formats].map { |f| JRuby::Profiler.const_get("#{f.to_s.camelize}ProfilePrinter") }.compact
klasses.each do |klass|
@@ -61,7 +61,7 @@ module ActiveSupport
end
end
- module Metrics
+ module Metrics
class Base
def profile
yield
@@ -85,7 +85,7 @@ module ActiveSupport
ManagementFactory.thread_mx_bean.get_current_thread_cpu_time / 1000 / 1000 / 1000.0 # seconds
end
end
-
+
class UserTime < Time
def measure
ManagementFactory.thread_mx_bean.get_current_thread_user_time / 1000 / 1000 / 1000.0 # seconds
@@ -97,7 +97,7 @@ module ActiveSupport
ManagementFactory.memory_mx_bean.non_heap_memory_usage.used + ManagementFactory.memory_mx_bean.heap_memory_usage.used
end
end
-
+
class GcRuns < Amount
def measure
ManagementFactory.garbage_collector_mx_beans.inject(0) { |total_runs, current_gc| total_runs += current_gc.collection_count }
diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb
index 198d235548..d9ebfbe352 100644
--- a/activesupport/lib/active_support/testing/performance/rubinius.rb
+++ b/activesupport/lib/active_support/testing/performance/rubinius.rb
@@ -10,12 +10,12 @@ module ActiveSupport
{ :metrics => [:wall_time],
:formats => [:flat, :graph] }
end).freeze
-
+
protected
def run_gc
GC.run(true)
end
-
+
class Performer; end
class Profiler < Performer
@@ -23,35 +23,35 @@ module ActiveSupport
super
@supported = @metric.is_a?(Metrics::WallTime)
end
-
+
def run
return unless @supported
-
+
@profiler = Rubinius::Profiler::Instrumenter.new
-
+
@total = time_with_block do
@profiler.profile(false) do
full_profile_options[:runs].to_i.times { run_test(@metric, :profile) }
end
end
end
-
+
def record
return unless @supported
-
+
if(full_profile_options[:formats].include?(:flat))
create_path_and_open_file(:flat) do |file|
@profiler.show(file)
end
end
-
+
if(full_profile_options[:formats].include?(:graph))
create_path_and_open_file(:graph) do |file|
@profiler.show(file)
end
end
end
-
+
protected
def create_path_and_open_file(printer_name)
fname = "#{output_filename}_#{printer_name}.txt"
@@ -62,10 +62,10 @@ module ActiveSupport
end
end
- module Metrics
+ module Metrics
class Base
attr_reader :loopback
-
+
def profile
yield
end
diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb
index b29ec6719c..7d6d047ef6 100644
--- a/activesupport/lib/active_support/testing/performance/ruby.rb
+++ b/activesupport/lib/active_support/testing/performance/ruby.rb
@@ -16,7 +16,7 @@ module ActiveSupport
:metrics => [:process_time, :memory, :objects],
:formats => [:flat, :graph_html, :call_tree, :call_stack] }
end).freeze
-
+
protected
def run_gc
GC.start
@@ -77,7 +77,7 @@ module ActiveSupport
def measure_mode
self.class::Mode
end
-
+
def profile
RubyProf.resume
yield
@@ -91,7 +91,7 @@ module ActiveSupport
yield
end
end
-
+
class ProcessTime < Time
Mode = RubyProf::PROCESS_TIME if RubyProf.const_defined?(:PROCESS_TIME)
diff --git a/activesupport/lib/active_support/testing/performance/ruby/mri.rb b/activesupport/lib/active_support/testing/performance/ruby/mri.rb
index 86e650050b..142279dd6e 100644
--- a/activesupport/lib/active_support/testing/performance/ruby/mri.rb
+++ b/activesupport/lib/active_support/testing/performance/ruby/mri.rb
@@ -15,7 +15,7 @@ module ActiveSupport
end
end
end
-
+
class Memory < DigitalInformationUnit
# Ruby 1.8 + ruby-prof wrapper
if RubyProf.respond_to?(:measure_memory)
@@ -24,7 +24,7 @@ module ActiveSupport
end
end
end
-
+
class Objects < Amount
# Ruby 1.8 + ruby-prof wrapper
if RubyProf.respond_to?(:measure_allocations)
@@ -33,7 +33,7 @@ module ActiveSupport
end
end
end
-
+
class GcRuns < Amount
# Ruby 1.8 + ruby-prof wrapper
if RubyProf.respond_to?(:measure_gc_runs)
@@ -42,7 +42,7 @@ module ActiveSupport
end
end
end
-
+
class GcTime < Time
# Ruby 1.8 + ruby-prof wrapper
if RubyProf.respond_to?(:measure_gc_time)
@@ -55,5 +55,3 @@ module ActiveSupport
end
end
end
-
-
diff --git a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb
index 62095a8fe4..7873262331 100644
--- a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb
+++ b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb
@@ -15,7 +15,7 @@ module ActiveSupport
end
end
end
-
+
class Memory < DigitalInformationUnit
# Ruby 1.9 + GCdata patch
if GC.respond_to?(:malloc_allocated_size)
@@ -24,7 +24,7 @@ module ActiveSupport
end
end
end
-
+
class Objects < Amount
# Ruby 1.9 + GCdata patch
if GC.respond_to?(:malloc_allocations)
@@ -33,7 +33,7 @@ module ActiveSupport
end
end
end
-
+
class GcRuns < Amount
# Ruby 1.9
if GC.respond_to?(:count)
@@ -42,7 +42,7 @@ module ActiveSupport
end
end
end
-
+
class GcTime < Time
# Ruby 1.9 with GC::Profiler
if defined?(GC::Profiler) && GC::Profiler.respond_to?(:total_time)
diff --git a/activesupport/lib/active_support/version.rb b/activesupport/lib/active_support/version.rb
index e135872bf6..bd8e7f907a 100644
--- a/activesupport/lib/active_support/version.rb
+++ b/activesupport/lib/active_support/version.rb
@@ -1,9 +1,9 @@
module ActiveSupport
module VERSION #:nodoc:
MAJOR = 3
- MINOR = 1
+ MINOR = 2
TINY = 0
- PRE = "rc1"
+ PRE = "beta"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
diff --git a/activesupport/test/configurable_test.rb b/activesupport/test/configurable_test.rb
index c6d8191298..2e5ea2c360 100644
--- a/activesupport/test/configurable_test.rb
+++ b/activesupport/test/configurable_test.rb
@@ -58,16 +58,26 @@ class ConfigurableActiveSupport < ActiveSupport::TestCase
child = Class.new(parent)
parent.config.bar = :foo
- assert !parent.config.respond_to?(:bar)
- assert !child.config.respond_to?(:bar)
- assert !child.new.config.respond_to?(:bar)
+ assert_method_not_defined parent.config, :bar
+ assert_method_not_defined child.config, :bar
+ assert_method_not_defined child.new.config, :bar
parent.config.compile_methods!
assert_equal :foo, parent.config.bar
assert_equal :foo, child.new.config.bar
- assert_respond_to parent.config, :bar
- assert_respond_to child.config, :bar
- assert_respond_to child.new.config, :bar
+ assert_method_defined parent.config, :bar
+ assert_method_defined child.config, :bar
+ assert_method_defined child.new.config, :bar
+ end
+
+ def assert_method_defined(object, method)
+ methods = object.public_methods.map(&:to_s)
+ assert methods.include?(method.to_s), "Expected #{methods.inspect} to include #{method.to_s.inspect}"
+ end
+
+ def assert_method_not_defined(object, method)
+ methods = object.public_methods.map(&:to_s)
+ assert !methods.include?(method.to_s), "Expected #{methods.inspect} to not include #{method.to_s.inspect}"
end
end
diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb
index 0e5407bc35..e532010b18 100644
--- a/activesupport/test/core_ext/array_ext_test.rb
+++ b/activesupport/test/core_ext/array_ext_test.rb
@@ -456,8 +456,9 @@ class ArrayWrapperTests < Test::Unit::TestCase
assert_equal [o], Array.wrap(o)
end
- def test_wrap_returns_nil_if_to_ary_returns_nil
- assert_nil Array.wrap(NilToAry.new)
+ def test_wrap_returns_wrapped_if_to_ary_returns_nil
+ o = NilToAry.new
+ assert_equal [o], Array.wrap(o)
end
def test_wrap_does_not_complain_if_to_ary_does_not_return_an_array
diff --git a/activesupport/test/core_ext/class/attribute_accessor_test.rb b/activesupport/test/core_ext/class/attribute_accessor_test.rb
index 456f4b7948..6b50f8db37 100644
--- a/activesupport/test/core_ext/class/attribute_accessor_test.rb
+++ b/activesupport/test/core_ext/class/attribute_accessor_test.rb
@@ -5,8 +5,9 @@ class ClassAttributeAccessorTest < Test::Unit::TestCase
def setup
@class = Class.new do
cattr_accessor :foo
- cattr_accessor :bar, :instance_writer => false
- cattr_reader :shaq, :instance_reader => false
+ cattr_accessor :bar, :instance_writer => false
+ cattr_reader :shaq, :instance_reader => false
+ cattr_accessor :camp, :instance_accessor => false
end
@object = @class.new
end
@@ -35,4 +36,10 @@ class ClassAttributeAccessorTest < Test::Unit::TestCase
assert_respond_to @class, :shaq
assert !@object.respond_to?(:shaq)
end
+
+ def test_should_not_create_instance_accessors
+ assert_respond_to @class, :camp
+ assert !@object.respond_to?(:camp)
+ assert !@object.respond_to?(:camp=)
+ end
end
diff --git a/activesupport/test/core_ext/class/attribute_test.rb b/activesupport/test/core_ext/class/attribute_test.rb
index d58b60482b..e290a6e012 100644
--- a/activesupport/test/core_ext/class/attribute_test.rb
+++ b/activesupport/test/core_ext/class/attribute_test.rb
@@ -60,6 +60,12 @@ class ClassAttributeTest < ActiveSupport::TestCase
assert_raise(NoMethodError) { object.setting = 'boom' }
end
+ test 'disabling instance reader' do
+ object = Class.new { class_attribute :setting, :instance_reader => false }.new
+ assert_raise(NoMethodError) { object.setting }
+ assert_raise(NoMethodError) { object.setting? }
+ end
+
test 'works well with singleton classes' do
object = @klass.new
object.singleton_class.setting = 'foo'
diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb
index d81693209f..b4f848cd44 100644
--- a/activesupport/test/core_ext/date_ext_test.rb
+++ b/activesupport/test/core_ext/date_ext_test.rb
@@ -454,4 +454,10 @@ class DateExtBehaviorTest < Test::Unit::TestCase
Date.today.freeze.inspect
end
end
+
+ def test_can_freeze_twice
+ assert_nothing_raised do
+ Date.today.freeze.freeze
+ end
+ end
end
diff --git a/activesupport/test/core_ext/module/attribute_accessor_test.rb b/activesupport/test/core_ext/module/attribute_accessor_test.rb
index 118fb070a0..29889b51e0 100644
--- a/activesupport/test/core_ext/module/attribute_accessor_test.rb
+++ b/activesupport/test/core_ext/module/attribute_accessor_test.rb
@@ -7,6 +7,7 @@ class ModuleAttributeAccessorTest < Test::Unit::TestCase
mattr_accessor :foo
mattr_accessor :bar, :instance_writer => false
mattr_reader :shaq, :instance_reader => false
+ mattr_accessor :camp, :instance_accessor => false
end
@class = Class.new
@class.instance_eval { include m }
@@ -37,4 +38,10 @@ class ModuleAttributeAccessorTest < Test::Unit::TestCase
assert_respond_to @module, :shaq
assert !@object.respond_to?(:shaq)
end
+
+ def test_should_not_create_instance_accessors
+ assert_respond_to @module, :camp
+ assert !@object.respond_to?(:camp)
+ assert !@object.respond_to?(:camp=)
+ end
end
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index 0fd0cb8ac7..4000cc913a 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -252,7 +252,7 @@ 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?
@@ -354,6 +354,10 @@ class OutputSafetyTest < ActiveSupport::TestCase
test "A fixnum is safe by default" do
assert 5.html_safe?
end
+
+ test "a float is safe by default" do
+ assert 5.7.html_safe?
+ end
test "An object is unsafe by default" do
assert !@object.html_safe?
@@ -452,6 +456,12 @@ class OutputSafetyTest < ActiveSupport::TestCase
assert !'ruby'.encoding_aware?
end
end
+
+ test "call to_param returns a normal string" do
+ string = @string.html_safe
+ assert string.html_safe?
+ assert !string.to_param.html_safe?
+ end
end
class StringExcludeTest < ActiveSupport::TestCase
diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb
index 44e02109b1..c4c4381957 100644
--- a/activesupport/test/core_ext/time_ext_test.rb
+++ b/activesupport/test/core_ext/time_ext_test.rb
@@ -767,6 +767,26 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase
assert_equal false, Time === DateTime.civil(2000)
end
+ def test_all_day
+ assert_equal Time.local(2011,6,7,0,0,0)..Time.local(2011,6,7,23,59,59,999999.999), Time.local(2011,6,7,10,10,10).all_day
+ end
+
+ def test_all_week
+ assert_equal Time.local(2011,6,6,0,0,0)..Time.local(2011,6,12,23,59,59,999999.999), Time.local(2011,6,7,10,10,10).all_week
+ end
+
+ def test_all_month
+ assert_equal Time.local(2011,6,1,0,0,0)..Time.local(2011,6,30,23,59,59,999999.999), Time.local(2011,6,7,10,10,10).all_month
+ end
+
+ def test_all_quarter
+ assert_equal Time.local(2011,4,1,0,0,0)..Time.local(2011,6,30,23,59,59,999999.999), Time.local(2011,6,7,10,10,10).all_quarter
+ end
+
+ def test_all_year
+ assert_equal Time.local(2011,1,1,0,0,0)..Time.local(2011,12,31,23,59,59,999999.999), Time.local(2011,6,7,10,10,10).all_year
+ end
+
protected
def with_env_tz(new_tz = 'US/Eastern')
old_tz, ENV['TZ'] = ENV['TZ'], new_tz
diff --git a/activesupport/test/flush_cache_on_private_memoization_test.rb b/activesupport/test/flush_cache_on_private_memoization_test.rb
index a7db96eb71..20768b777a 100644
--- a/activesupport/test/flush_cache_on_private_memoization_test.rb
+++ b/activesupport/test/flush_cache_on_private_memoization_test.rb
@@ -2,7 +2,9 @@ require 'abstract_unit'
require 'test/unit'
class FlashCacheOnPrivateMemoizationTest < Test::Unit::TestCase
- extend ActiveSupport::Memoizable
+ ActiveSupport::Deprecation.silence do
+ extend ActiveSupport::Memoizable
+ end
def test_public
assert_method_unmemoizable :pub
diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb
index 95f18126d4..b9e299af75 100644
--- a/activesupport/test/inflector_test.rb
+++ b/activesupport/test/inflector_test.rb
@@ -94,6 +94,88 @@ class InflectorTest < Test::Unit::TestCase
assert_equal('capital', ActiveSupport::Inflector.camelize('Capital', false))
end
+ def test_camelize_with_underscores
+ assert_equal("CamelCase", ActiveSupport::Inflector.camelize('Camel_Case'))
+ end
+
+ def test_acronyms
+ ActiveSupport::Inflector.inflections do |inflect|
+ inflect.acronym("API")
+ inflect.acronym("HTML")
+ inflect.acronym("HTTP")
+ inflect.acronym("RESTful")
+ inflect.acronym("W3C")
+ inflect.acronym("PhD")
+ inflect.acronym("RoR")
+ inflect.acronym("SSL")
+ end
+
+ # camelize underscore humanize titleize
+ [
+ ["API", "api", "API", "API"],
+ ["APIController", "api_controller", "API controller", "API Controller"],
+ ["Nokogiri::HTML", "nokogiri/html", "Nokogiri/HTML", "Nokogiri/HTML"],
+ ["HTTPAPI", "http_api", "HTTP API", "HTTP API"],
+ ["HTTP::Get", "http/get", "HTTP/get", "HTTP/Get"],
+ ["SSLError", "ssl_error", "SSL error", "SSL Error"],
+ ["RESTful", "restful", "RESTful", "RESTful"],
+ ["RESTfulController", "restful_controller", "RESTful controller", "RESTful Controller"],
+ ["IHeartW3C", "i_heart_w3c", "I heart W3C", "I Heart W3C"],
+ ["PhDRequired", "phd_required", "PhD required", "PhD Required"],
+ ["IRoRU", "i_ror_u", "I RoR u", "I RoR U"],
+ ["RESTfulHTTPAPI", "restful_http_api", "RESTful HTTP API", "RESTful HTTP API"],
+
+ # misdirection
+ ["Capistrano", "capistrano", "Capistrano", "Capistrano"],
+ ["CapiController", "capi_controller", "Capi controller", "Capi Controller"],
+ ["HttpsApis", "https_apis", "Https apis", "Https Apis"],
+ ["Html5", "html5", "Html5", "Html5"],
+ ["Restfully", "restfully", "Restfully", "Restfully"],
+ ["RoRails", "ro_rails", "Ro rails", "Ro Rails"]
+ ].each do |camel, under, human, title|
+ assert_equal(camel, ActiveSupport::Inflector.camelize(under))
+ assert_equal(camel, ActiveSupport::Inflector.camelize(camel))
+ assert_equal(under, ActiveSupport::Inflector.underscore(under))
+ assert_equal(under, ActiveSupport::Inflector.underscore(camel))
+ assert_equal(title, ActiveSupport::Inflector.titleize(under))
+ assert_equal(title, ActiveSupport::Inflector.titleize(camel))
+ assert_equal(human, ActiveSupport::Inflector.humanize(under))
+ end
+ end
+
+ def test_acronym_override
+ ActiveSupport::Inflector.inflections do |inflect|
+ inflect.acronym("API")
+ inflect.acronym("LegacyApi")
+ end
+
+ assert_equal("LegacyApi", ActiveSupport::Inflector.camelize("legacyapi"))
+ assert_equal("LegacyAPI", ActiveSupport::Inflector.camelize("legacy_api"))
+ assert_equal("SomeLegacyApi", ActiveSupport::Inflector.camelize("some_legacyapi"))
+ assert_equal("Nonlegacyapi", ActiveSupport::Inflector.camelize("nonlegacyapi"))
+ end
+
+ def test_acronyms_camelize_lower
+ ActiveSupport::Inflector.inflections do |inflect|
+ inflect.acronym("API")
+ inflect.acronym("HTML")
+ end
+
+ assert_equal("htmlAPI", ActiveSupport::Inflector.camelize("html_api", false))
+ assert_equal("htmlAPI", ActiveSupport::Inflector.camelize("htmlAPI", false))
+ assert_equal("htmlAPI", ActiveSupport::Inflector.camelize("HTMLAPI", false))
+ end
+
+ def test_underscore_acronym_sequence
+ ActiveSupport::Inflector.inflections do |inflect|
+ inflect.acronym("API")
+ inflect.acronym("HTML5")
+ inflect.acronym("HTML")
+ end
+
+ assert_equal("html5_html_api", ActiveSupport::Inflector.underscore("HTML5HTMLAPI"))
+ end
+
def test_underscore
CamelToUnderscore.each do |camel, underscore|
assert_equal(underscore, ActiveSupport::Inflector.underscore(camel))
@@ -148,8 +230,8 @@ class InflectorTest < Test::Unit::TestCase
end
def test_parameterize_with_custom_separator
- StringToParameterized.each do |some_string, parameterized_string|
- assert_equal(parameterized_string.gsub('-', '_'), ActiveSupport::Inflector.parameterize(some_string, '_'))
+ StringToParameterizeWithUnderscore.each do |some_string, parameterized_string|
+ assert_equal(parameterized_string, ActiveSupport::Inflector.parameterize(some_string, '_'))
end
end
diff --git a/activesupport/test/inflector_test_cases.rb b/activesupport/test/inflector_test_cases.rb
index ec9d92794c..0cb1f70657 100644
--- a/activesupport/test/inflector_test_cases.rb
+++ b/activesupport/test/inflector_test_cases.rb
@@ -168,6 +168,7 @@ module InflectorTestCases
StringToParameterizeWithNoSeparator = {
"Donald E. Knuth" => "donaldeknuth",
+ "With-some-dashes" => "with-some-dashes",
"Random text with *(bad)* characters" => "randomtextwithbadcharacters",
"Trailing bad characters!@#" => "trailingbadcharacters",
"!@#Leading bad characters" => "leadingbadcharacters",
@@ -179,6 +180,8 @@ module InflectorTestCases
StringToParameterizeWithUnderscore = {
"Donald E. Knuth" => "donald_e_knuth",
"Random text with *(bad)* characters" => "random_text_with_bad_characters",
+ "With-some-dashes" => "with-some-dashes",
+ "Retain_underscore" => "retain_underscore",
"Trailing bad characters!@#" => "trailing_bad_characters",
"!@#Leading bad characters" => "leading_bad_characters",
"Squeeze separators" => "squeeze_separators",
diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb
index bceac1315b..e333b9a78c 100644
--- a/activesupport/test/memoizable_test.rb
+++ b/activesupport/test/memoizable_test.rb
@@ -2,7 +2,9 @@ require 'abstract_unit'
class MemoizableTest < ActiveSupport::TestCase
class Person
- extend ActiveSupport::Memoizable
+ ActiveSupport::Deprecation.silence do
+ extend ActiveSupport::Memoizable
+ end
attr_reader :name_calls, :age_calls, :is_developer_calls, :name_query_calls
@@ -65,7 +67,9 @@ class MemoizableTest < ActiveSupport::TestCase
end
module Rates
- extend ActiveSupport::Memoizable
+ ActiveSupport::Deprecation.silence do
+ extend ActiveSupport::Memoizable
+ end
attr_reader :sales_tax_calls
def sales_tax(price)
@@ -77,7 +81,9 @@ class MemoizableTest < ActiveSupport::TestCase
end
class Calculator
- extend ActiveSupport::Memoizable
+ ActiveSupport::Deprecation.silence do
+ extend ActiveSupport::Memoizable
+ end
include Rates
attr_reader :fib_calls
@@ -96,6 +102,15 @@ class MemoizableTest < ActiveSupport::TestCase
end
memoize :fib
+ def add_or_subtract(i, j, add)
+ if add
+ i + j
+ else
+ i - j
+ end
+ end
+ memoize :add_or_subtract
+
def counter
@count ||= 0
@count += 1
@@ -199,9 +214,16 @@ class MemoizableTest < ActiveSupport::TestCase
assert_equal 13, @calculator.fib_calls
end
+ def test_memoization_with_boolean_arg
+ assert_equal 4, @calculator.add_or_subtract(2, 2, true)
+ assert_equal 2, @calculator.add_or_subtract(4, 2, false)
+ end
+
def test_object_memoization
[Company.new, Company.new, Company.new].each do |company|
- company.extend ActiveSupport::Memoizable
+ ActiveSupport::Deprecation.silence do
+ company.extend ActiveSupport::Memoizable
+ end
company.memoize :name
assert_equal "37signals", company.name
@@ -235,11 +257,15 @@ class MemoizableTest < ActiveSupport::TestCase
def test_double_memoization
assert_raise(RuntimeError) { Person.memoize :name }
person = Person.new
- person.extend ActiveSupport::Memoizable
+ ActiveSupport::Deprecation.silence do
+ person.extend ActiveSupport::Memoizable
+ end
assert_raise(RuntimeError) { person.memoize :name }
company = Company.new
- company.extend ActiveSupport::Memoizable
+ ActiveSupport::Deprecation.silence do
+ company.extend ActiveSupport::Memoizable
+ end
company.memoize :name
assert_raise(RuntimeError) { company.memoize :name }
end
diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb
index a4e2acbb32..46bc0d7a34 100644
--- a/activesupport/test/safe_buffer_test.rb
+++ b/activesupport/test/safe_buffer_test.rb
@@ -4,6 +4,7 @@ begin
rescue LoadError
end
+require 'active_support/core_ext/string/inflections'
require 'yaml'
class SafeBufferTest < ActiveSupport::TestCase
@@ -45,7 +46,7 @@ class SafeBufferTest < ActiveSupport::TestCase
assert_equal ActiveSupport::SafeBuffer, new_buffer.class
end
- def test_to_yaml
+ test "Should be converted to_yaml" do
str = 'hello!'
buf = ActiveSupport::SafeBuffer.new str
yaml = buf.to_yaml
@@ -54,10 +55,57 @@ class SafeBufferTest < ActiveSupport::TestCase
assert_equal 'hello!', YAML.load(yaml)
end
- def test_nested
+ test "Should work in nested to_yaml conversion" do
str = 'hello!'
data = { 'str' => ActiveSupport::SafeBuffer.new(str) }
yaml = YAML.dump data
assert_equal({'str' => str}, YAML.load(yaml))
end
+
+ test "Should work with underscore" do
+ str = "MyTest".html_safe.underscore
+ assert_equal "my_test", str
+ end
+
+ test "Should not return safe buffer from gsub" do
+ altered_buffer = @buffer.gsub('', 'asdf')
+ assert_equal 'asdf', altered_buffer
+ assert !altered_buffer.html_safe?
+ end
+
+ test "Should not return safe buffer from gsub!" do
+ @buffer.gsub!('', 'asdf')
+ assert_equal 'asdf', @buffer
+ assert !@buffer.html_safe?
+ end
+
+ test "Should escape dirty buffers on add" do
+ dirty = @buffer
+ clean = "hello".html_safe
+ @buffer.gsub!('', '<>')
+ assert_equal "hello&lt;&gt;", clean + @buffer
+ end
+
+ test "Should concat as a normal string when dirty" do
+ dirty = @buffer
+ clean = "hello".html_safe
+ @buffer.gsub!('', '<>')
+ assert_equal "<>hello", @buffer + clean
+ end
+
+ test "Should preserve dirty? status on copy" do
+ @buffer.gsub!('', '<>')
+ assert !@buffer.dup.html_safe?
+ end
+
+ test "Should raise an error when safe_concat is called on dirty buffers" do
+ @buffer.gsub!('', '<>')
+ assert_raise ActiveSupport::SafeBuffer::SafeConcatError do
+ @buffer.safe_concat "BUSTED"
+ end
+ end
+
+ test "should not fail if the returned object is not a string" do
+ assert_kind_of NilClass, @buffer.slice("chipchop")
+ end
end
diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb
index ee5a20c789..5bd995aa32 100644
--- a/activesupport/test/test_test.rb
+++ b/activesupport/test/test_test.rb
@@ -50,7 +50,7 @@ class AssertDifferenceTest < ActiveSupport::TestCase
def test_expression_is_evaluated_in_the_appropriate_scope
silence_warnings do
- local_scope = 'foo'
+ local_scope = local_scope = 'foo'
assert_difference('local_scope; @object.num') { @object.increment }
end
end
diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb
index 49cefc6e82..3575175517 100644
--- a/activesupport/test/time_zone_test.rb
+++ b/activesupport/test/time_zone_test.rb
@@ -224,9 +224,9 @@ class TimeZoneTest < Test::Unit::TestCase
end
def test_formatted_offset_positive
- zone = ActiveSupport::TimeZone['Moscow']
- assert_equal "+03:00", zone.formatted_offset
- assert_equal "+0300", zone.formatted_offset(false)
+ zone = ActiveSupport::TimeZone['New Delhi']
+ assert_equal "+05:30", zone.formatted_offset
+ assert_equal "+0530", zone.formatted_offset(false)
end
def test_formatted_offset_negative
@@ -257,7 +257,7 @@ class TimeZoneTest < Test::Unit::TestCase
end
def test_to_s
- assert_equal "(GMT+03:00) Moscow", ActiveSupport::TimeZone['Moscow'].to_s
+ assert_equal "(GMT+05:30) New Delhi", ActiveSupport::TimeZone['New Delhi'].to_s
end
def test_all_sorted