activesupport 3.0.20 → 3.1.0.beta1

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.

Files changed (110) hide show
  1. data/CHANGELOG +14 -66
  2. data/README.rdoc +1 -1
  3. data/lib/active_support/backtrace_cleaner.rb +1 -1
  4. data/lib/active_support/buffered_logger.rb +4 -11
  5. data/lib/active_support/cache.rb +12 -15
  6. data/lib/active_support/cache/file_store.rb +3 -2
  7. data/lib/active_support/cache/mem_cache_store.rb +11 -3
  8. data/lib/active_support/cache/strategy/local_cache.rb +28 -23
  9. data/lib/active_support/callbacks.rb +195 -175
  10. data/lib/active_support/concern.rb +105 -35
  11. data/lib/active_support/configurable.rb +41 -2
  12. data/lib/active_support/core_ext/array/access.rb +2 -2
  13. data/lib/active_support/core_ext/array/random_access.rb +10 -7
  14. data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -2
  15. data/lib/active_support/core_ext/class/attribute.rb +27 -17
  16. data/lib/active_support/core_ext/class/inheritable_attributes.rb +12 -86
  17. data/lib/active_support/core_ext/class/subclasses.rb +20 -34
  18. data/lib/active_support/core_ext/date/calculations.rb +14 -2
  19. data/lib/active_support/core_ext/date/conversions.rb +6 -0
  20. data/lib/active_support/core_ext/date_time/calculations.rb +26 -9
  21. data/lib/active_support/core_ext/date_time/conversions.rb +1 -1
  22. data/lib/active_support/core_ext/date_time/zones.rb +1 -1
  23. data/lib/active_support/core_ext/enumerable.rb +2 -5
  24. data/lib/active_support/core_ext/float/rounding.rb +1 -1
  25. data/lib/active_support/core_ext/hash.rb +1 -0
  26. data/lib/active_support/core_ext/hash/conversions.rb +23 -36
  27. data/lib/active_support/core_ext/hash/deep_dup.rb +11 -0
  28. data/lib/active_support/core_ext/hash/keys.rb +6 -4
  29. data/lib/active_support/core_ext/hash/reverse_merge.rb +9 -14
  30. data/lib/active_support/core_ext/kernel/reporting.rb +19 -0
  31. data/lib/active_support/core_ext/logger.rb +11 -38
  32. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +11 -12
  33. data/lib/active_support/core_ext/module/attr_internal.rb +13 -6
  34. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  35. data/lib/active_support/core_ext/object.rb +1 -1
  36. data/lib/active_support/core_ext/object/blank.rb +42 -9
  37. data/lib/active_support/core_ext/object/duplicable.rb +48 -9
  38. data/lib/active_support/core_ext/object/inclusion.rb +15 -0
  39. data/lib/active_support/core_ext/object/instance_variables.rb +1 -35
  40. data/lib/active_support/core_ext/object/to_param.rb +13 -8
  41. data/lib/active_support/core_ext/object/to_query.rb +2 -2
  42. data/lib/active_support/core_ext/object/try.rb +27 -10
  43. data/lib/active_support/core_ext/object/with_options.rb +19 -5
  44. data/lib/active_support/core_ext/range.rb +1 -0
  45. data/lib/active_support/core_ext/range/cover.rb +3 -0
  46. data/lib/active_support/core_ext/string.rb +1 -0
  47. data/lib/active_support/core_ext/string/filters.rb +3 -3
  48. data/lib/active_support/core_ext/string/inflections.rb +1 -1
  49. data/lib/active_support/core_ext/string/inquiry.rb +13 -0
  50. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  51. data/lib/active_support/core_ext/string/output_safety.rb +33 -89
  52. data/lib/active_support/core_ext/time/calculations.rb +14 -13
  53. data/lib/active_support/core_ext/time/conversions.rb +2 -24
  54. data/lib/active_support/core_ext/time/marshal.rb +0 -1
  55. data/lib/active_support/core_ext/time/zones.rb +32 -21
  56. data/lib/active_support/core_ext/uri.rb +8 -0
  57. data/lib/active_support/dependencies.rb +93 -37
  58. data/lib/active_support/deprecation.rb +2 -2
  59. data/lib/active_support/deprecation/behaviors.rb +7 -0
  60. data/lib/active_support/deprecation/proxy_wrappers.rb +1 -1
  61. data/lib/active_support/deprecation/reporting.rb +4 -0
  62. data/lib/active_support/duration.rb +4 -0
  63. data/lib/active_support/file_update_checker.rb +1 -1
  64. data/lib/active_support/file_watcher.rb +36 -0
  65. data/lib/active_support/gzip.rb +0 -1
  66. data/lib/active_support/hash_with_indifferent_access.rb +6 -4
  67. data/lib/active_support/i18n.rb +0 -1
  68. data/lib/active_support/i18n_railtie.rb +2 -2
  69. data/lib/active_support/inflector/inflections.rb +1 -1
  70. data/lib/active_support/json/decoding.rb +37 -23
  71. data/lib/active_support/json/encoding.rb +8 -3
  72. data/lib/active_support/lazy_load_hooks.rb +7 -7
  73. data/lib/active_support/log_subscriber.rb +3 -3
  74. data/lib/active_support/log_subscriber/test_helper.rb +4 -3
  75. data/lib/active_support/message_encryptor.rb +1 -1
  76. data/lib/active_support/message_verifier.rb +1 -1
  77. data/lib/active_support/multibyte/chars.rb +4 -3
  78. data/lib/active_support/multibyte/unicode.rb +1 -1
  79. data/lib/active_support/notifications.rb +9 -8
  80. data/lib/active_support/notifications/fanout.rb +3 -3
  81. data/lib/active_support/ordered_hash.rb +19 -2
  82. data/lib/active_support/ordered_options.rb +33 -3
  83. data/lib/active_support/railtie.rb +1 -1
  84. data/lib/active_support/rescuable.rb +1 -0
  85. data/lib/active_support/secure_random.rb +11 -5
  86. data/lib/active_support/test_case.rb +2 -10
  87. data/lib/active_support/testing/assertions.rb +17 -6
  88. data/lib/active_support/testing/mochaing.rb +7 -0
  89. data/lib/active_support/testing/pending.rb +27 -23
  90. data/lib/active_support/testing/setup_and_teardown.rb +8 -11
  91. data/lib/active_support/time_with_zone.rb +6 -3
  92. data/lib/active_support/version.rb +3 -3
  93. data/lib/active_support/whiny_nil.rb +1 -1
  94. data/lib/active_support/xml_mini.rb +4 -2
  95. data/lib/active_support/xml_mini/jdom.rb +9 -16
  96. data/lib/active_support/xml_mini/libxml.rb +1 -0
  97. data/lib/active_support/xml_mini/libxmlsax.rb +2 -1
  98. data/lib/active_support/xml_mini/nokogiri.rb +1 -0
  99. data/lib/active_support/xml_mini/nokogirisax.rb +1 -0
  100. data/lib/active_support/xml_mini/rexml.rb +1 -0
  101. metadata +50 -32
  102. checksums.yaml +0 -7
  103. data/lib/active_support/core_ext/cgi.rb +0 -1
  104. data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -19
  105. data/lib/active_support/core_ext/object/returning.rb +0 -43
  106. data/lib/active_support/json/backends/jsongem.rb +0 -47
  107. data/lib/active_support/json/backends/okjson.rb +0 -644
  108. data/lib/active_support/json/backends/yajl.rb +0 -44
  109. data/lib/active_support/json/backends/yaml.rb +0 -19
  110. data/lib/active_support/testing/default.rb +0 -9
@@ -7,13 +7,27 @@ class Object
7
7
  # provided. Each method called on the block variable must take an options
8
8
  # hash as its final argument.
9
9
  #
10
- # with_options :order => 'created_at', :class_name => 'Comment' do |post|
11
- # post.has_many :comments, :conditions => ['approved = ?', true], :dependent => :delete_all
12
- # post.has_many :unapproved_comments, :conditions => ['approved = ?', false]
13
- # post.has_many :all_comments
10
+ # Without with_options, this code contains duplication:
11
+ #
12
+ # class Account < ActiveRecord::Base
13
+ # has_many :customers, :dependent => :destroy
14
+ # has_many :products, :dependent => :destroy
15
+ # has_many :invoices, :dependent => :destroy
16
+ # has_many :expenses, :dependent => :destroy
17
+ # end
18
+ #
19
+ # Using with_options, we can remove the duplication:
20
+ #
21
+ # class Account < ActiveRecord::Base
22
+ # with_options :dependent => :destroy do |assoc|
23
+ # assoc.has_many :customers
24
+ # assoc.has_many :products
25
+ # assoc.has_many :invoices
26
+ # assoc.has_many :expenses
27
+ # end
14
28
  # end
15
29
  #
16
- # Can also be used with an explicit receiver:
30
+ # It can also be used with an explicit receiver:
17
31
  #
18
32
  # map.with_options :controller => "people" do |people|
19
33
  # people.connect "/people", :action => "index"
@@ -2,3 +2,4 @@ require 'active_support/core_ext/range/blockless_step'
2
2
  require 'active_support/core_ext/range/conversions'
3
3
  require 'active_support/core_ext/range/include_range'
4
4
  require 'active_support/core_ext/range/overlaps'
5
+ require 'active_support/core_ext/range/cover'
@@ -0,0 +1,3 @@
1
+ class Range
2
+ alias_method(:cover?, :include?) unless instance_methods.include?(:cover?)
3
+ end
@@ -11,3 +11,4 @@ require 'active_support/core_ext/string/output_safety'
11
11
  require 'active_support/core_ext/string/exclude'
12
12
  require 'active_support/core_ext/string/encoding'
13
13
  require 'active_support/core_ext/string/strip'
14
+ require 'active_support/core_ext/string/inquiry'
@@ -25,13 +25,13 @@ class String
25
25
  # "Once upon a time in a world far far away".truncate(27)
26
26
  # # => "Once upon a time in a wo..."
27
27
  #
28
- # The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
29
- # for a total length not exceeding <tt>:length</tt>:
28
+ # Pass a <tt>:separator</tt> to truncate +text+ at a natural break:
30
29
  #
31
30
  # "Once upon a time in a world far far away".truncate(27, :separator => ' ')
32
31
  # # => "Once upon a time in a..."
33
32
  #
34
- # Pass a <tt>:separator</tt> to truncate +text+ at a natural break:
33
+ # The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
34
+ # for a total length not exceeding <tt>:length</tt>:
35
35
  #
36
36
  # "And they found that many people were sleeping better.".truncate(25, :omission => "... (continued)")
37
37
  # # => "And they f... (continued)"
@@ -3,7 +3,7 @@ require 'active_support/inflector/inflections'
3
3
  require 'active_support/inflector/transliterate'
4
4
 
5
5
  # String inflections define new methods on the String class to transform names for different purposes.
6
- # For instance, you can figure out the name of a database from the name of a class.
6
+ # For instance, you can figure out the name of a table from the name of a class.
7
7
  #
8
8
  # "ScaleScore".tableize # => "scale_scores"
9
9
  #
@@ -0,0 +1,13 @@
1
+ require 'active_support/string_inquirer'
2
+
3
+ class String
4
+ # Wraps the current string in the ActiveSupport::StringInquirer class,
5
+ # which gives you a prettier way to test for equality. Example:
6
+ #
7
+ # env = "production".inquiry
8
+ # env.production? # => true
9
+ # env.development? # => false
10
+ def inquiry
11
+ ActiveSupport::StringInquirer.new(self)
12
+ end
13
+ end
@@ -9,7 +9,7 @@ class String
9
9
  #
10
10
  # In Ruby 1.8 and older it creates and returns an instance of the ActiveSupport::Multibyte::Chars class which
11
11
  # encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
12
- # class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsuled string.
12
+ # class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsulated string.
13
13
  #
14
14
  # name = 'Claus Müller'
15
15
  # name.reverse # => "rell??M sualC"
@@ -3,38 +3,28 @@ require 'active_support/core_ext/kernel/singleton_class'
3
3
 
4
4
  class ERB
5
5
  module Util
6
- HTML_ESCAPE = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;', "'" => '&#x27;' }
6
+ HTML_ESCAPE = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;' }
7
7
  JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' }
8
8
 
9
- if RUBY_VERSION >= '1.9'
10
- # A utility method for escaping HTML tag characters.
11
- # This method is also aliased as <tt>h</tt>.
12
- #
13
- # In your ERB templates, use this method to escape any unsafe content. For example:
14
- # <%=h @person.name %>
15
- #
16
- # ==== Example:
17
- # puts html_escape("is a > 0 & a < 10?")
18
- # # => is a &gt; 0 &amp; a &lt; 10?
19
- def html_escape(s)
20
- s = s.to_s
21
- if s.html_safe?
22
- s
23
- else
24
- s.gsub(/[&"'><]/, HTML_ESCAPE).html_safe
25
- end
26
- end
27
- else
28
- def html_escape(s) #:nodoc:
29
- s = s.to_s
30
- if s.html_safe?
31
- s
32
- else
33
- s.gsub(/[&"'><]/n) { |special| HTML_ESCAPE[special] }.html_safe
34
- end
9
+ # A utility method for escaping HTML tag characters.
10
+ # This method is also aliased as <tt>h</tt>.
11
+ #
12
+ # In your ERB templates, use this method to escape any unsafe content. For example:
13
+ # <%=h @person.name %>
14
+ #
15
+ # ==== Example:
16
+ # puts html_escape("is a > 0 & a < 10?")
17
+ # # => is a &gt; 0 &amp; a &lt; 10?
18
+ def html_escape(s)
19
+ s = s.to_s
20
+ if s.html_safe?
21
+ s
22
+ else
23
+ s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }.html_safe
35
24
  end
36
25
  end
37
26
 
27
+ # Aliasing twice issues a warning "discarding old...". Remove first to avoid it.
38
28
  remove_method(:h)
39
29
  alias h html_escape
40
30
 
@@ -61,8 +51,7 @@ class ERB
61
51
  # <%=j @person.to_json %>
62
52
  #
63
53
  def json_escape(s)
64
- result = s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
65
- s.html_safe? ? result.html_safe : result
54
+ s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
66
55
  end
67
56
 
68
57
  alias j json_escape
@@ -85,50 +74,10 @@ end
85
74
 
86
75
  module ActiveSupport #:nodoc:
87
76
  class SafeBuffer < String
88
- UNSAFE_STRING_METHODS = ["capitalize", "chomp", "chop", "delete", "downcase", "gsub", "lstrip", "next", "reverse", "rstrip", "slice", "squeeze", "strip", "sub", "succ", "swapcase", "tr", "tr_s", "upcase", "prepend"].freeze
89
-
90
- alias_method :original_concat, :concat
91
- private :original_concat
92
-
93
- class SafeConcatError < StandardError
94
- def initialize
95
- super "Could not concatenate to the buffer because it is not html safe."
96
- end
97
- end
98
-
99
- def [](*args)
100
- return super if args.size < 2
101
-
102
- if html_safe?
103
- new_safe_buffer = super
104
- new_safe_buffer.instance_eval { @html_safe = true }
105
- new_safe_buffer
106
- else
107
- to_str[*args]
108
- end
109
- end
110
-
111
- def safe_concat(value)
112
- raise SafeConcatError unless html_safe?
113
- original_concat(value)
114
- end
115
-
116
- def initialize(*)
117
- @html_safe = true
118
- super
119
- end
120
-
121
- def initialize_copy(other)
122
- super
123
- @html_safe = other.html_safe?
124
- end
125
-
126
- def clone_empty
127
- self[0, 0]
128
- end
77
+ alias safe_concat concat
129
78
 
130
79
  def concat(value)
131
- if !html_safe? || value.html_safe?
80
+ if value.html_safe?
132
81
  super(value)
133
82
  else
134
83
  super(ERB::Util.h(value))
@@ -141,39 +90,34 @@ module ActiveSupport #:nodoc:
141
90
  end
142
91
 
143
92
  def html_safe?
144
- defined?(@html_safe) && @html_safe
93
+ true
94
+ end
95
+
96
+ def html_safe
97
+ self
145
98
  end
146
99
 
147
100
  def to_s
148
101
  self
149
102
  end
150
103
 
151
- def to_param
152
- to_str
104
+ def encode_with(coder)
105
+ coder.represent_scalar nil, to_str
153
106
  end
154
107
 
155
108
  def to_yaml(*args)
156
- to_str.to_yaml(*args)
157
- end
109
+ return super() if defined?(YAML::ENGINE) && !YAML::ENGINE.syck?
158
110
 
159
- for unsafe_method in UNSAFE_STRING_METHODS
160
- if 'String'.respond_to?(unsafe_method)
161
- class_eval <<-EOT, __FILE__, __LINE__ + 1
162
- def #{unsafe_method}(*args, &block) # def capitalize(*args, &block)
163
- to_str.#{unsafe_method}(*args, &block) # to_str.capitalize(*args, &block)
164
- end # end
165
-
166
- def #{unsafe_method}!(*args) # def capitalize!(*args)
167
- @html_safe = false # @html_safe = false
168
- super # super
169
- end # end
170
- EOT
171
- end
111
+ to_str.to_yaml(*args)
172
112
  end
173
113
  end
174
114
  end
175
115
 
176
116
  class String
117
+ def html_safe!
118
+ raise "You can't call html_safe! on a String"
119
+ end
120
+
177
121
  def html_safe
178
122
  ActiveSupport::SafeBuffer.new(self)
179
123
  end
@@ -1,7 +1,4 @@
1
1
  require 'active_support/duration'
2
- require 'active_support/core_ext/date/acts_like'
3
- require 'active_support/core_ext/date/calculations'
4
- require 'active_support/core_ext/date_time/conversions'
5
2
 
6
3
  class Time
7
4
  COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
@@ -10,7 +7,7 @@ class Time
10
7
  class << self
11
8
  # Overriding case equality method so that it returns true for ActiveSupport::TimeWithZone instances
12
9
  def ===(other)
13
- super || (self == Time && other.is_a?(ActiveSupport::TimeWithZone))
10
+ other.is_a?(::Time)
14
11
  end
15
12
 
16
13
  # Return the number of days in the given month.
@@ -22,7 +19,7 @@ class Time
22
19
 
23
20
  # Returns a new Time if requested year can be accommodated by Ruby's Time class
24
21
  # (i.e., if year is within either 1970..2038 or 1902..2038, depending on system architecture);
25
- # otherwise returns a DateTime
22
+ # otherwise returns a DateTime.
26
23
  def time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
27
24
  time = ::Time.send(utc_or_local, year, month, day, hour, min, sec, usec)
28
25
  # This check is needed because Time.utc(y) returns a time object in the 2000s for 0 <= y <= 138.
@@ -117,6 +114,11 @@ class Time
117
114
  end
118
115
  alias :in :since
119
116
 
117
+ # Returns a new Time representing the time a number of specified weeks ago.
118
+ def weeks_ago(weeks)
119
+ advance(:weeks => -weeks)
120
+ end
121
+
120
122
  # Returns a new Time representing the time a number of specified months ago
121
123
  def months_ago(months)
122
124
  advance(:months => -months)
@@ -172,6 +174,11 @@ class Time
172
174
  end
173
175
  alias :at_end_of_week :end_of_week
174
176
 
177
+ # Returns a new Time representing the start of the given day in the previous week (default is Monday).
178
+ def prev_week(day = :monday)
179
+ ago(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
180
+ end
181
+
175
182
  # Returns a new Time representing the start of the given day in next week (default is Monday).
176
183
  def next_week(day = :monday)
177
184
  since(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
@@ -273,14 +280,8 @@ class Time
273
280
  # Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances
274
281
  # can be chronologically compared with a Time
275
282
  def compare_with_coercion(other)
276
- # if other is an ActiveSupport::TimeWithZone, coerce a Time instance from it so we can do <=> comparison
277
- other = other.comparable_time if other.respond_to?(:comparable_time)
278
- if other.acts_like?(:date)
279
- # other is a Date/DateTime, so coerce self #to_datetime and hand off to DateTime#<=>
280
- to_datetime.compare_without_coercion(other)
281
- else
282
- compare_without_coercion(other)
283
- end
283
+ # we're avoiding Time#to_datetime cause it's expensive
284
+ other.is_a?(Time) ? compare_without_coercion(other.to_time) : to_datetime <=> other
284
285
  end
285
286
  alias_method :compare_without_coercion, :<=>
286
287
  alias_method :<=>, :compare_with_coercion
@@ -19,8 +19,8 @@ class Time
19
19
  #
20
20
  # time = Time.now # => Thu Jan 18 06:10:17 CST 2007
21
21
  #
22
- # time.to_formatted_s(:time) # => "06:10:17"
23
- # time.to_s(:time) # => "06:10:17"
22
+ # time.to_formatted_s(:time) # => "06:10"
23
+ # time.to_s(:time) # => "06:10"
24
24
  #
25
25
  # time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
26
26
  # time.to_formatted_s(:number) # => "20070118061017"
@@ -55,31 +55,9 @@ class Time
55
55
  utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon)
56
56
  end
57
57
 
58
- # Converts a Time object to a Date, dropping hour, minute, and second precision.
59
- #
60
- # my_time = Time.now # => Mon Nov 12 22:59:51 -0500 2007
61
- # my_time.to_date # => Mon, 12 Nov 2007
62
- #
63
- # your_time = Time.parse("1/13/2009 1:13:03 P.M.") # => Tue Jan 13 13:13:03 -0500 2009
64
- # your_time.to_date # => Tue, 13 Jan 2009
65
- def to_date
66
- ::Date.new(year, month, day)
67
- end unless method_defined?(:to_date)
68
-
69
58
  # A method to keep Time, Date and DateTime instances interchangeable on conversions.
70
59
  # In this case, it simply returns +self+.
71
60
  def to_time
72
61
  self
73
62
  end unless method_defined?(:to_time)
74
-
75
- # Converts a Time instance to a Ruby DateTime instance, preserving UTC offset.
76
- #
77
- # my_time = Time.now # => Mon Nov 12 23:04:21 -0500 2007
78
- # my_time.to_datetime # => Mon, 12 Nov 2007 23:04:21 -0500
79
- #
80
- # your_time = Time.parse("1/13/2009 1:13:03 P.M.") # => Tue Jan 13 13:13:03 -0500 2009
81
- # your_time.to_datetime # => Tue, 13 Jan 2009 13:13:03 -0500
82
- def to_datetime
83
- ::DateTime.civil(year, month, day, hour, min, sec, Rational(utc_offset, 86400))
84
- end unless method_defined?(:to_datetime)
85
63
  end
@@ -37,7 +37,6 @@ if Time.local(2010).zone != Marshal.load(Marshal.dump(Time.local(2010))).zone
37
37
  time.instance_eval do
38
38
  if zone = defined?(@_zone) && remove_instance_variable('@_zone')
39
39
  ary = to_a
40
- ary[0] += subsec if ary[0] == sec
41
40
  ary[-1] = zone
42
41
  utc? ? Time.utc(*ary) : Time.local(*ary)
43
42
  else
@@ -19,40 +19,51 @@ class Time
19
19
  # * A TZInfo::Timezone object.
20
20
  # * An identifier for a TZInfo::Timezone object (e.g., "America/New_York").
21
21
  #
22
- # Here's an example of how you might set <tt>Time.zone</tt> on a per request basis -- <tt>current_user.time_zone</tt>
23
- # just needs to return a string identifying the user's preferred TimeZone:
22
+ # Here's an example of how you might set <tt>Time.zone</tt> on a per request basis and reset it when the request is done.
23
+ # <tt>current_user.time_zone</tt> just needs to return a string identifying the user's preferred time zone:
24
24
  #
25
25
  # class ApplicationController < ActionController::Base
26
- # before_filter :set_time_zone
26
+ # around_filter :set_time_zone
27
27
  #
28
28
  # def set_time_zone
29
- # Time.zone = current_user.time_zone
29
+ # old_time_zone = Time.zone
30
+ # Time.zone = current_user.time_zone if logged_in?
31
+ # yield
32
+ # ensure
33
+ # Time.zone = old_time_zone
30
34
  # end
31
35
  # end
32
36
  def zone=(time_zone)
33
- Thread.current[:time_zone] = get_zone(time_zone)
37
+ Thread.current[:time_zone] = find_zone!(time_zone)
34
38
  end
35
39
 
36
40
  # Allows override of <tt>Time.zone</tt> locally inside supplied block; resets <tt>Time.zone</tt> to existing value when done.
37
41
  def use_zone(time_zone)
38
- old_zone, ::Time.zone = ::Time.zone, get_zone(time_zone)
39
- yield
40
- ensure
41
- ::Time.zone = old_zone
42
+ new_zone = find_zone!(time_zone)
43
+ begin
44
+ old_zone, ::Time.zone = ::Time.zone, new_zone
45
+ yield
46
+ ensure
47
+ ::Time.zone = old_zone
48
+ end
42
49
  end
43
50
 
44
- private
45
- def get_zone(time_zone)
46
- return time_zone if time_zone.nil? || time_zone.is_a?(ActiveSupport::TimeZone)
47
- # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
48
- unless time_zone.respond_to?(:period_for_local)
49
- time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone) rescue nil
50
- end
51
- # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
52
- if time_zone
53
- time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
54
- end
51
+ # Returns a TimeZone instance or nil, or raises an ArgumentError for invalid timezones.
52
+ def find_zone!(time_zone)
53
+ return time_zone if time_zone.nil? || time_zone.is_a?(ActiveSupport::TimeZone)
54
+ # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
55
+ unless time_zone.respond_to?(:period_for_local)
56
+ time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
55
57
  end
58
+ # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
59
+ time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
60
+ rescue TZInfo::InvalidTimezoneIdentifier
61
+ raise ArgumentError, "Invalid Timezone: #{time_zone}"
62
+ end
63
+
64
+ def find_zone(time_zone)
65
+ find_zone!(time_zone) rescue nil
66
+ end
56
67
  end
57
68
 
58
69
  # Returns the simultaneous time in <tt>Time.zone</tt>.
@@ -70,6 +81,6 @@ class Time
70
81
  def in_time_zone(zone = ::Time.zone)
71
82
  return self unless zone
72
83
 
73
- ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone))
84
+ ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
74
85
  end
75
86
  end