activesupport 3.1.0 → 5.0.0

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 (276) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +798 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +13 -7
  5. data/lib/active_support/array_inquirer.rb +44 -0
  6. data/lib/active_support/backtrace_cleaner.rb +38 -34
  7. data/lib/active_support/benchmarkable.rb +17 -28
  8. data/lib/active_support/cache/file_store.rb +85 -70
  9. data/lib/active_support/cache/mem_cache_store.rb +75 -66
  10. data/lib/active_support/cache/memory_store.rb +31 -23
  11. data/lib/active_support/cache/null_store.rb +41 -0
  12. data/lib/active_support/cache/strategy/local_cache.rb +73 -70
  13. data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
  14. data/lib/active_support/cache.rb +360 -294
  15. data/lib/active_support/callbacks.rb +563 -393
  16. data/lib/active_support/concern.rb +42 -34
  17. data/lib/active_support/concurrency/latch.rb +19 -0
  18. data/lib/active_support/concurrency/share_lock.rb +186 -0
  19. data/lib/active_support/configurable.rb +70 -12
  20. data/lib/active_support/core_ext/array/access.rb +53 -9
  21. data/lib/active_support/core_ext/array/conversions.rb +109 -62
  22. data/lib/active_support/core_ext/array/extract_options.rb +2 -2
  23. data/lib/active_support/core_ext/array/grouping.rb +39 -32
  24. data/lib/active_support/core_ext/array/inquiry.rb +17 -0
  25. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
  26. data/lib/active_support/core_ext/array/wrap.rb +16 -18
  27. data/lib/active_support/core_ext/array.rb +2 -2
  28. data/lib/active_support/core_ext/benchmark.rb +7 -0
  29. data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -36
  30. data/lib/active_support/core_ext/class/attribute.rb +47 -34
  31. data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -79
  32. data/lib/active_support/core_ext/class/subclasses.rb +12 -7
  33. data/lib/active_support/core_ext/class.rb +0 -3
  34. data/lib/active_support/core_ext/date/blank.rb +12 -0
  35. data/lib/active_support/core_ext/date/calculations.rb +57 -167
  36. data/lib/active_support/core_ext/date/conversions.rb +31 -42
  37. data/lib/active_support/core_ext/date/zones.rb +2 -10
  38. data/lib/active_support/core_ext/date.rb +5 -0
  39. data/lib/active_support/core_ext/date_and_time/calculations.rb +335 -0
  40. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -0
  41. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  42. data/lib/active_support/core_ext/date_time/acts_like.rb +1 -0
  43. data/lib/active_support/core_ext/date_time/blank.rb +12 -0
  44. data/lib/active_support/core_ext/date_time/calculations.rb +132 -65
  45. data/lib/active_support/core_ext/date_time/compatibility.rb +5 -0
  46. data/lib/active_support/core_ext/date_time/conversions.rb +36 -34
  47. data/lib/active_support/core_ext/date_time.rb +5 -0
  48. data/lib/active_support/core_ext/digest/uuid.rb +51 -0
  49. data/lib/active_support/core_ext/enumerable.rb +81 -74
  50. data/lib/active_support/core_ext/file/atomic.rb +53 -26
  51. data/lib/active_support/core_ext/file.rb +0 -1
  52. data/lib/active_support/core_ext/hash/compact.rb +20 -0
  53. data/lib/active_support/core_ext/hash/conversions.rb +175 -70
  54. data/lib/active_support/core_ext/hash/deep_merge.rb +30 -8
  55. data/lib/active_support/core_ext/hash/except.rb +11 -12
  56. data/lib/active_support/core_ext/hash/indifferent_access.rb +7 -8
  57. data/lib/active_support/core_ext/hash/keys.rb +147 -24
  58. data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
  59. data/lib/active_support/core_ext/hash/slice.rb +22 -14
  60. data/lib/active_support/core_ext/hash/transform_values.rb +29 -0
  61. data/lib/active_support/core_ext/hash.rb +2 -2
  62. data/lib/active_support/core_ext/integer/inflections.rb +13 -1
  63. data/lib/active_support/core_ext/integer/multiple.rb +4 -0
  64. data/lib/active_support/core_ext/integer/time.rb +12 -22
  65. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -2
  66. data/lib/active_support/core_ext/kernel/concern.rb +12 -0
  67. data/lib/active_support/core_ext/kernel/debugger.rb +2 -15
  68. data/lib/active_support/core_ext/kernel/reporting.rb +12 -62
  69. data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
  70. data/lib/active_support/core_ext/kernel.rb +2 -3
  71. data/lib/active_support/core_ext/load_error.rb +14 -7
  72. data/lib/active_support/core_ext/marshal.rb +22 -0
  73. data/lib/active_support/core_ext/module/aliasing.rb +16 -12
  74. data/lib/active_support/core_ext/module/anonymous.rb +12 -8
  75. data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
  76. data/lib/active_support/core_ext/module/attribute_accessors.rb +165 -13
  77. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
  78. data/lib/active_support/core_ext/module/concerning.rb +135 -0
  79. data/lib/active_support/core_ext/module/delegation.rb +141 -68
  80. data/lib/active_support/core_ext/module/deprecation.rb +17 -3
  81. data/lib/active_support/core_ext/module/introspection.rb +9 -31
  82. data/lib/active_support/core_ext/module/method_transplanting.rb +3 -0
  83. data/lib/active_support/core_ext/module/qualified_const.rb +70 -0
  84. data/lib/active_support/core_ext/module/reachable.rb +1 -3
  85. data/lib/active_support/core_ext/module/remove_method.rb +24 -5
  86. data/lib/active_support/core_ext/module.rb +3 -3
  87. data/lib/active_support/core_ext/name_error.rb +15 -2
  88. data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
  89. data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
  90. data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
  91. data/lib/active_support/core_ext/numeric/time.rb +31 -36
  92. data/lib/active_support/core_ext/numeric.rb +2 -0
  93. data/lib/active_support/core_ext/object/acts_like.rb +4 -4
  94. data/lib/active_support/core_ext/object/blank.rb +52 -18
  95. data/lib/active_support/core_ext/object/deep_dup.rb +53 -0
  96. data/lib/active_support/core_ext/object/duplicable.rb +12 -20
  97. data/lib/active_support/core_ext/object/inclusion.rb +13 -1
  98. data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
  99. data/lib/active_support/core_ext/object/json.rb +205 -0
  100. data/lib/active_support/core_ext/object/to_param.rb +1 -55
  101. data/lib/active_support/core_ext/object/to_query.rb +66 -9
  102. data/lib/active_support/core_ext/object/try.rb +124 -33
  103. data/lib/active_support/core_ext/object/with_options.rb +37 -11
  104. data/lib/active_support/core_ext/object.rb +2 -1
  105. data/lib/active_support/core_ext/range/conversions.rb +17 -7
  106. data/lib/active_support/core_ext/range/each.rb +21 -0
  107. data/lib/active_support/core_ext/range/include_range.rb +20 -18
  108. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  109. data/lib/active_support/core_ext/range.rb +1 -2
  110. data/lib/active_support/core_ext/securerandom.rb +23 -0
  111. data/lib/active_support/core_ext/string/access.rb +95 -90
  112. data/lib/active_support/core_ext/string/behavior.rb +1 -1
  113. data/lib/active_support/core_ext/string/conversions.rb +41 -38
  114. data/lib/active_support/core_ext/string/exclude.rb +6 -1
  115. data/lib/active_support/core_ext/string/filters.rb +70 -17
  116. data/lib/active_support/core_ext/string/indent.rb +43 -0
  117. data/lib/active_support/core_ext/string/inflections.rb +139 -59
  118. data/lib/active_support/core_ext/string/inquiry.rb +2 -2
  119. data/lib/active_support/core_ext/string/multibyte.rb +46 -65
  120. data/lib/active_support/core_ext/string/output_safety.rb +153 -56
  121. data/lib/active_support/core_ext/string/strip.rb +3 -6
  122. data/lib/active_support/core_ext/string/zones.rb +14 -0
  123. data/lib/active_support/core_ext/string.rb +2 -3
  124. data/lib/active_support/core_ext/struct.rb +3 -0
  125. data/lib/active_support/core_ext/time/calculations.rb +173 -173
  126. data/lib/active_support/core_ext/time/compatibility.rb +5 -0
  127. data/lib/active_support/core_ext/time/conversions.rb +33 -29
  128. data/lib/active_support/core_ext/time/marshal.rb +2 -56
  129. data/lib/active_support/core_ext/time/zones.rb +57 -32
  130. data/lib/active_support/core_ext/time.rb +5 -0
  131. data/lib/active_support/core_ext/uri.rb +13 -19
  132. data/lib/active_support/core_ext.rb +3 -2
  133. data/lib/active_support/dependencies/autoload.rb +47 -20
  134. data/lib/active_support/dependencies/interlock.rb +51 -0
  135. data/lib/active_support/dependencies.rb +315 -265
  136. data/lib/active_support/deprecation/behaviors.rb +71 -30
  137. data/lib/active_support/deprecation/instance_delegator.rb +24 -0
  138. data/lib/active_support/deprecation/method_wrappers.rb +59 -18
  139. data/lib/active_support/deprecation/proxy_wrappers.rb +82 -14
  140. data/lib/active_support/deprecation/reporting.rb +61 -14
  141. data/lib/active_support/deprecation.rb +38 -13
  142. data/lib/active_support/descendants_tracker.rb +34 -19
  143. data/lib/active_support/duration/iso8601_parser.rb +122 -0
  144. data/lib/active_support/duration/iso8601_serializer.rb +51 -0
  145. data/lib/active_support/duration.rb +85 -14
  146. data/lib/active_support/evented_file_update_checker.rb +194 -0
  147. data/lib/active_support/execution_wrapper.rb +117 -0
  148. data/lib/active_support/executor.rb +6 -0
  149. data/lib/active_support/file_update_checker.rb +138 -17
  150. data/lib/active_support/gem_version.rb +15 -0
  151. data/lib/active_support/gzip.rb +11 -5
  152. data/lib/active_support/hash_with_indifferent_access.rb +199 -49
  153. data/lib/active_support/i18n.rb +6 -2
  154. data/lib/active_support/i18n_railtie.rb +40 -21
  155. data/lib/active_support/inflections.rb +22 -13
  156. data/lib/active_support/inflector/inflections.rb +175 -144
  157. data/lib/active_support/inflector/methods.rb +328 -91
  158. data/lib/active_support/inflector/transliterate.rb +51 -37
  159. data/lib/active_support/json/decoding.rb +31 -22
  160. data/lib/active_support/json/encoding.rb +88 -248
  161. data/lib/active_support/key_generator.rb +71 -0
  162. data/lib/active_support/lazy_load_hooks.rb +27 -25
  163. data/lib/active_support/locale/en.yml +102 -3
  164. data/lib/active_support/log_subscriber/test_helper.rb +24 -21
  165. data/lib/active_support/log_subscriber.rb +36 -49
  166. data/lib/active_support/logger.rb +106 -0
  167. data/lib/active_support/logger_silence.rb +28 -0
  168. data/lib/active_support/logger_thread_safe_level.rb +31 -0
  169. data/lib/active_support/message_encryptor.rb +72 -36
  170. data/lib/active_support/message_verifier.rb +96 -24
  171. data/lib/active_support/multibyte/chars.rb +88 -333
  172. data/lib/active_support/multibyte/unicode.rb +156 -136
  173. data/lib/active_support/multibyte.rb +5 -28
  174. data/lib/active_support/notifications/fanout.rb +115 -19
  175. data/lib/active_support/notifications/instrumenter.rb +52 -15
  176. data/lib/active_support/notifications.rb +168 -33
  177. data/lib/active_support/number_helper/number_converter.rb +182 -0
  178. data/lib/active_support/number_helper/number_to_currency_converter.rb +44 -0
  179. data/lib/active_support/number_helper/number_to_delimited_converter.rb +28 -0
  180. data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
  181. data/lib/active_support/number_helper/number_to_human_size_converter.rb +62 -0
  182. data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
  183. data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
  184. data/lib/active_support/number_helper/number_to_rounded_converter.rb +92 -0
  185. data/lib/active_support/number_helper.rb +368 -0
  186. data/lib/active_support/option_merger.rb +1 -1
  187. data/lib/active_support/ordered_hash.rb +18 -183
  188. data/lib/active_support/ordered_options.rb +44 -24
  189. data/lib/active_support/per_thread_registry.rb +58 -0
  190. data/lib/active_support/proxy_object.rb +13 -0
  191. data/lib/active_support/rails.rb +27 -0
  192. data/lib/active_support/railtie.rb +25 -34
  193. data/lib/active_support/reloader.rb +129 -0
  194. data/lib/active_support/rescuable.rb +98 -48
  195. data/lib/active_support/security_utils.rb +27 -0
  196. data/lib/active_support/string_inquirer.rb +14 -9
  197. data/lib/active_support/subscriber.rb +120 -0
  198. data/lib/active_support/tagged_logging.rb +78 -0
  199. data/lib/active_support/test_case.rb +69 -17
  200. data/lib/active_support/testing/assertions.rb +43 -41
  201. data/lib/active_support/testing/autorun.rb +12 -0
  202. data/lib/active_support/testing/constant_lookup.rb +50 -0
  203. data/lib/active_support/testing/declarative.rb +7 -21
  204. data/lib/active_support/testing/deprecation.rb +14 -33
  205. data/lib/active_support/testing/file_fixtures.rb +34 -0
  206. data/lib/active_support/testing/isolation.rb +53 -95
  207. data/lib/active_support/testing/method_call_assertions.rb +41 -0
  208. data/lib/active_support/testing/setup_and_teardown.rb +21 -82
  209. data/lib/active_support/testing/stream.rb +42 -0
  210. data/lib/active_support/testing/tagged_logging.rb +25 -0
  211. data/lib/active_support/testing/time_helpers.rb +134 -0
  212. data/lib/active_support/time.rb +6 -23
  213. data/lib/active_support/time_with_zone.rb +239 -92
  214. data/lib/active_support/values/time_zone.rb +236 -160
  215. data/lib/active_support/values/unicode_tables.dat +0 -0
  216. data/lib/active_support/version.rb +5 -7
  217. data/lib/active_support/xml_mini/jdom.rb +19 -13
  218. data/lib/active_support/xml_mini/libxml.rb +3 -4
  219. data/lib/active_support/xml_mini/libxmlsax.rb +2 -3
  220. data/lib/active_support/xml_mini/nokogiri.rb +3 -4
  221. data/lib/active_support/xml_mini/nokogirisax.rb +2 -3
  222. data/lib/active_support/xml_mini/rexml.rb +8 -10
  223. data/lib/active_support/xml_mini.rb +66 -34
  224. data/lib/active_support.rb +40 -23
  225. metadata +185 -134
  226. data/CHANGELOG +0 -1534
  227. data/lib/active_support/base64.rb +0 -42
  228. data/lib/active_support/basic_object.rb +0 -21
  229. data/lib/active_support/buffered_logger.rb +0 -137
  230. data/lib/active_support/cache/compressed_mem_cache_store.rb +0 -13
  231. data/lib/active_support/cache/synchronized_memory_store.rb +0 -11
  232. data/lib/active_support/core_ext/array/random_access.rb +0 -30
  233. data/lib/active_support/core_ext/array/uniq_by.rb +0 -16
  234. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -44
  235. data/lib/active_support/core_ext/class/inheritable_attributes.rb +0 -178
  236. data/lib/active_support/core_ext/date/freeze.rb +0 -31
  237. data/lib/active_support/core_ext/date_time/zones.rb +0 -21
  238. data/lib/active_support/core_ext/exception.rb +0 -3
  239. data/lib/active_support/core_ext/file/path.rb +0 -5
  240. data/lib/active_support/core_ext/float/rounding.rb +0 -19
  241. data/lib/active_support/core_ext/float.rb +0 -1
  242. data/lib/active_support/core_ext/hash/deep_dup.rb +0 -11
  243. data/lib/active_support/core_ext/hash/diff.rb +0 -13
  244. data/lib/active_support/core_ext/kernel/requires.rb +0 -28
  245. data/lib/active_support/core_ext/logger.rb +0 -81
  246. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +0 -31
  247. data/lib/active_support/core_ext/module/method_names.rb +0 -14
  248. data/lib/active_support/core_ext/module/synchronization.rb +0 -43
  249. data/lib/active_support/core_ext/object/to_json.rb +0 -19
  250. data/lib/active_support/core_ext/proc.rb +0 -14
  251. data/lib/active_support/core_ext/process/daemon.rb +0 -23
  252. data/lib/active_support/core_ext/process.rb +0 -1
  253. data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
  254. data/lib/active_support/core_ext/range/cover.rb +0 -3
  255. data/lib/active_support/core_ext/rexml.rb +0 -46
  256. data/lib/active_support/core_ext/string/encoding.rb +0 -11
  257. data/lib/active_support/core_ext/string/interpolation.rb +0 -2
  258. data/lib/active_support/core_ext/string/xchar.rb +0 -18
  259. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
  260. data/lib/active_support/file_watcher.rb +0 -36
  261. data/lib/active_support/json/variable.rb +0 -9
  262. data/lib/active_support/memoizable.rb +0 -105
  263. data/lib/active_support/multibyte/exceptions.rb +0 -8
  264. data/lib/active_support/multibyte/utils.rb +0 -60
  265. data/lib/active_support/ruby/shim.rb +0 -22
  266. data/lib/active_support/secure_random.rb +0 -6
  267. data/lib/active_support/testing/mochaing.rb +0 -7
  268. data/lib/active_support/testing/pending.rb +0 -52
  269. data/lib/active_support/testing/performance/jruby.rb +0 -115
  270. data/lib/active_support/testing/performance/rubinius.rb +0 -113
  271. data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
  272. data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
  273. data/lib/active_support/testing/performance/ruby.rb +0 -152
  274. data/lib/active_support/testing/performance.rb +0 -317
  275. data/lib/active_support/time/autoload.rb +0 -5
  276. data/lib/active_support/whiny_nil.rb +0 -60
@@ -1,13 +1,10 @@
1
+ require 'date'
1
2
  require 'active_support/inflector/methods'
2
3
  require 'active_support/core_ext/time/conversions'
3
4
  require 'active_support/core_ext/date_time/calculations'
4
5
  require 'active_support/values/time_zone'
5
6
 
6
7
  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
8
  # Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
12
9
  #
13
10
  # This method is aliased to <tt>to_s</tt>.
@@ -22,6 +19,7 @@ class DateTime
22
19
  # datetime.to_formatted_s(:long) # => "December 04, 2007 00:00"
23
20
  # datetime.to_formatted_s(:long_ordinal) # => "December 4th, 2007 00:00"
24
21
  # datetime.to_formatted_s(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
22
+ # datetime.to_formatted_s(:iso8601) # => "2007-12-04T00:00:00+00:00"
25
23
  #
26
24
  # == Adding your own datetime formats to to_formatted_s
27
25
  # DateTime formats are shared with Time. You can add your own to the
@@ -30,7 +28,7 @@ class DateTime
30
28
  # datetime argument as the value.
31
29
  #
32
30
  # # config/initializers/time_formats.rb
33
- # Time::DATE_FORMATS[:month_and_year] = "%B %Y"
31
+ # Time::DATE_FORMATS[:month_and_year] = '%B %Y'
34
32
  # Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
35
33
  def to_formatted_s(format = :default)
36
34
  if formatter = ::Time::DATE_FORMATS[format]
@@ -39,10 +37,11 @@ class DateTime
39
37
  to_default_s
40
38
  end
41
39
  end
42
- alias_method :to_default_s, :to_s unless (instance_methods(false) & [:to_s, 'to_s']).empty?
40
+ alias_method :to_default_s, :to_s if instance_methods(false).include?(:to_s)
43
41
  alias_method :to_s, :to_formatted_s
44
42
 
45
- # Returns the +utc_offset+ as an +HH:MM formatted string. Examples:
43
+ # Returns a formatted string of the offset from UTC, or an alternative
44
+ # string if the time zone is already UTC.
46
45
  #
47
46
  # datetime = DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-6, 24))
48
47
  # datetime.formatted_offset # => "-06:00"
@@ -58,46 +57,49 @@ class DateTime
58
57
  alias_method :default_inspect, :inspect
59
58
  alias_method :inspect, :readable_inspect
60
59
 
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
-
60
+ # Returns DateTime with local offset for given year if format is local else
61
+ # offset is zero.
62
+ #
63
+ # DateTime.civil_from_format :local, 2012
64
+ # # => Sun, 01 Jan 2012 00:00:00 +0300
65
+ # DateTime.civil_from_format :local, 2012, 12, 17
66
+ # # => Mon, 17 Dec 2012 00:00:00 +0000
77
67
  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
68
+ if utc_or_local.to_sym == :local
69
+ offset = ::Time.local(year, month, day).utc_offset.to_r / 86400
70
+ else
71
+ offset = 0
72
+ end
79
73
  civil(year, month, day, hour, min, sec, offset)
80
74
  end
81
75
 
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.
76
+ # Converts +self+ to a floating-point number of seconds, including fractional microseconds, since the Unix epoch.
88
77
  def to_f
89
- seconds_since_unix_epoch.to_f
78
+ seconds_since_unix_epoch.to_f + sec_fraction
90
79
  end
91
80
 
92
- # Converts self to an integer number of seconds since the Unix epoch.
81
+ # Converts +self+ to an integer number of seconds since the Unix epoch.
93
82
  def to_i
94
83
  seconds_since_unix_epoch.to_i
95
84
  end
96
85
 
86
+ # Returns the fraction of a second as microseconds
87
+ def usec
88
+ (sec_fraction * 1_000_000).to_i
89
+ end
90
+
91
+ # Returns the fraction of a second as nanoseconds
92
+ def nsec
93
+ (sec_fraction * 1_000_000_000).to_i
94
+ end
95
+
97
96
  private
98
97
 
98
+ def offset_in_seconds
99
+ (offset * 86400).to_i
100
+ end
101
+
99
102
  def seconds_since_unix_epoch
100
- seconds_per_day = 86_400
101
- (self - ::DateTime.civil(1970)) * seconds_per_day
103
+ (jd - 2440588) * 86400 - offset_in_seconds + seconds_since_midnight
102
104
  end
103
105
  end
@@ -0,0 +1,5 @@
1
+ require 'active_support/core_ext/date_time/acts_like'
2
+ require 'active_support/core_ext/date_time/blank'
3
+ require 'active_support/core_ext/date_time/calculations'
4
+ require 'active_support/core_ext/date_time/compatibility'
5
+ require 'active_support/core_ext/date_time/conversions'
@@ -0,0 +1,51 @@
1
+ require 'securerandom'
2
+
3
+ module Digest
4
+ module UUID
5
+ DNS_NAMESPACE = "k\xA7\xB8\x10\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
6
+ URL_NAMESPACE = "k\xA7\xB8\x11\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
7
+ OID_NAMESPACE = "k\xA7\xB8\x12\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
8
+ X500_NAMESPACE = "k\xA7\xB8\x14\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
9
+
10
+ # Generates a v5 non-random UUID (Universally Unique IDentifier).
11
+ #
12
+ # Using Digest::MD5 generates version 3 UUIDs; Digest::SHA1 generates version 5 UUIDs.
13
+ # uuid_from_hash always generates the same UUID for a given name and namespace combination.
14
+ #
15
+ # See RFC 4122 for details of UUID at: http://www.ietf.org/rfc/rfc4122.txt
16
+ def self.uuid_from_hash(hash_class, uuid_namespace, name)
17
+ if hash_class == Digest::MD5
18
+ version = 3
19
+ elsif hash_class == Digest::SHA1
20
+ version = 5
21
+ else
22
+ raise ArgumentError, "Expected Digest::SHA1 or Digest::MD5, got #{hash_class.name}."
23
+ end
24
+
25
+ hash = hash_class.new
26
+ hash.update(uuid_namespace)
27
+ hash.update(name)
28
+
29
+ ary = hash.digest.unpack('NnnnnN')
30
+ ary[2] = (ary[2] & 0x0FFF) | (version << 12)
31
+ ary[3] = (ary[3] & 0x3FFF) | 0x8000
32
+
33
+ "%08x-%04x-%04x-%04x-%04x%08x" % ary
34
+ end
35
+
36
+ # Convenience method for uuid_from_hash using Digest::MD5.
37
+ def self.uuid_v3(uuid_namespace, name)
38
+ self.uuid_from_hash(Digest::MD5, uuid_namespace, name)
39
+ end
40
+
41
+ # Convenience method for uuid_from_hash using Digest::SHA1.
42
+ def self.uuid_v5(uuid_namespace, name)
43
+ self.uuid_from_hash(Digest::SHA1, uuid_namespace, name)
44
+ end
45
+
46
+ # Convenience method for SecureRandom.uuid.
47
+ def self.uuid_v4
48
+ SecureRandom.uuid
49
+ end
50
+ end
51
+ end
@@ -1,41 +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
- assoc = ActiveSupport::OrderedHash.new
24
-
25
- each do |element|
26
- key = yield(element)
27
-
28
- if assoc.has_key?(key)
29
- assoc[key] << element
30
- else
31
- assoc[key] = [element]
32
- end
33
- end
34
-
35
- assoc
36
- end unless [].respond_to?(:group_by)
37
-
38
- # Calculates a sum from the elements. Examples:
2
+ # Calculates a sum from the elements.
39
3
  #
40
4
  # payments.sum { |p| p.price * p.tax_rate }
41
5
  # payments.sum(&:price)
@@ -47,71 +11,114 @@ module Enumerable
47
11
  # It can also calculate the sum without the use of a block.
48
12
  #
49
13
  # [5, 15, 10].sum # => 30
50
- # ["foo", "bar"].sum # => "foobar"
14
+ # ['foo', 'bar'].sum # => "foobar"
51
15
  # [[1, 2], [3, 1, 5]].sum => [1, 2, 3, 1, 5]
52
16
  #
53
17
  # The default sum of an empty list is zero. You can override this default:
54
18
  #
55
19
  # [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
56
- #
57
- def sum(identity = 0, &block)
20
+ def sum(identity = nil, &block)
58
21
  if block_given?
59
22
  map(&block).sum(identity)
60
23
  else
61
- inject { |sum, element| sum + element } || identity
24
+ sum = identity ? inject(identity, :+) : inject(:+)
25
+ sum || identity || 0
62
26
  end
63
27
  end
64
28
 
65
- # Iterates over a collection, passing the current element *and* the
66
- # +memo+ to the block. Handy for building up hashes or
67
- # reducing collections down to one object. Examples:
68
- #
69
- # %w(foo bar).each_with_object({}) { |str, hsh| hsh[str] = str.upcase }
70
- # # => {'foo' => 'FOO', 'bar' => 'BAR'}
71
- #
72
- # *Note* that you can't use immutable objects like numbers, true or false as
73
- # the memo. You would think the following returns 120, but since the memo is
74
- # never changed, it does not.
75
- #
76
- # (1..5).each_with_object(1) { |value, memo| memo *= value } # => 1
77
- #
78
- def each_with_object(memo, &block)
79
- each do |element|
80
- block.call(element, memo)
81
- end
82
- memo
83
- end unless [].respond_to?(:each_with_object)
84
-
85
- # Convert an enumerable to a hash. Examples:
29
+ # Convert an enumerable to a hash.
86
30
  #
87
31
  # people.index_by(&:login)
88
32
  # => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
89
33
  # people.index_by { |person| "#{person.first_name} #{person.last_name}" }
90
34
  # => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
91
- #
92
35
  def index_by
93
- Hash[map { |elem| [yield(elem), elem] }]
36
+ if block_given?
37
+ Hash[map { |elem| [yield(elem), elem] }]
38
+ else
39
+ to_enum(:index_by) { size if respond_to?(:size) }
40
+ end
94
41
  end
95
42
 
96
- # Returns true if the collection has more than 1 element. Functionally equivalent to collection.size > 1.
97
- # Can be called with a block too, much like any?, so people.many? { |p| p.age > 26 } returns true if more than 1 person is over 26.
98
- def many?(&block)
99
- size = block_given? ? count(&block) : self.size
100
- size > 1
43
+ # Returns +true+ if the enumerable has more than 1 element. Functionally
44
+ # equivalent to <tt>enum.to_a.size > 1</tt>. Can be called with a block too,
45
+ # much like any?, so <tt>people.many? { |p| p.age > 26 }</tt> returns +true+
46
+ # if more than one person is over 26.
47
+ def many?
48
+ cnt = 0
49
+ if block_given?
50
+ any? do |element|
51
+ cnt += 1 if yield element
52
+ cnt > 1
53
+ end
54
+ else
55
+ any? { (cnt += 1) > 1 }
56
+ end
101
57
  end
102
58
 
103
- # The negative of the Enumerable#include?. Returns true if the collection does not include the object.
59
+ # The negative of the <tt>Enumerable#include?</tt>. Returns +true+ if the
60
+ # collection does not include the object.
104
61
  def exclude?(object)
105
62
  !include?(object)
106
63
  end
64
+
65
+ # Returns a copy of the enumerable without the specified elements.
66
+ #
67
+ # ["David", "Rafael", "Aaron", "Todd"].without "Aaron", "Todd"
68
+ # => ["David", "Rafael"]
69
+ #
70
+ # {foo: 1, bar: 2, baz: 3}.without :bar
71
+ # => {foo: 1, baz: 3}
72
+ def without(*elements)
73
+ reject { |element| elements.include?(element) }
74
+ end
75
+
76
+ # Convert an enumerable to an array based on the given key.
77
+ #
78
+ # [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
79
+ # => ["David", "Rafael", "Aaron"]
80
+ #
81
+ # [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pluck(:id, :name)
82
+ # => [[1, "David"], [2, "Rafael"]]
83
+ def pluck(*keys)
84
+ if keys.many?
85
+ map { |element| keys.map { |key| element[key] } }
86
+ else
87
+ map { |element| element[keys.first] }
88
+ end
89
+ end
107
90
  end
108
91
 
109
92
  class Range #:nodoc:
110
93
  # Optimize range sum to use arithmetic progression if a block is not given and
111
94
  # we have a range of numeric values.
112
- def sum(identity = 0)
113
- return super if block_given? || !(first.instance_of?(Integer) && last.instance_of?(Integer))
114
- actual_last = exclude_end? ? (last - 1) : last
115
- (actual_last - first + 1) * (actual_last + first) / 2
95
+ def sum(identity = nil)
96
+ if block_given? || !(first.is_a?(Integer) && last.is_a?(Integer))
97
+ super
98
+ else
99
+ actual_last = exclude_end? ? (last - 1) : last
100
+ if actual_last >= first
101
+ sum = identity || 0
102
+ sum + (actual_last - first + 1) * (actual_last + first) / 2
103
+ else
104
+ identity || 0
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ # Array#sum was added in Ruby 2.4 but it only works with Numeric elements.
111
+ #
112
+ # We tried shimming it to attempt the fast native method, rescue TypeError,
113
+ # and fall back to the compatible implementation, but that's much slower than
114
+ # just calling the compat method in the first place.
115
+ if Array.instance_methods(false).include?(:sum) && !(%w[a].sum rescue false)
116
+ class Array
117
+ remove_method :sum
118
+
119
+ def sum(*args) #:nodoc:
120
+ # Use Enumerable#sum instead.
121
+ super
122
+ end
116
123
  end
117
124
  end
@@ -1,41 +1,68 @@
1
+ require 'fileutils'
2
+
1
3
  class File
2
- # Write to a file atomically. Useful for situations where you don't
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
- # If your temp directory is not on the same filesystem as the file you're
10
- # trying to write, you can provide a different temporary directory.
11
+ # This method needs to create a temporary file. By default it will create it
12
+ # in the same directory as the destination file. If you don't like this
13
+ # behavior you can provide a different directory but it must be on the
14
+ # same physical filesystem as the file you're trying to write.
11
15
  #
12
- # File.atomic_write("/data/something.important", "/data/tmp") do |file|
13
- # file.write("hello")
16
+ # File.atomic_write('/data/something.important', '/data/tmp') do |file|
17
+ # file.write('hello')
14
18
  # end
15
- def self.atomic_write(file_name, temp_dir = Dir.tmpdir)
19
+ def self.atomic_write(file_name, temp_dir = dirname(file_name))
16
20
  require 'tempfile' unless defined?(Tempfile)
17
- require 'fileutils' unless defined?(FileUtils)
18
21
 
19
- temp_file = Tempfile.new(basename(file_name), temp_dir)
20
- yield temp_file
21
- temp_file.close
22
+ Tempfile.open(".#{basename(file_name)}", temp_dir) do |temp_file|
23
+ temp_file.binmode
24
+ return_val = yield temp_file
25
+ temp_file.close
26
+
27
+ old_stat = if exist?(file_name)
28
+ # Get original file permissions
29
+ stat(file_name)
30
+ elsif temp_dir != dirname(file_name)
31
+ # If not possible, probe which are the default permissions in the
32
+ # destination directory.
33
+ probe_stat_in(dirname(file_name))
34
+ end
22
35
 
23
- begin
24
- # Get original file permissions
25
- old_stat = stat(file_name)
26
- rescue Errno::ENOENT
27
- # No old permissions, write a temp file to determine the defaults
28
- check_name = join(dirname(file_name), ".permissions_check.#{Thread.current.object_id}.#{Process.pid}.#{rand(1000000)}")
29
- open(check_name, "w") { }
30
- old_stat = stat(check_name)
31
- unlink(check_name)
36
+ if old_stat
37
+ # Set correct permissions on new file
38
+ begin
39
+ chown(old_stat.uid, old_stat.gid, temp_file.path)
40
+ # This operation will affect filesystem ACL's
41
+ chmod(old_stat.mode, temp_file.path)
42
+ rescue Errno::EPERM, Errno::EACCES
43
+ # Changing file ownership failed, moving on.
44
+ end
45
+ end
46
+
47
+ # Overwrite original file with temp file
48
+ rename(temp_file.path, file_name)
49
+ return_val
32
50
  end
51
+ end
33
52
 
34
- # Overwrite original file with temp file
35
- FileUtils.mv(temp_file.path, file_name)
53
+ # Private utility method.
54
+ def self.probe_stat_in(dir) #:nodoc:
55
+ basename = [
56
+ '.permissions_check',
57
+ Thread.current.object_id,
58
+ Process.pid,
59
+ rand(1000000)
60
+ ].join('.')
36
61
 
37
- # Set correct permissions on new file
38
- chown(old_stat.uid, old_stat.gid, file_name)
39
- chmod(old_stat.mode, file_name)
62
+ file_name = join(dir, basename)
63
+ FileUtils.touch(file_name)
64
+ stat(file_name)
65
+ ensure
66
+ FileUtils.rm_f(file_name) if file_name
40
67
  end
41
68
  end
@@ -1,2 +1 @@
1
1
  require 'active_support/core_ext/file/atomic'
2
- require 'active_support/core_ext/file/path'
@@ -0,0 +1,20 @@
1
+ class Hash
2
+ # Returns a hash with non +nil+ values.
3
+ #
4
+ # hash = { a: true, b: false, c: nil}
5
+ # hash.compact # => { a: true, b: false}
6
+ # hash # => { a: true, b: false, c: nil}
7
+ # { c: nil }.compact # => {}
8
+ def compact
9
+ self.select { |_, value| !value.nil? }
10
+ end
11
+
12
+ # Replaces current hash with non +nil+ values.
13
+ #
14
+ # hash = { a: true, b: false, c: nil}
15
+ # hash.compact! # => { a: true, b: false}
16
+ # hash # => { a: true, b: false}
17
+ def compact!
18
+ self.reject! { |_, value| value.nil? }
19
+ end
20
+ end