activesupport 3.0.0.beta2 → 3.0.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- data/CHANGELOG +7 -0
- data/lib/active_support/backtrace_cleaner.rb +7 -1
- data/lib/active_support/cache/mem_cache_store.rb +3 -3
- data/lib/active_support/cache/strategy/local_cache.rb +1 -1
- data/lib/active_support/callbacks.rb +2 -2
- data/lib/active_support/core_ext/array/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/attribute.rb +25 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +1 -0
- data/lib/active_support/core_ext/{object → kernel}/singleton_class.rb +3 -3
- data/lib/active_support/core_ext/module/aliasing.rb +1 -1
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +1 -1
- data/lib/active_support/core_ext/module/delegation.rb +1 -1
- data/lib/active_support/core_ext/module/synchronization.rb +1 -1
- data/lib/active_support/core_ext/object.rb +0 -1
- data/lib/active_support/core_ext/proc.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +1 -1
- data/lib/active_support/inflections.rb +1 -1
- data/lib/active_support/inflector/inflections.rb +1 -1
- data/lib/active_support/inflector/methods.rb +7 -5
- data/lib/active_support/inflector/transliterate.rb +38 -22
- data/lib/active_support/memoizable.rb +1 -1
- data/lib/active_support/multibyte/chars.rb +67 -18
- data/lib/active_support/ordered_hash.rb +24 -30
- data/lib/active_support/values/time_zone.rb +27 -63
- data/lib/active_support/version.rb +1 -1
- metadata +4 -4
data/CHANGELOG
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
*Rails 3.0.0 [beta 3] (April 13th, 2010)*
|
2
|
+
|
3
|
+
* Improve transliteration quality. #4374 [Norman Clarke]
|
4
|
+
|
5
|
+
* Speed up and add Ruby 1.9 support for ActiveSupport::Multibyte::Chars#tidy_bytes. #4350 [Norman Clarke]
|
6
|
+
|
7
|
+
|
1
8
|
*Rails 3.0.0 [beta 2] (April 1st, 2010)*
|
2
9
|
|
3
10
|
* Reduced load time by deferring configuration of classes using
|
@@ -4,7 +4,9 @@ module ActiveSupport
|
|
4
4
|
# context, so only the relevant lines are included.
|
5
5
|
#
|
6
6
|
# If you need to reconfigure an existing BacktraceCleaner, like the one in Rails, to show as much as possible, you can always
|
7
|
-
# call BacktraceCleaner#remove_silencers!
|
7
|
+
# call BacktraceCleaner#remove_silencers! Also, if you need to reconfigure an existing BacktraceCleaner so that it does not
|
8
|
+
# filter or modify the paths of any lines of the backtrace, you can call BacktraceCleaner#remove_filters! These two methods
|
9
|
+
# will give you a completely untouched backtrace.
|
8
10
|
#
|
9
11
|
# Example:
|
10
12
|
#
|
@@ -60,6 +62,10 @@ module ActiveSupport
|
|
60
62
|
@silencers = []
|
61
63
|
end
|
62
64
|
|
65
|
+
def remove_filters!
|
66
|
+
@filters = []
|
67
|
+
end
|
68
|
+
|
63
69
|
private
|
64
70
|
def filter(backtrace)
|
65
71
|
@filters.each do |f|
|
@@ -64,7 +64,7 @@ module ActiveSupport
|
|
64
64
|
@data.get(key, raw?(options))
|
65
65
|
end
|
66
66
|
rescue MemCache::MemCacheError => e
|
67
|
-
logger.error("MemCacheError (#{e}): #{e.message}")
|
67
|
+
logger.error("MemCacheError (#{e}): #{e.message}") if logger
|
68
68
|
nil
|
69
69
|
end
|
70
70
|
|
@@ -85,7 +85,7 @@ module ActiveSupport
|
|
85
85
|
response == Response::STORED
|
86
86
|
end
|
87
87
|
rescue MemCache::MemCacheError => e
|
88
|
-
logger.error("MemCacheError (#{e}): #{e.message}")
|
88
|
+
logger.error("MemCacheError (#{e}): #{e.message}") if logger
|
89
89
|
false
|
90
90
|
end
|
91
91
|
|
@@ -95,7 +95,7 @@ module ActiveSupport
|
|
95
95
|
response == Response::DELETED
|
96
96
|
end
|
97
97
|
rescue MemCache::MemCacheError => e
|
98
|
-
logger.error("MemCacheError (#{e}): #{e.message}")
|
98
|
+
logger.error("MemCacheError (#{e}): #{e.message}") if logger
|
99
99
|
false
|
100
100
|
end
|
101
101
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'active_support/core_ext/array/wrap'
|
2
2
|
require 'active_support/core_ext/class/inheritable_attributes'
|
3
3
|
require 'active_support/core_ext/kernel/reporting'
|
4
|
-
require 'active_support/core_ext/
|
4
|
+
require 'active_support/core_ext/kernel/singleton_class'
|
5
5
|
|
6
6
|
module ActiveSupport
|
7
7
|
# Callbacks are hooks into the lifecycle of an object that allow you to trigger logic
|
@@ -387,7 +387,7 @@ module ActiveSupport
|
|
387
387
|
send("_update_#{symbol}_superclass_callbacks")
|
388
388
|
body = send("_#{symbol}_callbacks").compile(nil)
|
389
389
|
|
390
|
-
body, line = <<-RUBY_EVAL, __LINE__
|
390
|
+
body, line = <<-RUBY_EVAL, __LINE__ + 1
|
391
391
|
def _run_#{symbol}_callbacks(key = nil, &blk)
|
392
392
|
if self.class.send("_update_#{symbol}_superclass_callbacks")
|
393
393
|
self.class.__define_runner(#{symbol.inspect})
|
@@ -131,7 +131,7 @@ class Array
|
|
131
131
|
require 'builder' unless defined?(Builder)
|
132
132
|
|
133
133
|
options = options.dup
|
134
|
-
options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? ActiveSupport::Inflector.pluralize(ActiveSupport::Inflector.underscore(first.class.name)) : "records"
|
134
|
+
options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? ActiveSupport::Inflector.pluralize(ActiveSupport::Inflector.underscore(first.class.name)).tr('/', '_') : "records"
|
135
135
|
options[:children] ||= options[:root].singularize
|
136
136
|
options[:indent] ||= 2
|
137
137
|
options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require 'active_support/core_ext/
|
2
|
-
require 'active_support/core_ext/module/delegation'
|
1
|
+
require 'active_support/core_ext/kernel/singleton_class'
|
3
2
|
require 'active_support/core_ext/module/remove_method'
|
4
3
|
|
5
4
|
class Class
|
@@ -41,21 +40,31 @@ class Class
|
|
41
40
|
def class_attribute(*attrs)
|
42
41
|
instance_writer = !attrs.last.is_a?(Hash) || attrs.pop[:instance_writer]
|
43
42
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
43
|
+
attrs.each do |name|
|
44
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
45
|
+
def self.#{name}() nil end
|
46
|
+
def self.#{name}?() !!#{name} end
|
47
|
+
|
48
|
+
def self.#{name}=(val)
|
49
|
+
singleton_class.class_eval do
|
50
|
+
remove_possible_method(:#{name})
|
51
|
+
define_method(:#{name}) { val }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def #{name}
|
56
|
+
defined?(@#{name}) ? @#{name} : singleton_class.#{name}
|
57
|
+
end
|
52
58
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
+
def #{name}?
|
60
|
+
!!#{name}
|
61
|
+
end
|
62
|
+
RUBY
|
63
|
+
|
64
|
+
if instance_writer
|
65
|
+
body = "def #{name}=(value) @#{name} = value end"
|
66
|
+
class_eval body, __FILE__, __LINE__ - 1
|
67
|
+
end
|
59
68
|
end
|
60
69
|
end
|
61
70
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_support/core_ext/object/blank'
|
2
2
|
require 'active_support/core_ext/array/extract_options'
|
3
|
-
require 'active_support/core_ext/
|
3
|
+
require 'active_support/core_ext/kernel/singleton_class'
|
4
4
|
require 'active_support/core_ext/module/remove_method'
|
5
5
|
|
6
6
|
class Class
|
@@ -1,12 +1,12 @@
|
|
1
|
-
|
1
|
+
module Kernel
|
2
2
|
# Returns the object's singleton class.
|
3
3
|
def singleton_class
|
4
4
|
class << self
|
5
5
|
self
|
6
6
|
end
|
7
|
-
end unless respond_to?(:singleton_class)
|
7
|
+
end unless respond_to?(:singleton_class) # exists in 1.9.2
|
8
8
|
|
9
|
-
# class_eval on an object acts like
|
9
|
+
# class_eval on an object acts like singleton_class.class_eval.
|
10
10
|
def class_eval(*args, &block)
|
11
11
|
singleton_class.class_eval(*args, &block)
|
12
12
|
end
|
@@ -61,7 +61,7 @@ class Module
|
|
61
61
|
# e.subject = "Megastars"
|
62
62
|
# e.title # => "Megastars"
|
63
63
|
def alias_attribute(new_name, old_name)
|
64
|
-
module_eval <<-STR, __FILE__, __LINE__+1
|
64
|
+
module_eval <<-STR, __FILE__, __LINE__ + 1
|
65
65
|
def #{new_name}; self.#{old_name}; end # def subject; self.title; end
|
66
66
|
def #{new_name}?; self.#{old_name}?; end # def subject?; self.title?; end
|
67
67
|
def #{new_name}=(v); self.#{old_name} = v; end # def subject=(v); self.title = v; end
|
@@ -21,7 +21,7 @@ class Module
|
|
21
21
|
def attr_accessor_with_default(sym, default = nil, &block)
|
22
22
|
raise 'Default value or block required' unless !default.nil? || block
|
23
23
|
define_method(sym, block_given? ? block : Proc.new { default })
|
24
|
-
module_eval(<<-EVAL, __FILE__, __LINE__)
|
24
|
+
module_eval(<<-EVAL, __FILE__, __LINE__ + 1)
|
25
25
|
def #{sym}=(value) # def age=(value)
|
26
26
|
class << self; attr_reader :#{sym} end # class << self; attr_reader :age end
|
27
27
|
@#{sym} = value # @age = value
|
@@ -126,7 +126,7 @@ class Module
|
|
126
126
|
%(raise "#{self}##{prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
|
127
127
|
end
|
128
128
|
|
129
|
-
module_eval(<<-EOS, file, line)
|
129
|
+
module_eval(<<-EOS, file, line - 5)
|
130
130
|
if instance_methods(false).map(&:to_s).include?("#{prefix}#{method}")
|
131
131
|
remove_possible_method("#{prefix}#{method}")
|
132
132
|
end
|
@@ -28,7 +28,7 @@ class Module
|
|
28
28
|
raise ArgumentError, "#{method} is already synchronized. Double synchronization is not currently supported."
|
29
29
|
end
|
30
30
|
|
31
|
-
module_eval(<<-EOS, __FILE__, __LINE__)
|
31
|
+
module_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
32
32
|
def #{aliased_method}_with_synchronization#{punctuation}(*args, &block) # def expire_with_synchronization(*args, &block)
|
33
33
|
#{with}.synchronize do # @@lock.synchronize do
|
34
34
|
#{aliased_method}_without_synchronization#{punctuation}(*args, &block) # expire_without_synchronization(*args, &block)
|
@@ -5,7 +5,6 @@ require 'active_support/core_ext/object/try'
|
|
5
5
|
|
6
6
|
require 'active_support/core_ext/object/conversions'
|
7
7
|
require 'active_support/core_ext/object/instance_variables'
|
8
|
-
require 'active_support/core_ext/object/singleton_class'
|
9
8
|
require 'active_support/core_ext/object/misc'
|
10
9
|
require 'active_support/core_ext/object/extending'
|
11
10
|
|
@@ -51,6 +51,6 @@ module ActiveSupport
|
|
51
51
|
inflect.irregular('move', 'moves')
|
52
52
|
inflect.irregular('cow', 'kine')
|
53
53
|
|
54
|
-
inflect.uncountable(%w(equipment information rice money species series fish sheep))
|
54
|
+
inflect.uncountable(%w(equipment information rice money species series fish sheep jeans))
|
55
55
|
end
|
56
56
|
end
|
@@ -148,7 +148,7 @@ module ActiveSupport
|
|
148
148
|
def singularize(word)
|
149
149
|
result = word.to_s.dup
|
150
150
|
|
151
|
-
if inflections.uncountables.
|
151
|
+
if inflections.uncountables.any? { |inflection| result =~ /#{inflection}\Z/i }
|
152
152
|
result
|
153
153
|
else
|
154
154
|
inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
|
@@ -36,11 +36,13 @@ module ActiveSupport
|
|
36
36
|
# "ActiveRecord".underscore # => "active_record"
|
37
37
|
# "ActiveRecord::Errors".underscore # => active_record/errors
|
38
38
|
def underscore(camel_cased_word)
|
39
|
-
camel_cased_word.to_s.
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
word = camel_cased_word.to_s.dup
|
40
|
+
word.gsub!(/::/, '/')
|
41
|
+
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
42
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
43
|
+
word.tr!("-", "_")
|
44
|
+
word.downcase!
|
45
|
+
word
|
44
46
|
end
|
45
47
|
|
46
48
|
# Replaces underscores with dashes in the string.
|
@@ -1,31 +1,47 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require 'iconv'
|
3
2
|
require 'active_support/core_ext/string/multibyte'
|
4
3
|
|
5
4
|
module ActiveSupport
|
6
5
|
module Inflector
|
7
6
|
extend self
|
8
|
-
|
9
|
-
# Replaces accented characters with their ascii equivalents.
|
10
|
-
def transliterate(string)
|
11
|
-
Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s
|
12
|
-
end
|
13
7
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
8
|
+
# UTF-8 byte => ASCII approximate UTF-8 byte(s)
|
9
|
+
ASCII_APPROXIMATIONS = {
|
10
|
+
198 => [65, 69], # Æ => AE
|
11
|
+
208 => 68, # Ð => D
|
12
|
+
216 => 79, # Ø => O
|
13
|
+
222 => [84, 104], # Þ => Þ
|
14
|
+
223 => [115, 115], # ß => ss
|
15
|
+
230 => [97, 101], # æ => ae
|
16
|
+
240 => 100, # ð => d
|
17
|
+
248 => 111, # ø => o
|
18
|
+
254 => [116, 104], # þ => th
|
19
|
+
272 => 68, # Đ => D
|
20
|
+
273 => 100, # đ => đ
|
21
|
+
294 => 72, # Ħ => H
|
22
|
+
295 => 104, # ħ => h
|
23
|
+
305 => 105, # ı => i
|
24
|
+
306 => [73, 74], # IJ =>IJ
|
25
|
+
307 => [105, 106], # ij => ij
|
26
|
+
312 => 107, # ĸ => k
|
27
|
+
319 => 76, # Ŀ => L
|
28
|
+
320 => 108, # ŀ => l
|
29
|
+
321 => 76, # Ł => L
|
30
|
+
322 => 108, # ł => l
|
31
|
+
329 => 110, # ʼn => n
|
32
|
+
330 => [78, 71], # Ŋ => NG
|
33
|
+
331 => [110, 103], # ŋ => ng
|
34
|
+
338 => [79, 69], # Œ => OE
|
35
|
+
339 => [111, 101], # œ => oe
|
36
|
+
358 => 84, # Ŧ => T
|
37
|
+
359 => 116 # ŧ => t
|
38
|
+
}
|
20
39
|
|
21
|
-
#
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
string.mb_chars.normalize(:kd). # Decompose accented characters
|
27
|
-
gsub(/[^\x00-\x7F]+/, '') # Remove anything non-ASCII entirely (e.g. diacritics).
|
28
|
-
end
|
40
|
+
# Replaces accented characters with an ASCII approximation, or deletes it if none exsits.
|
41
|
+
def transliterate(string)
|
42
|
+
ActiveSupport::Multibyte::Chars.new(string).tidy_bytes.normalize(:d).unpack("U*").map do |char|
|
43
|
+
ASCII_APPROXIMATIONS[char] || (char if char < 128)
|
44
|
+
end.compact.flatten.pack("U*")
|
29
45
|
end
|
30
46
|
|
31
47
|
# Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
|
@@ -56,6 +72,6 @@ module ActiveSupport
|
|
56
72
|
parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '')
|
57
73
|
end
|
58
74
|
parameterized_string.downcase
|
59
|
-
end
|
75
|
+
end
|
60
76
|
end
|
61
|
-
end
|
77
|
+
end
|
@@ -19,7 +19,7 @@ module ActiveSupport #:nodoc:
|
|
19
19
|
# bad.explicit_checking_method "T".mb_chars.downcase.to_s
|
20
20
|
#
|
21
21
|
# The default Chars implementation assumes that the encoding of the string is UTF-8, if you want to handle different
|
22
|
-
# encodings you can write your own multibyte string handler and configure it through
|
22
|
+
# encodings you can write your own multibyte string handler and configure it through
|
23
23
|
# ActiveSupport::Multibyte.proxy_class.
|
24
24
|
#
|
25
25
|
# class CharsForUTF32
|
@@ -458,8 +458,10 @@ module ActiveSupport #:nodoc:
|
|
458
458
|
end
|
459
459
|
|
460
460
|
# Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string.
|
461
|
-
|
462
|
-
|
461
|
+
#
|
462
|
+
# Passing +true+ will forcibly tidy all bytes, assuming that the string's encoding is entirely CP1252 or ISO-8859-1.
|
463
|
+
def tidy_bytes(force = false)
|
464
|
+
chars(self.class.tidy_bytes(@wrapped_string, force))
|
463
465
|
end
|
464
466
|
|
465
467
|
%w(lstrip rstrip strip reverse upcase downcase tidy_bytes capitalize).each do |method|
|
@@ -528,7 +530,7 @@ module ActiveSupport #:nodoc:
|
|
528
530
|
unpacked << codepoints[marker..pos-1]
|
529
531
|
marker = pos
|
530
532
|
end
|
531
|
-
end
|
533
|
+
end
|
532
534
|
unpacked
|
533
535
|
end
|
534
536
|
|
@@ -644,33 +646,80 @@ module ActiveSupport #:nodoc:
|
|
644
646
|
codepoints
|
645
647
|
end
|
646
648
|
|
649
|
+
def tidy_byte(byte)
|
650
|
+
if byte < 160
|
651
|
+
[UCD.cp1252[byte] || byte].pack("U").unpack("C*")
|
652
|
+
elsif byte < 192
|
653
|
+
[194, byte]
|
654
|
+
else
|
655
|
+
[195, byte - 64]
|
656
|
+
end
|
657
|
+
end
|
658
|
+
private :tidy_byte
|
659
|
+
|
647
660
|
# Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string.
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
661
|
+
#
|
662
|
+
# Passing +true+ will forcibly tidy all bytes, assuming that the string's encoding is entirely CP-1252 or ISO-8859-1.
|
663
|
+
def tidy_bytes(string, force = false)
|
664
|
+
if force
|
665
|
+
return string.unpack("C*").map do |b|
|
666
|
+
tidy_byte(b)
|
667
|
+
end.flatten.compact.pack("C*").unpack("U*").pack("U*")
|
668
|
+
end
|
669
|
+
|
670
|
+
bytes = string.unpack("C*")
|
671
|
+
conts_expected = 0
|
672
|
+
last_lead = 0
|
673
|
+
|
674
|
+
bytes.each_index do |i|
|
675
|
+
|
676
|
+
byte = bytes[i]
|
677
|
+
is_ascii = byte < 128
|
678
|
+
is_cont = byte > 127 && byte < 192
|
679
|
+
is_lead = byte > 191 && byte < 245
|
680
|
+
is_unused = byte > 240
|
681
|
+
is_restricted = byte > 244
|
682
|
+
|
683
|
+
# Impossible or highly unlikely byte? Clean it.
|
684
|
+
if is_unused || is_restricted
|
685
|
+
bytes[i] = tidy_byte(byte)
|
686
|
+
elsif is_cont
|
687
|
+
# Not expecting contination byte? Clean up. Otherwise, now expect one less.
|
688
|
+
conts_expected == 0 ? bytes[i] = tidy_byte(byte) : conts_expected -= 1
|
657
689
|
else
|
658
|
-
|
690
|
+
if conts_expected > 0
|
691
|
+
# Expected continuation, but got ASCII or leading? Clean backwards up to
|
692
|
+
# the leading byte.
|
693
|
+
(1..(i - last_lead)).each {|j| bytes[i - j] = tidy_byte(bytes[i - j])}
|
694
|
+
conts_expected = 0
|
695
|
+
end
|
696
|
+
if is_lead
|
697
|
+
# Final byte is leading? Clean it.
|
698
|
+
if i == bytes.length - 1
|
699
|
+
bytes[i] = tidy_byte(bytes.last)
|
700
|
+
else
|
701
|
+
# Valid leading byte? Expect continuations determined by position of
|
702
|
+
# first zero bit, with max of 3.
|
703
|
+
conts_expected = byte < 224 ? 1 : byte < 240 ? 2 : 3
|
704
|
+
last_lead = i
|
705
|
+
end
|
706
|
+
end
|
659
707
|
end
|
660
|
-
end
|
708
|
+
end
|
709
|
+
bytes.empty? ? "" : bytes.flatten.compact.pack("C*").unpack("U*").pack("U*")
|
661
710
|
end
|
662
711
|
end
|
663
712
|
|
664
713
|
protected
|
665
|
-
|
714
|
+
|
666
715
|
def translate_offset(byte_offset) #:nodoc:
|
667
716
|
return nil if byte_offset.nil?
|
668
717
|
return 0 if @wrapped_string == ''
|
669
|
-
|
718
|
+
|
670
719
|
if @wrapped_string.respond_to?(:force_encoding)
|
671
720
|
@wrapped_string = @wrapped_string.dup.force_encoding(Encoding::ASCII_8BIT)
|
672
721
|
end
|
673
|
-
|
722
|
+
|
674
723
|
begin
|
675
724
|
@wrapped_string[0...byte_offset].unpack('U*').length
|
676
725
|
rescue ArgumentError => e
|
@@ -1,13 +1,28 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
|
+
YAML.add_builtin_type("omap") do |type, val|
|
4
|
+
ActiveSupport::OrderedHash[val.map(&:to_a).map(&:first)]
|
5
|
+
end
|
6
|
+
|
3
7
|
# OrderedHash is namespaced to prevent conflicts with other implementations
|
4
8
|
module ActiveSupport
|
5
|
-
|
6
|
-
|
7
|
-
|
9
|
+
class OrderedHash < ::Hash #:nodoc:
|
10
|
+
def to_yaml_type
|
11
|
+
"!tag:yaml.org,2002:omap"
|
8
12
|
end
|
9
|
-
|
10
|
-
|
13
|
+
|
14
|
+
def to_yaml(opts = {})
|
15
|
+
YAML.quick_emit(self, opts) do |out|
|
16
|
+
out.seq(taguri, to_yaml_style) do |seq|
|
17
|
+
each do |k, v|
|
18
|
+
seq.add(k => v)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Hash is ordered in Ruby 1.9!
|
25
|
+
if RUBY_VERSION < '1.9'
|
11
26
|
def initialize(*args, &block)
|
12
27
|
super
|
13
28
|
@keys = []
|
@@ -55,7 +70,7 @@ module ActiveSupport
|
|
55
70
|
end
|
56
71
|
super
|
57
72
|
end
|
58
|
-
|
73
|
+
|
59
74
|
def delete_if
|
60
75
|
super
|
61
76
|
sync_keys!
|
@@ -134,31 +149,10 @@ module ActiveSupport
|
|
134
149
|
"#<OrderedHash #{super}>"
|
135
150
|
end
|
136
151
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
@keys.delete_if {|k| !has_key?(k)}
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
class OrderedHash #:nodoc:
|
146
|
-
def to_yaml_type
|
147
|
-
"!tag:yaml.org,2002:omap"
|
148
|
-
end
|
149
|
-
|
150
|
-
def to_yaml(opts = {})
|
151
|
-
YAML.quick_emit(self, opts) do |out|
|
152
|
-
out.seq(taguri, to_yaml_style) do |seq|
|
153
|
-
each do |k, v|
|
154
|
-
seq.add(k => v)
|
155
|
-
end
|
152
|
+
private
|
153
|
+
def sync_keys!
|
154
|
+
@keys.delete_if {|k| !has_key?(k)}
|
156
155
|
end
|
157
|
-
end
|
158
156
|
end
|
159
157
|
end
|
160
|
-
|
161
|
-
YAML.add_builtin_type("omap") do |type, val|
|
162
|
-
ActiveSupport::OrderedHash[val.map(&:to_a).map(&:first)]
|
163
|
-
end
|
164
158
|
end
|
@@ -194,7 +194,7 @@ module ActiveSupport
|
|
194
194
|
# offset is the number of seconds that this time zone is offset from UTC
|
195
195
|
# (GMT). Seconds were chosen as the offset unit because that is the unit that
|
196
196
|
# Ruby uses to represent time zone offsets (see Time#utc_offset).
|
197
|
-
def initialize(name, utc_offset, tzinfo = nil)
|
197
|
+
def initialize(name, utc_offset = nil, tzinfo = nil)
|
198
198
|
@name = name
|
199
199
|
@utc_offset = utc_offset
|
200
200
|
@tzinfo = tzinfo
|
@@ -202,8 +202,12 @@ module ActiveSupport
|
|
202
202
|
end
|
203
203
|
|
204
204
|
def utc_offset
|
205
|
-
@
|
206
|
-
|
205
|
+
if @utc_offset
|
206
|
+
@utc_offset
|
207
|
+
else
|
208
|
+
@current_period ||= tzinfo.current_period
|
209
|
+
@current_period.utc_offset
|
210
|
+
end
|
207
211
|
end
|
208
212
|
|
209
213
|
# Returns the offset of this time zone as a formatted string, of the
|
@@ -305,75 +309,29 @@ module ActiveSupport
|
|
305
309
|
tzinfo.period_for_local(time, dst)
|
306
310
|
end
|
307
311
|
|
308
|
-
# TODO: Preload instead of lazy load for thread safety
|
309
312
|
def tzinfo
|
313
|
+
@tzinfo ||= TimeZone.find_tzinfo(name)
|
314
|
+
end
|
315
|
+
|
316
|
+
# TODO: Preload instead of lazy load for thread safety
|
317
|
+
def self.find_tzinfo(name)
|
310
318
|
require 'tzinfo' unless defined?(::TZInfo)
|
311
|
-
|
319
|
+
::TZInfo::Timezone.get(MAPPING[name] || name)
|
320
|
+
rescue TZInfo::InvalidTimezoneIdentifier
|
321
|
+
nil
|
312
322
|
end
|
313
323
|
|
314
324
|
unless const_defined?(:ZONES)
|
315
325
|
ZONES = []
|
316
326
|
ZONES_MAP = {}
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
"Arizona" ],
|
323
|
-
[-21_600, "Central Time (US & Canada)", "Saskatchewan", "Guadalajara",
|
324
|
-
"Mexico City", "Monterrey", "Central America" ],
|
325
|
-
[-18_000, "Eastern Time (US & Canada)", "Indiana (East)", "Bogota",
|
326
|
-
"Lima", "Quito" ],
|
327
|
-
[-16_200, "Caracas" ],
|
328
|
-
[-14_400, "Atlantic Time (Canada)", "Georgetown", "La Paz", "Santiago" ],
|
329
|
-
[-12_600, "Newfoundland" ],
|
330
|
-
[-10_800, "Brasilia", "Buenos Aires", "Greenland" ],
|
331
|
-
[ -7_200, "Mid-Atlantic" ],
|
332
|
-
[ -3_600, "Azores", "Cape Verde Is." ],
|
333
|
-
[ 0, "Dublin", "Edinburgh", "Lisbon", "London", "Casablanca",
|
334
|
-
"Monrovia", "UTC" ],
|
335
|
-
[ 3_600, "Belgrade", "Bratislava", "Budapest", "Ljubljana", "Prague",
|
336
|
-
"Sarajevo", "Skopje", "Warsaw", "Zagreb", "Brussels",
|
337
|
-
"Copenhagen", "Madrid", "Paris", "Amsterdam", "Berlin",
|
338
|
-
"Bern", "Rome", "Stockholm", "Vienna",
|
339
|
-
"West Central Africa" ],
|
340
|
-
[ 7_200, "Bucharest", "Cairo", "Helsinki", "Kyiv", "Riga", "Sofia",
|
341
|
-
"Tallinn", "Vilnius", "Athens", "Istanbul", "Minsk",
|
342
|
-
"Jerusalem", "Harare", "Pretoria" ],
|
343
|
-
[ 10_800, "Moscow", "St. Petersburg", "Volgograd", "Kuwait", "Riyadh",
|
344
|
-
"Nairobi", "Baghdad" ],
|
345
|
-
[ 12_600, "Tehran" ],
|
346
|
-
[ 14_400, "Abu Dhabi", "Muscat", "Baku", "Tbilisi", "Yerevan" ],
|
347
|
-
[ 16_200, "Kabul" ],
|
348
|
-
[ 18_000, "Ekaterinburg", "Islamabad", "Karachi", "Tashkent" ],
|
349
|
-
[ 19_800, "Chennai", "Kolkata", "Mumbai", "New Delhi", "Sri Jayawardenepura" ],
|
350
|
-
[ 20_700, "Kathmandu" ],
|
351
|
-
[ 21_600, "Astana", "Dhaka", "Almaty",
|
352
|
-
"Novosibirsk" ],
|
353
|
-
[ 23_400, "Rangoon" ],
|
354
|
-
[ 25_200, "Bangkok", "Hanoi", "Jakarta", "Krasnoyarsk" ],
|
355
|
-
[ 28_800, "Beijing", "Chongqing", "Hong Kong", "Urumqi",
|
356
|
-
"Kuala Lumpur", "Singapore", "Taipei", "Perth", "Irkutsk",
|
357
|
-
"Ulaan Bataar" ],
|
358
|
-
[ 32_400, "Seoul", "Osaka", "Sapporo", "Tokyo", "Yakutsk" ],
|
359
|
-
[ 34_200, "Darwin", "Adelaide" ],
|
360
|
-
[ 36_000, "Canberra", "Melbourne", "Sydney", "Brisbane", "Hobart",
|
361
|
-
"Vladivostok", "Guam", "Port Moresby" ],
|
362
|
-
[ 39_600, "Magadan", "Solomon Is.", "New Caledonia" ],
|
363
|
-
[ 43_200, "Fiji", "Kamchatka", "Marshall Is.", "Auckland",
|
364
|
-
"Wellington" ],
|
365
|
-
[ 46_800, "Nuku'alofa" ]].
|
366
|
-
each do |offset, *places|
|
367
|
-
places.each do |place|
|
368
|
-
place.freeze
|
369
|
-
zone = new(place, offset)
|
370
|
-
ZONES << zone
|
371
|
-
ZONES_MAP[place] = zone
|
372
|
-
end
|
327
|
+
MAPPING.each_key do |place|
|
328
|
+
place.freeze
|
329
|
+
zone = new(place)
|
330
|
+
ZONES << zone
|
331
|
+
ZONES_MAP[place] = zone
|
373
332
|
end
|
374
333
|
ZONES.sort!
|
375
334
|
ZONES.freeze
|
376
|
-
ZONES_MAP.freeze
|
377
335
|
|
378
336
|
US_ZONES = ZONES.find_all { |z| z.name =~ /US|Arizona|Indiana|Hawaii|Alaska/ }
|
379
337
|
US_ZONES.freeze
|
@@ -404,7 +362,7 @@ module ActiveSupport
|
|
404
362
|
def [](arg)
|
405
363
|
case arg
|
406
364
|
when String
|
407
|
-
ZONES_MAP[arg]
|
365
|
+
ZONES_MAP[arg] ||= lookup(arg)
|
408
366
|
when Numeric, ActiveSupport::Duration
|
409
367
|
arg *= 3600 if arg.abs <= 13
|
410
368
|
all.find { |z| z.utc_offset == arg.to_i }
|
@@ -418,6 +376,12 @@ module ActiveSupport
|
|
418
376
|
def us_zones
|
419
377
|
US_ZONES
|
420
378
|
end
|
379
|
+
|
380
|
+
private
|
381
|
+
|
382
|
+
def lookup(name)
|
383
|
+
(tzinfo = find_tzinfo(name)) && create(tzinfo.name.freeze)
|
384
|
+
end
|
421
385
|
end
|
422
386
|
end
|
423
387
|
end
|
metadata
CHANGED
@@ -6,8 +6,8 @@ version: !ruby/object:Gem::Version
|
|
6
6
|
- 3
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 3.0.0.
|
9
|
+
- beta3
|
10
|
+
version: 3.0.0.beta3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- David Heinemeier Hansson
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-04-
|
18
|
+
date: 2010-04-13 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -152,6 +152,7 @@ files:
|
|
152
152
|
- lib/active_support/core_ext/kernel/debugger.rb
|
153
153
|
- lib/active_support/core_ext/kernel/reporting.rb
|
154
154
|
- lib/active_support/core_ext/kernel/requires.rb
|
155
|
+
- lib/active_support/core_ext/kernel/singleton_class.rb
|
155
156
|
- lib/active_support/core_ext/kernel.rb
|
156
157
|
- lib/active_support/core_ext/load_error.rb
|
157
158
|
- lib/active_support/core_ext/logger.rb
|
@@ -180,7 +181,6 @@ files:
|
|
180
181
|
- lib/active_support/core_ext/object/instance_variables.rb
|
181
182
|
- lib/active_support/core_ext/object/misc.rb
|
182
183
|
- lib/active_support/core_ext/object/returning.rb
|
183
|
-
- lib/active_support/core_ext/object/singleton_class.rb
|
184
184
|
- lib/active_support/core_ext/object/to_param.rb
|
185
185
|
- lib/active_support/core_ext/object/to_query.rb
|
186
186
|
- lib/active_support/core_ext/object/try.rb
|