diff options
Diffstat (limited to 'activesupport')
69 files changed, 676 insertions, 780 deletions
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index b91ae65e9f..f2d957f154 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -1,4 +1,5 @@ require 'benchmark' +require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/benchmark' require 'active_support/core_ext/exception' require 'active_support/core_ext/class/attribute_accessors' @@ -43,7 +44,7 @@ module ActiveSupport # ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new) # # => returns MyOwnCacheStore.new def self.lookup_store(*store_option) - store, *parameters = *([ store_option ].flatten) + store, *parameters = *Array.wrap(store_option).flatten case store when Symbol diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb index bec9de86ed..1b6b820ca4 100644 --- a/activesupport/lib/active_support/cache/mem_cache_store.rb +++ b/activesupport/lib/active_support/cache/mem_cache_store.rb @@ -38,6 +38,11 @@ module ActiveSupport # # If no addresses are specified, then MemCacheStore will connect to # localhost port 11211 (the default memcached port). + # + # Instead of addresses one can pass in a MemCache-like object. For example: + # + # require 'memcached' # gem install memcached; uses C bindings to libmemcached + # ActiveSupport::Cache::MemCacheStore.new(Memcached::Rails.new("localhost:11211")) def initialize(*addresses) if addresses.first.respond_to?(:get) @data = addresses.first diff --git a/activesupport/lib/active_support/core_ext/array/wrap.rb b/activesupport/lib/active_support/core_ext/array/wrap.rb index 38bb68c1ec..f48d5ce500 100644 --- a/activesupport/lib/active_support/core_ext/array/wrap.rb +++ b/activesupport/lib/active_support/core_ext/array/wrap.rb @@ -4,11 +4,10 @@ class Array def self.wrap(object) if object.nil? [] - # to_a doesn't work correctly with Array() but to_ary always does - elsif object.respond_to?(:to_a) && !object.respond_to?(:to_ary) - [object] + elsif object.respond_to?(:to_ary) + object.to_ary else - Array(object) + [object] end end end diff --git a/activesupport/lib/active_support/core_ext/date.rb b/activesupport/lib/active_support/core_ext/date.rb deleted file mode 100644 index 6672129076..0000000000 --- a/activesupport/lib/active_support/core_ext/date.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'date' - -require 'active_support/core_ext/date/acts_like' -require 'active_support/core_ext/date/freeze' - -require 'active_support/core_ext/date/calculations' -require 'active_support/core_ext/date/conversions' diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb index b41ad5b686..f6c870035b 100644 --- a/activesupport/lib/active_support/core_ext/date/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date/conversions.rb @@ -1,7 +1,4 @@ require 'active_support/inflector' -require 'active_support/core_ext/time/conversions' -require 'active_support/core_ext/date_time/conversions' -require 'active_support/values/time_zone' class Date DATE_FORMATS = { diff --git a/activesupport/lib/active_support/core_ext/date_time.rb b/activesupport/lib/active_support/core_ext/date_time.rb deleted file mode 100644 index 004fd0ad29..0000000000 --- a/activesupport/lib/active_support/core_ext/date_time.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'active_support/core_ext/time' -require 'active_support/core_ext/date_time/acts_like' -require 'active_support/core_ext/date_time/calculations' -require 'active_support/core_ext/date_time/conversions' -require 'active_support/core_ext/date_time/zones' diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb index 15a303cf04..b11c916f61 100644 --- a/activesupport/lib/active_support/core_ext/enumerable.rb +++ b/activesupport/lib/active_support/core_ext/enumerable.rb @@ -101,15 +101,6 @@ module Enumerable size = block_given? ? select(&block).size : self.size size > 1 end - - # Returns true if none of the elements match the given block. - # - # success = responses.none? {|r| r.status / 100 == 5 } - # - # This is a builtin method in Ruby 1.8.7 and later. - def none?(&block) - !any?(&block) - end unless [].respond_to?(:none?) end class Range #:nodoc: diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb index 190173f8a0..35ccec5df4 100644 --- a/activesupport/lib/active_support/core_ext/hash/conversions.rb +++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb @@ -1,4 +1,5 @@ require 'active_support/time' +require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/hash/reverse_merge' class Hash @@ -138,7 +139,7 @@ class Hash case value.class.to_s when 'Hash' if value['type'] == 'array' - child_key, entries = value.detect { |k,v| k != 'type' } # child_key is throwaway + child_key, entries = Array.wrap(value.detect { |k,v| k != 'type' }) # child_key is throwaway if entries.nil? || (c = value['__content__'] && c.blank?) [] else diff --git a/activesupport/lib/active_support/core_ext/integer.rb b/activesupport/lib/active_support/core_ext/integer.rb index 7ba018ed7f..a44a1b4c74 100644 --- a/activesupport/lib/active_support/core_ext/integer.rb +++ b/activesupport/lib/active_support/core_ext/integer.rb @@ -1,3 +1,3 @@ -require 'active_support/core_ext/integer/even_odd' +require 'active_support/core_ext/integer/multiple' require 'active_support/core_ext/integer/inflections' require 'active_support/core_ext/integer/time' diff --git a/activesupport/lib/active_support/core_ext/integer/even_odd.rb b/activesupport/lib/active_support/core_ext/integer/even_odd.rb deleted file mode 100644 index 8f9a97b44c..0000000000 --- a/activesupport/lib/active_support/core_ext/integer/even_odd.rb +++ /dev/null @@ -1,16 +0,0 @@ -class Integer - # Check whether the integer is evenly divisible by the argument. - def multiple_of?(number) - self % number == 0 - end - - # Is the integer a multiple of 2? - def even? - multiple_of? 2 - end unless method_defined?(:even?) - - # Is the integer not a multiple of 2? - def odd? - !even? - end unless method_defined?(:odd?) -end diff --git a/activesupport/lib/active_support/core_ext/integer/multiple.rb b/activesupport/lib/active_support/core_ext/integer/multiple.rb new file mode 100644 index 0000000000..40bea54c67 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/integer/multiple.rb @@ -0,0 +1,6 @@ +class Integer + # Check whether the integer is evenly divisible by the argument. + def multiple_of?(number) + self % number == 0 + end +end diff --git a/activesupport/lib/active_support/core_ext/kernel/debugger.rb b/activesupport/lib/active_support/core_ext/kernel/debugger.rb index 0813a51383..59e03e3df7 100644 --- a/activesupport/lib/active_support/core_ext/kernel/debugger.rb +++ b/activesupport/lib/active_support/core_ext/kernel/debugger.rb @@ -7,6 +7,7 @@ module Kernel end end + undef :breakpoint if respond_to?(:breakpoint) def breakpoint message = "\n***** The 'breakpoint' command has been renamed 'debugger' -- please change *****\n" defined?(Rails) ? Rails.logger.info(message) : $stderr.puts(message) diff --git a/activesupport/lib/active_support/core_ext/logger.rb b/activesupport/lib/active_support/core_ext/logger.rb index 22749229a3..e4df8fe338 100644 --- a/activesupport/lib/active_support/core_ext/logger.rb +++ b/activesupport/lib/active_support/core_ext/logger.rb @@ -137,10 +137,10 @@ class Logger attr_writer :formatter public :formatter= - alias old_format_datetime format_datetime + alias old_format_datetime format_datetime if method_defined?(:format_datetime) def format_datetime(datetime) datetime end - alias old_msg2str msg2str + alias old_msg2str msg2str if method_defined?(:msg2str) def msg2str(msg) msg end end end diff --git a/activesupport/lib/active_support/core_ext/name_error.rb b/activesupport/lib/active_support/core_ext/name_error.rb index cd165626c8..e1ebd4f91c 100644 --- a/activesupport/lib/active_support/core_ext/name_error.rb +++ b/activesupport/lib/active_support/core_ext/name_error.rb @@ -1,7 +1,9 @@ class NameError # Extract the name of the missing constant from the exception message. def missing_name - $1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message + if /undefined local variable or method/ !~ message + $1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message + end end # Was this exception raised because the given name was missing? diff --git a/activesupport/lib/active_support/core_ext/object/extending.rb b/activesupport/lib/active_support/core_ext/object/extending.rb index bbf6f8563b..0cc74c8298 100644 --- a/activesupport/lib/active_support/core_ext/object/extending.rb +++ b/activesupport/lib/active_support/core_ext/object/extending.rb @@ -50,31 +50,4 @@ class Object def extend_with_included_modules_from(object) #:nodoc: object.extended_by.each { |mod| extend mod } end - - unless defined? instance_exec # 1.9 - module InstanceExecMethods #:nodoc: - end - include InstanceExecMethods - - # Evaluate the block with the given arguments within the context of - # this object, so self is set to the method receiver. - # - # From Mauricio's http://eigenclass.org/hiki/bounded+space+instance_exec - def instance_exec(*args, &block) - begin - old_critical, Thread.critical = Thread.critical, true - n = 0 - n += 1 while respond_to?(method_name = "__instance_exec#{n}") - InstanceExecMethods.module_eval { define_method(method_name, &block) } - ensure - Thread.critical = old_critical - end - - begin - send(method_name, *args) - ensure - InstanceExecMethods.module_eval { remove_method(method_name) } rescue nil - end - end - end end diff --git a/activesupport/lib/active_support/core_ext/object/instance_variables.rb b/activesupport/lib/active_support/core_ext/object/instance_variables.rb index 4ecaab3bbb..866317b17a 100644 --- a/activesupport/lib/active_support/core_ext/object/instance_variables.rb +++ b/activesupport/lib/active_support/core_ext/object/instance_variables.rb @@ -1,11 +1,4 @@ class Object - # Available in 1.8.6 and later. - unless respond_to?(:instance_variable_defined?) - def instance_variable_defined?(variable) - instance_variables.include?(variable.to_s) - end - end - # Returns a hash that maps instance variable names without "@" to their # corresponding values. Keys are strings both in Ruby 1.8 and 1.9. # diff --git a/activesupport/lib/active_support/core_ext/object/misc.rb b/activesupport/lib/active_support/core_ext/object/misc.rb index 80011dfbed..3e3af03cc5 100644 --- a/activesupport/lib/active_support/core_ext/object/misc.rb +++ b/activesupport/lib/active_support/core_ext/object/misc.rb @@ -1,3 +1,2 @@ require 'active_support/core_ext/object/returning' -require 'active_support/core_ext/object/tap' require 'active_support/core_ext/object/with_options' diff --git a/activesupport/lib/active_support/core_ext/object/tap.rb b/activesupport/lib/active_support/core_ext/object/tap.rb deleted file mode 100644 index db7e715e2d..0000000000 --- a/activesupport/lib/active_support/core_ext/object/tap.rb +++ /dev/null @@ -1,16 +0,0 @@ -class Object - # Yields <code>x</code> to the block, and then returns <code>x</code>. - # The primary purpose of this method is to "tap into" a method chain, - # in order to perform operations on intermediate results within the chain. - # - # (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a. - # tap { |x| puts "array: #{x.inspect}" }. - # select { |x| x%2 == 0 }. - # tap { |x| puts "evens: #{x.inspect}" }. - # map { |x| x*x }. - # tap { |x| puts "squares: #{x.inspect}" } - def tap - yield self - self - end unless Object.respond_to?(:tap) -end diff --git a/activesupport/lib/active_support/core_ext/string.rb b/activesupport/lib/active_support/core_ext/string.rb index 6c52f12712..0365b6af1c 100644 --- a/activesupport/lib/active_support/core_ext/string.rb +++ b/activesupport/lib/active_support/core_ext/string.rb @@ -4,7 +4,6 @@ require 'active_support/core_ext/string/multibyte' require 'active_support/core_ext/string/starts_ends_with' require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/string/access' -require 'active_support/core_ext/string/iterators' require 'active_support/core_ext/string/xchar' require 'active_support/core_ext/string/behavior' require 'active_support/core_ext/string/interpolation' diff --git a/activesupport/lib/active_support/core_ext/string/access.rb b/activesupport/lib/active_support/core_ext/string/access.rb index 57385d86d2..182b3e745d 100644 --- a/activesupport/lib/active_support/core_ext/string/access.rb +++ b/activesupport/lib/active_support/core_ext/string/access.rb @@ -1,3 +1,5 @@ +require "active_support/multibyte" + class String unless '1.9'.respond_to?(:force_encoding) # Returns the character at the +position+ treating the string as an array (where 0 is the first character). diff --git a/activesupport/lib/active_support/core_ext/string/bytesize.rb b/activesupport/lib/active_support/core_ext/string/bytesize.rb deleted file mode 100644 index ed051b921e..0000000000 --- a/activesupport/lib/active_support/core_ext/string/bytesize.rb +++ /dev/null @@ -1,5 +0,0 @@ -unless '1.9'.respond_to?(:bytesize) - class String - alias :bytesize :size - end -end diff --git a/activesupport/lib/active_support/core_ext/string/interpolation.rb b/activesupport/lib/active_support/core_ext/string/interpolation.rb index d9159b690a..2048d35091 100644 --- a/activesupport/lib/active_support/core_ext/string/interpolation.rb +++ b/activesupport/lib/active_support/core_ext/string/interpolation.rb @@ -5,8 +5,7 @@ You may redistribute it and/or modify it under the same license terms as Ruby. =end -if RUBY_VERSION < '1.9' - require 'active_support/core_ext/string/bytesize' +if RUBY_VERSION < '1.9' && !"".respond_to?(:interpolate_without_ruby_19_syntax) # KeyError is raised by String#% when the string contains a named placeholder # that is not contained in the given arguments hash. Ruby 1.9 includes and diff --git a/activesupport/lib/active_support/core_ext/string/iterators.rb b/activesupport/lib/active_support/core_ext/string/iterators.rb deleted file mode 100644 index 2f8aa84024..0000000000 --- a/activesupport/lib/active_support/core_ext/string/iterators.rb +++ /dev/null @@ -1,13 +0,0 @@ -unless '1.9'.respond_to?(:each_char) - class String - # Yields a single-character string for each character in the string. - # When $KCODE = 'UTF8', multi-byte characters are yielded appropriately. - def each_char - require 'strscan' unless defined? ::StringScanner - scanner, char = ::StringScanner.new(self), /./mu - while c = scanner.scan(char) - yield c - end - end - end -end diff --git a/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb b/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb index f65bb8f75b..641acf62d0 100644 --- a/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb +++ b/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb @@ -1,18 +1,4 @@ class String - unless '1.8.7 and up'.respond_to?(:start_with?) - # Does the string start with the specified +prefix+? - def start_with?(prefix) - prefix = prefix.to_s - self[0, prefix.length] == prefix - end - - # Does the string end with the specified +suffix+? - def end_with?(suffix) - suffix = suffix.to_s - self[-suffix.length, suffix.length] == suffix - end - end - alias_method :starts_with?, :start_with? alias_method :ends_with?, :end_with? end diff --git a/activesupport/lib/active_support/core_ext/symbol.rb b/activesupport/lib/active_support/core_ext/symbol.rb deleted file mode 100644 index c103cd9dcf..0000000000 --- a/activesupport/lib/active_support/core_ext/symbol.rb +++ /dev/null @@ -1 +0,0 @@ -require 'active_support/core_ext/symbol/to_proc' diff --git a/activesupport/lib/active_support/core_ext/symbol/to_proc.rb b/activesupport/lib/active_support/core_ext/symbol/to_proc.rb deleted file mode 100644 index 520369452b..0000000000 --- a/activesupport/lib/active_support/core_ext/symbol/to_proc.rb +++ /dev/null @@ -1,14 +0,0 @@ -class Symbol - # Turns the symbol into a simple proc, which is especially useful for enumerations. Examples: - # - # # The same as people.collect { |p| p.name } - # people.collect(&:name) - # - # # The same as people.select { |p| p.manager? }.collect { |p| p.salary } - # people.select(&:manager?).collect(&:salary) - # - # This is a builtin method in Ruby 1.8.7 and later. - def to_proc - Proc.new { |*args| args.shift.__send__(self, *args) } - end unless :to_proc.respond_to?(:to_proc) -end diff --git a/activesupport/lib/active_support/core_ext/time.rb b/activesupport/lib/active_support/core_ext/time.rb deleted file mode 100644 index b28f7f1a32..0000000000 --- a/activesupport/lib/active_support/core_ext/time.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'date' -require 'time' - -require 'active_support/core_ext/time/publicize_conversion_methods' -require 'active_support/core_ext/time/marshal_with_utc_flag' - -require 'active_support/core_ext/time/acts_like' -require 'active_support/core_ext/time/calculations' -require 'active_support/core_ext/time/conversions' -require 'active_support/core_ext/time/zones' diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 7f6f012721..e858bcdc80 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -339,7 +339,7 @@ module ActiveSupport #:nodoc: next end [ nesting_camel ] - end.flatten.compact.uniq + end.compact.flatten.compact.uniq end # Search for a file in load_paths matching the provided suffix. diff --git a/activesupport/lib/active_support/deprecated_callbacks.rb b/activesupport/lib/active_support/deprecated_callbacks.rb index 20fb03cbeb..f56fef0b6d 100644 --- a/activesupport/lib/active_support/deprecated_callbacks.rb +++ b/activesupport/lib/active_support/deprecated_callbacks.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/array/extract_options' +require 'active_support/core_ext/array/wrap' module ActiveSupport # Callbacks are hooks into the lifecycle of an object that allow you to trigger logic @@ -194,8 +195,8 @@ module ActiveSupport end def should_run_callback?(*args) - [options[:if]].flatten.compact.all? { |a| evaluate_method(a, *args) } && - ![options[:unless]].flatten.compact.any? { |a| evaluate_method(a, *args) } + Array.wrap(options[:if]).flatten.compact.all? { |a| evaluate_method(a, *args) } && + !Array.wrap(options[:unless]).flatten.compact.any? { |a| evaluate_method(a, *args) } end end diff --git a/activesupport/lib/active_support/inflector.rb b/activesupport/lib/active_support/inflector.rb index 67aea2782f..215a60eba7 100644 --- a/activesupport/lib/active_support/inflector.rb +++ b/activesupport/lib/active_support/inflector.rb @@ -1,410 +1,7 @@ -# encoding: utf-8 -require 'iconv' -require 'active_support/core_ext/object/blank' -require 'active_support/core_ext/string/access' -require 'active_support/core_ext/string/multibyte' - -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 - # in inflections.rb. - # - # The Rails core team has stated patches for the inflections library will not be accepted - # in order to avoid breaking legacy applications which may be relying on errant inflections. - # If you discover an incorrect inflection and require it for your application, you'll need - # to correct it yourself (explained below). - 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. Examples: - # - # ActiveSupport::Inflector.inflections do |inflect| - # inflect.plural /^(ox)$/i, '\1\2en' - # inflect.singular /^(ox)en/i, '\1' - # - # inflect.irregular 'octopus', 'octopi' - # - # inflect.uncountable "equipment" - # end - # - # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the - # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may - # already have been loaded. - class Inflections - def self.instance - @__instance__ ||= new - end - - attr_reader :plurals, :singulars, :uncountables, :humans - - def initialize - @plurals, @singulars, @uncountables, @humans = [], [], [], [] - end - - # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression. - # The replacement should always be a string that may include references to the matched data from the rule. - def plural(rule, replacement) - @uncountables.delete(rule) if rule.is_a?(String) - @uncountables.delete(replacement) - @plurals.insert(0, [rule, replacement]) - end - - # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression. - # The replacement should always be a string that may include references to the matched data from the rule. - def singular(rule, replacement) - @uncountables.delete(rule) if rule.is_a?(String) - @uncountables.delete(replacement) - @singulars.insert(0, [rule, replacement]) - end - - # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used - # for strings, not regular expressions. You simply pass the irregular in singular and plural form. - # - # Examples: - # irregular 'octopus', 'octopi' - # irregular 'person', 'people' - def irregular(singular, plural) - @uncountables.delete(singular) - @uncountables.delete(plural) - if singular[0,1].upcase == plural[0,1].upcase - plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1]) - plural(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + plural[1..-1]) - singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1]) - else - plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1]) - plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1]) - plural(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), plural[0,1].upcase + plural[1..-1]) - plural(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), plural[0,1].downcase + plural[1..-1]) - singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1]) - singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1]) - end - end - - # Add uncountable words that shouldn't be attempted inflected. - # - # Examples: - # uncountable "money" - # uncountable "money", "information" - # uncountable %w( money information rice ) - def uncountable(*words) - (@uncountables << words).flatten! - end - - # Specifies a humanized form of a string by a regular expression rule or by a string mapping. - # When using a regular expression based replacement, the normal humanize formatting is called after the replacement. - # When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name') - # - # Examples: - # human /_cnt$/i, '\1_count' - # human "legacy_col_person_name", "Name" - def human(rule, replacement) - @humans.insert(0, [rule, replacement]) - end - - # Clears the loaded inflections within a given scope (default is <tt>:all</tt>). - # Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>, - # <tt>:singulars</tt>, <tt>:uncountables</tt>, <tt>:humans</tt>. - # - # Examples: - # clear :all - # clear :plurals - def clear(scope = :all) - case scope - when :all - @plurals, @singulars, @uncountables = [], [], [] - else - instance_variable_set "@#{scope}", [] - end - end - end - - # Yields a singleton instance of Inflector::Inflections so you can specify additional - # inflector rules. - # - # Example: - # ActiveSupport::Inflector.inflections do |inflect| - # inflect.uncountable "rails" - # end - def inflections - if block_given? - yield Inflections.instance - else - 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.include?(result.downcase) - 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. - # - # +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces. - # - # Examples: - # "active_record".camelize # => "ActiveRecord" - # "active_record".camelize(:lower) # => "activeRecord" - # "active_record/errors".camelize # => "ActiveRecord::Errors" - # "active_record/errors".camelize(:lower) # => "activeRecord::Errors" - 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 } - else - lower_case_and_underscored_word.to_s.first.downcase + camelize(lower_case_and_underscored_word)[1..-1] - end - 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 - - # The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string. - # - # Changes '::' to '/' to convert namespaces to paths. - # - # Examples: - # "ActiveRecord".underscore # => "active_record" - # "ActiveRecord::Errors".underscore # => active_record/errors - def underscore(camel_cased_word) - camel_cased_word.to_s.gsub(/::/, '/'). - gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). - gsub(/([a-z\d])([A-Z])/,'\1_\2'). - tr("-", "_"). - downcase - end - - # Replaces underscores with dashes in the string. - # - # Example: - # "puni_puni" # => "puni-puni" - def dasherize(underscored_word) - underscored_word.gsub(/_/, '-') - 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 - - # Removes the module part from the expression in the string. - # - # Examples: - # "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections" - # "Inflections".demodulize # => "Inflections" - def demodulize(class_name_in_module) - class_name_in_module.to_s.gsub(/^.*::/, '') - end - - # Replaces special characters in a string so that it may be used as part of a 'pretty' URL. - # - # ==== Examples - # - # class Person - # def to_param - # "#{id}-#{name.parameterize}" - # end - # end - # - # @person = Person.find(1) - # # => #<Person id: 1, name: "Donald E. Knuth"> - # - # <%= link_to(@person.name, person_path(@person)) %> - # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a> - def parameterize(string, sep = '-') - # replace accented chars with their ascii equivalents - parameterized_string = transliterate(string) - # Turn unwanted chars into the separator - parameterized_string.gsub!(/[^a-z0-9\-_\+]+/i, sep) - unless sep.blank? - re_sep = Regexp.escape(sep) - # No more than one of the separator in a row. - parameterized_string.gsub!(/#{re_sep}{2,}/, sep) - # Remove leading/trailing separator. - parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '') - end - parameterized_string.downcase - end - - - # Replaces accented characters with their ascii equivalents. - def transliterate(string) - Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s - end - - if RUBY_VERSION >= '1.9' - undef_method :transliterate - def transliterate(string) - warn "Ruby 1.9 doesn't support Unicode normalization yet" - string.dup - end - - # The iconv transliteration code doesn't function correctly - # on some platforms, but it's very fast where it does function. - elsif "foo" != (Inflector.transliterate("föö") rescue nil) - undef_method :transliterate - def transliterate(string) - string.mb_chars.normalize(:kd). # Decompose accented characters - gsub(/[^\x00-\x7F]+/, '') # Remove anything non-ASCII entirely (e.g. diacritics). - end - 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 - - # Creates a foreign key name from a class name. - # +separate_class_name_and_id_with_underscore+ sets whether - # the method should put '_' between the name and 'id'. - # - # Examples: - # "Message".foreign_key # => "message_id" - # "Message".foreign_key(false) # => "messageid" - # "Admin::Post".foreign_key # => "post_id" - def foreign_key(class_name, separate_class_name_and_id_with_underscore = true) - underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id") - end - - # Ruby 1.9 introduces an inherit argument for Module#const_get and - # #const_defined? and changes their default behavior. - if Module.method(:const_get).arity == 1 - # Tries to find a constant with the name specified in the argument string: - # - # "Module".constantize # => Module - # "Test::Unit".constantize # => Test::Unit - # - # The name is assumed to be the one of a top-level constant, no matter whether - # it starts with "::" or not. No lexical context is taken into account: - # - # C = 'outside' - # module M - # C = 'inside' - # C # => 'inside' - # "C".constantize # => 'outside', same as ::C - # end - # - # NameError is raised when the name is not in CamelCase or the constant is - # unknown. - def constantize(camel_cased_word) - names = camel_cased_word.split('::') - names.shift if names.empty? || names.first.empty? - - constant = Object - names.each do |name| - constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name) - end - constant - end - else - 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) || constant.const_missing(name) - end - constant - end - end - - # Turns a number into an ordinal string used to denote the position in an - # ordered sequence such as 1st, 2nd, 3rd, 4th. - # - # Examples: - # ordinalize(1) # => "1st" - # ordinalize(2) # => "2nd" - # ordinalize(1002) # => "1002nd" - # ordinalize(1003) # => "1003rd" - def ordinalize(number) - if (11..13).include?(number.to_i % 100) - "#{number}th" - else - case number.to_i % 10 - when 1; "#{number}st" - when 2; "#{number}nd" - when 3; "#{number}rd" - else "#{number}th" - end - end - end - end -end - # in case active_support/inflector is required without the rest of active_support +require 'active_support/inflector/inflections' +require 'active_support/inflector/transliterate' +require 'active_support/inflector/methods' + require 'active_support/inflections' require 'active_support/core_ext/string/inflections' diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb new file mode 100644 index 0000000000..785e245ea4 --- /dev/null +++ b/activesupport/lib/active_support/inflector/inflections.rb @@ -0,0 +1,211 @@ +module ActiveSupport + module Inflector + # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional + # inflection rules. Examples: + # + # ActiveSupport::Inflector.inflections do |inflect| + # inflect.plural /^(ox)$/i, '\1\2en' + # inflect.singular /^(ox)en/i, '\1' + # + # inflect.irregular 'octopus', 'octopi' + # + # inflect.uncountable "equipment" + # end + # + # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the + # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may + # already have been loaded. + class Inflections + def self.instance + @__instance__ ||= new + end + + attr_reader :plurals, :singulars, :uncountables, :humans + + def initialize + @plurals, @singulars, @uncountables, @humans = [], [], [], [] + end + + # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression. + # The replacement should always be a string that may include references to the matched data from the rule. + def plural(rule, replacement) + @uncountables.delete(rule) if rule.is_a?(String) + @uncountables.delete(replacement) + @plurals.insert(0, [rule, replacement]) + end + + # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression. + # The replacement should always be a string that may include references to the matched data from the rule. + def singular(rule, replacement) + @uncountables.delete(rule) if rule.is_a?(String) + @uncountables.delete(replacement) + @singulars.insert(0, [rule, replacement]) + end + + # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used + # for strings, not regular expressions. You simply pass the irregular in singular and plural form. + # + # Examples: + # irregular 'octopus', 'octopi' + # irregular 'person', 'people' + def irregular(singular, plural) + @uncountables.delete(singular) + @uncountables.delete(plural) + if singular[0,1].upcase == plural[0,1].upcase + plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1]) + plural(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + plural[1..-1]) + singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1]) + else + plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1]) + plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1]) + plural(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), plural[0,1].upcase + plural[1..-1]) + plural(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), plural[0,1].downcase + plural[1..-1]) + singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1]) + singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1]) + end + end + + # Add uncountable words that shouldn't be attempted inflected. + # + # Examples: + # uncountable "money" + # uncountable "money", "information" + # uncountable %w( money information rice ) + def uncountable(*words) + (@uncountables << words).flatten! + end + + # Specifies a humanized form of a string by a regular expression rule or by a string mapping. + # When using a regular expression based replacement, the normal humanize formatting is called after the replacement. + # When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name') + # + # Examples: + # human /_cnt$/i, '\1_count' + # human "legacy_col_person_name", "Name" + def human(rule, replacement) + @humans.insert(0, [rule, replacement]) + end + + # Clears the loaded inflections within a given scope (default is <tt>:all</tt>). + # Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>, + # <tt>:singulars</tt>, <tt>:uncountables</tt>, <tt>:humans</tt>. + # + # Examples: + # clear :all + # clear :plurals + def clear(scope = :all) + case scope + when :all + @plurals, @singulars, @uncountables = [], [], [] + else + instance_variable_set "@#{scope}", [] + end + end + end + + # Yields a singleton instance of Inflector::Inflections so you can specify additional + # inflector rules. + # + # Example: + # ActiveSupport::Inflector.inflections do |inflect| + # inflect.uncountable "rails" + # end + def inflections + if block_given? + yield Inflections.instance + else + 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.include?(result.downcase) + 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 new file mode 100644 index 0000000000..41277893e3 --- /dev/null +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -0,0 +1,139 @@ +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 + # in inflections.rb. + # + # The Rails core team has stated patches for the inflections library will not be accepted + # in order to avoid breaking legacy applications which may be relying on errant inflections. + # If you discover an incorrect inflection and require it for your application, you'll need + # to correct it yourself (explained below). + module Inflector + extend self + + # By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+ + # is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase. + # + # +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces. + # + # Examples: + # "active_record".camelize # => "ActiveRecord" + # "active_record".camelize(:lower) # => "activeRecord" + # "active_record/errors".camelize # => "ActiveRecord::Errors" + # "active_record/errors".camelize(:lower) # => "activeRecord::Errors" + 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 } + else + lower_case_and_underscored_word.to_s[0].chr.downcase + camelize(lower_case_and_underscored_word)[1..-1] + end + end + + # The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string. + # + # Changes '::' to '/' to convert namespaces to paths. + # + # Examples: + # "ActiveRecord".underscore # => "active_record" + # "ActiveRecord::Errors".underscore # => active_record/errors + def underscore(camel_cased_word) + camel_cased_word.to_s.gsub(/::/, '/'). + gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). + gsub(/([a-z\d])([A-Z])/,'\1_\2'). + tr("-", "_"). + downcase + end + + # Replaces underscores with dashes in the string. + # + # Example: + # "puni_puni" # => "puni-puni" + def dasherize(underscored_word) + underscored_word.gsub(/_/, '-') + end + + # Removes the module part from the expression in the string. + # + # Examples: + # "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections" + # "Inflections".demodulize # => "Inflections" + def demodulize(class_name_in_module) + class_name_in_module.to_s.gsub(/^.*::/, '') + end + + # Creates a foreign key name from a class name. + # +separate_class_name_and_id_with_underscore+ sets whether + # the method should put '_' between the name and 'id'. + # + # Examples: + # "Message".foreign_key # => "message_id" + # "Message".foreign_key(false) # => "messageid" + # "Admin::Post".foreign_key # => "post_id" + def foreign_key(class_name, separate_class_name_and_id_with_underscore = true) + underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id") + end + + # Ruby 1.9 introduces an inherit argument for Module#const_get and + # #const_defined? and changes their default behavior. + if Module.method(:const_get).arity == 1 + # Tries to find a constant with the name specified in the argument string: + # + # "Module".constantize # => Module + # "Test::Unit".constantize # => Test::Unit + # + # The name is assumed to be the one of a top-level constant, no matter whether + # it starts with "::" or not. No lexical context is taken into account: + # + # C = 'outside' + # module M + # C = 'inside' + # C # => 'inside' + # "C".constantize # => 'outside', same as ::C + # end + # + # NameError is raised when the name is not in CamelCase or the constant is + # unknown. + def constantize(camel_cased_word) + names = camel_cased_word.split('::') + names.shift if names.empty? || names.first.empty? + + constant = Object + names.each do |name| + constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name) + end + constant + end + else + 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) || constant.const_missing(name) + end + constant + end + end + + # Turns a number into an ordinal string used to denote the position in an + # ordered sequence such as 1st, 2nd, 3rd, 4th. + # + # Examples: + # ordinalize(1) # => "1st" + # ordinalize(2) # => "2nd" + # ordinalize(1002) # => "1002nd" + # ordinalize(1003) # => "1003rd" + def ordinalize(number) + if (11..13).include?(number.to_i % 100) + "#{number}th" + else + case number.to_i % 10 + when 1; "#{number}st" + when 2; "#{number}nd" + when 3; "#{number}rd" + else "#{number}th" + end + end + end + end +end
\ No newline at end of file diff --git a/activesupport/lib/active_support/inflector/transliterate.rb b/activesupport/lib/active_support/inflector/transliterate.rb new file mode 100644 index 0000000000..30a9072ee1 --- /dev/null +++ b/activesupport/lib/active_support/inflector/transliterate.rb @@ -0,0 +1,61 @@ +# encoding: utf-8 +require 'iconv' +require 'active_support/core_ext/string/multibyte' + +module ActiveSupport + module Inflector + extend self + + # Replaces accented characters with their ascii equivalents. + def transliterate(string) + Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s + end + + if RUBY_VERSION >= '1.9' + undef_method :transliterate + def transliterate(string) + warn "Ruby 1.9 doesn't support Unicode normalization yet" + string.dup + end + + # The iconv transliteration code doesn't function correctly + # on some platforms, but it's very fast where it does function. + elsif "foo" != (Inflector.transliterate("föö") rescue nil) + undef_method :transliterate + def transliterate(string) + string.mb_chars.normalize(:kd). # Decompose accented characters + gsub(/[^\x00-\x7F]+/, '') # Remove anything non-ASCII entirely (e.g. diacritics). + end + end + + # Replaces special characters in a string so that it may be used as part of a 'pretty' URL. + # + # ==== Examples + # + # class Person + # def to_param + # "#{id}-#{name.parameterize}" + # end + # end + # + # @person = Person.find(1) + # # => #<Person id: 1, name: "Donald E. Knuth"> + # + # <%= link_to(@person.name, person_path(@person)) %> + # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a> + def parameterize(string, sep = '-') + # replace accented chars with their ascii equivalents + parameterized_string = transliterate(string) + # Turn unwanted chars into the separator + parameterized_string.gsub!(/[^a-z0-9\-_\+]+/i, sep) + unless sep.nil? || sep.empty? + re_sep = Regexp.escape(sep) + # No more than one of the separator in a row. + parameterized_string.gsub!(/#{re_sep}{2,}/, sep) + # Remove leading/trailing separator. + parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '') + end + parameterized_string.downcase + end + end +end
\ No newline at end of file diff --git a/activesupport/lib/active_support/json/backends/jsongem.rb b/activesupport/lib/active_support/json/backends/jsongem.rb index c6c17a3c4e..cfe28d7bb9 100644 --- a/activesupport/lib/active_support/json/backends/jsongem.rb +++ b/activesupport/lib/active_support/json/backends/jsongem.rb @@ -23,15 +23,18 @@ module ActiveSupport private def convert_dates_from(data) case data - when DATE_REGEX - DateTime.parse(data) - when Array - data.map! { |d| convert_dates_from(d) } - when Hash - data.each do |key, value| - data[key] = convert_dates_from(value) - end - else data + when nil + nil + when DATE_REGEX + DateTime.parse(data) + when Array + data.map! { |d| convert_dates_from(d) } + when Hash + data.each do |key, value| + data[key] = convert_dates_from(value) + end + else + data end end end diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index 8e8f9022c1..3c15056c41 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -6,7 +6,7 @@ require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/object/instance_variables' require 'active_support/deprecation' -require 'active_support/time_with_zone' +require 'active_support/time' # Hack to load json gem first so we can overwrite its to_json. begin diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index 282346b1a6..87e4b1ad33 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/string/bytesize' - module ActiveSupport # MessageVerifier makes it easy to generate and verify messages which are signed # to prevent tampering. diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index d372b0ab1f..c7225fec06 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -1,4 +1,5 @@ # encoding: utf-8 +require 'active_support/core_ext/string/access' require 'active_support/core_ext/string/behavior' module ActiveSupport #:nodoc: @@ -197,7 +198,7 @@ module ActiveSupport #:nodoc: # 'Café périferôl'.mb_chars.index('ô') #=> 12 # 'Café périferôl'.mb_chars.index(/\w/u) #=> 0 def index(needle, offset=0) - wrapped_offset = self.first(offset).wrapped_string.length + wrapped_offset = first(offset).wrapped_string.length index = @wrapped_string.index(needle, wrapped_offset) index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil end @@ -211,7 +212,7 @@ module ActiveSupport #:nodoc: # 'Café périferôl'.mb_chars.rindex(/\w/u) #=> 13 def rindex(needle, offset=nil) offset ||= length - wrapped_offset = self.first(offset).wrapped_string.length + wrapped_offset = first(offset).wrapped_string.length index = @wrapped_string.rindex(needle, wrapped_offset) index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil end diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb index 9eae3bebe2..e2540cd598 100644 --- a/activesupport/lib/active_support/notifications.rb +++ b/activesupport/lib/active_support/notifications.rb @@ -41,7 +41,7 @@ module ActiveSupport # to subscribers in a thread. You can use any queue implementation you want. # module Notifications - mattr_accessor :queue + mattr_accessor :queue, :listener class << self delegate :instrument, :transaction_id, :transaction, :to => :instrumenter @@ -54,8 +54,13 @@ module ActiveSupport @publisher ||= Publisher.new(queue) end - def subscribe(pattern=nil, &block) - Subscriber.new(queue).bind(pattern).subscribe(&block) + def subscriber + @subscriber ||= Subscriber.new(queue) + end + + def subscribe(pattern=nil, options={}, &block) + with = options[:with] || listener + subscriber.bind(with, pattern).subscribe(&block) end end @@ -104,14 +109,15 @@ module ActiveSupport @queue = queue end - def bind(pattern) - @pattern = pattern + def bind(listener, pattern) + @listener = listener + @pattern = pattern self end def subscribe - @queue.subscribe(@pattern) do |*args| - yield *args + @queue.subscribe(@listener, @pattern) do |*args| + yield(*args) end end end @@ -138,54 +144,70 @@ module ActiveSupport end end - # This is a default queue implementation that ships with Notifications. It - # consumes events in a thread and publish them to all registered subscribers. - # - class LittleFanout - def initialize - @listeners = [] - @stream = Queue.new + class AsyncListener + def initialize(pattern, &block) + @pattern = pattern + @subscriber = block + @queue = Queue.new Thread.new { consume } end - def publish(*args) - @stream.push(args) - end - - def subscribe(pattern=nil, &block) - @listeners << Listener.new(pattern, &block) + def publish(name, *args) + if !@pattern || @pattern === name.to_s + @queue << args.unshift(name) + end end def consume - while args = @stream.shift - @listeners.each { |l| l.publish(*args) } + while args = @queue.shift + @subscriber.call(*args) end end - class Listener - # attr_reader :thread + def drained? + @queue.size.zero? + end + end - def initialize(pattern, &block) - @pattern = pattern - @subscriber = block - @queue = Queue.new - Thread.new { consume } - end + class SyncListener + def initialize(pattern, &block) + @pattern = pattern + @subscriber = block + end - def publish(name, *args) - if !@pattern || @pattern === name.to_s - @queue << args.unshift(name) - end + def publish(name, *args) + if !@pattern || @pattern === name.to_s + @subscriber.call(*args.unshift(name)) end + end - def consume - while args = @queue.shift - @subscriber.call(*args) - end - end + def drained? + true + end + end + + # This is a default queue implementation that ships with Notifications. It + # consumes events in a thread and publish them to all registered subscribers. + # + class LittleFanout + def initialize + @listeners = [] + end + + def publish(*args) + @listeners.each { |l| l.publish(*args) } + end + + def subscribe(listener, pattern=nil, &block) + @listeners << listener.new(pattern, &block) + end + + def drained? + @listeners.all? &:drained? end end end - Notifications.queue = Notifications::LittleFanout.new + Notifications.queue = Notifications::LittleFanout.new + Notifications.listener = Notifications::AsyncListener end diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb index 879662c16c..f0119f5994 100644 --- a/activesupport/lib/active_support/rescuable.rb +++ b/activesupport/lib/active_support/rescuable.rb @@ -81,7 +81,7 @@ module ActiveSupport def handler_for_rescue(exception) # We go from right to left because pairs are pushed onto rescue_handlers # as rescue_from declarations are found. - _, rescuer = Array(rescue_handlers).reverse.detect do |klass_name, handler| + _, rescuer = rescue_handlers.reverse.detect do |klass_name, handler| # The purpose of allowing strings in rescue_from is to support the # declaration of handler associations for exception classes whose # definition is yet unknown. diff --git a/activesupport/lib/active_support/ruby/shim.rb b/activesupport/lib/active_support/ruby/shim.rb index 37c57c485a..f811239077 100644 --- a/activesupport/lib/active_support/ruby/shim.rb +++ b/activesupport/lib/active_support/ruby/shim.rb @@ -4,21 +4,15 @@ # Date next_year, next_month # DateTime to_date, to_datetime, xmlschema # Enumerable group_by, each_with_object, none? -# Integer even?, odd? -# Object tap # Process Process.daemon # REXML security fix # String ord -# Symbol to_proc # Time to_date, to_time, to_datetime require 'active_support' require 'active_support/core_ext/date/calculations' require 'active_support/core_ext/date_time/conversions' require 'active_support/core_ext/enumerable' -require 'active_support/core_ext/integer/even_odd' -require 'active_support/core_ext/object/tap' require 'active_support/core_ext/process/daemon' require 'active_support/core_ext/string/conversions' require 'active_support/core_ext/rexml' -require 'active_support/core_ext/symbol/to_proc' require 'active_support/core_ext/time/conversions' diff --git a/activesupport/lib/active_support/testing/isolation.rb b/activesupport/lib/active_support/testing/isolation.rb index c75b59c284..81f7e3c9df 100644 --- a/activesupport/lib/active_support/testing/isolation.rb +++ b/activesupport/lib/active_support/testing/isolation.rb @@ -1,10 +1,25 @@ module ActiveSupport module Testing + class RemoteError < StandardError + + attr_reader :message, :backtrace + + def initialize(exception) + @message = "caught #{exception.class.name}: #{exception.message}" + @backtrace = exception.backtrace + end + end + class ProxyTestResult def initialize @calls = [] end + def add_error(e) + e = Test::Unit::Error.new(e.test_name, RemoteError.new(e.exception)) + @calls << [:add_error, e] + end + def __replay__(result) @calls.each do |name, args| result.send(name, *args) diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb index 7952eb50c3..0e998d2dbe 100644 --- a/activesupport/lib/active_support/testing/setup_and_teardown.rb +++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb @@ -21,12 +21,12 @@ module ActiveSupport run_callbacks :setup result = super rescue Exception => e - result = runner.puke(self.class, self.name, e) + result = runner.puke(self.class, method_name, e) ensure begin run_callbacks :teardown, :enumerator => :reverse_each rescue Exception => e - result = runner.puke(self.class, self.name, e) + result = runner.puke(self.class, method_name, e) end end result diff --git a/activesupport/lib/active_support/time.rb b/activesupport/lib/active_support/time.rb index d36a683601..0f421421d0 100644 --- a/activesupport/lib/active_support/time.rb +++ b/activesupport/lib/active_support/time.rb @@ -1,7 +1,4 @@ require 'active_support' -require 'active_support/core_ext/time' -require 'active_support/core_ext/date' -require 'active_support/core_ext/date_time' module ActiveSupport autoload :Duration, 'active_support/duration' @@ -12,3 +9,26 @@ module ActiveSupport [Duration, TimeWithZone, TimeZone] end end + +require 'date' +require 'time' + +require 'active_support/core_ext/time/publicize_conversion_methods' +require 'active_support/core_ext/time/marshal_with_utc_flag' +require 'active_support/core_ext/time/acts_like' +require 'active_support/core_ext/time/calculations' +require 'active_support/core_ext/time/conversions' +require 'active_support/core_ext/time/zones' + +require 'active_support/core_ext/date/acts_like' +require 'active_support/core_ext/date/freeze' +require 'active_support/core_ext/date/calculations' +require 'active_support/core_ext/date/conversions' + +require 'active_support/core_ext/date_time/acts_like' +require 'active_support/core_ext/date_time/calculations' +require 'active_support/core_ext/date_time/conversions' +require 'active_support/core_ext/date_time/zones' + +require 'active_support/core_ext/integer/time' +require 'active_support/core_ext/numeric/time' diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index a64128e49e..8304f6c434 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -1,10 +1,4 @@ -require 'active_support/duration' -require 'active_support/values/time_zone' -require 'active_support/core_ext/numeric/time' -require 'active_support/core_ext/integer/time' -require 'active_support/core_ext/time/conversions' -require 'active_support/core_ext/date/conversions' -require 'active_support/core_ext/date_time/conversions' +require "active_support/values/time_zone" module ActiveSupport # A Time-like class that can represent a time in any time zone. Necessary because standard Ruby Time instances are diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 53a4c7acf5..cbb8e890ae 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -1,6 +1,4 @@ -require 'active_support/core_ext/time' -require 'active_support/core_ext/date' -require 'active_support/core_ext/date_time' +require 'active_support/core_ext/object/blank' # The TimeZone class serves as a wrapper around TZInfo::Timezone instances. It allows us to do the following: # diff --git a/activesupport/lib/active_support/vendor.rb b/activesupport/lib/active_support/vendor.rb index 4a711b7e25..eb5080888c 100644 --- a/activesupport/lib/active_support/vendor.rb +++ b/activesupport/lib/active_support/vendor.rb @@ -9,7 +9,7 @@ end unless ActiveSupport.requirable? lib # Try to activate a gem ~> satisfying the requested version first. begin - gem lib, "~> #{version}" + gem lib, ">= #{version}" # Use the vendored lib if the gem's missing or we aren't using RubyGems. rescue LoadError, NoMethodError # There could be symlinks diff --git a/activesupport/lib/active_support/whiny_nil.rb b/activesupport/lib/active_support/whiny_nil.rb index 36fe9510ba..c4aaba7ab3 100644 --- a/activesupport/lib/active_support/whiny_nil.rb +++ b/activesupport/lib/active_support/whiny_nil.rb @@ -43,7 +43,14 @@ class NilClass private def method_missing(method, *args, &block) - raise_nil_warning_for METHOD_CLASS_MAP[method], method, caller + # Ruby 1.9.2: disallow explicit coercion via method_missing. + if method == :to_ary || method == :to_str + super + elsif klass = METHOD_CLASS_MAP[method] + raise_nil_warning_for klass, method, caller + else + super + end end # Raises a NoMethodError when you attempt to call a method on +nil+. @@ -55,4 +62,3 @@ class NilClass raise NoMethodError, message, with_caller || caller end end - diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb index f390c66838..dda139372e 100644 --- a/activesupport/test/abstract_unit.rb +++ b/activesupport/test/abstract_unit.rb @@ -1,22 +1,15 @@ ORIG_ARGV = ARGV.dup -root = File.expand_path('../../..', __FILE__) + begin - require "#{root}/vendor/gems/environment" + require File.expand_path('../../../vendor/gems/environment', __FILE__) rescue LoadError - $:.unshift("#{root}/activesupport/lib") - $:.unshift("#{root}/activerecord/lib") end +lib = File.expand_path("#{File.dirname(__FILE__)}/../lib") +$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) require 'test/unit' - -begin - require 'mocha' -rescue LoadError - $stderr.puts 'Loading rubygems' - require 'rubygems' - require 'mocha' -end +require 'mocha' ENV['NO_RELOAD'] = '1' require 'active_support' diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index 6a51ce9402..00e05f76fe 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -30,7 +30,9 @@ class CacheStoreSettingTest < ActiveSupport::TestCase def test_mem_cache_fragment_cache_store_with_given_mem_cache_like_object MemCache.expects(:new).never - store = ActiveSupport::Cache.lookup_store :mem_cache_store, stub("memcache", :get => true) + memcache = Object.new + def memcache.get() true end + store = ActiveSupport::Cache.lookup_store :mem_cache_store, memcache assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) end diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb index 8198b9bd2c..f5f91ddd80 100644 --- a/activesupport/test/core_ext/array_ext_test.rb +++ b/activesupport/test/core_ext/array_ext_test.rb @@ -339,6 +339,11 @@ class ArrayWrapperTests < Test::Unit::TestCase end end + class Proxy + def initialize(target) @target = target end + def method_missing(*a) @target.send(*a) end + end + def test_array ary = %w(foo bar) assert_same ary, Array.wrap(ary) @@ -364,4 +369,19 @@ class ArrayWrapperTests < Test::Unit::TestCase def test_object_with_to_ary assert_equal ["foo", "bar"], Array.wrap(FakeCollection.new) end + + def test_proxy_object + p = Proxy.new(Object.new) + assert_equal [p], Array.wrap(p) + end + + def test_proxy_to_object_with_to_ary + p = Proxy.new(FakeCollection.new) + assert_equal [p], Array.wrap(p) + end + + def test_struct + o = Struct.new(:foo).new(123) + assert_equal [o], Array.wrap(o) + end end diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index 18422d68bc..23c9bc7fb1 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -1,5 +1,5 @@ require 'abstract_unit' -require 'active_support/core_ext/date' +require 'active_support/time' class DateExtCalculationsTest < Test::Unit::TestCase def test_to_s diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index a7b179b2be..4341ead488 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -1,5 +1,5 @@ require 'abstract_unit' -require 'active_support/core_ext/date_time' +require 'active_support/time' class DateTimeExtCalculationsTest < Test::Unit::TestCase def test_to_s diff --git a/activesupport/test/core_ext/enumerable_test.rb b/activesupport/test/core_ext/enumerable_test.rb index 4170de3dce..66f5f9fbde 100644 --- a/activesupport/test/core_ext/enumerable_test.rb +++ b/activesupport/test/core_ext/enumerable_test.rb @@ -1,6 +1,5 @@ require 'abstract_unit' require 'active_support/core_ext/array' -require 'active_support/core_ext/symbol' require 'active_support/core_ext/enumerable' Payment = Struct.new(:price) @@ -90,15 +89,4 @@ class EnumerableTests < Test::Unit::TestCase assert ![ 1, 2 ].many? {|x| x > 1 } assert [ 1, 2, 2 ].many? {|x| x > 1 } end - - def test_none - assert [].none? - assert [nil, false].none? - assert ![1].none? - - assert [].none? {|x| x > 1 } - assert ![ 2 ].none? {|x| x > 1 } - assert ![ 1, 2 ].none? {|x| x > 1 } - assert [ 1, 1 ].none? {|x| x > 1 } - end end diff --git a/activesupport/test/core_ext/integer_ext_test.rb b/activesupport/test/core_ext/integer_ext_test.rb index 956ae5189d..e1591089f5 100644 --- a/activesupport/test/core_ext/integer_ext_test.rb +++ b/activesupport/test/core_ext/integer_ext_test.rb @@ -2,22 +2,6 @@ require 'abstract_unit' require 'active_support/core_ext/integer' class IntegerExtTest < Test::Unit::TestCase - def test_even - assert [ -2, 0, 2, 4 ].all? { |i| i.even? } - assert ![ -1, 1, 3 ].all? { |i| i.even? } - - assert 22953686867719691230002707821868552601124472329079.odd? - assert !22953686867719691230002707821868552601124472329079.even? - assert 22953686867719691230002707821868552601124472329080.even? - assert !22953686867719691230002707821868552601124472329080.odd? - end - - def test_odd - assert ![ -2, 0, 2, 4 ].all? { |i| i.odd? } - assert [ -1, 1, 3 ].all? { |i| i.odd? } - assert 1000000000000000000000000000000000000000000000000000000001.odd? - end - def test_multiple_of [ -7, 0, 7, 14 ].each { |i| assert i.multiple_of?(7) } [ -7, 7, 14 ].each { |i| assert ! i.multiple_of?(6) } diff --git a/activesupport/test/core_ext/name_error_test.rb b/activesupport/test/core_ext/name_error_test.rb index 10913e2ade..6352484d04 100644 --- a/activesupport/test/core_ext/name_error_test.rb +++ b/activesupport/test/core_ext/name_error_test.rb @@ -3,23 +3,19 @@ require 'active_support/core_ext/name_error' class NameErrorTest < Test::Unit::TestCase def test_name_error_should_set_missing_name - begin - SomeNameThatNobodyWillUse____Really ? 1 : 0 - flunk "?!?!" - rescue NameError => exc - assert_equal "NameErrorTest::SomeNameThatNobodyWillUse____Really", exc.missing_name - assert exc.missing_name?(:SomeNameThatNobodyWillUse____Really) - assert exc.missing_name?("NameErrorTest::SomeNameThatNobodyWillUse____Really") - end + SomeNameThatNobodyWillUse____Really ? 1 : 0 + flunk "?!?!" + rescue NameError => exc + assert_equal "NameErrorTest::SomeNameThatNobodyWillUse____Really", exc.missing_name + assert exc.missing_name?(:SomeNameThatNobodyWillUse____Really) + assert exc.missing_name?("NameErrorTest::SomeNameThatNobodyWillUse____Really") end def test_missing_method_should_ignore_missing_name - begin - some_method_that_does_not_exist - flunk "?!?!" - rescue NameError => exc - assert_equal nil, exc.missing_name - assert ! exc.missing_name?(:Foo) - end + some_method_that_does_not_exist + flunk "?!?!" + rescue NameError => exc + assert !exc.missing_name?(:Foo) + assert_nil exc.missing_name end end diff --git a/activesupport/test/core_ext/object_and_class_ext_test.rb b/activesupport/test/core_ext/object_and_class_ext_test.rb index f0121b862d..e6fbdb637b 100644 --- a/activesupport/test/core_ext/object_and_class_ext_test.rb +++ b/activesupport/test/core_ext/object_and_class_ext_test.rb @@ -182,13 +182,6 @@ class ObjectInstanceVariableTest < Test::Unit::TestCase assert_equal %w(@bar @baz), @source.instance_variable_names.sort end - def test_instance_variable_defined - assert @source.instance_variable_defined?('@bar') - assert @source.instance_variable_defined?(:@bar) - assert !@source.instance_variable_defined?(:@foo) - assert !@source.instance_variable_defined?('@foo') - end - def test_copy_instance_variables_from_without_explicit_excludes assert_equal [], @dest.instance_variables @dest.copy_instance_variables_from(@source) diff --git a/activesupport/test/core_ext/object_ext_test.rb b/activesupport/test/core_ext/object_ext_test.rb deleted file mode 100644 index 04c19ed2aa..0000000000 --- a/activesupport/test/core_ext/object_ext_test.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'abstract_unit' -require 'active_support/core_ext/object/metaclass' - -class ObjectExtTest < Test::Unit::TestCase - def test_tap_yields_and_returns_self - foo = Object.new - assert_equal foo, foo.tap { |x| assert_equal foo, x; :bar } - end -end diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb index 2565c56b8a..5701eeef28 100644 --- a/activesupport/test/core_ext/range_ext_test.rb +++ b/activesupport/test/core_ext/range_ext_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' +require 'active_support/time' require 'active_support/core_ext/range' -require 'active_support/core_ext/date/conversions' class RangeTest < Test::Unit::TestCase def test_to_s_from_dates diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 584a41b631..56ed296dac 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -4,7 +4,8 @@ require 'abstract_unit' require 'inflector_test_cases' require 'active_support/core_ext/string' -require 'active_support/core_ext/time' +require 'active_support/time' +require 'active_support/core_ext/kernel/reporting' class StringInflectionsTest < Test::Unit::TestCase include InflectorTestCases @@ -185,17 +186,9 @@ class StringInflectionsTest < Test::Unit::TestCase assert s.starts_with?('hel') assert !s.starts_with?('el') - assert s.start_with?('h') - assert s.start_with?('hel') - assert !s.start_with?('el') - assert s.ends_with?('o') assert s.ends_with?('lo') assert !s.ends_with?('el') - - assert s.end_with?('o') - assert s.end_with?('lo') - assert !s.end_with?('el') end def test_string_squish @@ -214,17 +207,6 @@ class StringInflectionsTest < Test::Unit::TestCase # And changes the original string: assert_equal original, expected end - - if RUBY_VERSION < '1.9' - def test_each_char_with_utf8_string_when_kcode_is_utf8 - with_kcode('UTF8') do - '€2.99'.each_char do |char| - assert_not_equal 1, char.length - break - end - end - end - end end class StringBehaviourTest < Test::Unit::TestCase @@ -350,13 +332,6 @@ class TestGetTextString < Test::Unit::TestCase end end -class StringBytesizeTest < Test::Unit::TestCase - def test_bytesize - assert_respond_to 'foo', :bytesize - assert_equal 3, 'foo'.bytesize - end -end - class OutputSafetyTest < ActiveSupport::TestCase def setup @string = "hello" diff --git a/activesupport/test/core_ext/symbol_test.rb b/activesupport/test/core_ext/symbol_test.rb deleted file mode 100644 index 1eaccb9965..0000000000 --- a/activesupport/test/core_ext/symbol_test.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'abstract_unit' - -class SymbolTests < Test::Unit::TestCase - def test_to_proc - assert_equal %w(one two three), [:one, :two, :three].map(&:to_s) - assert_equal(%w(one two three), - {1 => "one", 2 => "two", 3 => "three"}.sort_by(&:first).map(&:last)) - end -end diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index 97d70cf8c4..0fcf1eaf00 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -3,7 +3,6 @@ require 'pp' require 'active_support/dependencies' require 'active_support/core_ext/module/loading' require 'active_support/core_ext/kernel/reporting' -require 'active_support/core_ext/symbol/to_proc' module ModuleWithMissing mattr_accessor :missing_count diff --git a/activesupport/test/i18n_test.rb b/activesupport/test/i18n_test.rb index 9868f1e87d..dfcd4f822d 100644 --- a/activesupport/test/i18n_test.rb +++ b/activesupport/test/i18n_test.rb @@ -9,8 +9,8 @@ class I18nTest < Test::Unit::TestCase end def test_time_zone_localization_with_default_format - Time.zone.stubs(:now).returns Time.local(2000) - assert_equal Time.zone.now.strftime("%a, %d %b %Y %H:%M:%S %z"), I18n.localize(Time.zone.now) + now = Time.local(2000) + assert_equal now.strftime("%a, %d %b %Y %H:%M:%S %z"), I18n.localize(now) end def test_date_localization_should_use_default_format diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb index 7b5a4d0416..8fcb16abfb 100644 --- a/activesupport/test/json/decoding_test.rb +++ b/activesupport/test/json/decoding_test.rb @@ -1,6 +1,7 @@ # encoding: UTF-8 require 'abstract_unit' require 'active_support/json' +require 'active_support/time' require 'active_support/core_ext/kernel/reporting' class TestJSONDecoding < ActiveSupport::TestCase diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb index ed3461571a..5c2b44f188 100644 --- a/activesupport/test/message_encryptor_test.rb +++ b/activesupport/test/message_encryptor_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'active_support/time' class MessageEncryptorTest < Test::Unit::TestCase def setup diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index ef300e4e26..714a3b3a39 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -7,6 +7,8 @@ rescue LoadError, NameError $stderr.puts "Skipping MessageVerifier test: broken OpenSSL install" else +require 'active_support/time' + class MessageVerifierTest < Test::Unit::TestCase def setup @verifier = ActiveSupport::MessageVerifier.new("Hey, I'm a secret!") diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index 4ff74abf61..0e489c10e1 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -228,10 +228,10 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase assert !@chars.include?('a') end - def test_include_raises_type_error_when_nil_is_passed - assert_raise(TypeError) do - @chars.include?(nil) - end + def test_include_raises_when_nil_is_passed + @chars.include?(nil) + flunk "Expected chars.include?(nil) to raise TypeError or NoMethodError" + rescue Exception => e end def test_index_should_return_character_offset @@ -659,4 +659,4 @@ class MultibyteInternalsTest < ActiveSupport::TestCase "Expected byte offset #{byte_offset} to translate to #{character_offset}" end end -end
\ No newline at end of file +end diff --git a/activesupport/test/multibyte_utils_test.rb b/activesupport/test/multibyte_utils_test.rb index 0a2f20d282..1dff944922 100644 --- a/activesupport/test/multibyte_utils_test.rb +++ b/activesupport/test/multibyte_utils_test.rb @@ -2,6 +2,7 @@ require 'abstract_unit' require 'multibyte_test_helpers' +require 'active_support/core_ext/kernel/reporting' class MultibyteUtilsTest < ActiveSupport::TestCase include MultibyteTestHelpers diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb index 9175c8f26e..35d44367cf 100644 --- a/activesupport/test/notifications_test.rb +++ b/activesupport/test/notifications_test.rb @@ -75,7 +75,7 @@ class NotificationsMainTest < Test::Unit::TestCase 1 + 1 end - sleep(0.1) + drain assert_equal 1, @events.size assert_equal :awesome, @events.last.name @@ -88,19 +88,18 @@ class NotificationsMainTest < Test::Unit::TestCase 1 + 1 end - sleep(0.1) + drain assert_equal 1, @events.size assert_equal :wot, @events.first.name assert_equal Hash[:payload => "child"], @events.first.payload end - sleep(0.1) + drain assert_equal 2, @events.size assert_equal :awesome, @events.last.name assert_equal Hash[:payload => "notifications"], @events.last.payload - assert_in_delta 100, @events.last.duration, 70 end def test_event_is_pushed_even_if_block_fails @@ -108,7 +107,7 @@ class NotificationsMainTest < Test::Unit::TestCase raise "OMG" end rescue RuntimeError - sleep(0.1) + drain assert_equal 1, @events.size assert_equal :awesome, @events.last.name @@ -117,7 +116,7 @@ class NotificationsMainTest < Test::Unit::TestCase def test_event_is_pushed_even_without_block ActiveSupport::Notifications.instrument(:awesome, :payload => "notifications") - sleep(0.1) + drain assert_equal 1, @events.size assert_equal :awesome, @events.last.name @@ -137,8 +136,9 @@ class NotificationsMainTest < Test::Unit::TestCase end ActiveSupport::Notifications.instrument(:cache){ 1 } - sleep 0.1 + drain + assert_equal 3, @another.size before, during, after = @another.map {|e| e.transaction_id } assert_equal before, after assert_not_equal before, during @@ -153,7 +153,7 @@ class NotificationsMainTest < Test::Unit::TestCase ActiveSupport::Notifications.instrument(:cache){ 1 } - sleep(0.1) + drain assert_equal 1, @another.size assert_equal :cache, @another.first.name @@ -169,7 +169,22 @@ class NotificationsMainTest < Test::Unit::TestCase ActiveSupport::Notifications.instrument(:something){ 0 } ActiveSupport::Notifications.instrument(:cache){ 1 } - sleep(0.1) + drain + + assert_equal 1, @another.size + assert_equal :cache, @another.first.name + assert_equal 1, @another.first.result + end + + def test_subscriber_allows_sync_listeners + @another = [] + ActiveSupport::Notifications.subscribe(/cache/, :with => ActiveSupport::Notifications::SyncListener) do |*args| + @another << ActiveSupport::Notifications::Event.new(*args) + end + + Thread.expects(:new).never + ActiveSupport::Notifications.instrument(:something){ 0 } + ActiveSupport::Notifications.instrument(:cache){ 1 } assert_equal 1, @another.size assert_equal :cache, @another.first.name @@ -186,7 +201,7 @@ class NotificationsMainTest < Test::Unit::TestCase ActiveSupport::Notifications.instrument(:value){ i } end - sleep 0.1 + drain assert_equal 100, @events.size assert_equal :value, @events.first.name @@ -198,4 +213,9 @@ class NotificationsMainTest < Test::Unit::TestCase assert_equal 1, @another.first.result assert_equal 100, @another.last.result end + + private + def drain + sleep(0.05) until ActiveSupport::Notifications.queue.drained? + end end diff --git a/activesupport/test/whiny_nil_test.rb b/activesupport/test/whiny_nil_test.rb index 4cb22c41b2..009d97940f 100644 --- a/activesupport/test/whiny_nil_test.rb +++ b/activesupport/test/whiny_nil_test.rb @@ -13,7 +13,7 @@ class WhinyNilTest < Test::Unit::TestCase def test_unchanged nil.method_thats_not_in_whiners rescue NoMethodError => nme - assert_match(/nil.method_thats_not_in_whiners/, nme.message) + assert(nme.message =~ /nil:NilClass/) end def test_active_record @@ -35,4 +35,16 @@ class WhinyNilTest < Test::Unit::TestCase rescue RuntimeError => nme assert(!(nme.message =~ /nil:NilClass/)) end + + def test_no_to_ary_coercion + nil.to_ary + rescue NoMethodError => nme + assert(nme.message =~ /nil:NilClass/) + end + + def test_no_to_str_coercion + nil.to_str + rescue NoMethodError => nme + assert(nme.message =~ /nil:NilClass/) + end end |