activesupport 3.2.22.5 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +364 -135
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -4
  5. data/lib/active_support/backtrace_cleaner.rb +33 -25
  6. data/lib/active_support/basic_object.rb +7 -17
  7. data/lib/active_support/benchmarkable.rb +19 -15
  8. data/lib/active_support/buffered_logger.rb +9 -113
  9. data/lib/active_support/cache/file_store.rb +14 -14
  10. data/lib/active_support/cache/mem_cache_store.rb +24 -30
  11. data/lib/active_support/cache/memory_store.rb +2 -0
  12. data/lib/active_support/cache/strategy/local_cache.rb +48 -37
  13. data/lib/active_support/cache.rb +228 -183
  14. data/lib/active_support/callbacks.rb +201 -253
  15. data/lib/active_support/concern.rb +16 -23
  16. data/lib/active_support/concurrency/latch.rb +27 -0
  17. data/lib/active_support/configurable.rb +69 -12
  18. data/lib/active_support/core_ext/array/access.rb +17 -9
  19. data/lib/active_support/core_ext/array/conversions.rb +115 -55
  20. data/lib/active_support/core_ext/array/extract_options.rb +2 -2
  21. data/lib/active_support/core_ext/array/grouping.rb +21 -22
  22. data/lib/active_support/core_ext/array/uniq_by.rb +12 -9
  23. data/lib/active_support/core_ext/array/wrap.rb +13 -16
  24. data/lib/active_support/core_ext/array.rb +0 -1
  25. data/lib/active_support/core_ext/benchmark.rb +7 -0
  26. data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -24
  27. data/lib/active_support/core_ext/class/attribute.rb +40 -32
  28. data/lib/active_support/core_ext/class/attribute_accessors.rb +14 -12
  29. data/lib/active_support/core_ext/class/delegating_attributes.rb +15 -19
  30. data/lib/active_support/core_ext/class/subclasses.rb +11 -5
  31. data/lib/active_support/core_ext/date/calculations.rb +44 -187
  32. data/lib/active_support/core_ext/date/conversions.rb +16 -38
  33. data/lib/active_support/core_ext/date/zones.rb +25 -2
  34. data/lib/active_support/core_ext/date.rb +5 -0
  35. data/lib/active_support/core_ext/date_and_time/calculations.rb +232 -0
  36. data/lib/active_support/core_ext/date_time/acts_like.rb +0 -1
  37. data/lib/active_support/core_ext/date_time/calculations.rb +77 -62
  38. data/lib/active_support/core_ext/date_time/conversions.rb +21 -33
  39. data/lib/active_support/core_ext/date_time/zones.rb +11 -8
  40. data/lib/active_support/core_ext/date_time.rb +4 -0
  41. data/lib/active_support/core_ext/enumerable.rb +26 -73
  42. data/lib/active_support/core_ext/file/atomic.rb +27 -11
  43. data/lib/active_support/core_ext/file.rb +0 -1
  44. data/lib/active_support/core_ext/hash/conversions.rb +145 -79
  45. data/lib/active_support/core_ext/hash/deep_merge.rb +14 -8
  46. data/lib/active_support/core_ext/hash/diff.rb +5 -4
  47. data/lib/active_support/core_ext/hash/except.rb +1 -9
  48. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -5
  49. data/lib/active_support/core_ext/hash/keys.rb +108 -24
  50. data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
  51. data/lib/active_support/core_ext/hash/slice.rb +12 -12
  52. data/lib/active_support/core_ext/hash.rb +0 -1
  53. data/lib/active_support/core_ext/integer/inflections.rb +13 -1
  54. data/lib/active_support/core_ext/integer/time.rb +17 -12
  55. data/lib/active_support/core_ext/kernel/debugger.rb +2 -2
  56. data/lib/active_support/core_ext/kernel/reporting.rb +36 -22
  57. data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
  58. data/lib/active_support/core_ext/load_error.rb +7 -5
  59. data/lib/active_support/core_ext/logger.rb +7 -23
  60. data/lib/active_support/core_ext/marshal.rb +21 -0
  61. data/lib/active_support/core_ext/module/aliasing.rb +8 -9
  62. data/lib/active_support/core_ext/module/anonymous.rb +2 -7
  63. data/lib/active_support/core_ext/module/attr_internal.rb +0 -1
  64. data/lib/active_support/core_ext/module/attribute_accessors.rb +12 -10
  65. data/lib/active_support/core_ext/module/delegation.rb +92 -49
  66. data/lib/active_support/core_ext/module/deprecation.rb +19 -3
  67. data/lib/active_support/core_ext/module/introspection.rb +17 -27
  68. data/lib/active_support/core_ext/module/qualified_const.rb +8 -20
  69. data/lib/active_support/core_ext/module/remove_method.rb +1 -5
  70. data/lib/active_support/core_ext/module.rb +1 -3
  71. data/lib/active_support/core_ext/numeric/conversions.rb +135 -0
  72. data/lib/active_support/core_ext/numeric/time.rb +6 -6
  73. data/lib/active_support/core_ext/numeric.rb +1 -0
  74. data/lib/active_support/core_ext/object/acts_like.rb +4 -4
  75. data/lib/active_support/core_ext/object/blank.rb +7 -23
  76. data/lib/active_support/core_ext/object/deep_dup.rb +46 -0
  77. data/lib/active_support/core_ext/object/duplicable.rb +1 -30
  78. data/lib/active_support/core_ext/object/inclusion.rb +8 -7
  79. data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
  80. data/lib/active_support/core_ext/object/to_json.rb +8 -0
  81. data/lib/active_support/core_ext/object/to_param.rb +5 -2
  82. data/lib/active_support/core_ext/object/try.rb +46 -25
  83. data/lib/active_support/core_ext/object/with_options.rb +7 -8
  84. data/lib/active_support/core_ext/object.rb +1 -0
  85. data/lib/active_support/core_ext/proc.rb +3 -0
  86. data/lib/active_support/core_ext/range/conversions.rb +0 -2
  87. data/lib/active_support/core_ext/range/include_range.rb +3 -1
  88. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  89. data/lib/active_support/core_ext/range.rb +0 -2
  90. data/lib/active_support/core_ext/string/access.rb +95 -90
  91. data/lib/active_support/core_ext/string/conversions.rb +27 -38
  92. data/lib/active_support/core_ext/string/encoding.rb +6 -9
  93. data/lib/active_support/core_ext/string/filters.rb +24 -18
  94. data/lib/active_support/core_ext/string/indent.rb +43 -0
  95. data/lib/active_support/core_ext/string/inflections.rb +70 -60
  96. data/lib/active_support/core_ext/string/inquiry.rb +2 -2
  97. data/lib/active_support/core_ext/string/multibyte.rb +41 -64
  98. data/lib/active_support/core_ext/string/output_safety.rb +59 -51
  99. data/lib/active_support/core_ext/string/zones.rb +13 -0
  100. data/lib/active_support/core_ext/string.rb +2 -3
  101. data/lib/active_support/core_ext/struct.rb +6 -0
  102. data/lib/active_support/core_ext/thread.rb +74 -0
  103. data/lib/active_support/core_ext/time/calculations.rb +108 -184
  104. data/lib/active_support/core_ext/time/conversions.rb +27 -51
  105. data/lib/active_support/core_ext/time/marshal.rb +0 -27
  106. data/lib/active_support/core_ext/time/zones.rb +27 -17
  107. data/lib/active_support/core_ext/time.rb +5 -0
  108. data/lib/active_support/core_ext/uri.rb +13 -17
  109. data/lib/active_support/core_ext.rb +3 -2
  110. data/lib/active_support/dependencies/autoload.rb +47 -20
  111. data/lib/active_support/dependencies.rb +160 -141
  112. data/lib/active_support/deprecation/behaviors.rb +44 -30
  113. data/lib/active_support/deprecation/instance_delegator.rb +24 -0
  114. data/lib/active_support/deprecation/method_wrappers.rb +33 -18
  115. data/lib/active_support/deprecation/proxy_wrappers.rb +58 -13
  116. data/lib/active_support/deprecation/reporting.rb +40 -11
  117. data/lib/active_support/deprecation.rb +39 -14
  118. data/lib/active_support/descendants_tracker.rb +34 -19
  119. data/lib/active_support/duration.rb +6 -8
  120. data/lib/active_support/file_update_checker.rb +63 -47
  121. data/lib/active_support/gzip.rb +11 -5
  122. data/lib/active_support/hash_with_indifferent_access.rb +127 -42
  123. data/lib/active_support/i18n.rb +4 -0
  124. data/lib/active_support/i18n_railtie.rb +5 -22
  125. data/lib/active_support/inflections.rb +14 -12
  126. data/lib/active_support/inflector/inflections.rb +108 -71
  127. data/lib/active_support/inflector/methods.rb +181 -160
  128. data/lib/active_support/inflector/transliterate.rb +16 -17
  129. data/lib/active_support/json/decoding.rb +18 -17
  130. data/lib/active_support/json/encoding.rb +93 -39
  131. data/lib/active_support/json/variable.rb +10 -1
  132. data/lib/active_support/key_generator.rb +75 -0
  133. data/lib/active_support/lazy_load_hooks.rb +21 -19
  134. data/lib/active_support/locale/en.yml +100 -3
  135. data/lib/active_support/log_subscriber/test_helper.rb +18 -15
  136. data/lib/active_support/log_subscriber.rb +35 -52
  137. data/lib/active_support/logger.rb +57 -0
  138. data/lib/active_support/logger_silence.rb +24 -0
  139. data/lib/active_support/message_encryptor.rb +38 -35
  140. data/lib/active_support/message_verifier.rb +9 -15
  141. data/lib/active_support/multibyte/chars.rb +80 -333
  142. data/lib/active_support/multibyte/unicode.rb +74 -64
  143. data/lib/active_support/multibyte.rb +5 -28
  144. data/lib/active_support/notifications/fanout.rb +112 -18
  145. data/lib/active_support/notifications/instrumenter.rb +33 -14
  146. data/lib/active_support/notifications.rb +79 -26
  147. data/lib/active_support/number_helper.rb +637 -0
  148. data/lib/active_support/ordered_hash.rb +8 -190
  149. data/lib/active_support/ordered_options.rb +21 -23
  150. data/lib/active_support/per_thread_registry.rb +52 -0
  151. data/lib/active_support/proxy_object.rb +13 -0
  152. data/lib/active_support/rails.rb +27 -0
  153. data/lib/active_support/railtie.rb +12 -32
  154. data/lib/active_support/rescuable.rb +9 -4
  155. data/lib/active_support/string_inquirer.rb +13 -8
  156. data/lib/active_support/subscriber.rb +93 -0
  157. data/lib/active_support/tagged_logging.rb +51 -73
  158. data/lib/active_support/test_case.rb +46 -17
  159. data/lib/active_support/testing/assertions.rb +56 -26
  160. data/lib/active_support/testing/autorun.rb +5 -0
  161. data/lib/active_support/testing/constant_lookup.rb +54 -0
  162. data/lib/active_support/testing/declarative.rb +1 -1
  163. data/lib/active_support/testing/deprecation.rb +0 -19
  164. data/lib/active_support/testing/isolation.rb +29 -58
  165. data/lib/active_support/testing/pending.rb +5 -43
  166. data/lib/active_support/testing/setup_and_teardown.rb +6 -92
  167. data/lib/active_support/testing/tagged_logging.rb +25 -0
  168. data/lib/active_support/time.rb +6 -21
  169. data/lib/active_support/time_with_zone.rb +80 -43
  170. data/lib/active_support/values/time_zone.rb +81 -60
  171. data/lib/active_support/values/unicode_tables.dat +0 -0
  172. data/lib/active_support/version.rb +7 -6
  173. data/lib/active_support/xml_mini/jdom.rb +9 -11
  174. data/lib/active_support/xml_mini/libxml.rb +1 -2
  175. data/lib/active_support/xml_mini/libxmlsax.rb +2 -3
  176. data/lib/active_support/xml_mini/nokogiri.rb +1 -2
  177. data/lib/active_support/xml_mini/nokogirisax.rb +2 -3
  178. data/lib/active_support/xml_mini/rexml.rb +6 -8
  179. data/lib/active_support/xml_mini.rb +35 -17
  180. data/lib/active_support.rb +8 -21
  181. metadata +104 -72
  182. data/lib/active_support/base64.rb +0 -54
  183. data/lib/active_support/core_ext/array/random_access.rb +0 -30
  184. data/lib/active_support/core_ext/date/freeze.rb +0 -33
  185. data/lib/active_support/core_ext/exception.rb +0 -3
  186. data/lib/active_support/core_ext/file/path.rb +0 -5
  187. data/lib/active_support/core_ext/float/rounding.rb +0 -19
  188. data/lib/active_support/core_ext/float.rb +0 -1
  189. data/lib/active_support/core_ext/hash/deep_dup.rb +0 -18
  190. data/lib/active_support/core_ext/io.rb +0 -15
  191. data/lib/active_support/core_ext/module/method_names.rb +0 -14
  192. data/lib/active_support/core_ext/module/synchronization.rb +0 -45
  193. data/lib/active_support/core_ext/process/daemon.rb +0 -23
  194. data/lib/active_support/core_ext/process.rb +0 -1
  195. data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
  196. data/lib/active_support/core_ext/range/cover.rb +0 -3
  197. data/lib/active_support/core_ext/rexml.rb +0 -46
  198. data/lib/active_support/core_ext/string/interpolation.rb +0 -2
  199. data/lib/active_support/core_ext/string/xchar.rb +0 -18
  200. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
  201. data/lib/active_support/memoizable.rb +0 -116
  202. data/lib/active_support/multibyte/exceptions.rb +0 -8
  203. data/lib/active_support/multibyte/utils.rb +0 -60
  204. data/lib/active_support/ruby/shim.rb +0 -22
  205. data/lib/active_support/security_utils.rb +0 -27
  206. data/lib/active_support/testing/mochaing.rb +0 -7
  207. data/lib/active_support/testing/performance/jruby.rb +0 -115
  208. data/lib/active_support/testing/performance/rubinius.rb +0 -113
  209. data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
  210. data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
  211. data/lib/active_support/testing/performance/ruby.rb +0 -152
  212. data/lib/active_support/testing/performance.rb +0 -317
  213. data/lib/active_support/time/autoload.rb +0 -5
  214. data/lib/active_support/whiny_nil.rb +0 -24
@@ -1,46 +1,67 @@
1
- require 'rational' unless RUBY_VERSION >= '1.9.2'
1
+ require 'active_support/deprecation'
2
2
 
3
3
  class DateTime
4
4
  class << self
5
- # 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
5
+ # *DEPRECATED*: Use +DateTime.civil_from_format+ directly.
6
6
  def local_offset
7
+ ActiveSupport::Deprecation.warn 'DateTime.local_offset is deprecated. Use DateTime.civil_from_format directly.'
8
+
7
9
  ::Time.local(2012).utc_offset.to_r / 86400
8
10
  end
9
11
 
10
- # Returns <tt>Time.zone.now.to_datetime</tt> when <tt>Time.zone</tt> or <tt>config.time_zone</tt> are set, otherwise returns <tt>Time.now.to_datetime</tt>.
12
+ # Returns <tt>Time.zone.now.to_datetime</tt> when <tt>Time.zone</tt> or
13
+ # <tt>config.time_zone</tt> are set, otherwise returns
14
+ # <tt>Time.now.to_datetime</tt>.
11
15
  def current
12
16
  ::Time.zone ? ::Time.zone.now.to_datetime : ::Time.now.to_datetime
13
17
  end
14
18
  end
15
19
 
16
- # Tells whether the DateTime object's datetime lies in the past
20
+ # Tells whether the DateTime object's datetime lies in the past.
17
21
  def past?
18
22
  self < ::DateTime.current
19
23
  end
20
24
 
21
- # Tells whether the DateTime object's datetime lies in the future
25
+ # Tells whether the DateTime object's datetime lies in the future.
22
26
  def future?
23
27
  self > ::DateTime.current
24
28
  end
25
29
 
26
- # Seconds since midnight: DateTime.now.seconds_since_midnight
30
+ # Seconds since midnight: DateTime.now.seconds_since_midnight.
27
31
  def seconds_since_midnight
28
32
  sec + (min * 60) + (hour * 3600)
29
33
  end
30
34
 
31
- # Returns a new DateTime where one or more of the elements have been changed according to the +options+ parameter. The time options
32
- # (hour, minute, sec) reset cascadingly, so if only the hour is passed, then minute and sec is set to 0. If the hour and
33
- # minute is passed, then sec is set to 0.
35
+ # Returns the number of seconds until 23:59:59.
36
+ #
37
+ # DateTime.new(2012, 8, 29, 0, 0, 0).seconds_until_end_of_day # => 86399
38
+ # DateTime.new(2012, 8, 29, 12, 34, 56).seconds_until_end_of_day # => 41103
39
+ # DateTime.new(2012, 8, 29, 23, 59, 59).seconds_until_end_of_day # => 0
40
+ def seconds_until_end_of_day
41
+ end_of_day.to_i - to_i
42
+ end
43
+
44
+ # Returns a new DateTime where one or more of the elements have been changed
45
+ # according to the +options+ parameter. The time options (<tt>:hour</tt>,
46
+ # <tt>:min</tt>, <tt>:sec</tt>) reset cascadingly, so if only the hour is
47
+ # passed, then minute and sec is set to 0. If the hour and minute is passed,
48
+ # then sec is set to 0. The +options+ parameter takes a hash with any of these
49
+ # keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>, <tt>:hour</tt>,
50
+ # <tt>:min</tt>, <tt>:sec</tt>, <tt>:offset</tt>, <tt>:start</tt>.
51
+ #
52
+ # DateTime.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => DateTime.new(2012, 8, 1, 22, 35, 0)
53
+ # DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => DateTime.new(1981, 8, 1, 22, 35, 0)
54
+ # DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => DateTime.new(1981, 8, 29, 0, 0, 0)
34
55
  def change(options)
35
56
  ::DateTime.civil(
36
- options[:year] || year,
37
- options[:month] || month,
38
- options[:day] || day,
39
- options[:hour] || hour,
40
- options[:min] || (options[:hour] ? 0 : min),
41
- options[:sec] || ((options[:hour] || options[:min]) ? 0 : sec),
42
- options[:offset] || offset,
43
- options[:start] || start
57
+ options.fetch(:year, year),
58
+ options.fetch(:month, month),
59
+ options.fetch(:day, day),
60
+ options.fetch(:hour, hour),
61
+ options.fetch(:min, options[:hour] ? 0 : min),
62
+ options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec + sec_fraction),
63
+ options.fetch(:offset, offset),
64
+ options.fetch(:start, start)
44
65
  )
45
66
  end
46
67
 
@@ -51,24 +72,33 @@ class DateTime
51
72
  def advance(options)
52
73
  d = to_date.advance(options)
53
74
  datetime_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
54
- seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
55
- seconds_to_advance == 0 ? datetime_advanced_by_date : datetime_advanced_by_date.since(seconds_to_advance)
75
+ seconds_to_advance = \
76
+ options.fetch(:seconds, 0) +
77
+ options.fetch(:minutes, 0) * 60 +
78
+ options.fetch(:hours, 0) * 3600
79
+
80
+ if seconds_to_advance.zero?
81
+ datetime_advanced_by_date
82
+ else
83
+ datetime_advanced_by_date.since seconds_to_advance
84
+ end
56
85
  end
57
86
 
58
- # Returns a new DateTime representing the time a number of seconds ago
87
+ # Returns a new DateTime representing the time a number of seconds ago.
59
88
  # Do not use this method in combination with x.months, use months_ago instead!
60
89
  def ago(seconds)
61
90
  since(-seconds)
62
91
  end
63
92
 
64
- # Returns a new DateTime representing the time a number of seconds since the instance time
65
- # Do not use this method in combination with x.months, use months_since instead!
93
+ # Returns a new DateTime representing the time a number of seconds since the
94
+ # instance time. Do not use this method in combination with x.months, use
95
+ # months_since instead!
66
96
  def since(seconds)
67
97
  self + Rational(seconds.round, 86400)
68
98
  end
69
99
  alias :in :since
70
100
 
71
- # Returns a new DateTime representing the start of the day (0:00)
101
+ # Returns a new DateTime representing the start of the day (0:00).
72
102
  def beginning_of_day
73
103
  change(:hour => 0)
74
104
  end
@@ -76,74 +106,59 @@ class DateTime
76
106
  alias :at_midnight :beginning_of_day
77
107
  alias :at_beginning_of_day :beginning_of_day
78
108
 
79
- # Returns a new DateTime representing the end of the day (23:59:59)
109
+ # Returns a new DateTime representing the end of the day (23:59:59).
80
110
  def end_of_day
81
111
  change(:hour => 23, :min => 59, :sec => 59)
82
112
  end
113
+ alias :at_end_of_day :end_of_day
83
114
 
84
- # Returns a new DateTime representing the start of the hour (hh:00:00)
115
+ # Returns a new DateTime representing the start of the hour (hh:00:00).
85
116
  def beginning_of_hour
86
117
  change(:min => 0)
87
118
  end
88
119
  alias :at_beginning_of_hour :beginning_of_hour
89
120
 
90
- # Returns a new DateTime representing the end of the hour (hh:59:59)
121
+ # Returns a new DateTime representing the end of the hour (hh:59:59).
91
122
  def end_of_hour
92
123
  change(:min => 59, :sec => 59)
93
124
  end
125
+ alias :at_end_of_hour :end_of_hour
94
126
 
95
- # 1.9.3 defines + and - on DateTime, < 1.9.3 do not.
96
- if DateTime.public_instance_methods(false).include?(:+)
97
- def plus_with_duration(other) #:nodoc:
98
- if ActiveSupport::Duration === other
99
- other.since(self)
100
- else
101
- plus_without_duration(other)
102
- end
103
- end
104
- alias_method :plus_without_duration, :+
105
- alias_method :+, :plus_with_duration
106
-
107
- def minus_with_duration(other) #:nodoc:
108
- if ActiveSupport::Duration === other
109
- plus_with_duration(-other)
110
- else
111
- minus_without_duration(other)
112
- end
113
- end
114
- alias_method :minus_without_duration, :-
115
- alias_method :-, :minus_with_duration
127
+ # Returns a new DateTime representing the start of the minute (hh:mm:00).
128
+ def beginning_of_minute
129
+ change(:sec => 0)
116
130
  end
131
+ alias :at_beginning_of_minute :beginning_of_minute
117
132
 
118
- # Adjusts DateTime to UTC by adding its offset value; offset is set to 0
119
- #
120
- # Example:
133
+ # Returns a new DateTime representing the end of the minute (hh:mm:59).
134
+ def end_of_minute
135
+ change(:sec => 59)
136
+ end
137
+ alias :at_end_of_minute :end_of_minute
138
+
139
+ # Adjusts DateTime to UTC by adding its offset value; offset is set to 0.
121
140
  #
122
- # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600
123
- # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 +0000
141
+ # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600
142
+ # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 +0000
124
143
  def utc
125
144
  new_offset(0)
126
145
  end
127
146
  alias_method :getutc, :utc
128
147
 
129
- # Returns true if offset == 0
148
+ # Returns +true+ if <tt>offset == 0</tt>.
130
149
  def utc?
131
150
  offset == 0
132
151
  end
133
152
 
134
- # Returns the offset value in seconds
153
+ # Returns the offset value in seconds.
135
154
  def utc_offset
136
155
  (offset * 86400).to_i
137
156
  end
138
157
 
139
- # Layers additional behavior on DateTime#<=> so that Time and ActiveSupport::TimeWithZone instances can be compared with a DateTime
158
+ # Layers additional behavior on DateTime#<=> so that Time and
159
+ # ActiveSupport::TimeWithZone instances can be compared with a DateTime.
140
160
  def <=>(other)
141
- if other.kind_of?(Infinity)
142
- super
143
- elsif other.respond_to? :to_datetime
144
- super other.to_datetime
145
- else
146
- nil
147
- end
161
+ super other.to_datetime
148
162
  end
163
+
149
164
  end
@@ -4,10 +4,6 @@ require 'active_support/core_ext/date_time/calculations'
4
4
  require 'active_support/values/time_zone'
5
5
 
6
6
  class DateTime
7
- # Ruby 1.9 has DateTime#to_time which internally relies on Time. We define our own #to_time which allows
8
- # DateTimes outside the range of what can be created with Time.
9
- remove_method :to_time if instance_methods.include?(:to_time)
10
-
11
7
  # Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
12
8
  #
13
9
  # This method is aliased to <tt>to_s</tt>.
@@ -30,7 +26,7 @@ class DateTime
30
26
  # datetime argument as the value.
31
27
  #
32
28
  # # config/initializers/time_formats.rb
33
- # Time::DATE_FORMATS[:month_and_year] = "%B %Y"
29
+ # Time::DATE_FORMATS[:month_and_year] = '%B %Y'
34
30
  # Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
35
31
  def to_formatted_s(format = :default)
36
32
  if formatter = ::Time::DATE_FORMATS[format]
@@ -39,10 +35,9 @@ class DateTime
39
35
  to_default_s
40
36
  end
41
37
  end
42
- alias_method :to_default_s, :to_s unless (instance_methods(false) & [:to_s, 'to_s']).empty?
38
+ alias_method :to_default_s, :to_s if instance_methods(false).include?(:to_s)
43
39
  alias_method :to_s, :to_formatted_s
44
40
 
45
- # Returns the +utc_offset+ as an +HH:MM formatted string. Examples:
46
41
  #
47
42
  # datetime = DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-6, 24))
48
43
  # datetime.formatted_offset # => "-06:00"
@@ -58,46 +53,39 @@ class DateTime
58
53
  alias_method :default_inspect, :inspect
59
54
  alias_method :inspect, :readable_inspect
60
55
 
61
- # Converts self to a Ruby Date object; time portion is discarded.
62
- def to_date
63
- ::Date.new(year, month, day)
64
- end unless instance_methods(false).include?(:to_date)
65
-
66
- # Attempts to convert self to a Ruby Time object; returns self if out of range of Ruby Time class.
67
- # 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.
68
- def to_time
69
- self.offset == 0 ? ::Time.utc_time(year, month, day, hour, min, sec, sec_fraction * (RUBY_VERSION < '1.9' ? 86400000000 : 1000000)) : self
70
- end
71
-
72
- # To be able to keep Times, Dates and DateTimes interchangeable on conversions.
73
- def to_datetime
74
- self
75
- end unless instance_methods(false).include?(:to_datetime)
76
-
56
+ # Returns DateTime with local offset for given year if format is local else
57
+ # offset is zero.
58
+ #
59
+ # DateTime.civil_from_format :local, 2012
60
+ # # => Sun, 01 Jan 2012 00:00:00 +0300
61
+ # DateTime.civil_from_format :local, 2012, 12, 17
62
+ # # => Mon, 17 Dec 2012 00:00:00 +0000
77
63
  def self.civil_from_format(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0)
78
- offset = utc_or_local.to_sym == :local ? local_offset : 0
64
+ if utc_or_local.to_sym == :local
65
+ offset = ::Time.local(year, month, day).utc_offset.to_r / 86400
66
+ else
67
+ offset = 0
68
+ end
79
69
  civil(year, month, day, hour, min, sec, offset)
80
70
  end
81
71
 
82
- # Converts datetime to an appropriate format for use in XML.
83
- def xmlschema
84
- strftime("%Y-%m-%dT%H:%M:%S%Z")
85
- end unless instance_methods(false).include?(:xmlschema)
86
-
87
- # Converts self to a floating-point number of seconds since the Unix epoch.
72
+ # Converts +self+ to a floating-point number of seconds since the Unix epoch.
88
73
  def to_f
89
74
  seconds_since_unix_epoch.to_f
90
75
  end
91
76
 
92
- # Converts self to an integer number of seconds since the Unix epoch.
77
+ # Converts +self+ to an integer number of seconds since the Unix epoch.
93
78
  def to_i
94
79
  seconds_since_unix_epoch.to_i
95
80
  end
96
81
 
97
82
  private
98
83
 
84
+ def offset_in_seconds
85
+ (offset * 86400).to_i
86
+ end
87
+
99
88
  def seconds_since_unix_epoch
100
- seconds_per_day = 86_400
101
- (self - ::DateTime.civil(1970)) * seconds_per_day
89
+ (jd - 2440588) * 86400 - offset_in_seconds + seconds_since_midnight
102
90
  end
103
91
  end
@@ -6,16 +6,19 @@ class DateTime
6
6
  # Time.zone = 'Hawaii' # => 'Hawaii'
7
7
  # DateTime.new(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
8
8
  #
9
- # This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
10
- # instead of the operating system's time zone.
9
+ # This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt>
10
+ # as the local zone instead of the operating system's time zone.
11
11
  #
12
- # You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument,
13
- # and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
12
+ # You can also pass in a TimeZone instance or string that identifies a TimeZone
13
+ # as an argument, and the conversion will be based on that zone instead of
14
+ # <tt>Time.zone</tt>.
14
15
  #
15
- # DateTime.new(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
16
+ # DateTime.new(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
16
17
  def in_time_zone(zone = ::Time.zone)
17
- return self unless zone
18
-
19
- ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
18
+ if zone
19
+ ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
20
+ else
21
+ self
22
+ end
20
23
  end
21
24
  end
@@ -0,0 +1,4 @@
1
+ require 'active_support/core_ext/date_time/acts_like'
2
+ require 'active_support/core_ext/date_time/calculations'
3
+ require 'active_support/core_ext/date_time/conversions'
4
+ require 'active_support/core_ext/date_time/zones'
@@ -1,42 +1,5 @@
1
- require 'active_support/ordered_hash'
2
-
3
1
  module Enumerable
4
- # Ruby 1.8.7 introduces group_by, but the result isn't ordered. Override it.
5
- remove_method(:group_by) if [].respond_to?(:group_by) && RUBY_VERSION < '1.9'
6
-
7
- # Collect an enumerable into sets, grouped by the result of a block. Useful,
8
- # for example, for grouping records by date.
9
- #
10
- # Example:
11
- #
12
- # latest_transcripts.group_by(&:day).each do |day, transcripts|
13
- # p "#{day} -> #{transcripts.map(&:class).join(', ')}"
14
- # end
15
- # "2006-03-01 -> Transcript"
16
- # "2006-02-28 -> Transcript"
17
- # "2006-02-27 -> Transcript, Transcript"
18
- # "2006-02-26 -> Transcript, Transcript"
19
- # "2006-02-25 -> Transcript"
20
- # "2006-02-24 -> Transcript, Transcript"
21
- # "2006-02-23 -> Transcript"
22
- def group_by
23
- return to_enum :group_by unless block_given?
24
- assoc = ActiveSupport::OrderedHash.new
25
-
26
- each do |element|
27
- key = yield(element)
28
-
29
- if assoc.has_key?(key)
30
- assoc[key] << element
31
- else
32
- assoc[key] = [element]
33
- end
34
- end
35
-
36
- assoc
37
- end unless [].respond_to?(:group_by)
38
-
39
- # Calculates a sum from the elements. Examples:
2
+ # Calculates a sum from the elements.
40
3
  #
41
4
  # payments.sum { |p| p.price * p.tax_rate }
42
5
  # payments.sum(&:price)
@@ -48,56 +11,38 @@ module Enumerable
48
11
  # It can also calculate the sum without the use of a block.
49
12
  #
50
13
  # [5, 15, 10].sum # => 30
51
- # ["foo", "bar"].sum # => "foobar"
14
+ # ['foo', 'bar'].sum # => "foobar"
52
15
  # [[1, 2], [3, 1, 5]].sum => [1, 2, 3, 1, 5]
53
16
  #
54
17
  # The default sum of an empty list is zero. You can override this default:
55
18
  #
56
19
  # [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
57
- #
58
20
  def sum(identity = 0, &block)
59
21
  if block_given?
60
22
  map(&block).sum(identity)
61
23
  else
62
- inject(:+) || identity
24
+ inject { |sum, element| sum + element } || identity
63
25
  end
64
26
  end
65
27
 
66
- # Iterates over a collection, passing the current element *and* the
67
- # +memo+ to the block. Handy for building up hashes or
68
- # reducing collections down to one object. Examples:
69
- #
70
- # %w(foo bar).each_with_object({}) { |str, hsh| hsh[str] = str.upcase }
71
- # # => {'foo' => 'FOO', 'bar' => 'BAR'}
72
- #
73
- # *Note* that you can't use immutable objects like numbers, true or false as
74
- # the memo. You would think the following returns 120, but since the memo is
75
- # never changed, it does not.
76
- #
77
- # (1..5).each_with_object(1) { |value, memo| memo *= value } # => 1
78
- #
79
- def each_with_object(memo)
80
- return to_enum :each_with_object, memo unless block_given?
81
- each do |element|
82
- yield element, memo
83
- end
84
- memo
85
- end unless [].respond_to?(:each_with_object)
86
-
87
- # Convert an enumerable to a hash. Examples:
28
+ # Convert an enumerable to a hash.
88
29
  #
89
30
  # people.index_by(&:login)
90
31
  # => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
91
32
  # people.index_by { |person| "#{person.first_name} #{person.last_name}" }
92
33
  # => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
93
- #
94
34
  def index_by
95
- return to_enum :index_by unless block_given?
96
- Hash[map { |elem| [yield(elem), elem] }]
35
+ if block_given?
36
+ Hash[map { |elem| [yield(elem), elem] }]
37
+ else
38
+ to_enum :index_by
39
+ end
97
40
  end
98
41
 
99
- # Returns true if the enumerable has more than 1 element. Functionally equivalent to enum.to_a.size > 1.
100
- # Can be called with a block too, much like any?, so <tt>people.many? { |p| p.age > 26 }</tt> returns true if more than one person is over 26.
42
+ # Returns +true+ if the enumerable has more than 1 element. Functionally
43
+ # equivalent to <tt>enum.to_a.size > 1</tt>. Can be called with a block too,
44
+ # much like any?, so <tt>people.many? { |p| p.age > 26 }</tt> returns +true+
45
+ # if more than one person is over 26.
101
46
  def many?
102
47
  cnt = 0
103
48
  if block_given?
@@ -106,11 +51,12 @@ module Enumerable
106
51
  cnt > 1
107
52
  end
108
53
  else
109
- any?{ (cnt += 1) > 1 }
54
+ any? { (cnt += 1) > 1 }
110
55
  end
111
56
  end
112
57
 
113
- # The negative of the <tt>Enumerable#include?</tt>. Returns true if the collection does not include the object.
58
+ # The negative of the <tt>Enumerable#include?</tt>. Returns +true+ if the
59
+ # collection does not include the object.
114
60
  def exclude?(object)
115
61
  !include?(object)
116
62
  end
@@ -120,8 +66,15 @@ class Range #:nodoc:
120
66
  # Optimize range sum to use arithmetic progression if a block is not given and
121
67
  # we have a range of numeric values.
122
68
  def sum(identity = 0)
123
- return super if block_given? || !(first.instance_of?(Integer) && last.instance_of?(Integer))
124
- actual_last = exclude_end? ? (last - 1) : last
125
- (actual_last - first + 1) * (actual_last + first) / 2
69
+ if block_given? || !(first.is_a?(Integer) && last.is_a?(Integer))
70
+ super
71
+ else
72
+ actual_last = exclude_end? ? (last - 1) : last
73
+ if actual_last >= first
74
+ (actual_last - first + 1) * (actual_last + first) / 2
75
+ else
76
+ identity
77
+ end
78
+ end
126
79
  end
127
80
  end
@@ -1,16 +1,18 @@
1
+ require 'fileutils'
2
+
1
3
  class File
2
4
  # Write to a file atomically. Useful for situations where you don't
3
5
  # want other processes or threads to see half-written files.
4
6
  #
5
- # File.atomic_write("important.file") do |file|
6
- # file.write("hello")
7
+ # File.atomic_write('important.file') do |file|
8
+ # file.write('hello')
7
9
  # end
8
10
  #
9
11
  # If your temp directory is not on the same filesystem as the file you're
10
12
  # trying to write, you can provide a different temporary directory.
11
13
  #
12
- # File.atomic_write("/data/something.important", "/data/tmp") do |file|
13
- # file.write("hello")
14
+ # File.atomic_write('/data/something.important', '/data/tmp') do |file|
15
+ # file.write('hello')
14
16
  # end
15
17
  def self.atomic_write(file_name, temp_dir = Dir.tmpdir)
16
18
  require 'tempfile' unless defined?(Tempfile)
@@ -21,15 +23,13 @@ class File
21
23
  yield temp_file
22
24
  temp_file.close
23
25
 
24
- begin
26
+ if File.exists?(file_name)
25
27
  # Get original file permissions
26
28
  old_stat = stat(file_name)
27
- rescue Errno::ENOENT
28
- # No old permissions, write a temp file to determine the defaults
29
- check_name = join(dirname(file_name), ".permissions_check.#{Thread.current.object_id}.#{Process.pid}.#{rand(1000000)}")
30
- open(check_name, "w") { }
31
- old_stat = stat(check_name)
32
- unlink(check_name)
29
+ else
30
+ # If not possible, probe which are the default permissions in the
31
+ # destination directory.
32
+ old_stat = probe_stat_in(dirname(file_name))
33
33
  end
34
34
 
35
35
  # Overwrite original file with temp file
@@ -44,4 +44,20 @@ class File
44
44
  # Changing file ownership failed, moving on.
45
45
  end
46
46
  end
47
+
48
+ # Private utility method.
49
+ def self.probe_stat_in(dir) #:nodoc:
50
+ basename = [
51
+ '.permissions_check',
52
+ Thread.current.object_id,
53
+ Process.pid,
54
+ rand(1000000)
55
+ ].join('.')
56
+
57
+ file_name = join(dir, basename)
58
+ FileUtils.touch(file_name)
59
+ stat(file_name)
60
+ ensure
61
+ FileUtils.rm_f(file_name) if file_name
62
+ end
47
63
  end
@@ -1,2 +1 @@
1
1
  require 'active_support/core_ext/file/atomic'
2
- require 'active_support/core_ext/file/path'