diff options
Diffstat (limited to 'activesupport')
26 files changed, 315 insertions, 168 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 29109ea64d..09ec4ed618 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,7 @@ ## Rails 4.0.0 (unreleased) ## +* AS::Callbacks: deprecate `:rescuable` option. *Bogdan Gusiev* + * Adds Integer#ordinal to get the ordinal suffix string of an integer. *Tim Gildea* * AS::Callbacks: `:per_key` option is no longer supported @@ -24,9 +26,22 @@ * Unicode database updated to 6.1.0. + +## Rails 3.2.1 (January 26, 2012) ## + +* Documentation fixes and improvements. + +* Update time zone offset information. *Ravil Bayramgalin* + +* The deprecated `ActiveSupport::Base64.decode64` calls `::Base64.decode64` + now. *Jonathan Viney* + +* Fixes uninitialized constant `ActiveSupport::TaggedLogging::ERROR`. *kennyj* + + ## Rails 3.2.0 (January 20, 2012) ## -* Add ActiveSupport::Cache::NullStore for use in development and testing. *Brian Durand* +* ActiveSupport::Base64 is deprecated in favor of ::Base64. *Sergey Nartimov* * Module#synchronize is deprecated with no replacement. Please use `monitor` from ruby's standard library. @@ -95,6 +110,37 @@ * ActiveSupport::BufferedLogger#flush is deprecated. Set sync on your filehandle, or tune your filesystem. + +## Rails 3.1.4 (March 1, 2012) ## + +* No changes + + +## Rails 3.1.3 (November 20, 2011) ## + +* No changes + + +## Rails 3.1.2 (November 18, 2011) ## + +* No changes + + +## Rails 3.1.1 (October 7, 2011) ## + +* ruby193: String#prepend is also unsafe *Akira Matsuda* + +* Fix obviously breakage of Time.=== for Time subclasses *jeremyevans* + +* Added fix so that file store does not raise an exception when cache dir does + not exist yet. This can happen if a delete_matched is called before anything + is saved in the cache. *Philippe Huibonhoa* + +* Fixed performance issue where TimeZone lookups would require tzinfo each time *Tim Lucas* + +* ActiveSupport::OrderedHash is now marked as extractable when using Array#extract_options! *Prem Sichanugrist* + + ## Rails 3.1.0 (August 30, 2011) ## * ActiveSupport::Dependencies#load and ActiveSupport::Dependencies#require now @@ -137,12 +183,38 @@ * JSON decoding now uses the multi_json gem which also vendors a json engine called OkJson. The yaml backend has been removed in favor of OkJson as a default engine for 1.8.x, while the built in 1.9.x json implementation will be used by default. *Josh Kalderimis* +## Rails 3.0.12 (March 1, 2012) ## + +* No changes. + + +## Rails 3.0.11 (November 18, 2011) ## + +* No changes. + + +## Rails 3.0.10 (August 16, 2011) ## + +* Delayed backtrace scrubbing in `load_missing_constant` until we actually + raise the exception + + +## Rails 3.0.9 (June 16, 2011) ## + +* No changes. + + +## Rails 3.0.8 (June 7, 2011) ## + +* No changes. + + ## Rails 3.0.7 (April 18, 2011) ## * Hash.from_xml no longer loses attributes on tags containing only whitespace *André Arko* -* Rails 3.0.6 (April 5, 2011) +## Rails 3.0.6 (April 5, 2011) ## * No changes. diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 26e737e917..d7408eff9f 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -382,11 +382,7 @@ module ActiveSupport options = merged_options(options) instrument(:exist?, name) do |payload| entry = read_entry(namespaced_key(name, options), options) - if entry && !entry.expired? - true - else - false - end + entry && !entry.expired? end end diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index 9460532af0..b7712a4a15 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -143,7 +143,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 = path[cache_path.to_s.size..-1].split(File::SEPARATOR, 4).last Rack::Utils.unescape(fname) end diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb index e38a8387b4..2e1ccb72d8 100644 --- a/activesupport/lib/active_support/cache/mem_cache_store.rb +++ b/activesupport/lib/active_support/cache/mem_cache_store.rb @@ -6,7 +6,6 @@ rescue LoadError => e end require 'digest/md5' -require 'active_support/core_ext/string/encoding' module ActiveSupport module Cache diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 1834027e7b..6e36edee4f 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -307,7 +307,6 @@ module ActiveSupport @name = name @config = { :terminator => "false", - :rescuable => false, :scope => [ :kind ] }.merge(config) end @@ -317,35 +316,16 @@ module ActiveSupport method << "value = nil" method << "halted = false" - callbacks = yielding + callbacks = "value = yield if block_given? && !halted" reverse_each do |callback| callbacks = callback.apply(callbacks) end method << callbacks - method << "raise rescued_error if rescued_error" if config[:rescuable] method << "halted ? false : (block_given? ? value : true)" method.flatten.compact.join("\n") end - # Returns part of method that evaluates the callback block - def yielding - method = [] - if config[:rescuable] - method << "rescued_error = nil" - method << "begin" - end - - method << "value = yield if block_given? && !halted" - - if config[:rescuable] - method << "rescue Exception => e" - method << "rescued_error = e" - method << "end" - end - method.join("\n") - end - end module ClassMethods @@ -356,7 +336,7 @@ module ActiveSupport # def __run_callbacks(kind, object, &blk) #:nodoc: name = __callback_runner_name(kind) - unless object.respond_to?(name) + unless object.respond_to?(name, true) str = object.send("_#{kind}_callbacks").compile class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 def #{name}() #{str} end @@ -508,11 +488,6 @@ module ActiveSupport # if callback chain was terminated or not. # Option makes sence only when <tt>:terminator</tt> option is specified. # - # * <tt>:rescuable</tt> - By default, after filters are not executed if - # the given block or a before filter raises an error. By setting this option - # to <tt>true</tt> exception raised by given block is stored and after - # executing all the after callbacks the stored exception is raised. - # # * <tt>:scope</tt> - Indicates which methods should be executed when an object # is used as a callback. # diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb index af78226c21..6d4270f8b0 100644 --- a/activesupport/lib/active_support/core_ext/date/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date/calculations.rb @@ -182,6 +182,13 @@ class Date result = (self - 7).beginning_of_week + DAYS_INTO_WEEK[day] self.acts_like?(:time) ? result.change(:hour => 0) : result end + alias :last_week :prev_week + + # Alias of prev_month + alias :last_month :prev_month + + # Alias of prev_year + alias :last_year :prev_year # Returns a new Date/DateTime representing the start of the given day in next week (default is :monday). def next_week(day = :monday) diff --git a/activesupport/lib/active_support/core_ext/file/atomic.rb b/activesupport/lib/active_support/core_ext/file/atomic.rb index 3645597301..fc3277f4d2 100644 --- a/activesupport/lib/active_support/core_ext/file/atomic.rb +++ b/activesupport/lib/active_support/core_ext/file/atomic.rb @@ -17,6 +17,7 @@ class File require 'fileutils' unless defined?(FileUtils) temp_file = Tempfile.new(basename(file_name), temp_dir) + temp_file.binmode yield temp_file temp_file.close diff --git a/activesupport/lib/active_support/core_ext/object/blank.rb b/activesupport/lib/active_support/core_ext/object/blank.rb index 7271671908..d67711f3b8 100644 --- a/activesupport/lib/active_support/core_ext/object/blank.rb +++ b/activesupport/lib/active_support/core_ext/object/blank.rb @@ -1,5 +1,4 @@ # encoding: utf-8 -require 'active_support/core_ext/string/encoding' class Object # An object is blank if it's false, empty, or a whitespace string. diff --git a/activesupport/lib/active_support/core_ext/range/overlaps.rb b/activesupport/lib/active_support/core_ext/range/overlaps.rb index 7df653b53f..603657c180 100644 --- a/activesupport/lib/active_support/core_ext/range/overlaps.rb +++ b/activesupport/lib/active_support/core_ext/range/overlaps.rb @@ -3,6 +3,6 @@ class Range # (1..5).overlaps?(4..6) # => true # (1..5).overlaps?(7..9) # => false def overlaps?(other) - include?(other.first) || other.include?(first) + cover?(other.first) || other.cover?(first) end end diff --git a/activesupport/lib/active_support/core_ext/string.rb b/activesupport/lib/active_support/core_ext/string.rb index 72522d395c..ab49af55bf 100644 --- a/activesupport/lib/active_support/core_ext/string.rb +++ b/activesupport/lib/active_support/core_ext/string.rb @@ -9,6 +9,5 @@ require 'active_support/core_ext/string/behavior' require 'active_support/core_ext/string/interpolation' require 'active_support/core_ext/string/output_safety' require 'active_support/core_ext/string/exclude' -require 'active_support/core_ext/string/encoding' require 'active_support/core_ext/string/strip' require 'active_support/core_ext/string/inquiry' diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index dd780da157..4903687b73 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -103,29 +103,39 @@ module ActiveSupport #:nodoc: end end - def[](*args) - new_safe_buffer = super - new_safe_buffer.instance_eval { @dirty = false } - new_safe_buffer + def [](*args) + return super if args.size < 2 + + if html_safe? + new_safe_buffer = super + new_safe_buffer.instance_eval { @html_safe = true } + new_safe_buffer + else + to_str[*args] + end end def safe_concat(value) - raise SafeConcatError if dirty? + raise SafeConcatError unless html_safe? original_concat(value) end def initialize(*) - @dirty = false + @html_safe = true super end def initialize_copy(other) super - @dirty = other.dirty? + @html_safe = other.html_safe? + end + + def clone_empty + self[0, 0] end def concat(value) - if dirty? || value.html_safe? + if !html_safe? || value.html_safe? super(value) else super(ERB::Util.h(value)) @@ -138,7 +148,7 @@ module ActiveSupport #:nodoc: end def html_safe? - !dirty? + defined?(@html_safe) && @html_safe end def to_s @@ -161,18 +171,12 @@ module ActiveSupport #:nodoc: end # end def #{unsafe_method}!(*args) # def capitalize!(*args) - @dirty = true # @dirty = true + @html_safe = false # @html_safe = false super # super end # end EOT end end - - protected - - def dirty? - @dirty - end end end diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 4f300329f5..5076697c04 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -67,7 +67,7 @@ class Time end # Returns a new Time where one or more of the elements have been changed according to the +options+ parameter. The time options - # (hour, minute, sec, usec) reset cascadingly, so if only the hour is passed, then minute, sec, and usec is set to 0. If the hour and + # (hour, min, sec, usec) reset cascadingly, so if only the hour is passed, then minute, sec, and usec is set to 0. If the hour and # minute is passed, then sec and usec is set to 0. def change(options) ::Time.send( @@ -145,6 +145,7 @@ class Time def prev_year years_ago(1) end + alias_method :last_year, :prev_year # Short-hand for years_since(1) def next_year @@ -155,6 +156,7 @@ class Time def prev_month months_ago(1) end + alias_method :last_month, :prev_month # Short-hand for months_since(1) def next_month @@ -199,6 +201,7 @@ class Time def prev_week(day = :monday) ago(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0) end + alias_method :last_week, :prev_week # Returns a new Time representing the start of the given day in next week (default is :monday). def next_week(day = :monday) diff --git a/activesupport/lib/active_support/gzip.rb b/activesupport/lib/active_support/gzip.rb index f7036315d6..420b965c87 100644 --- a/activesupport/lib/active_support/gzip.rb +++ b/activesupport/lib/active_support/gzip.rb @@ -1,6 +1,5 @@ require 'zlib' require 'stringio' -require 'active_support/core_ext/string/encoding' module ActiveSupport # A convenient wrapper for the zlib standard library that allows compression/decompression of strings with gzip. diff --git a/activesupport/lib/active_support/inflections.rb b/activesupport/lib/active_support/inflections.rb index 527cce2594..b3eb1333ca 100644 --- a/activesupport/lib/active_support/inflections.rb +++ b/activesupport/lib/active_support/inflections.rb @@ -2,7 +2,7 @@ module ActiveSupport Inflector.inflections do |inflect| inflect.plural(/$/, 's') inflect.plural(/s$/i, 's') - inflect.plural(/(ax|test)is$/i, '\1es') + inflect.plural(/^(ax|test)is$/i, '\1es') inflect.plural(/(octop|vir)us$/i, '\1i') inflect.plural(/(octop|vir)i$/i, '\1i') inflect.plural(/(alias|status)$/i, '\1es') @@ -23,10 +23,11 @@ module ActiveSupport inflect.plural(/(quiz)$/i, '\1zes') inflect.singular(/s$/i, '') + inflect.singular(/(ss)$/i, '\1') inflect.singular(/(n)ews$/i, '\1ews') inflect.singular(/([ti])a$/i, '\1um') - inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis') - inflect.singular(/(^analy)ses$/i, '\1sis') + inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '\1\2sis') + inflect.singular(/(^analy)(sis|ses)$/i, '\1sis') inflect.singular(/([^f])ves$/i, '\1fe') inflect.singular(/(hive)s$/i, '\1') inflect.singular(/(tive)s$/i, '\1') @@ -36,12 +37,13 @@ module ActiveSupport inflect.singular(/(m)ovies$/i, '\1ovie') inflect.singular(/(x|ch|ss|sh)es$/i, '\1') inflect.singular(/(m|l)ice$/i, '\1ouse') - inflect.singular(/(bus)es$/i, '\1') + inflect.singular(/(bus)(es)?$/i, '\1') inflect.singular(/(o)es$/i, '\1') inflect.singular(/(shoe)s$/i, '\1') - inflect.singular(/(cris|ax|test)es$/i, '\1is') - inflect.singular(/(octop|vir)i$/i, '\1us') - inflect.singular(/(alias|status)es$/i, '\1') + inflect.singular(/(cris|test)(is|es)$/i, '\1is') + inflect.singular(/^(a)x[ie]s$/i, '\1xis') + inflect.singular(/(octop|vir)(us|i)$/i, '\1us') + inflect.singular(/(alias|status)(es)?$/i, '\1') inflect.singular(/^(ox)en/i, '\1') inflect.singular(/(vert|ind)ices$/i, '\1ex') inflect.singular(/(matr)ices$/i, '\1ix') diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb index 90bb62f57b..13b23d627a 100644 --- a/activesupport/lib/active_support/inflector/inflections.rb +++ b/activesupport/lib/active_support/inflector/inflections.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/array/prepend_and_append' + module ActiveSupport module Inflector # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional @@ -26,6 +28,13 @@ module ActiveSupport @plurals, @singulars, @uncountables, @humans, @acronyms, @acronym_regex = [], [], [], [], {}, /(?=a)b/ end + # Private, for the test suite. + def initialize_dup(orig) + %w(plurals singulars uncountables humans acronyms acronym_regex).each do |scope| + instance_variable_set("@#{scope}", orig.send(scope).dup) + end + 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 @@ -82,7 +91,7 @@ module ActiveSupport def plural(rule, replacement) @uncountables.delete(rule) if rule.is_a?(String) @uncountables.delete(replacement) - @plurals.insert(0, [rule, replacement]) + @plurals.prepend([rule, replacement]) end # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression. @@ -90,7 +99,7 @@ module ActiveSupport def singular(rule, replacement) @uncountables.delete(rule) if rule.is_a?(String) @uncountables.delete(replacement) - @singulars.insert(0, [rule, replacement]) + @singulars.prepend([rule, replacement]) end # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used @@ -134,7 +143,7 @@ module ActiveSupport # human /_cnt$/i, '\1_count' # human "legacy_col_person_name", "Name" def human(rule, replacement) - @humans.insert(0, [rule, replacement]) + @humans.prepend([rule, replacement]) end # Clears the loaded inflections within a given scope (default is <tt>:all</tt>). diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 4b7c36f839..48ea5653c7 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -92,9 +92,9 @@ module ActiveSupport # "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) } + inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) } result.gsub!(/_id$/, "") - result.gsub!(/_/, ' ') + result.tr!('_', ' ') result.gsub(/([a-z\d]*)/i) { |match| "#{inflections.acronyms[match] || match.downcase}" }.gsub(/^\w/) { $&.upcase } @@ -146,7 +146,7 @@ module ActiveSupport # Example: # "puni_puni" # => "puni-puni" def dasherize(underscored_word) - underscored_word.gsub(/_/, '-') + underscored_word.tr('_', '-') end # Removes the module part from the expression in the string: @@ -209,12 +209,10 @@ module ActiveSupport def constantize(camel_cased_word) #:nodoc: names = camel_cased_word.split('::') names.shift if names.empty? || names.first.empty? - - constant = Object - names.each do |name| - constant = constant.const_get(name, false) + + names.inject(Object) do |constant, name| + constant.const_get(name, false) end - constant end # Tries to find a constant with the name specified in the argument string: @@ -308,10 +306,10 @@ module ActiveSupport def apply_inflections(word, rules) result = word.to_s.dup - if word.empty? || inflections.uncountables.any? { |inflection| result =~ /\b#{inflection}\Z/i } + if word.empty? || inflections.uncountables.include?(result.downcase[/\b\w+\Z/]) result else - rules.each { |(rule, replacement)| break if result.gsub!(rule, replacement) } + rules.each { |(rule, replacement)| break if result.sub!(rule, replacement) } result end end diff --git a/activesupport/lib/active_support/ordered_options.rb b/activesupport/lib/active_support/ordered_options.rb index 9e5a5d0246..538e41e0eb 100644 --- a/activesupport/lib/active_support/ordered_options.rb +++ b/activesupport/lib/active_support/ordered_options.rb @@ -1,5 +1,3 @@ -require 'active_support/ordered_hash' - # Usually key value pairs are handled something like this: # # h = {} @@ -17,7 +15,7 @@ require 'active_support/ordered_hash' # h.girl # => 'Mary' # module ActiveSupport #:nodoc: - class OrderedOptions < OrderedHash + class OrderedOptions < Hash alias_method :_get, :[] # preserve the original #[] method protected :_get # make it protected diff --git a/activesupport/lib/active_support/ruby/shim.rb b/activesupport/lib/active_support/ruby/shim.rb index 41fd866481..13e96b3596 100644 --- a/activesupport/lib/active_support/ruby/shim.rb +++ b/activesupport/lib/active_support/ruby/shim.rb @@ -12,5 +12,4 @@ require 'active_support/core_ext/date_time/conversions' require 'active_support/core_ext/enumerable' require 'active_support/core_ext/string/conversions' require 'active_support/core_ext/string/interpolation' -require 'active_support/core_ext/string/encoding' require 'active_support/core_ext/time/conversions' diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb index 3c995e0793..25688a9da5 100644 --- a/activesupport/test/callbacks_test.rb +++ b/activesupport/test/callbacks_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' module CallbacksTest class Phone include ActiveSupport::Callbacks - define_callbacks :save, :rescuable => true + define_callbacks :save set_callback :save, :before, :before_save1 set_callback :save, :after, :after_save1 @@ -439,13 +439,6 @@ module CallbacksTest end class CallbacksTest < ActiveSupport::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 diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index 6e91fdedce..760d138623 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -175,6 +175,18 @@ class DateExtCalculationsTest < ActiveSupport::TestCase assert_equal Date.new(1582,10,4), Date.new(1583,10,14).prev_year end + def test_last_year + assert_equal Date.new(2004,6,5), Date.new(2005,6,5).last_year + end + + def test_last_year_in_leap_years + assert_equal Date.new(1999,2,28), Date.new(2000,2,29).last_year + end + + def test_last_year_in_calendar_reform + assert_equal Date.new(1582,10,4), Date.new(1583,10,14).last_year + end + def test_next_year assert_equal Date.new(2006,6,5), Date.new(2005,6,5).next_year end @@ -245,6 +257,14 @@ class DateExtCalculationsTest < ActiveSupport::TestCase assert_equal Date.new(2010,2,27), Date.new(2010,3,4).prev_week(:saturday) end + def test_last_week + assert_equal Date.new(2005,5,9), Date.new(2005,5,17).last_week + assert_equal Date.new(2006,12,25), Date.new(2007,1,7).last_week + assert_equal Date.new(2010,2,12), Date.new(2010,2,19).last_week(:friday) + assert_equal Date.new(2010,2,13), Date.new(2010,2,19).last_week(:saturday) + assert_equal Date.new(2010,2,27), Date.new(2010,3,4).last_week(:saturday) + end + def test_next_week assert_equal Date.new(2005,2,28), Date.new(2005,2,22).next_week assert_equal Date.new(2005,3,4), Date.new(2005,2,22).next_week(:friday) @@ -265,6 +285,10 @@ class DateExtCalculationsTest < ActiveSupport::TestCase assert_equal Date.new(2004, 2, 29), Date.new(2004, 3, 31).prev_month end + def test_last_month_on_31st + assert_equal Date.new(2004, 2, 29), Date.new(2004, 3, 31).last_month + end + def test_yesterday_constructor assert_equal Date.current - 1, Date.yesterday end diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index 57b5b95a66..cd8cb5d18b 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -159,6 +159,10 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase assert_equal DateTime.civil(2004,6,5,10), DateTime.civil(2005,6,5,10,0,0).prev_year end + def test_last_year + assert_equal DateTime.civil(2004,6,5,10), DateTime.civil(2005,6,5,10,0,0).last_year + end + def test_next_year assert_equal DateTime.civil(2006,6,5,10), DateTime.civil(2005,6,5,10,0,0).next_year end @@ -232,6 +236,14 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase assert_equal DateTime.civil(2006,11,15), DateTime.civil(2006,11,23,0,0,0).prev_week(:wednesday) end + def test_last_week + assert_equal DateTime.civil(2005,2,21), DateTime.civil(2005,3,1,15,15,10).last_week + assert_equal DateTime.civil(2005,2,22), DateTime.civil(2005,3,1,15,15,10).last_week(:tuesday) + assert_equal DateTime.civil(2005,2,25), DateTime.civil(2005,3,1,15,15,10).last_week(:friday) + assert_equal DateTime.civil(2006,10,30), DateTime.civil(2006,11,6,0,0,0).last_week + assert_equal DateTime.civil(2006,11,15), DateTime.civil(2006,11,23,0,0,0).last_week(:wednesday) + end + def test_next_week assert_equal DateTime.civil(2005,2,28), DateTime.civil(2005,2,22,15,15,10).next_week assert_equal DateTime.civil(2005,3,4), DateTime.civil(2005,2,22,15,15,10).next_week(:friday) @@ -247,6 +259,10 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase assert_equal DateTime.civil(2004, 2, 29), DateTime.civil(2004, 3, 31).prev_month end + def test_last_month_on_31st + assert_equal DateTime.civil(2004, 2, 29), DateTime.civil(2004, 3, 31).last_month + end + def test_xmlschema assert_match(/^1880-02-28T15:15:10\+00:?00$/, DateTime.civil(1880, 2, 28, 15, 15, 10).xmlschema) assert_match(/^1980-02-28T15:15:10\+00:?00$/, DateTime.civil(1980, 2, 28, 15, 15, 10).xmlschema) diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb index 8a91f6d69c..cf1ec448c2 100644 --- a/activesupport/test/core_ext/range_ext_test.rb +++ b/activesupport/test/core_ext/range_ext_test.rb @@ -71,4 +71,16 @@ class RangeTest < ActiveSupport::TestCase range = (1..3) assert range.method(:include?) != range.method(:cover?) end + + def test_overlaps_on_time + time_range_1 = Time.utc(2005, 12, 10, 15, 30)..Time.utc(2005, 12, 10, 17, 30) + time_range_2 = Time.utc(2005, 12, 10, 17, 00)..Time.utc(2005, 12, 10, 18, 00) + assert time_range_1.overlaps?(time_range_2) + end + + def test_no_overlaps_on_time + time_range_1 = Time.utc(2005, 12, 10, 15, 30)..Time.utc(2005, 12, 10, 17, 30) + time_range_2 = Time.utc(2005, 12, 10, 17, 31)..Time.utc(2005, 12, 10, 18, 00) + assert !time_range_1.overlaps?(time_range_2) + end end diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index eda8066579..c542acca68 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -198,6 +198,10 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.local(2004,6,5,10), Time.local(2005,6,5,10,0,0).prev_year end + def test_last_year + assert_equal Time.local(2004,6,5,10), Time.local(2005,6,5,10,0,0).last_year + end + def test_next_year assert_equal Time.local(2006,6,5,10), Time.local(2005,6,5,10,0,0).next_year end @@ -505,6 +509,16 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.local(2006,11,15), Time.local(2006,11,23,0,0,0).prev_week(:wednesday) end end + + def test_last_week + with_env_tz 'US/Eastern' do + assert_equal Time.local(2005,2,21), Time.local(2005,3,1,15,15,10).last_week + assert_equal Time.local(2005,2,22), Time.local(2005,3,1,15,15,10).last_week(:tuesday) + assert_equal Time.local(2005,2,25), Time.local(2005,3,1,15,15,10).last_week(:friday) + assert_equal Time.local(2006,10,30), Time.local(2006,11,6,0,0,0).last_week + assert_equal Time.local(2006,11,15), Time.local(2006,11,23,0,0,0).last_week(:wednesday) + end + end def test_next_week with_env_tz 'US/Eastern' do @@ -662,6 +676,10 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.local(2004, 2, 29), Time.local(2004, 3, 31).prev_month end + def test_last_month_on_31st + assert_equal Time.local(2004, 2, 29), Time.local(2004, 3, 31).last_month + end + def test_xmlschema_is_available assert_nothing_raised { Time.now.xmlschema } end diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb index e7c671778a..91ae6bc189 100644 --- a/activesupport/test/inflector_test.rb +++ b/activesupport/test/inflector_test.rb @@ -26,23 +26,20 @@ class InflectorTest < ActiveSupport::TestCase end def test_uncountable_word_is_not_greedy - uncountable_word = "ors" - countable_word = "sponsor" + with_dup do + uncountable_word = "ors" + countable_word = "sponsor" - cached_uncountables = ActiveSupport::Inflector.inflections.uncountables + ActiveSupport::Inflector.inflections.uncountable << uncountable_word - 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 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 + 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)) + end end SingularToPlural.each do |singular, plural| @@ -66,6 +63,14 @@ class InflectorTest < ActiveSupport::TestCase end end + SingularToPlural.each do |singular, plural| + define_method "test_singularize_singular_#{singular}" do + assert_equal(singular, ActiveSupport::Inflector.singularize(singular)) + assert_equal(singular.capitalize, ActiveSupport::Inflector.singularize(singular.capitalize)) + end + end + + def test_overwrite_previous_inflectors assert_equal("series", ActiveSupport::Inflector.singularize("series")) ActiveSupport::Inflector.inflections.singular "series", "serie" @@ -295,7 +300,7 @@ class InflectorTest < ActiveSupport::TestCase ActiveSupport::Inflector.constantize(string) end end - + def test_safe_constantize run_safe_constantize_tests_on do |string| ActiveSupport::Inflector.safe_constantize(string) @@ -341,56 +346,50 @@ class InflectorTest < ActiveSupport::TestCase %w{plurals singulars uncountables humans}.each do |inflection_type| class_eval <<-RUBY, __FILE__, __LINE__ + 1 def test_clear_#{inflection_type} - cached_values = ActiveSupport::Inflector.inflections.#{inflection_type} - ActiveSupport::Inflector.inflections.clear :#{inflection_type} - assert ActiveSupport::Inflector.inflections.#{inflection_type}.empty?, \"#{inflection_type} inflections should be empty after clear :#{inflection_type}\" - ActiveSupport::Inflector.inflections.instance_variable_set :@#{inflection_type}, cached_values + with_dup do + ActiveSupport::Inflector.inflections.clear :#{inflection_type} + assert ActiveSupport::Inflector.inflections.#{inflection_type}.empty?, \"#{inflection_type} inflections should be empty after clear :#{inflection_type}\" + end end RUBY end def test_clear_all - cached_values = ActiveSupport::Inflector.inflections.plurals.dup, ActiveSupport::Inflector.inflections.singulars.dup, ActiveSupport::Inflector.inflections.uncountables.dup, ActiveSupport::Inflector.inflections.humans.dup - ActiveSupport::Inflector.inflections do |inflect| - # ensure any data is present - inflect.plural(/(quiz)$/i, '\1zes') - inflect.singular(/(database)s$/i, '\1') - inflect.uncountable('series') - inflect.human("col_rpted_bugs", "Reported bugs") - - inflect.clear :all - - assert inflect.plurals.empty? - assert inflect.singulars.empty? - assert inflect.uncountables.empty? - assert inflect.humans.empty? + with_dup do + ActiveSupport::Inflector.inflections do |inflect| + # ensure any data is present + inflect.plural(/(quiz)$/i, '\1zes') + inflect.singular(/(database)s$/i, '\1') + inflect.uncountable('series') + inflect.human("col_rpted_bugs", "Reported bugs") + + inflect.clear :all + + assert inflect.plurals.empty? + assert inflect.singulars.empty? + assert inflect.uncountables.empty? + assert inflect.humans.empty? + end end - ActiveSupport::Inflector.inflections.instance_variable_set :@plurals, cached_values[0] - ActiveSupport::Inflector.inflections.instance_variable_set :@singulars, cached_values[1] - ActiveSupport::Inflector.inflections.instance_variable_set :@uncountables, cached_values[2] - ActiveSupport::Inflector.inflections.instance_variable_set :@humans, cached_values[3] end def test_clear_with_default - cached_values = ActiveSupport::Inflector.inflections.plurals.dup, ActiveSupport::Inflector.inflections.singulars.dup, ActiveSupport::Inflector.inflections.uncountables.dup, ActiveSupport::Inflector.inflections.humans.dup - ActiveSupport::Inflector.inflections do |inflect| - # ensure any data is present - inflect.plural(/(quiz)$/i, '\1zes') - inflect.singular(/(database)s$/i, '\1') - inflect.uncountable('series') - inflect.human("col_rpted_bugs", "Reported bugs") - - inflect.clear - - assert inflect.plurals.empty? - assert inflect.singulars.empty? - assert inflect.uncountables.empty? - assert inflect.humans.empty? + with_dup do + ActiveSupport::Inflector.inflections do |inflect| + # ensure any data is present + inflect.plural(/(quiz)$/i, '\1zes') + inflect.singular(/(database)s$/i, '\1') + inflect.uncountable('series') + inflect.human("col_rpted_bugs", "Reported bugs") + + inflect.clear + + assert inflect.plurals.empty? + assert inflect.singulars.empty? + assert inflect.uncountables.empty? + assert inflect.humans.empty? + end end - ActiveSupport::Inflector.inflections.instance_variable_set :@plurals, cached_values[0] - ActiveSupport::Inflector.inflections.instance_variable_set :@singulars, cached_values[1] - ActiveSupport::Inflector.inflections.instance_variable_set :@uncountables, cached_values[2] - ActiveSupport::Inflector.inflections.instance_variable_set :@humans, cached_values[3] end Irregularities.each do |irregularity| @@ -439,26 +438,28 @@ class InflectorTest < ActiveSupport::TestCase end end - { :singulars => :singular, :plurals => :plural, :uncountables => :uncountable, :humans => :human }.each do |scope, method| + %w(plurals singulars uncountables humans acronyms).each do |scope| ActiveSupport::Inflector.inflections do |inflect| define_method("test_clear_inflections_with_#{scope}") do - # save the inflections - values = inflect.send(scope) - - # clear the inflections - inflect.clear(scope) - - assert_equal [], inflect.send(scope) - - # restore the inflections - if scope == :uncountables - inflect.send(method, values) - else - values.reverse.each { |value| inflect.send(method, *value) } + with_dup do + # clear the inflections + inflect.clear(scope) + assert_equal [], inflect.send(scope) end - - assert_equal values, inflect.send(scope) end end end + + # Dups the singleton and yields, restoring the original inflections later. + # Use this in tests what modify the state of the singleton. + # + # This helper is implemented by setting @__instance__ because in some tests + # there are module functions that access ActiveSupport::Inflector.inflections, + # so we need to replace the singleton itself. + def with_dup + original = ActiveSupport::Inflector.inflections + ActiveSupport::Inflector::Inflections.instance_variable_set(:@__instance__, original.dup) + ensure + ActiveSupport::Inflector::Inflections.instance_variable_set(:@__instance__, original) + end end diff --git a/activesupport/test/inflector_test_cases.rb b/activesupport/test/inflector_test_cases.rb index eb2915c286..809b8b46c9 100644 --- a/activesupport/test/inflector_test_cases.rb +++ b/activesupport/test/inflector_test_cases.rb @@ -93,6 +93,7 @@ module InflectorTestCases "matrix_fu" => "matrix_fus", "axis" => "axes", + "taxi" => "taxis", # prevents regression "testis" => "testes", "crisis" => "crises", diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb index bdde5141a9..047b89be2a 100644 --- a/activesupport/test/safe_buffer_test.rb +++ b/activesupport/test/safe_buffer_test.rb @@ -84,13 +84,13 @@ class SafeBufferTest < ActiveSupport::TestCase assert_equal "hello<>", clean + @buffer end - test "Should concat as a normal string when dirty" do + test "Should concat as a normal string when safe" do clean = "hello".html_safe @buffer.gsub!('', '<>') assert_equal "<>hello", @buffer + clean end - test "Should preserve dirty? status on copy" do + test "Should preserve html_safe? status on copy" do @buffer.gsub!('', '<>') assert !@buffer.dup.html_safe? end @@ -102,20 +102,42 @@ class SafeBufferTest < ActiveSupport::TestCase assert_equal "<script>", result_buffer end - test "Should raise an error when safe_concat is called on dirty buffers" do + test "Should raise an error when safe_concat is called on unsafe 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 + test "Should not fail if the returned object is not a string" do assert_kind_of NilClass, @buffer.slice("chipchop") end - test "Should initialize @dirty to false for new instance when sliced" do - dirty = @buffer[0,0].send(:dirty?) - assert_not_nil dirty - assert !dirty + test "clone_empty returns an empty buffer" do + assert_equal '', ActiveSupport::SafeBuffer.new('foo').clone_empty + end + + test "clone_empty keeps the original dirtyness" do + assert @buffer.clone_empty.html_safe? + assert !@buffer.gsub!('', '').clone_empty.html_safe? + end + + test "Should be safe when sliced if original value was safe" do + new_buffer = @buffer[0,0] + assert_not_nil new_buffer + assert new_buffer.html_safe?, "should be safe" + end + + test "Should continue unsafe on slice" do + x = 'foo'.html_safe.gsub!('f', '<script>alert("lolpwnd");</script>') + + # calling gsub! makes the dirty flag true + assert !x.html_safe?, "should not be safe" + + # getting a slice of it + y = x[0..-1] + + # should still be unsafe + assert !y.html_safe?, "should not be safe" end end |