diff options
Diffstat (limited to 'activesupport/lib')
10 files changed, 219 insertions, 44 deletions
diff --git a/activesupport/lib/active_support/core_ext/object/try.rb b/activesupport/lib/active_support/core_ext/object/try.rb index 9974b61078..1079ddde98 100644 --- a/activesupport/lib/active_support/core_ext/object/try.rb +++ b/activesupport/lib/active_support/core_ext/object/try.rb @@ -37,7 +37,7 @@ class Object public_send(*a, &b) if respond_to?(a.first) end end - + # Same as #try, but will raise a NoMethodError exception if the receiving is not nil and # does not implemented the tried method. def try!(*a, &b) @@ -63,7 +63,7 @@ class NilClass def try(*args) nil end - + def try!(*args) nil end diff --git a/activesupport/lib/active_support/core_ext/string.rb b/activesupport/lib/active_support/core_ext/string.rb index fb36262528..ad864765a3 100644 --- a/activesupport/lib/active_support/core_ext/string.rb +++ b/activesupport/lib/active_support/core_ext/string.rb @@ -10,3 +10,4 @@ require 'active_support/core_ext/string/output_safety' require 'active_support/core_ext/string/exclude' require 'active_support/core_ext/string/strip' require 'active_support/core_ext/string/inquiry' +require 'active_support/core_ext/string/indent' diff --git a/activesupport/lib/active_support/core_ext/string/indent.rb b/activesupport/lib/active_support/core_ext/string/indent.rb new file mode 100644 index 0000000000..afc3032272 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/string/indent.rb @@ -0,0 +1,43 @@ +class String + # Same as +indent+, except it indents the receiver in-place. + # + # Returns the indented string, or +nil+ if there was nothing to indent. + def indent!(amount, indent_string=nil, indent_empty_lines=false) + indent_string = indent_string || self[/^[ \t]/] || ' ' + re = indent_empty_lines ? /^/ : /^(?!$)/ + gsub!(re, indent_string * amount) + end + + # Indents the lines in the receiver: + # + # <<EOS.indent(2) + # def some_method + # some_code + # end + # EOS + # # => + # def some_method + # some_code + # end + # + # The second argument, +indent_string+, specifies which indent string to + # use. The default is +nil+, which tells the method to make a guess by + # peeking at the first indented line, and fallback to a space if there is + # none. + # + # " foo".indent(2) # => " foo" + # "foo\n\t\tbar".indent(2) # => "\t\tfoo\n\t\t\t\tbar" + # "foo".indent(2, "\t") # => "\t\tfoo" + # + # While +indent_string+ is tipically one space or tab, it may be any string. + # + # The third argument, +indent_empty_lines+, is a flag that says whether + # empty lines should be indented. Default is false. + # + # "foo\n\nbar".indent(2) # => " foo\n\n bar" + # "foo\n\nbar".indent(2, nil, true) # => " foo\n \n bar" + # + def indent(amount, indent_string=nil, indent_empty_lines=false) + dup.tap {|_| _.indent!(amount, indent_string, indent_empty_lines)} + end +end diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb index 2cdc991120..a0139b7d8e 100644 --- a/activesupport/lib/active_support/duration.rb +++ b/activesupport/lib/active_support/duration.rb @@ -70,7 +70,7 @@ module ActiveSupport alias :until :ago def inspect #:nodoc: - consolidated = parts.inject(::Hash.new(0)) { |h,part| h[part.first] += part.last; h } + consolidated = parts.inject(::Hash.new(0)) { |h,(l,r)| h[l] += r; h } parts = [:years, :months, :days, :minutes, :seconds].map do |length| n = consolidated[length] "#{n} #{n == 1 ? length.to_s.singularize : length.to_s}" if n.nonzero? diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index 389df58ec4..1a95bd63e6 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/object/to_json' require 'active_support/core_ext/module/delegation' +require 'active_support/json/variable' require 'bigdecimal' require 'active_support/core_ext/big_decimal/conversions' # for #to_s diff --git a/activesupport/lib/active_support/json/variable.rb b/activesupport/lib/active_support/json/variable.rb new file mode 100644 index 0000000000..8af661a795 --- /dev/null +++ b/activesupport/lib/active_support/json/variable.rb @@ -0,0 +1,17 @@ +require 'active_support/deprecation' + +module ActiveSupport + module JSON + # Deprecated: A string that returns itself as its JSON-encoded form. + class Variable < String + def initialize(*args) + ActiveSupport::Deprecation.warn 'ActiveSupport::JSON::Variable is deprecated and will be removed in Rails 4.1. ' \ + 'For your own custom JSON literals, define #as_json and #encode_json yourself.' + super + end + + def as_json(options = nil) self end #:nodoc: + def encode_json(encoder) self end #:nodoc: + end + end +end diff --git a/activesupport/lib/active_support/locale/en.yml b/activesupport/lib/active_support/locale/en.yml index 18c7d47026..f4900dc935 100644 --- a/activesupport/lib/active_support/locale/en.yml +++ b/activesupport/lib/active_support/locale/en.yml @@ -49,7 +49,7 @@ en: significant: false # If set, the zeros after the decimal separator will always be stripped (eg.: 1.200 will be 1.2) strip_insignificant_zeros: false - + # Used in NumberHelper.number_to_currency() currency: format: @@ -62,7 +62,7 @@ en: precision: 2 significant: false strip_insignificant_zeros: false - + # Used in NumberHelper.number_to_percentage() percentage: format: @@ -73,7 +73,7 @@ en: # significant: false # strip_insignificant_zeros: false format: "%n%" - + # Used in NumberHelper.number_to_rounded() precision: format: @@ -83,7 +83,7 @@ en: # precision: # significant: false # strip_insignificant_zeros: false - + # Used in NumberHelper.number_to_human_size() and NumberHelper.number_to_human() human: format: @@ -131,5 +131,3 @@ en: billion: Billion trillion: Trillion quadrillion: Quadrillion - -
\ No newline at end of file diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb index 6ffc091233..2e5bcf4639 100644 --- a/activesupport/lib/active_support/notifications/fanout.rb +++ b/activesupport/lib/active_support/notifications/fanout.rb @@ -59,10 +59,10 @@ module ActiveSupport module Subscribers # :nodoc: def self.new(pattern, listener) - if listener.respond_to?(:call) - subscriber = Timed.new pattern, listener - else + if listener.respond_to?(:start) and listener.respond_to?(:finish) subscriber = Evented.new pattern, listener + else + subscriber = Timed.new pattern, listener end unless pattern diff --git a/activesupport/lib/active_support/number_helper.rb b/activesupport/lib/active_support/number_helper.rb index 99f6489adb..3849f94a31 100644 --- a/activesupport/lib/active_support/number_helper.rb +++ b/activesupport/lib/active_support/number_helper.rb @@ -7,12 +7,108 @@ module ActiveSupport module NumberHelper extend self + DEFAULTS = { + # Used in number_to_delimited + # These are also the defaults for 'currency', 'percentage', 'precision', and 'human' + format: { + # Sets the separator between the units, for more precision (e.g. 1.0 / 2.0 == 0.5) + separator: ".", + # Delimits thousands (e.g. 1,000,000 is a million) (always in groups of three) + delimiter: ",", + # Number of decimals, behind the separator (the number 1 with a precision of 2 gives: 1.00) + precision: 3, + # If set to true, precision will mean the number of significant digits instead + # of the number of decimal digits (1234 with precision 2 becomes 1200, 1.23543 becomes 1.2) + significant: false, + # If set, the zeros after the decimal separator will always be stripped (eg.: 1.200 will be 1.2) + strip_insignificant_zeros: false + }, + + # Used in number_to_currency + currency: { + format: { + format: "%u%n", + negative_format: "-%u%n", + unit: "$", + # These five are to override number.format and are optional + separator: ".", + delimiter: ",", + precision: 2, + significant: false, + strip_insignificant_zeros: false + } + }, + + # Used in number_to_percentage + percentage: { + format: { + delimiter: "", + format: "%n%" + } + }, + + # Used in number_to_rounded + precision: { + format: { + delimiter: "" + } + }, + + # Used in number_to_human_size and number_to_human + human: { + format: { + # These five are to override number.format and are optional + delimiter: "", + precision: 3, + significant: true, + strip_insignificant_zeros: true + }, + # Used in number_to_human_size + storage_units: { + # Storage units output formatting. + # %u is the storage unit, %n is the number (default: 2 MB) + format: "%n %u", + units: { + byte: "Bytes", + kb: "KB", + mb: "MB", + gb: "GB", + tb: "TB" + } + }, + # Used in number_to_human + decimal_units: { + format: "%n %u", + # Decimal units output formatting + # By default we will only quantify some of the exponents + # but the commented ones might be defined or overridden + # by the user. + units: { + # femto: Quadrillionth + # pico: Trillionth + # nano: Billionth + # micro: Millionth + # mili: Thousandth + # centi: Hundredth + # deci: Tenth + unit: "", + # ten: + # one: Ten + # other: Tens + # hundred: Hundred + thousand: "Thousand", + million: "Million", + billion: "Billion", + trillion: "Trillion", + quadrillion: "Quadrillion" + } + } + } + } + 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) @@ -106,10 +202,10 @@ module ActiveSupport return unless number options = options.symbolize_keys - currency = translations_for('currency', options[:locale]) + currency = i18n_format_options(options[:locale], :currency) currency[:negative_format] ||= "-" + currency[:format] if currency[:format] - defaults = DEFAULT_CURRENCY_VALUES.merge(defaults_translations(options[:locale])).merge!(currency) + defaults = default_format_options(:currency).merge!(currency) defaults[:negative_format] = "-" + options[:format] if options[:format] options = defaults.merge!(options) @@ -160,7 +256,7 @@ module ActiveSupport return unless number options = options.symbolize_keys - defaults = format_translations('percentage', options[:locale]) + defaults = format_options(options[:locale], :percentage) options = defaults.merge!(options) format = options[:format] || "%n%" @@ -197,7 +293,7 @@ module ActiveSupport return number unless valid_float?(number) - options = defaults_translations(options[:locale]).merge(options) + options = format_options(options[:locale]).merge!(options) parts = number.to_s.to_str.split('.') parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}") @@ -248,7 +344,7 @@ module ActiveSupport number = Float(number) options = options.symbolize_keys - defaults = format_translations('precision', options[:locale]) + defaults = format_options(options[:locale], :precision) options = defaults.merge!(options) precision = options.delete :precision @@ -328,18 +424,18 @@ module ActiveSupport return number unless valid_float?(number) number = Float(number) - defaults = format_translations('human', options[:locale]) + defaults = format_options(options[:locale], :human) options = defaults.merge!(options) #for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros) - storage_units_format = I18n.translate(:'number.human.storage_units.format', :locale => options[:locale], :raise => true) + storage_units_format = translate_number_value_with_default('human.storage_units.format', :locale => options[:locale], :raise => true) base = options[:prefix] == :si ? 1000 : 1024 if number.to_i < base - unit = I18n.translate(:'number.human.storage_units.units.byte', :locale => options[:locale], :count => number.to_i, :raise => true) + unit = translate_number_value_with_default('human.storage_units.units.byte', :locale => options[:locale], :count => number.to_i, :raise => true) storage_units_format.gsub(/%n/, number.to_i.to_s).gsub(/%u/, unit) else max_exp = STORAGE_UNITS.size - 1 @@ -348,7 +444,7 @@ module ActiveSupport number /= base ** exponent unit_key = STORAGE_UNITS[exponent] - unit = I18n.translate(:"number.human.storage_units.units.#{unit_key}", :locale => options[:locale], :count => number, :raise => true) + unit = translate_number_value_with_default("human.storage_units.units.#{unit_key}", :locale => options[:locale], :count => number, :raise => true) formatted_number = self.number_to_rounded(number, options) storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit) @@ -458,7 +554,7 @@ module ActiveSupport return number unless valid_float?(number) number = Float(number) - defaults = format_translations('human', options[:locale]) + defaults = format_options(options[:locale], :human) options = defaults.merge!(options) #for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files @@ -473,7 +569,7 @@ module ActiveSupport when String, Symbol I18n.translate(:"#{units}", :locale => options[:locale], :raise => true) when nil - I18n.translate(:"number.human.decimal_units.units", :locale => options[:locale], :raise => true) + translate_number_value_with_default("human.decimal_units.units", :locale => options[:locale], :raise => true) else raise ArgumentError, ":units must be a Hash or String translation scope." end.keys.map{|e_name| inverted_du[e_name] }.sort_by{|e| -e} @@ -488,34 +584,47 @@ module ActiveSupport when String, Symbol I18n.translate(:"#{units}.#{DECIMAL_UNITS[display_exponent]}", :locale => options[:locale], :count => number.to_i) else - I18n.translate(:"number.human.decimal_units.units.#{DECIMAL_UNITS[display_exponent]}", :locale => options[:locale], :count => number.to_i) + translate_number_value_with_default("human.decimal_units.units.#{DECIMAL_UNITS[display_exponent]}", :locale => options[:locale], :count => number.to_i) end - decimal_format = options[:format] || I18n.translate(:'number.human.decimal_units.format', :locale => options[:locale], :default => "%n %u") + decimal_format = options[:format] || translate_number_value_with_default('human.decimal_units.format', :locale => options[:locale]) formatted_number = self.number_to_rounded(number, options) decimal_format.gsub(/%n/, formatted_number).gsub(/%u/, unit).strip end - def self.private_module_and_instance_method(method_name) + def self.private_module_and_instance_method(method_name) #:nodoc: private method_name private_class_method method_name end private_class_method :private_module_and_instance_method - def format_translations(namespace, locale) #:nodoc: - defaults_translations(locale).merge(translations_for(namespace, locale)) + def format_options(locale, namespace = nil) #:nodoc: + default_format_options(namespace).merge!(i18n_format_options(locale, namespace)) + end + private_module_and_instance_method :format_options + + def default_format_options(namespace = nil) #:nodoc: + options = DEFAULTS[:format].dup + options.merge!(DEFAULTS[namespace][:format]) if namespace + options end - private_module_and_instance_method :format_translations + private_module_and_instance_method :default_format_options - def defaults_translations(locale) #:nodoc: - I18n.translate(:'number.format', :locale => locale, :default => {}) + def i18n_format_options(locale, namespace = nil) #:nodoc: + options = I18n.translate(:'number.format', locale: locale, default: {}).dup + if namespace + options.merge!(I18n.translate(:"number.#{namespace}.format", locale: locale, default: {})) + end + options end - private_module_and_instance_method :defaults_translations + private_module_and_instance_method :i18n_format_options + + def translate_number_value_with_default(key, i18n_options = {}) #:nodoc: + default = key.split('.').reduce(DEFAULTS) { |defaults, k| defaults[k.to_sym] } - def translations_for(namespace, locale) #:nodoc: - I18n.translate(:"number.#{namespace}.format", :locale => locale, :default => {}) + I18n.translate(key, { default: default, scope: :number }.merge!(i18n_options)) end - private_module_and_instance_method :translations_for + private_module_and_instance_method :translate_number_value_with_default def valid_float?(number) #:nodoc: Float(number) diff --git a/activesupport/lib/active_support/string_inquirer.rb b/activesupport/lib/active_support/string_inquirer.rb index f3f3909a90..5f20bfa7bc 100644 --- a/activesupport/lib/active_support/string_inquirer.rb +++ b/activesupport/lib/active_support/string_inquirer.rb @@ -10,12 +10,18 @@ module ActiveSupport # Rails.env.production? # class StringInquirer < String - def method_missing(method_name, *arguments) - if method_name[-1, 1] == "?" - self == method_name[0..-2] - else - super + private + + def respond_to_missing?(method_name, include_private = false) + method_name[-1] == '?' + end + + def method_missing(method_name, *arguments) + if method_name[-1] == '?' + self == method_name[0..-2] + else + super + end end - end end end |