diff options
author | Jeremy Kemper <jeremy@bitsweat.net> | 2009-11-22 10:31:47 -0800 |
---|---|---|
committer | Jeremy Kemper <jeremy@bitsweat.net> | 2009-11-22 10:31:47 -0800 |
commit | e68bc3f14ea93eabdd4274e66071b65debb5a0a8 (patch) | |
tree | 223c11f38dac1217d8e7e3cd427fdf6018975a9d /activesupport/lib | |
parent | 3cb46b40a0df1a1f4912625cc2be40b3d630f1f3 (diff) | |
parent | e1935e3c0c35f8f1196239e2b1213c4436049fa5 (diff) | |
download | rails-e68bc3f14ea93eabdd4274e66071b65debb5a0a8.tar.gz rails-e68bc3f14ea93eabdd4274e66071b65debb5a0a8.tar.bz2 rails-e68bc3f14ea93eabdd4274e66071b65debb5a0a8.zip |
Merge commit 'origin/master' into mail
Diffstat (limited to 'activesupport/lib')
45 files changed, 506 insertions, 618 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/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..7a9f76b26a 100644 --- a/activesupport/lib/active_support/notifications.rb +++ b/activesupport/lib/active_support/notifications.rb @@ -111,7 +111,7 @@ module ActiveSupport def subscribe @queue.subscribe(@pattern) do |*args| - yield *args + yield(*args) end end end @@ -144,27 +144,21 @@ module ActiveSupport class LittleFanout def initialize @listeners = [] - @stream = Queue.new - Thread.new { consume } end def publish(*args) - @stream.push(args) + @listeners.each { |l| l.publish(*args) } end def subscribe(pattern=nil, &block) @listeners << Listener.new(pattern, &block) end - def consume - while args = @stream.shift - @listeners.each { |l| l.publish(*args) } - end + def drained? + @listeners.all? &:drained? end class Listener - # attr_reader :thread - def initialize(pattern, &block) @pattern = pattern @subscriber = block @@ -183,6 +177,10 @@ module ActiveSupport @subscriber.call(*args) end end + + def drained? + @queue.size.zero? + end end end 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/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 - |