activesupport 4.0.13 → 5.2.5

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