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 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
 
@@ -18,7 +18,7 @@ module ActiveSupport
18
18
  def middleware
19
19
  @middleware ||= begin
20
20
  klass = Class.new
21
- klass.class_eval(<<-EOS, __FILE__, __LINE__)
21
+ klass.class_eval(<<-EOS, __FILE__, __LINE__ + 1)
22
22
  def initialize(app)
23
23
  @app = app
24
24
  end
@@ -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/object/singleton_class'
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/object/singleton_class'
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
- s = singleton_class
45
- attrs.each do |attr|
46
- s.send(:define_method, attr) { }
47
- s.send(:define_method, :"#{attr}?") { !!send(attr) }
48
- s.send(:define_method, :"#{attr}=") do |value|
49
- singleton_class.remove_possible_method(attr)
50
- singleton_class.send(:define_method, attr) { value }
51
- end
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
- define_method(attr) { self.class.send(attr) }
54
- define_method(:"#{attr}?") { !!send(attr) }
55
- define_method(:"#{attr}=") do |value|
56
- singleton_class.remove_possible_method(attr)
57
- singleton_class.send(:define_method, attr) { value }
58
- end if instance_writer
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/object/singleton_class'
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
@@ -2,3 +2,4 @@ require 'active_support/core_ext/kernel/reporting'
2
2
  require 'active_support/core_ext/kernel/agnostics'
3
3
  require 'active_support/core_ext/kernel/requires'
4
4
  require 'active_support/core_ext/kernel/debugger'
5
+ require 'active_support/core_ext/kernel/singleton_class'
@@ -1,12 +1,12 @@
1
- class Object
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 singleton_class_eval.
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
 
@@ -1,4 +1,4 @@
1
- require "active_support/core_ext/object"
1
+ require "active_support/core_ext/kernel/singleton_class"
2
2
 
3
3
  class Proc #:nodoc:
4
4
  def bind(object)
@@ -1,5 +1,5 @@
1
1
  require 'erb'
2
- require 'active_support/core_ext/object/singleton_class'
2
+ require 'active_support/core_ext/kernel/singleton_class'
3
3
 
4
4
  class ERB
5
5
  module Util
@@ -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.include?(result.downcase)
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.gsub(/::/, '/').
40
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
41
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
42
- tr("-", "_").
43
- downcase
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
- if RUBY_VERSION >= '1.9'
15
- undef_method :transliterate
16
- def transliterate(string)
17
- proxy = ActiveSupport::Multibyte.proxy_class.new(string)
18
- proxy.normalize(:kd).gsub(/[^\x00-\x7F]+/, '')
19
- end
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
- # The iconv transliteration code doesn't function correctly
22
- # on some platforms, but it's very fast where it does function.
23
- elsif "foo" != (Inflector.transliterate("föö") rescue nil)
24
- undef_method :transliterate
25
- def transliterate(string)
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
@@ -1,4 +1,4 @@
1
- require 'active_support/core_ext/object/singleton_class'
1
+ require 'active_support/core_ext/kernel/singleton_class'
2
2
  require 'active_support/core_ext/module/aliasing'
3
3
 
4
4
  module ActiveSupport
@@ -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
- def tidy_bytes
462
- chars(self.class.tidy_bytes(@wrapped_string))
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
- def tidy_bytes(string)
649
- string.split(//u).map do |c|
650
- c.force_encoding(Encoding::ASCII) if c.respond_to?(:force_encoding)
651
-
652
- if !ActiveSupport::Multibyte::VALID_CHARACTER['UTF-8'].match(c)
653
- n = c.unpack('C')[0]
654
- n < 128 ? n.chr :
655
- n < 160 ? [UCD.cp1252[n] || n].pack('U') :
656
- n < 192 ? "\xC2" + n.chr : "\xC3" + (n-64).chr
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
- c
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.join
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
- # Hash is ordered in Ruby 1.9!
6
- if RUBY_VERSION >= '1.9'
7
- class OrderedHash < ::Hash #:nodoc:
9
+ class OrderedHash < ::Hash #:nodoc:
10
+ def to_yaml_type
11
+ "!tag:yaml.org,2002:omap"
8
12
  end
9
- else
10
- class OrderedHash < Hash #:nodoc:
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
- private
138
-
139
- def sync_keys!
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
- @current_period ||= tzinfo.current_period
206
- @current_period.utc_offset
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
- @tzinfo ||= ::TZInfo::Timezone.get(MAPPING[name])
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
- [[-39_600, "International Date Line West", "Midway Island", "Samoa" ],
318
- [-36_000, "Hawaii" ],
319
- [-32_400, "Alaska" ],
320
- [-28_800, "Pacific Time (US & Canada)", "Tijuana" ],
321
- [-25_200, "Mountain Time (US & Canada)", "Chihuahua", "Mazatlan",
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
@@ -3,7 +3,7 @@ module ActiveSupport
3
3
  MAJOR = 3
4
4
  MINOR = 0
5
5
  TINY = 0
6
- BUILD = "beta2"
6
+ BUILD = "beta3"
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
9
9
  end
metadata CHANGED
@@ -6,8 +6,8 @@ version: !ruby/object:Gem::Version
6
6
  - 3
7
7
  - 0
8
8
  - 0
9
- - beta2
10
- version: 3.0.0.beta2
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-01 00:00:00 -07:00
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