mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Initial pass at removing dead 1.8.x code from Active Support.
There are a bunch of other implicit branches that adds 1.8.x specific code that still needs to be removed. Pull requests for those cases are welcome.
This commit is contained in:
parent
51095be1b0
commit
7ab4775106
27 changed files with 117 additions and 759 deletions
|
@ -7,24 +7,6 @@ require 'active_support/core_ext/time/zones'
|
|||
class Date
|
||||
DAYS_INTO_WEEK = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6 }
|
||||
|
||||
if RUBY_VERSION < '1.9'
|
||||
undef :>>
|
||||
|
||||
# Backported from 1.9. The one in 1.8 leads to incorrect next_month and
|
||||
# friends for dates where the calendar reform is involved. It additionally
|
||||
# prevents an infinite loop fixed in r27013.
|
||||
def >>(n)
|
||||
y, m = (year * 12 + (mon - 1) + n).divmod(12)
|
||||
m, = (m + 1) .divmod(1)
|
||||
d = mday
|
||||
until jd2 = self.class.valid_civil?(y, m, d, start)
|
||||
d -= 1
|
||||
raise ArgumentError, 'invalid date' unless d > 0
|
||||
end
|
||||
self + (jd2 - jd)
|
||||
end
|
||||
end
|
||||
|
||||
class << self
|
||||
# Returns a new Date representing the date 1 day ago (i.e. yesterday's date).
|
||||
def yesterday
|
||||
|
|
|
@ -63,12 +63,6 @@ class Date
|
|||
alias_method :default_inspect, :inspect
|
||||
alias_method :inspect, :readable_inspect
|
||||
|
||||
# A method to keep Time, Date and DateTime instances interchangeable on conversions.
|
||||
# In this case, it simply returns +self+.
|
||||
def to_date
|
||||
self
|
||||
end if RUBY_VERSION < '1.9'
|
||||
|
||||
# Converts a Date instance to a Time, where the time is set to the beginning of the day.
|
||||
# The timezone can be either :local or :utc (default :local).
|
||||
#
|
||||
|
@ -83,23 +77,6 @@ class Date
|
|||
::Time.send("#{form}_time", year, month, day)
|
||||
end
|
||||
|
||||
# Converts a Date instance to a DateTime, where the time is set to the beginning of the day
|
||||
# and UTC offset is set to 0.
|
||||
#
|
||||
# ==== Examples
|
||||
# date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
|
||||
#
|
||||
# date.to_datetime # => Sat, 10 Nov 2007 00:00:00 0000
|
||||
def to_datetime
|
||||
::DateTime.civil(year, month, day, 0, 0, 0, 0)
|
||||
end if RUBY_VERSION < '1.9'
|
||||
|
||||
def iso8601
|
||||
strftime('%F')
|
||||
end if RUBY_VERSION < '1.9'
|
||||
|
||||
alias_method :rfc3339, :iso8601 if RUBY_VERSION < '1.9'
|
||||
|
||||
def xmlschema
|
||||
to_time_in_current_zone.xmlschema
|
||||
end
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
require 'rational' unless RUBY_VERSION >= '1.9.2'
|
||||
|
||||
class DateTime
|
||||
class << self
|
||||
# DateTimes aren't aware of DST rules, so use a consistent non-DST offset when creating a DateTime with an offset in the local zone
|
||||
|
|
|
@ -66,7 +66,7 @@ class DateTime
|
|||
# Attempts to convert self to a Ruby Time object; returns self if out of range of Ruby Time class.
|
||||
# If self has an offset other than 0, self will just be returned unaltered, since there's no clean way to map it to a Time.
|
||||
def to_time
|
||||
self.offset == 0 ? ::Time.utc_time(year, month, day, hour, min, sec, sec_fraction * (RUBY_VERSION < '1.9' ? 86400000000 : 1000000)) : self
|
||||
self.offset == 0 ? ::Time.utc_time(year, month, day, hour, min, sec, sec_fraction * 1000000) : self
|
||||
end
|
||||
|
||||
# To be able to keep Times, Dates and DateTimes interchangeable on conversions.
|
||||
|
|
|
@ -1,41 +1,4 @@
|
|||
require 'active_support/ordered_hash'
|
||||
|
||||
module Enumerable
|
||||
# Ruby 1.8.7 introduces group_by, but the result isn't ordered. Override it.
|
||||
remove_method(:group_by) if [].respond_to?(:group_by) && RUBY_VERSION < '1.9'
|
||||
|
||||
# Collect an enumerable into sets, grouped by the result of a block. Useful,
|
||||
# for example, for grouping records by date.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# latest_transcripts.group_by(&:day).each do |day, transcripts|
|
||||
# p "#{day} -> #{transcripts.map(&:class).join(', ')}"
|
||||
# end
|
||||
# "2006-03-01 -> Transcript"
|
||||
# "2006-02-28 -> Transcript"
|
||||
# "2006-02-27 -> Transcript, Transcript"
|
||||
# "2006-02-26 -> Transcript, Transcript"
|
||||
# "2006-02-25 -> Transcript"
|
||||
# "2006-02-24 -> Transcript, Transcript"
|
||||
# "2006-02-23 -> Transcript"
|
||||
def group_by
|
||||
return to_enum :group_by unless block_given?
|
||||
assoc = ActiveSupport::OrderedHash.new
|
||||
|
||||
each do |element|
|
||||
key = yield(element)
|
||||
|
||||
if assoc.has_key?(key)
|
||||
assoc[key] << element
|
||||
else
|
||||
assoc[key] = [element]
|
||||
end
|
||||
end
|
||||
|
||||
assoc
|
||||
end unless [].respond_to?(:group_by)
|
||||
|
||||
# Calculates a sum from the elements. Examples:
|
||||
#
|
||||
# payments.sum { |p| p.price * p.tax_rate }
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module ActiveSupport
|
||||
FrozenObjectError = RUBY_VERSION < '1.9' ? TypeError : RuntimeError
|
||||
FrozenObjectError = RuntimeError
|
||||
end
|
||||
|
|
|
@ -57,27 +57,8 @@ class Module
|
|||
parents
|
||||
end
|
||||
|
||||
if RUBY_VERSION < '1.9'
|
||||
# Returns the constants that have been defined locally by this object and
|
||||
# not in an ancestor. This method is exact if running under Ruby 1.9. In
|
||||
# previous versions it may miss some constants if their definition in some
|
||||
# ancestor is identical to their definition in the receiver.
|
||||
def local_constants
|
||||
inherited = {}
|
||||
|
||||
ancestors.each do |anc|
|
||||
next if anc == self
|
||||
anc.constants.each { |const| inherited[const] = anc.const_get(const) }
|
||||
end
|
||||
|
||||
constants.select do |const|
|
||||
!inherited.key?(const) || inherited[const].object_id != const_get(const).object_id
|
||||
end
|
||||
end
|
||||
else
|
||||
def local_constants #:nodoc:
|
||||
constants(false)
|
||||
end
|
||||
def local_constants #:nodoc:
|
||||
constants(false)
|
||||
end
|
||||
|
||||
# Returns the names of the constants defined locally rather than the
|
||||
|
|
|
@ -23,11 +23,7 @@ class Object
|
|||
# end
|
||||
#
|
||||
# C.new(0, 1).instance_variable_names # => ["@y", "@x"]
|
||||
if RUBY_VERSION >= '1.9'
|
||||
def instance_variable_names
|
||||
instance_variables.map { |var| var.to_s }
|
||||
end
|
||||
else
|
||||
alias_method :instance_variable_names, :instance_variables
|
||||
def instance_variable_names
|
||||
instance_variables.map { |var| var.to_s }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,4 +2,3 @@ require 'active_support/core_ext/range/blockless_step'
|
|||
require 'active_support/core_ext/range/conversions'
|
||||
require 'active_support/core_ext/range/include_range'
|
||||
require 'active_support/core_ext/range/overlaps'
|
||||
require 'active_support/core_ext/range/cover'
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
class Range
|
||||
alias_method(:cover?, :include?) unless instance_methods.include?(:cover?)
|
||||
end
|
|
@ -1,11 +1,5 @@
|
|||
class String
|
||||
if defined?(Encoding) && "".respond_to?(:encode)
|
||||
def encoding_aware?
|
||||
true
|
||||
end
|
||||
else
|
||||
def encoding_aware?
|
||||
false
|
||||
end
|
||||
def encoding_aware?
|
||||
true
|
||||
end
|
||||
end
|
|
@ -2,71 +2,55 @@
|
|||
require 'active_support/multibyte'
|
||||
|
||||
class String
|
||||
if RUBY_VERSION >= "1.9"
|
||||
# == Multibyte proxy
|
||||
#
|
||||
# +mb_chars+ is a multibyte safe proxy for string methods.
|
||||
#
|
||||
# In Ruby 1.8 and older it creates and returns an instance of the ActiveSupport::Multibyte::Chars class which
|
||||
# encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
|
||||
# class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsulated string.
|
||||
#
|
||||
# name = 'Claus Müller'
|
||||
# name.reverse # => "rell??M sualC"
|
||||
# name.length # => 13
|
||||
#
|
||||
# name.mb_chars.reverse.to_s # => "rellüM sualC"
|
||||
# name.mb_chars.length # => 12
|
||||
#
|
||||
# In Ruby 1.9 and newer +mb_chars+ returns +self+ because String is (mostly) encoding aware. This means that
|
||||
# it becomes easy to run one version of your code on multiple Ruby versions.
|
||||
#
|
||||
# == Method chaining
|
||||
#
|
||||
# All the methods on the Chars proxy which normally return a string will return a Chars object. This allows
|
||||
# method chaining on the result of any of these methods.
|
||||
#
|
||||
# name.mb_chars.reverse.length # => 12
|
||||
#
|
||||
# == Interoperability and configuration
|
||||
#
|
||||
# The Chars object tries to be as interchangeable with String objects as possible: sorting and comparing between
|
||||
# String and Char work like expected. The bang! methods change the internal string representation in the Chars
|
||||
# object. Interoperability problems can be resolved easily with a +to_s+ call.
|
||||
#
|
||||
# For more information about the methods defined on the Chars proxy see ActiveSupport::Multibyte::Chars. For
|
||||
# information about how to change the default Multibyte behavior see ActiveSupport::Multibyte.
|
||||
def mb_chars
|
||||
if ActiveSupport::Multibyte.proxy_class.consumes?(self)
|
||||
ActiveSupport::Multibyte.proxy_class.new(self)
|
||||
else
|
||||
self
|
||||
end
|
||||
# == Multibyte proxy
|
||||
#
|
||||
# +mb_chars+ is a multibyte safe proxy for string methods.
|
||||
#
|
||||
# In Ruby 1.8 and older it creates and returns an instance of the ActiveSupport::Multibyte::Chars class which
|
||||
# encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
|
||||
# class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsulated string.
|
||||
#
|
||||
# name = 'Claus Müller'
|
||||
# name.reverse # => "rell??M sualC"
|
||||
# name.length # => 13
|
||||
#
|
||||
# name.mb_chars.reverse.to_s # => "rellüM sualC"
|
||||
# name.mb_chars.length # => 12
|
||||
#
|
||||
# In Ruby 1.9 and newer +mb_chars+ returns +self+ because String is (mostly) encoding aware. This means that
|
||||
# it becomes easy to run one version of your code on multiple Ruby versions.
|
||||
#
|
||||
# == Method chaining
|
||||
#
|
||||
# All the methods on the Chars proxy which normally return a string will return a Chars object. This allows
|
||||
# method chaining on the result of any of these methods.
|
||||
#
|
||||
# name.mb_chars.reverse.length # => 12
|
||||
#
|
||||
# == Interoperability and configuration
|
||||
#
|
||||
# The Chars object tries to be as interchangeable with String objects as possible: sorting and comparing between
|
||||
# String and Char work like expected. The bang! methods change the internal string representation in the Chars
|
||||
# object. Interoperability problems can be resolved easily with a +to_s+ call.
|
||||
#
|
||||
# For more information about the methods defined on the Chars proxy see ActiveSupport::Multibyte::Chars. For
|
||||
# information about how to change the default Multibyte behavior see ActiveSupport::Multibyte.
|
||||
def mb_chars
|
||||
if ActiveSupport::Multibyte.proxy_class.consumes?(self)
|
||||
ActiveSupport::Multibyte.proxy_class.new(self)
|
||||
else
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
def is_utf8?
|
||||
case encoding
|
||||
when Encoding::UTF_8
|
||||
valid_encoding?
|
||||
when Encoding::ASCII_8BIT, Encoding::US_ASCII
|
||||
dup.force_encoding(Encoding::UTF_8).valid_encoding?
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
else
|
||||
def mb_chars
|
||||
if ActiveSupport::Multibyte.proxy_class.wants?(self)
|
||||
ActiveSupport::Multibyte.proxy_class.new(self)
|
||||
else
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
# Returns true if the string has UTF-8 semantics (a String used for purely byte resources is unlikely to have
|
||||
# them), returns false otherwise.
|
||||
def is_utf8?
|
||||
ActiveSupport::Multibyte::Chars.consumes?(self)
|
||||
def is_utf8?
|
||||
case encoding
|
||||
when Encoding::UTF_8
|
||||
valid_encoding?
|
||||
when Encoding::ASCII_8BIT, Encoding::US_ASCII
|
||||
dup.force_encoding(Encoding::UTF_8).valid_encoding?
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,22 +1,18 @@
|
|||
# encoding: utf-8
|
||||
|
||||
if RUBY_VERSION >= '1.9'
|
||||
require 'uri'
|
||||
require 'uri'
|
||||
str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese.
|
||||
parser = URI::Parser.new
|
||||
|
||||
str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese.
|
||||
|
||||
parser = URI::Parser.new
|
||||
|
||||
unless str == parser.unescape(parser.escape(str))
|
||||
URI::Parser.class_eval do
|
||||
remove_method :unescape
|
||||
def unescape(str, escaped = /%[a-fA-F\d]{2}/)
|
||||
# TODO: Are we actually sure that ASCII == UTF-8?
|
||||
# YK: My initial experiments say yes, but let's be sure please
|
||||
enc = str.encoding
|
||||
enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
|
||||
str.gsub(escaped) { [$&[1, 2].hex].pack('C') }.force_encoding(enc)
|
||||
end
|
||||
unless str == parser.unescape(parser.escape(str))
|
||||
URI::Parser.class_eval do
|
||||
remove_method :unescape
|
||||
def unescape(str, escaped = /%[a-fA-F\d]{2}/)
|
||||
# TODO: Are we actually sure that ASCII == UTF-8?
|
||||
# YK: My initial experiments say yes, but let's be sure please
|
||||
enc = str.encoding
|
||||
enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
|
||||
str.gsub(escaped) { [$&[1, 2].hex].pack('C') }.force_encoding(enc)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -38,16 +38,10 @@ module ActiveSupport #:nodoc:
|
|||
alias to_s wrapped_string
|
||||
alias to_str wrapped_string
|
||||
|
||||
if RUBY_VERSION >= "1.9"
|
||||
# Creates a new Chars instance by wrapping _string_.
|
||||
def initialize(string)
|
||||
@wrapped_string = string
|
||||
@wrapped_string.force_encoding(Encoding::UTF_8) unless @wrapped_string.frozen?
|
||||
end
|
||||
else
|
||||
def initialize(string) #:nodoc:
|
||||
@wrapped_string = string
|
||||
end
|
||||
# Creates a new Chars instance by wrapping _string_.
|
||||
def initialize(string)
|
||||
@wrapped_string = string
|
||||
@wrapped_string.force_encoding(Encoding::UTF_8) unless @wrapped_string.frozen?
|
||||
end
|
||||
|
||||
# Forward all undefined methods to the wrapped string.
|
||||
|
@ -94,151 +88,8 @@ module ActiveSupport #:nodoc:
|
|||
@wrapped_string <=> other.to_s
|
||||
end
|
||||
|
||||
if RUBY_VERSION < "1.9"
|
||||
# Returns +true+ if the Chars class can and should act as a proxy for the string _string_. Returns
|
||||
# +false+ otherwise.
|
||||
def self.wants?(string)
|
||||
$KCODE == 'UTF8' && consumes?(string)
|
||||
end
|
||||
|
||||
# Returns a new Chars object containing the _other_ object concatenated to the string.
|
||||
#
|
||||
# Example:
|
||||
# ('Café'.mb_chars + ' périferôl').to_s # => "Café périferôl"
|
||||
def +(other)
|
||||
chars(@wrapped_string + other)
|
||||
end
|
||||
|
||||
# Like <tt>String#=~</tt> only it returns the character offset (in codepoints) instead of the byte offset.
|
||||
#
|
||||
# Example:
|
||||
# 'Café périferôl'.mb_chars =~ /ô/ # => 12
|
||||
def =~(other)
|
||||
translate_offset(@wrapped_string =~ other)
|
||||
end
|
||||
|
||||
# Inserts the passed string at specified codepoint offsets.
|
||||
#
|
||||
# Example:
|
||||
# 'Café'.mb_chars.insert(4, ' périferôl').to_s # => "Café périferôl"
|
||||
def insert(offset, fragment)
|
||||
unpacked = Unicode.u_unpack(@wrapped_string)
|
||||
unless offset > unpacked.length
|
||||
@wrapped_string.replace(
|
||||
Unicode.u_unpack(@wrapped_string).insert(offset, *Unicode.u_unpack(fragment)).pack('U*')
|
||||
)
|
||||
else
|
||||
raise IndexError, "index #{offset} out of string"
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
# Returns +true+ if contained string contains _other_. Returns +false+ otherwise.
|
||||
#
|
||||
# Example:
|
||||
# 'Café'.mb_chars.include?('é') # => true
|
||||
def include?(other)
|
||||
# We have to redefine this method because Enumerable defines it.
|
||||
@wrapped_string.include?(other)
|
||||
end
|
||||
|
||||
# Returns the position _needle_ in the string, counting in codepoints. Returns +nil+ if _needle_ isn't found.
|
||||
#
|
||||
# Example:
|
||||
# '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 = first(offset).wrapped_string.length
|
||||
index = @wrapped_string.index(needle, wrapped_offset)
|
||||
index ? (Unicode.u_unpack(@wrapped_string.slice(0...index)).size) : nil
|
||||
end
|
||||
|
||||
# Returns the position _needle_ in the string, counting in
|
||||
# codepoints, searching backward from _offset_ or the end of the
|
||||
# string. Returns +nil+ if _needle_ isn't found.
|
||||
#
|
||||
# Example:
|
||||
# 'Café périferôl'.mb_chars.rindex('é') # => 6
|
||||
# 'Café périferôl'.mb_chars.rindex(/\w/u) # => 13
|
||||
def rindex(needle, offset=nil)
|
||||
offset ||= length
|
||||
wrapped_offset = first(offset).wrapped_string.length
|
||||
index = @wrapped_string.rindex(needle, wrapped_offset)
|
||||
index ? (Unicode.u_unpack(@wrapped_string.slice(0...index)).size) : nil
|
||||
end
|
||||
|
||||
# Returns the number of codepoints in the string
|
||||
def size
|
||||
Unicode.u_unpack(@wrapped_string).size
|
||||
end
|
||||
alias_method :length, :size
|
||||
|
||||
# Strips entire range of Unicode whitespace from the right of the string.
|
||||
def rstrip
|
||||
chars(@wrapped_string.gsub(Unicode::TRAILERS_PAT, ''))
|
||||
end
|
||||
|
||||
# Strips entire range of Unicode whitespace from the left of the string.
|
||||
def lstrip
|
||||
chars(@wrapped_string.gsub(Unicode::LEADERS_PAT, ''))
|
||||
end
|
||||
|
||||
# Strips entire range of Unicode whitespace from the right and left of the string.
|
||||
def strip
|
||||
rstrip.lstrip
|
||||
end
|
||||
|
||||
# Returns the codepoint of the first character in the string.
|
||||
#
|
||||
# Example:
|
||||
# 'こんにちは'.mb_chars.ord # => 12371
|
||||
def ord
|
||||
Unicode.u_unpack(@wrapped_string)[0]
|
||||
end
|
||||
|
||||
# Works just like <tt>String#rjust</tt>, only integer specifies characters instead of bytes.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# "¾ cup".mb_chars.rjust(8).to_s
|
||||
# # => " ¾ cup"
|
||||
#
|
||||
# "¾ cup".mb_chars.rjust(8, " ").to_s # Use non-breaking whitespace
|
||||
# # => " ¾ cup"
|
||||
def rjust(integer, padstr=' ')
|
||||
justify(integer, :right, padstr)
|
||||
end
|
||||
|
||||
# Works just like <tt>String#ljust</tt>, only integer specifies characters instead of bytes.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# "¾ cup".mb_chars.rjust(8).to_s
|
||||
# # => "¾ cup "
|
||||
#
|
||||
# "¾ cup".mb_chars.rjust(8, " ").to_s # Use non-breaking whitespace
|
||||
# # => "¾ cup "
|
||||
def ljust(integer, padstr=' ')
|
||||
justify(integer, :left, padstr)
|
||||
end
|
||||
|
||||
# Works just like <tt>String#center</tt>, only integer specifies characters instead of bytes.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# "¾ cup".mb_chars.center(8).to_s
|
||||
# # => " ¾ cup "
|
||||
#
|
||||
# "¾ cup".mb_chars.center(8, " ").to_s # Use non-breaking whitespace
|
||||
# # => " ¾ cup "
|
||||
def center(integer, padstr=' ')
|
||||
justify(integer, :center, padstr)
|
||||
end
|
||||
|
||||
else
|
||||
def =~(other)
|
||||
@wrapped_string =~ other
|
||||
end
|
||||
def =~(other)
|
||||
@wrapped_string =~ other
|
||||
end
|
||||
|
||||
# Works just like <tt>String#split</tt>, with the exception that the items in the resulting list are Chars
|
||||
|
|
|
@ -51,172 +51,5 @@ module ActiveSupport
|
|||
def extractable_options?
|
||||
true
|
||||
end
|
||||
|
||||
# Hash is ordered in Ruby 1.9!
|
||||
if RUBY_VERSION < '1.9'
|
||||
|
||||
# In MRI the Hash class is core and written in C. In particular, methods are
|
||||
# programmed with explicit C function calls and polymorphism is not honored.
|
||||
#
|
||||
# For example, []= is crucial in this implementation to maintain the @keys
|
||||
# array but hash.c invokes rb_hash_aset() originally. This prevents method
|
||||
# reuse through inheritance and forces us to reimplement stuff.
|
||||
#
|
||||
# For instance, we cannot use the inherited #merge! because albeit the algorithm
|
||||
# itself would work, our []= is not being called at all by the C code.
|
||||
|
||||
def initialize(*args, &block)
|
||||
super
|
||||
@keys = []
|
||||
end
|
||||
|
||||
def self.[](*args)
|
||||
ordered_hash = new
|
||||
|
||||
if (args.length == 1 && args.first.is_a?(Array))
|
||||
args.first.each do |key_value_pair|
|
||||
next unless (key_value_pair.is_a?(Array))
|
||||
ordered_hash[key_value_pair[0]] = key_value_pair[1]
|
||||
end
|
||||
|
||||
return ordered_hash
|
||||
end
|
||||
|
||||
unless (args.size % 2 == 0)
|
||||
raise ArgumentError.new("odd number of arguments for Hash")
|
||||
end
|
||||
|
||||
args.each_with_index do |val, ind|
|
||||
next if (ind % 2 != 0)
|
||||
ordered_hash[val] = args[ind + 1]
|
||||
end
|
||||
|
||||
ordered_hash
|
||||
end
|
||||
|
||||
def initialize_copy(other)
|
||||
super
|
||||
# make a deep copy of keys
|
||||
@keys = other.keys
|
||||
end
|
||||
|
||||
def []=(key, value)
|
||||
@keys << key unless has_key?(key)
|
||||
super
|
||||
end
|
||||
|
||||
def delete(key)
|
||||
if has_key? key
|
||||
index = @keys.index(key)
|
||||
@keys.delete_at index
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
def delete_if
|
||||
super
|
||||
sync_keys!
|
||||
self
|
||||
end
|
||||
|
||||
def reject!
|
||||
super
|
||||
sync_keys!
|
||||
self
|
||||
end
|
||||
|
||||
def reject(&block)
|
||||
dup.reject!(&block)
|
||||
end
|
||||
|
||||
def keys
|
||||
@keys.dup
|
||||
end
|
||||
|
||||
def values
|
||||
@keys.collect { |key| self[key] }
|
||||
end
|
||||
|
||||
def to_hash
|
||||
self
|
||||
end
|
||||
|
||||
def to_a
|
||||
@keys.map { |key| [ key, self[key] ] }
|
||||
end
|
||||
|
||||
def each_key
|
||||
return to_enum(:each_key) unless block_given?
|
||||
@keys.each { |key| yield key }
|
||||
self
|
||||
end
|
||||
|
||||
def each_value
|
||||
return to_enum(:each_value) unless block_given?
|
||||
@keys.each { |key| yield self[key]}
|
||||
self
|
||||
end
|
||||
|
||||
def each
|
||||
return to_enum(:each) unless block_given?
|
||||
@keys.each {|key| yield [key, self[key]]}
|
||||
self
|
||||
end
|
||||
|
||||
def each_pair
|
||||
return to_enum(:each_pair) unless block_given?
|
||||
@keys.each {|key| yield key, self[key]}
|
||||
self
|
||||
end
|
||||
|
||||
alias_method :select, :find_all
|
||||
|
||||
def clear
|
||||
super
|
||||
@keys.clear
|
||||
self
|
||||
end
|
||||
|
||||
def shift
|
||||
k = @keys.first
|
||||
v = delete(k)
|
||||
[k, v]
|
||||
end
|
||||
|
||||
def merge!(other_hash)
|
||||
if block_given?
|
||||
other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v }
|
||||
else
|
||||
other_hash.each { |k, v| self[k] = v }
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
alias_method :update, :merge!
|
||||
|
||||
def merge(other_hash, &block)
|
||||
dup.merge!(other_hash, &block)
|
||||
end
|
||||
|
||||
# When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
|
||||
def replace(other)
|
||||
super
|
||||
@keys = other.keys
|
||||
self
|
||||
end
|
||||
|
||||
def invert
|
||||
OrderedHash[self.to_a.map!{|key_value_pair| key_value_pair.reverse}]
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<OrderedHash #{super}>"
|
||||
end
|
||||
|
||||
private
|
||||
def sync_keys!
|
||||
@keys.delete_if {|k| !has_key?(k)}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -144,8 +144,6 @@ end
|
|||
|
||||
if RUBY_VERSION.between?('1.9.2', '2.0')
|
||||
require 'active_support/testing/performance/ruby/yarv'
|
||||
elsif RUBY_VERSION.between?('1.8.6', '1.9')
|
||||
require 'active_support/testing/performance/ruby/mri'
|
||||
else
|
||||
$stderr.puts 'Update your ruby interpreter to be able to run benchmarks.'
|
||||
exit
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
module ActiveSupport
|
||||
module Testing
|
||||
module Performance
|
||||
module Metrics
|
||||
class Base
|
||||
protected
|
||||
# Ruby 1.8 + ruby-prof wrapper (enable/disable stats for Benchmarker)
|
||||
if GC.respond_to?(:enable_stats)
|
||||
def with_gc_stats
|
||||
GC.enable_stats
|
||||
GC.start
|
||||
yield
|
||||
ensure
|
||||
GC.disable_stats
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Memory < DigitalInformationUnit
|
||||
# Ruby 1.8 + ruby-prof wrapper
|
||||
if RubyProf.respond_to?(:measure_memory)
|
||||
def measure
|
||||
RubyProf.measure_memory
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Objects < Amount
|
||||
# Ruby 1.8 + ruby-prof wrapper
|
||||
if RubyProf.respond_to?(:measure_allocations)
|
||||
def measure
|
||||
RubyProf.measure_allocations
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class GcRuns < Amount
|
||||
# Ruby 1.8 + ruby-prof wrapper
|
||||
if RubyProf.respond_to?(:measure_gc_runs)
|
||||
def measure
|
||||
RubyProf.measure_gc_runs
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class GcTime < Time
|
||||
# Ruby 1.8 + ruby-prof wrapper
|
||||
if RubyProf.respond_to?(:measure_gc_time)
|
||||
def measure
|
||||
RubyProf.measure_gc_time / 1000.0 / 1000.0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -11,15 +11,11 @@ lib = File.expand_path("#{File.dirname(__FILE__)}/../lib")
|
|||
$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
|
||||
|
||||
require 'active_support/core_ext/kernel/reporting'
|
||||
|
||||
require 'active_support/core_ext/string/encoding'
|
||||
if "ruby".encoding_aware?
|
||||
# These are the normal settings that will be set up by Railties
|
||||
# TODO: Have these tests support other combinations of these values
|
||||
silence_warnings do
|
||||
Encoding.default_internal = "UTF-8"
|
||||
Encoding.default_external = "UTF-8"
|
||||
end
|
||||
|
||||
silence_warnings do
|
||||
Encoding.default_internal = "UTF-8"
|
||||
Encoding.default_external = "UTF-8"
|
||||
end
|
||||
|
||||
require 'test/unit'
|
||||
|
@ -30,9 +26,6 @@ silence_warnings { require 'mocha' }
|
|||
ENV['NO_RELOAD'] = '1'
|
||||
require 'active_support'
|
||||
|
||||
# Include shims until we get off 1.8.6
|
||||
require 'active_support/ruby/shim' if RUBY_VERSION < '1.8.7'
|
||||
|
||||
def uses_memcached(test_name)
|
||||
require 'memcache'
|
||||
begin
|
||||
|
@ -43,22 +36,5 @@ def uses_memcached(test_name)
|
|||
end
|
||||
end
|
||||
|
||||
def with_kcode(code)
|
||||
if RUBY_VERSION < '1.9'
|
||||
begin
|
||||
old_kcode, $KCODE = $KCODE, code
|
||||
yield
|
||||
ensure
|
||||
$KCODE = old_kcode
|
||||
end
|
||||
else
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
# Show backtraces for deprecated behavior for quicker cleanup.
|
||||
ActiveSupport::Deprecation.debug = true
|
||||
|
||||
if RUBY_VERSION < '1.9'
|
||||
$KCODE = 'UTF8'
|
||||
end
|
||||
ActiveSupport::Deprecation.debug = true
|
|
@ -384,16 +384,6 @@ class DateExtCalculationsTest < ActiveSupport::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
if RUBY_VERSION < '1.9'
|
||||
def test_rfc3339
|
||||
assert_equal('1980-02-28', Date.new(1980, 2, 28).rfc3339)
|
||||
end
|
||||
|
||||
def test_iso8601
|
||||
assert_equal('1980-02-28', Date.new(1980, 2, 28).iso8601)
|
||||
end
|
||||
end
|
||||
|
||||
def test_today
|
||||
Date.stubs(:current).returns(Date.new(2000, 1, 1))
|
||||
assert_equal false, Date.new(1999, 12, 31).today?
|
||||
|
|
|
@ -27,11 +27,7 @@ class HashExtTest < Test::Unit::TestCase
|
|||
@symbols = { :a => 1, :b => 2 }
|
||||
@mixed = { :a => 1, 'b' => 2 }
|
||||
@fixnums = { 0 => 1, 1 => 2 }
|
||||
if RUBY_VERSION < '1.9.0'
|
||||
@illegal_symbols = { "\0" => 1, "" => 2, [] => 3 }
|
||||
else
|
||||
@illegal_symbols = { [] => 3 }
|
||||
end
|
||||
@illegal_symbols = { [] => 3 }
|
||||
end
|
||||
|
||||
def test_methods
|
||||
|
|
|
@ -63,15 +63,8 @@ class RangeTest < Test::Unit::TestCase
|
|||
assert_equal [1,3,5,7,9], array
|
||||
end
|
||||
|
||||
if RUBY_VERSION < '1.9'
|
||||
def test_cover
|
||||
assert((1..3).cover?(2))
|
||||
assert !(1..3).cover?(4)
|
||||
end
|
||||
else
|
||||
def test_cover_is_not_override
|
||||
range = (1..3)
|
||||
assert range.method(:include?) != range.method(:cover?)
|
||||
end
|
||||
def test_cover_is_not_override
|
||||
range = (1..3)
|
||||
assert range.method(:include?) != range.method(:cover?)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -160,14 +160,6 @@ class StringInflectionsTest < Test::Unit::TestCase
|
|||
assert_equal 97, 'abc'.ord
|
||||
end
|
||||
|
||||
if RUBY_VERSION < '1.9'
|
||||
def test_getbyte
|
||||
assert_equal 97, 'a'.getbyte(0)
|
||||
assert_equal 99, 'abc'.getbyte(2)
|
||||
assert_nil 'abc'.getbyte(3)
|
||||
end
|
||||
end
|
||||
|
||||
def test_string_to_time
|
||||
assert_equal Time.utc(2005, 2, 27, 23, 50), "2005-02-27 23:50".to_time
|
||||
assert_equal Time.local(2005, 2, 27, 23, 50), "2005-02-27 23:50".to_time(:local)
|
||||
|
@ -287,21 +279,9 @@ class StringInflectionsTest < Test::Unit::TestCase
|
|||
assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, :omission => "[...]", :separator => ' ')
|
||||
end
|
||||
|
||||
if RUBY_VERSION < '1.9.0'
|
||||
def test_truncate_multibyte
|
||||
with_kcode 'none' do
|
||||
assert_equal "\354\225\210\353\205\225\355...", "\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224".truncate(10)
|
||||
end
|
||||
with_kcode 'u' do
|
||||
assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...",
|
||||
"\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".truncate(10)
|
||||
end
|
||||
end
|
||||
else
|
||||
def test_truncate_multibyte
|
||||
assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'),
|
||||
"\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8').truncate(10)
|
||||
end
|
||||
def test_truncate_multibyte
|
||||
assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'),
|
||||
"\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8').truncate(10)
|
||||
end
|
||||
|
||||
def test_constantize
|
||||
|
@ -338,22 +318,8 @@ class CoreExtStringMultibyteTest < ActiveSupport::TestCase
|
|||
assert !BYTE_STRING.is_utf8?
|
||||
end
|
||||
|
||||
if RUBY_VERSION < '1.9'
|
||||
def test_mb_chars_returns_self_when_kcode_not_set
|
||||
with_kcode('none') do
|
||||
assert_kind_of String, UNICODE_STRING.mb_chars
|
||||
end
|
||||
end
|
||||
|
||||
def test_mb_chars_returns_an_instance_of_the_chars_proxy_when_kcode_utf8
|
||||
with_kcode('UTF8') do
|
||||
assert_kind_of ActiveSupport::Multibyte.proxy_class, UNICODE_STRING.mb_chars
|
||||
end
|
||||
end
|
||||
else
|
||||
def test_mb_chars_returns_instance_of_proxy_class
|
||||
assert_kind_of ActiveSupport::Multibyte.proxy_class, UNICODE_STRING.mb_chars
|
||||
end
|
||||
def test_mb_chars_returns_instance_of_proxy_class
|
||||
assert_kind_of ActiveSupport::Multibyte.proxy_class, UNICODE_STRING.mb_chars
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -479,11 +445,7 @@ class OutputSafetyTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
test 'knows whether it is encoding aware' do
|
||||
if RUBY_VERSION >= "1.9"
|
||||
assert 'ruby'.encoding_aware?
|
||||
else
|
||||
assert !'ruby'.encoding_aware?
|
||||
end
|
||||
assert 'ruby'.encoding_aware?
|
||||
end
|
||||
|
||||
test "call to_param returns a normal string" do
|
||||
|
|
|
@ -448,9 +448,8 @@ class TimeWithZoneTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_ruby_19_weekday_name_query_methods
|
||||
ruby_19_or_greater = RUBY_VERSION >= '1.9'
|
||||
%w(sunday? monday? tuesday? wednesday? thursday? friday? saturday?).each do |name|
|
||||
assert_equal ruby_19_or_greater, @twz.respond_to?(name)
|
||||
assert_respond_to @twz, name
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -88,25 +88,21 @@ class TestJSONEncoding < Test::Unit::TestCase
|
|||
assert_equal %({\"a\":\"b\",\"c\":\"d\"}), sorted_json(ActiveSupport::JSON.encode(:a => :b, :c => :d))
|
||||
end
|
||||
|
||||
def test_utf8_string_encoded_properly_when_kcode_is_utf8
|
||||
with_kcode 'UTF8' do
|
||||
result = ActiveSupport::JSON.encode('€2.99')
|
||||
assert_equal '"\\u20ac2.99"', result
|
||||
assert_equal(Encoding::UTF_8, result.encoding) if result.respond_to?(:encoding)
|
||||
def test_utf8_string_encoded_properly
|
||||
result = ActiveSupport::JSON.encode('€2.99')
|
||||
assert_equal '"\\u20ac2.99"', result
|
||||
assert_equal(Encoding::UTF_8, result.encoding) if result.respond_to?(:encoding)
|
||||
|
||||
result = ActiveSupport::JSON.encode('✎☺')
|
||||
assert_equal '"\\u270e\\u263a"', result
|
||||
assert_equal(Encoding::UTF_8, result.encoding) if result.respond_to?(:encoding)
|
||||
end
|
||||
result = ActiveSupport::JSON.encode('✎☺')
|
||||
assert_equal '"\\u270e\\u263a"', result
|
||||
assert_equal(Encoding::UTF_8, result.encoding) if result.respond_to?(:encoding)
|
||||
end
|
||||
|
||||
if '1.9'.respond_to?(:force_encoding)
|
||||
def test_non_utf8_string_transcodes
|
||||
s = '二'.encode('Shift_JIS')
|
||||
result = ActiveSupport::JSON.encode(s)
|
||||
assert_equal '"\\u4e8c"', result
|
||||
assert_equal Encoding::UTF_8, result.encoding
|
||||
end
|
||||
def test_non_utf8_string_transcodes
|
||||
s = '二'.encode('Shift_JIS')
|
||||
result = ActiveSupport::JSON.encode(s)
|
||||
assert_equal '"\\u4e8c"', result
|
||||
assert_equal Encoding::UTF_8, result.encoding
|
||||
end
|
||||
|
||||
def test_exception_raised_when_encoding_circular_reference_in_array
|
||||
|
|
|
@ -101,15 +101,8 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase
|
|||
|
||||
def setup
|
||||
@chars = UNICODE_STRING.dup.mb_chars
|
||||
|
||||
if RUBY_VERSION < '1.9'
|
||||
# Multibyte support all kinds of whitespace (ie. NEWLINE, SPACE, EM SPACE)
|
||||
@whitespace = "\n\t#{[32, 8195].pack('U*')}"
|
||||
else
|
||||
# Ruby 1.9 only supports basic whitespace
|
||||
@whitespace = "\n\t "
|
||||
end
|
||||
|
||||
# Ruby 1.9 only supports basic whitespace
|
||||
@whitespace = "\n\t "
|
||||
@byte_order_mark = [65279].pack('U')
|
||||
end
|
||||
|
||||
|
|
|
@ -56,37 +56,9 @@ class MultibyteUtilsTest < ActiveSupport::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
if RUBY_VERSION < '1.9'
|
||||
test "clean leaves ASCII strings intact" do
|
||||
with_encoding('None') do
|
||||
[
|
||||
'word', "\270\236\010\210\245"
|
||||
].each do |string|
|
||||
assert_equal string, ActiveSupport::Multibyte.clean(string)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "clean cleans invalid characters from UTF-8 encoded strings" do
|
||||
with_encoding('UTF8') do
|
||||
cleaned_utf8 = [8].pack('C*')
|
||||
assert_equal example('valid UTF-8'), ActiveSupport::Multibyte.clean(example('valid UTF-8'))
|
||||
assert_equal cleaned_utf8, ActiveSupport::Multibyte.clean(example('invalid UTF-8'))
|
||||
end
|
||||
end
|
||||
|
||||
test "clean cleans invalid characters from Shift-JIS encoded strings" do
|
||||
with_encoding('SJIS') do
|
||||
cleaned_sjis = [184, 0, 136, 165].pack('C*')
|
||||
assert_equal example('valid Shift-JIS'), ActiveSupport::Multibyte.clean(example('valid Shift-JIS'))
|
||||
assert_equal cleaned_sjis, ActiveSupport::Multibyte.clean(example('invalid Shift-JIS'))
|
||||
end
|
||||
end
|
||||
else
|
||||
test "clean is a no-op" do
|
||||
with_encoding('UTF8') do
|
||||
assert_equal example('invalid Shift-JIS'), ActiveSupport::Multibyte.clean(example('invalid Shift-JIS'))
|
||||
end
|
||||
test "clean is a no-op" do
|
||||
with_encoding('UTF8') do
|
||||
assert_equal example('invalid Shift-JIS'), ActiveSupport::Multibyte.clean(example('invalid Shift-JIS'))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -119,19 +91,13 @@ class MultibyteUtilsTest < ActiveSupport::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
if 'string'.respond_to?(:encoding)
|
||||
KCODE_TO_ENCODING = Hash.new(Encoding::BINARY).
|
||||
update('UTF8' => Encoding::UTF_8, 'SJIS' => Encoding::Shift_JIS)
|
||||
KCODE_TO_ENCODING = Hash.new(Encoding::BINARY).
|
||||
update('UTF8' => Encoding::UTF_8, 'SJIS' => Encoding::Shift_JIS)
|
||||
|
||||
def with_encoding(enc)
|
||||
before = Encoding.default_external
|
||||
silence_warnings { Encoding.default_external = KCODE_TO_ENCODING[enc] }
|
||||
|
||||
yield
|
||||
|
||||
silence_warnings { Encoding.default_external = before }
|
||||
end
|
||||
else
|
||||
alias with_encoding with_kcode
|
||||
def with_encoding(enc)
|
||||
before = Encoding.default_external
|
||||
silence_warnings { Encoding.default_external = KCODE_TO_ENCODING[enc] }
|
||||
yield
|
||||
silence_warnings { Encoding.default_external = before }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -81,24 +81,21 @@ class OrderedHashTest < Test::Unit::TestCase
|
|||
keys = []
|
||||
assert_equal @ordered_hash, @ordered_hash.each_key { |k| keys << k }
|
||||
assert_equal @keys, keys
|
||||
expected_class = RUBY_VERSION < '1.9' ? Enumerable::Enumerator : Enumerator
|
||||
assert_kind_of expected_class, @ordered_hash.each_key
|
||||
assert_kind_of Enumerator, @ordered_hash.each_key
|
||||
end
|
||||
|
||||
def test_each_value
|
||||
values = []
|
||||
assert_equal @ordered_hash, @ordered_hash.each_value { |v| values << v }
|
||||
assert_equal @values, values
|
||||
expected_class = RUBY_VERSION < '1.9' ? Enumerable::Enumerator : Enumerator
|
||||
assert_kind_of expected_class, @ordered_hash.each_value
|
||||
assert_kind_of Enumerator, @ordered_hash.each_value
|
||||
end
|
||||
|
||||
def test_each
|
||||
values = []
|
||||
assert_equal @ordered_hash, @ordered_hash.each {|key, value| values << value}
|
||||
assert_equal @values, values
|
||||
expected_class = RUBY_VERSION < '1.9' ? Enumerable::Enumerator : Enumerator
|
||||
assert_kind_of expected_class, @ordered_hash.each
|
||||
assert_kind_of Enumerator, @ordered_hash.each
|
||||
end
|
||||
|
||||
def test_each_with_index
|
||||
|
@ -114,9 +111,7 @@ class OrderedHashTest < Test::Unit::TestCase
|
|||
end
|
||||
assert_equal @values, values
|
||||
assert_equal @keys, keys
|
||||
|
||||
expected_class = RUBY_VERSION < '1.9' ? Enumerable::Enumerator : Enumerator
|
||||
assert_kind_of expected_class, @ordered_hash.each_pair
|
||||
assert_kind_of Enumerator, @ordered_hash.each_pair
|
||||
end
|
||||
|
||||
def test_find_all
|
||||
|
|
Loading…
Reference in a new issue