diff options
Diffstat (limited to 'activesupport')
18 files changed, 179 insertions, 39 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 00fcfe2001..87b956e3fc 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,7 @@ ## Rails 4.0.0 (unreleased) ## +* AS::Callbacks: deprecate usage of filter object with `#before` and `#after` methods as `around` callback. *Bogdan Gusiev* + * Add `Time#prev_quarter' and 'Time#next_quarter' short-hands for months_ago(3) and months_since(3). *SungHee Kang* * Remove obsolete and unused `require_association` method from dependencies. *fxn* diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 0aa3efbb63..6cc875c69a 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -283,7 +283,8 @@ module ActiveSupport filter.singleton_class.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 def #{kind}(context, &block) filter(context, &block) end RUBY_EVAL - elsif filter.respond_to?(:before) && filter.respond_to?(:after) && kind == :around + elsif filter.respond_to?(:before) && filter.respond_to?(:after) && kind == :around && !filter.respond_to?(:around) + ActiveSupport::Deprecation.warn("Filter object with #before and #after methods is deprecated. Define #around method instead.") def filter.around(context) should_continue = before(context) yield if should_continue diff --git a/activesupport/lib/active_support/concern.rb b/activesupport/lib/active_support/concern.rb index c94a8d99f4..b927b58a9a 100644 --- a/activesupport/lib/active_support/concern.rb +++ b/activesupport/lib/active_support/concern.rb @@ -56,7 +56,7 @@ module ActiveSupport # these from +Host+ directly including +Foo+ in +Bar+: # # module Bar - # include Foo + # include Foo # def self.included(base) # base.method_injected_by_foo # end @@ -94,9 +94,8 @@ module ActiveSupport # class Host # include Bar # works, Bar takes care now of its dependencies # end - # module Concern - def self.extended(base) + def self.extended(base) #:nodoc: base.instance_variable_set("@_dependencies", []) end diff --git a/activesupport/lib/active_support/configurable.rb b/activesupport/lib/active_support/configurable.rb index 4fb8c7af3f..307ae40398 100644 --- a/activesupport/lib/active_support/configurable.rb +++ b/activesupport/lib/active_support/configurable.rb @@ -98,15 +98,15 @@ module ActiveSupport names.each do |name| raise NameError.new('invalid config attribute name') unless name =~ /^[_A-Za-z]\w*$/ - reader, line = "def #{name}; config.#{name}; end", __LINE__ - writer, line = "def #{name}=(value); config.#{name} = value; end", __LINE__ + reader, reader_line = "def #{name}; config.#{name}; end", __LINE__ + writer, writer_line = "def #{name}=(value); config.#{name} = value; end", __LINE__ - singleton_class.class_eval reader, __FILE__, line - singleton_class.class_eval writer, __FILE__, line + singleton_class.class_eval reader, __FILE__, reader_line + singleton_class.class_eval writer, __FILE__, writer_line unless options[:instance_accessor] == false - class_eval reader, __FILE__, line unless options[:instance_reader] == false - class_eval writer, __FILE__, line unless options[:instance_writer] == false + class_eval reader, __FILE__, reader_line unless options[:instance_reader] == false + class_eval writer, __FILE__, writer_line unless options[:instance_writer] == false end end end diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index 1e0de651c7..d6ae031c0d 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -1,6 +1,5 @@ require 'active_support/xml_mini' require 'active_support/core_ext/hash/keys' -require 'active_support/core_ext/hash/reverse_merge' require 'active_support/core_ext/string/inflections' class Array @@ -62,14 +61,10 @@ class Array :last_word_connector => ', and ' } if defined?(I18n) - namespace = 'support.array.' - default_connectors.each_key do |name| - i18n_key = (namespace + name.to_s).to_sym - default_connectors[name] = I18n.translate i18n_key, :locale => options[:locale] - end + i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {}) + default_connectors.merge!(i18n_connectors) end - - options.reverse_merge! default_connectors + options = default_connectors.merge!(options) case length when 0 diff --git a/activesupport/lib/active_support/core_ext/hash/keys.rb b/activesupport/lib/active_support/core_ext/hash/keys.rb index 8e728691c6..e753e36124 100644 --- a/activesupport/lib/active_support/core_ext/hash/keys.rb +++ b/activesupport/lib/active_support/core_ext/hash/keys.rb @@ -7,7 +7,7 @@ class Hash # # => { "NAME" => "Rob", "AGE" => "28" } def transform_keys result = {} - keys.each do |key| + each_key do |key| result[yield(key)] = self[key] end result diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 28c8b53b78..e8623a9c54 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -1,5 +1,6 @@ require 'active_support/duration' require 'active_support/core_ext/time/conversions' +require 'active_support/time_with_zone' class Time COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] diff --git a/activesupport/lib/active_support/file_update_checker.rb b/activesupport/lib/active_support/file_update_checker.rb index 48c39d9370..9decbaef32 100644 --- a/activesupport/lib/active_support/file_update_checker.rb +++ b/activesupport/lib/active_support/file_update_checker.rb @@ -101,7 +101,9 @@ module ActiveSupport end def updated_at(paths) - @updated_at || paths.map { |path| File.mtime(path) }.max || Time.at(0) + time_now = Time.now + @updated_at || paths.map { |path| File.mtime(path) }. + reject { |time| time > time_now }.max || Time.at(0) end def compile_glob(hash) diff --git a/activesupport/lib/active_support/inflections.rb b/activesupport/lib/active_support/inflections.rb index c04c2ed15b..ca2d8cb270 100644 --- a/activesupport/lib/active_support/inflections.rb +++ b/activesupport/lib/active_support/inflections.rb @@ -1,3 +1,5 @@ +require 'active_support/inflector/inflections' + module ActiveSupport Inflector.inflections do |inflect| inflect.plural(/$/, 's') diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb index 600e353812..c9e50a9462 100644 --- a/activesupport/lib/active_support/inflector/inflections.rb +++ b/activesupport/lib/active_support/inflector/inflections.rb @@ -2,6 +2,8 @@ require 'active_support/core_ext/array/prepend_and_append' module ActiveSupport module Inflector + extend self + # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional # inflection rules. # diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 2acc6ddee5..c14a43de0d 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -1,6 +1,7 @@ # encoding: utf-8 require 'active_support/inflector/inflections' +require 'active_support/inflections' module ActiveSupport # The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without, diff --git a/activesupport/lib/active_support/number_helper.rb b/activesupport/lib/active_support/number_helper.rb index c736041066..99f6489adb 100644 --- a/activesupport/lib/active_support/number_helper.rb +++ b/activesupport/lib/active_support/number_helper.rb @@ -7,9 +7,14 @@ module ActiveSupport module NumberHelper extend self + DECIMAL_UNITS = { 0 => :unit, 1 => :ten, 2 => :hundred, 3 => :thousand, 6 => :million, 9 => :billion, 12 => :trillion, 15 => :quadrillion, + -1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto } + DEFAULT_CURRENCY_VALUES = { :format => "%u%n", :negative_format => "-%u%n", :unit => "$", :separator => ".", :delimiter => ",", :precision => 2, :significant => false, :strip_insignificant_zeros => false } + STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb] + # Formats a +number+ into a US phone number (e.g., (555) # 123-9876). You can customize the format in the +options+ hash. # @@ -116,8 +121,7 @@ module ActiveSupport number = number.respond_to?("abs") ? number.abs : number.sub(/^-/, '') end - formatted_number = format.gsub('%n', self.number_to_rounded(number, options)).gsub('%u', unit) - formatted_number + format.gsub('%n', self.number_to_rounded(number, options)).gsub('%u', unit) end # Formats a +number+ as a percentage string (e.g., 65%). You can @@ -160,9 +164,7 @@ module ActiveSupport options = defaults.merge!(options) format = options[:format] || "%n%" - - formatted_number = format.gsub('%n', self.number_to_rounded(number, options)) - formatted_number + format.gsub('%n', self.number_to_rounded(number, options)) end # Formats a +number+ with grouped thousands using +delimiter+ @@ -242,10 +244,9 @@ module ActiveSupport # number_to_rounded(1111.2345, precision: 2, separator: ',', delimiter: '.') # # => 1.111,23 def number_to_rounded(number, options = {}) - options = options.symbolize_keys - return number unless valid_float?(number) - number = Float(number) + number = Float(number) + options = options.symbolize_keys defaults = format_translations('precision', options[:locale]) options = defaults.merge!(options) @@ -254,7 +255,7 @@ module ActiveSupport significant = options.delete :significant strip_insignificant_zeros = options.delete :strip_insignificant_zeros - if significant and precision > 0 + if significant && precision > 0 if number == 0 digits, rounded_number = 1, 0 else @@ -263,10 +264,10 @@ module ActiveSupport digits = (Math.log10(rounded_number.abs) + 1).floor # After rounding, the number of digits may have changed end precision -= digits - precision = precision > 0 ? precision : 0 #don't let it be negative + precision = 0 if precision < 0 # don't let it be negative else rounded_number = BigDecimal.new(number.to_s).round(precision).to_f - rounded_number = rounded_number.zero? ? rounded_number.abs : rounded_number #prevent showing negative zeros + rounded_number = rounded_number.abs if rounded_number.zero? # prevent showing negative zeros end formatted_number = self.number_to_delimited("%01.#{precision}f" % rounded_number, options) if strip_insignificant_zeros @@ -277,8 +278,6 @@ module ActiveSupport end end - STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb].freeze - # Formats the bytes in +number+ into a more understandable # representation (e.g., giving it 1500 yields 1.5 KB). This # method is useful for reporting file sizes to users. You can @@ -356,9 +355,6 @@ module ActiveSupport end end - DECIMAL_UNITS = {0 => :unit, 1 => :ten, 2 => :hundred, 3 => :thousand, 6 => :million, 9 => :billion, 12 => :trillion, 15 => :quadrillion, - -1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto}.freeze - # Pretty prints (formats and approximates) a number in a way it # is more readable by humans (eg.: 1200000000 becomes "1.2 # Billion"). This is useful for numbers that can get very large @@ -527,6 +523,5 @@ module ActiveSupport false end private_module_and_instance_method :valid_float? - end end diff --git a/activesupport/lib/active_support/testing/declarative.rb b/activesupport/lib/active_support/testing/declarative.rb index 1c05d45888..508e37254a 100644 --- a/activesupport/lib/active_support/testing/declarative.rb +++ b/activesupport/lib/active_support/testing/declarative.rb @@ -2,7 +2,7 @@ module ActiveSupport module Testing module Declarative - def self.extended(klass) + def self.extended(klass) #:nodoc: klass.class_eval do unless method_defined?(:describe) diff --git a/activesupport/lib/active_support/testing/isolation.rb b/activesupport/lib/active_support/testing/isolation.rb index 50ec50ca52..27d444fd91 100644 --- a/activesupport/lib/active_support/testing/isolation.rb +++ b/activesupport/lib/active_support/testing/isolation.rb @@ -64,7 +64,7 @@ module ActiveSupport end end - def self.included klass + def self.included(klass) #:nodoc: klass.extend(Module.new { def test_methods ParallelEach.new super diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb index 58835c0ac5..9dfa2cbf11 100644 --- a/activesupport/test/core_ext/array_ext_test.rb +++ b/activesupport/test/core_ext/array_ext_test.rb @@ -90,6 +90,12 @@ class ArrayExtToSentenceTests < ActiveSupport::TestCase def test_one_non_string_element assert_equal '1', [1].to_sentence end + + def test_does_not_modify_given_hash + options = { words_connector: ' ' } + assert_equal "one two, and three", ['one', 'two', 'three'].to_sentence(options) + assert_equal({ words_connector: ' ' }, options) + end end class ArrayExtToSTests < ActiveSupport::TestCase diff --git a/activesupport/test/file_update_checker_test.rb b/activesupport/test/file_update_checker_test.rb index 8adff5de8d..bd1df0f858 100644 --- a/activesupport/test/file_update_checker_test.rb +++ b/activesupport/test/file_update_checker_test.rb @@ -48,6 +48,21 @@ class FileUpdateCheckerWithEnumerableTest < ActiveSupport::TestCase assert_equal 1, i end + def test_should_be_robust_to_handle_files_with_wrong_modified_time + i = 0 + now = Time.now + time = Time.mktime(now.year + 1, now.month, now.day) # wrong mtime from the future + File.utime time, time, FILES[2] + + checker = ActiveSupport::FileUpdateChecker.new(FILES){ i += 1 } + + sleep(1) + FileUtils.touch(FILES[0..1]) + + assert checker.execute_if_updated + assert_equal 1, i + end + def test_should_cache_updated_result_until_execute i = 0 checker = ActiveSupport::FileUpdateChecker.new(FILES){ i += 1 } diff --git a/activesupport/test/i18n_test.rb b/activesupport/test/i18n_test.rb index 4f2027f4eb..ddbba444cf 100644 --- a/activesupport/test/i18n_test.rb +++ b/activesupport/test/i18n_test.rb @@ -97,4 +97,9 @@ class I18nTest < ActiveSupport::TestCase I18n.backend.store_translations 'en', :support => { :array => { :two_words_connector => default_two_words_connector } } I18n.backend.store_translations 'en', :support => { :array => { :last_word_connector => default_last_word_connector } } end + + def test_to_sentence_with_empty_i18n_store + I18n.backend.store_translations 'empty', {} + assert_equal 'a, b, and c', %w[a b c].to_sentence(locale: 'empty') + end end diff --git a/activesupport/test/number_helper_i18n_test.rb b/activesupport/test/number_helper_i18n_test.rb new file mode 100644 index 0000000000..e07198027b --- /dev/null +++ b/activesupport/test/number_helper_i18n_test.rb @@ -0,0 +1,114 @@ +require 'abstract_unit' +require 'active_support/number_helper' + +module ActiveSupport + class NumberHelperI18nTest < ActiveSupport::TestCase + include ActiveSupport::NumberHelper + + def setup + I18n.backend.store_translations 'ts', + :number => { + :format => { :precision => 3, :delimiter => ',', :separator => '.', :significant => false, :strip_insignificant_zeros => false }, + :currency => { :format => { :unit => '&$', :format => '%u - %n', :negative_format => '(%u - %n)', :precision => 2 } }, + :human => { + :format => { + :precision => 2, + :significant => true, + :strip_insignificant_zeros => true + }, + :storage_units => { + :format => "%n %u", + :units => { + :byte => "b", + :kb => "k" + } + }, + :decimal_units => { + :format => "%n %u", + :units => { + :deci => {:one => "Tenth", :other => "Tenths"}, + :unit => "u", + :ten => {:one => "Ten", :other => "Tens"}, + :thousand => "t", + :million => "m", + :billion =>"b", + :trillion =>"t" , + :quadrillion =>"q" + } + } + }, + :percentage => { :format => {:delimiter => '', :precision => 2, :strip_insignificant_zeros => true} }, + :precision => { :format => {:delimiter => '', :significant => true} } + }, + :custom_units_for_number_to_human => {:mili => "mm", :centi => "cm", :deci => "dm", :unit => "m", :ten => "dam", :hundred => "hm", :thousand => "km"} + end + + def test_number_to_i18n_currency + assert_equal("&$ - 10.00", number_to_currency(10, :locale => 'ts')) + assert_equal("(&$ - 10.00)", number_to_currency(-10, :locale => 'ts')) + assert_equal("-10.00 - &$", number_to_currency(-10, :locale => 'ts', :format => "%n - %u")) + end + + def test_number_to_currency_with_empty_i18n_store + I18n.backend.store_translations 'empty', {} + + assert_equal("$10.00", number_to_currency(10, :locale => 'empty')) + assert_equal("-$10.00", number_to_currency(-10, :locale => 'empty')) + end + + def test_number_to_currency_without_currency_negative_format + I18n.backend.store_translations 'no_negative_format', :number => { + :currency => { :format => { :unit => '@', :format => '%n %u' } } + } + + assert_equal("-10.00 @", number_to_currency(-10, :locale => 'no_negative_format')) + end + + def test_number_with_i18n_precision + #Delimiter was set to "" + assert_equal("10000", number_to_rounded(10000, :locale => 'ts')) + + #Precision inherited and significant was set + assert_equal("1.00", number_to_rounded(1.0, :locale => 'ts')) + end + + def test_number_with_i18n_delimiter + #Delimiter "," and separator "." + assert_equal("1,000,000.234", number_to_delimited(1000000.234, :locale => 'ts')) + end + + def test_number_to_i18n_percentage + # to see if strip_insignificant_zeros is true + assert_equal("1%", number_to_percentage(1, :locale => 'ts')) + # precision is 2, significant should be inherited + assert_equal("1.24%", number_to_percentage(1.2434, :locale => 'ts')) + # no delimiter + assert_equal("12434%", number_to_percentage(12434, :locale => 'ts')) + end + + def test_number_to_i18n_human_size + #b for bytes and k for kbytes + assert_equal("2 k", number_to_human_size(2048, :locale => 'ts')) + assert_equal("42 b", number_to_human_size(42, :locale => 'ts')) + end + + def test_number_to_human_with_default_translation_scope + #Using t for thousand + assert_equal "2 t", number_to_human(2000, :locale => 'ts') + #Significant was set to true with precision 2, using b for billion + assert_equal "1.2 b", number_to_human(1234567890, :locale => 'ts') + #Using pluralization (Ten/Tens and Tenth/Tenths) + assert_equal "1 Tenth", number_to_human(0.1, :locale => 'ts') + assert_equal "1.3 Tenth", number_to_human(0.134, :locale => 'ts') + assert_equal "2 Tenths", number_to_human(0.2, :locale => 'ts') + assert_equal "1 Ten", number_to_human(10, :locale => 'ts') + assert_equal "1.2 Ten", number_to_human(12, :locale => 'ts') + assert_equal "2 Tens", number_to_human(20, :locale => 'ts') + end + + def test_number_to_human_with_custom_translation_scope + #Significant was set to true with precision 2, with custom translated units + assert_equal "4.3 cm", number_to_human(0.0432, :locale => 'ts', :units => :custom_units_for_number_to_human) + end + end +end |