activesupport 4.2.8 → 5.2.6

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 (256) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +424 -373
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  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 +7 -5
  8. data/lib/active_support/benchmarkable.rb +6 -4
  9. data/lib/active_support/builder.rb +3 -1
  10. data/lib/active_support/cache/file_store.rb +41 -35
  11. data/lib/active_support/cache/mem_cache_store.rb +91 -91
  12. data/lib/active_support/cache/memory_store.rb +27 -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 +67 -34
  16. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  17. data/lib/active_support/cache.rb +287 -196
  18. data/lib/active_support/callbacks.rb +640 -590
  19. data/lib/active_support/concern.rb +11 -5
  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 +29 -1
  24. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  25. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  26. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  27. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  28. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  29. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  30. data/lib/active_support/core_ext/array.rb +9 -6
  31. data/lib/active_support/core_ext/benchmark.rb +3 -1
  32. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  33. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  34. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  35. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  36. data/lib/active_support/core_ext/class/subclasses.rb +20 -6
  37. data/lib/active_support/core_ext/class.rb +4 -3
  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 +11 -9
  41. data/lib/active_support/core_ext/date/conversions.rb +25 -23
  42. data/lib/active_support/core_ext/date/zones.rb +4 -2
  43. data/lib/active_support/core_ext/date.rb +6 -4
  44. data/lib/active_support/core_ext/date_and_time/calculations.rb +170 -58
  45. data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -17
  46. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  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 +29 -16
  50. data/lib/active_support/core_ext/date_time/compatibility.rb +14 -1
  51. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  52. data/lib/active_support/core_ext/date_time.rb +7 -5
  53. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  54. data/lib/active_support/core_ext/digest.rb +3 -0
  55. data/lib/active_support/core_ext/enumerable.rb +101 -33
  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 +14 -9
  59. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  60. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  61. data/lib/active_support/core_ext/hash/except.rb +11 -8
  62. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  63. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  64. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  65. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  66. data/lib/active_support/core_ext/hash/transform_values.rb +14 -5
  67. data/lib/active_support/core_ext/hash.rb +11 -9
  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 -18
  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 +5 -1
  74. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +6 -5
  77. data/lib/active_support/core_ext/load_error.rb +3 -22
  78. data/lib/active_support/core_ext/marshal.rb +8 -8
  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 -9
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  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 +11 -12
  85. data/lib/active_support/core_ext/module/delegation.rb +99 -29
  86. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  87. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  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 -11
  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 +78 -81
  95. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  96. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  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 +27 -2
  100. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  101. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  102. data/lib/active_support/core_ext/object/duplicable.rb +41 -14
  103. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  104. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  105. data/lib/active_support/core_ext/object/json.rb +49 -19
  106. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  107. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  108. data/lib/active_support/core_ext/object/try.rb +69 -21
  109. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  110. data/lib/active_support/core_ext/object.rb +14 -13
  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 +8 -6
  121. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  122. data/lib/active_support/core_ext/string/conversions.rb +7 -4
  123. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  124. data/lib/active_support/core_ext/string/filters.rb +6 -5
  125. data/lib/active_support/core_ext/string/indent.rb +6 -4
  126. data/lib/active_support/core_ext/string/inflections.rb +61 -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 +34 -38
  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 -2
  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 +88 -52
  136. data/lib/active_support/core_ext/time/compatibility.rb +12 -1
  137. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  138. data/lib/active_support/core_ext/time/zones.rb +41 -7
  139. data/lib/active_support/core_ext/time.rb +7 -6
  140. data/lib/active_support/core_ext/uri.rb +6 -8
  141. data/lib/active_support/core_ext.rb +3 -1
  142. data/lib/active_support/current_attributes.rb +195 -0
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/dependencies.rb +152 -161
  146. data/lib/active_support/deprecation/behaviors.rb +44 -11
  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 +12 -9
  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 +314 -38
  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 +5 -3
  165. data/lib/active_support/gzip.rb +7 -5
  166. data/lib/active_support/hash_with_indifferent_access.rb +127 -28
  167. data/lib/active_support/i18n.rb +8 -6
  168. data/lib/active_support/i18n_railtie.rb +37 -13
  169. data/lib/active_support/inflections.rb +13 -11
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +163 -136
  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 +16 -13
  175. data/lib/active_support/json/encoding.rb +11 -58
  176. data/lib/active_support/json.rb +4 -2
  177. data/lib/active_support/key_generator.rb +25 -25
  178. data/lib/active_support/lazy_load_hooks.rb +50 -20
  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 +19 -7
  183. data/lib/active_support/logger_silence.rb +6 -4
  184. data/lib/active_support/logger_thread_safe_level.rb +7 -5
  185. data/lib/active_support/message_encryptor.rb +168 -53
  186. data/lib/active_support/message_verifier.rb +150 -17
  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 +36 -23
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/multibyte.rb +4 -2
  193. data/lib/active_support/notifications/fanout.rb +11 -9
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/notifications.rb +11 -7
  196. data/lib/active_support/number_helper/number_converter.rb +13 -11
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/number_helper.rb +94 -68
  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 +23 -5
  209. data/lib/active_support/per_thread_registry.rb +9 -4
  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 +15 -11
  216. data/lib/active_support/string_inquirer.rb +11 -3
  217. data/lib/active_support/subscriber.rb +21 -16
  218. data/lib/active_support/tagged_logging.rb +14 -11
  219. data/lib/active_support/test_case.rb +19 -47
  220. data/lib/active_support/testing/assertions.rb +137 -20
  221. data/lib/active_support/testing/autorun.rb +4 -2
  222. data/lib/active_support/testing/constant_lookup.rb +2 -1
  223. data/lib/active_support/testing/declarative.rb +3 -1
  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 +34 -25
  227. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  228. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  229. data/lib/active_support/testing/stream.rb +44 -0
  230. data/lib/active_support/testing/tagged_logging.rb +3 -1
  231. data/lib/active_support/testing/time_helpers.rb +91 -23
  232. data/lib/active_support/time.rb +14 -12
  233. data/lib/active_support/time_with_zone.rb +182 -40
  234. data/lib/active_support/values/time_zone.rb +196 -61
  235. data/lib/active_support/values/unicode_tables.dat +0 -0
  236. data/lib/active_support/version.rb +3 -1
  237. data/lib/active_support/xml_mini/jdom.rb +116 -114
  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 +11 -9
  243. data/lib/active_support/xml_mini.rb +37 -37
  244. data/lib/active_support.rb +12 -11
  245. metadata +54 -25
  246. data/lib/active_support/concurrency/latch.rb +0 -27
  247. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  248. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  249. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  250. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  251. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  252. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  253. data/lib/active_support/core_ext/object/itself.rb +0 -15
  254. data/lib/active_support/core_ext/struct.rb +0 -6
  255. data/lib/active_support/core_ext/thread.rb +0 -86
  256. data/lib/active_support/core_ext/time/marshal.rb +0 -30
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2005-2014 David Heinemeier Hansson
1
+ Copyright (c) 2005-2018 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
17
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
18
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
19
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc CHANGED
@@ -10,18 +10,18 @@ outside of Rails.
10
10
 
11
11
  The latest version of Active Support can be installed with RubyGems:
12
12
 
13
- % [sudo] gem install activesupport
13
+ $ gem install activesupport
14
14
 
15
15
  Source code can be downloaded as part of the Rails project on GitHub:
16
16
 
17
- * https://github.com/rails/rails/tree/4-2-stable/activesupport
17
+ * https://github.com/rails/rails/tree/5-2-stable/activesupport
18
18
 
19
19
 
20
20
  == License
21
21
 
22
22
  Active Support is released under the MIT license:
23
23
 
24
- * http://www.opensource.org/licenses/MIT
24
+ * https://opensource.org/licenses/MIT
25
25
 
26
26
 
27
27
  == Support
@@ -30,11 +30,10 @@ API documentation is at:
30
30
 
31
31
  * http://api.rubyonrails.org
32
32
 
33
- Bug reports can be filed for the Ruby on Rails project here:
33
+ Bug reports for the Ruby on Rails project can be filed here:
34
34
 
35
35
  * https://github.com/rails/rails/issues
36
36
 
37
37
  Feature requests should be discussed on the rails-core mailing list here:
38
38
 
39
39
  * https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
40
-
@@ -1,3 +1,5 @@
1
- require 'active_support'
2
- require 'active_support/time'
3
- require 'active_support/core_ext'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+ require "active_support/time"
5
+ require "active_support/core_ext"
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # Wrapping an array in an +ArrayInquirer+ gives a friendlier way to check
5
+ # its string-like contents:
6
+ #
7
+ # variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
8
+ #
9
+ # variants.phone? # => true
10
+ # variants.tablet? # => true
11
+ # variants.desktop? # => false
12
+ class ArrayInquirer < Array
13
+ # Passes each element of +candidates+ collection to ArrayInquirer collection.
14
+ # The method returns true if any element from the ArrayInquirer collection
15
+ # is equal to the stringified or symbolized form of any element in the +candidates+ collection.
16
+ #
17
+ # If +candidates+ collection is not given, method returns true.
18
+ #
19
+ # variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
20
+ #
21
+ # variants.any? # => true
22
+ # variants.any?(:phone, :tablet) # => true
23
+ # variants.any?('phone', 'desktop') # => true
24
+ # variants.any?(:desktop, :watch) # => false
25
+ def any?(*candidates)
26
+ if candidates.none?
27
+ super
28
+ else
29
+ candidates.any? do |candidate|
30
+ include?(candidate.to_sym) || include?(candidate.to_s)
31
+ end
32
+ end
33
+ end
34
+
35
+ private
36
+ def respond_to_missing?(name, include_private = false)
37
+ (name[-1] == "?") || super
38
+ end
39
+
40
+ def method_missing(name, *args)
41
+ if name[-1] == "?"
42
+ any?(name[0..-2])
43
+ else
44
+ super
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  # Backtraces often include many lines that are not relevant for the context
3
5
  # under review. This makes it hard to find the signal amongst the backtrace
@@ -12,9 +14,9 @@ module ActiveSupport
12
14
  # is to exclude the output of a noisy library from the backtrace, so that you
13
15
  # can focus on the rest.
14
16
  #
15
- # bc = BacktraceCleaner.new
17
+ # bc = ActiveSupport::BacktraceCleaner.new
16
18
  # bc.add_filter { |line| line.gsub(Rails.root.to_s, '') } # strip the Rails.root prefix
17
- # bc.add_silencer { |line| line =~ /mongrel|rubygems/ } # skip any lines from mongrel or rubygems
19
+ # bc.add_silencer { |line| line =~ /puma|rubygems/ } # skip any lines from puma or rubygems
18
20
  # bc.clean(exception.backtrace) # perform the cleanup
19
21
  #
20
22
  # To reconfigure an existing BacktraceCleaner (like the default one in Rails)
@@ -25,7 +27,7 @@ module ActiveSupport
25
27
  # of the backtrace, you can call <tt>BacktraceCleaner#remove_filters!</tt>
26
28
  # These two methods will give you a completely untouched backtrace.
27
29
  #
28
- # Inspired by the Quiet Backtrace gem by Thoughtbot.
30
+ # Inspired by the Quiet Backtrace gem by thoughtbot.
29
31
  class BacktraceCleaner
30
32
  def initialize
31
33
  @filters, @silencers = [], []
@@ -59,8 +61,8 @@ module ActiveSupport
59
61
  # Adds a silencer from the block provided. If the silencer returns +true+
60
62
  # for a given line, it will be excluded from the clean backtrace.
61
63
  #
62
- # # Will reject all lines that include the word "mongrel", like "/gems/mongrel/server.rb" or "/app/my_mongrel_server/rb"
63
- # backtrace_cleaner.add_silencer { |line| line =~ /mongrel/ }
64
+ # # Will reject all lines that include the word "puma", like "/gems/puma/server.rb" or "/app/my_puma_server/rb"
65
+ # backtrace_cleaner.add_silencer { |line| line =~ /puma/ }
64
66
  def add_silencer(&block)
65
67
  @silencers << block
66
68
  end
@@ -1,5 +1,7 @@
1
- require 'active_support/core_ext/benchmark'
2
- require 'active_support/core_ext/hash/keys'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/benchmark"
4
+ require "active_support/core_ext/hash/keys"
3
5
 
4
6
  module ActiveSupport
5
7
  module Benchmarkable
@@ -38,8 +40,8 @@ module ActiveSupport
38
40
  options[:level] ||= :info
39
41
 
40
42
  result = nil
41
- ms = Benchmark.ms { result = options[:silence] ? silence { yield } : yield }
42
- logger.send(options[:level], '%s (%.1fms)' % [ message, ms ])
43
+ ms = Benchmark.ms { result = options[:silence] ? logger.silence { yield } : yield }
44
+ logger.send(options[:level], "%s (%.1fms)" % [ message, ms ])
43
45
  result
44
46
  else
45
47
  yield
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
- require 'builder'
4
+ require "builder"
3
5
  rescue LoadError => e
4
6
  $stderr.puts "You don't have builder installed in your application. Please add it to your Gemfile and run bundle install"
5
7
  raise e
@@ -1,7 +1,9 @@
1
- require 'active_support/core_ext/marshal'
2
- require 'active_support/core_ext/file/atomic'
3
- require 'active_support/core_ext/string/conversions'
4
- require 'uri/common'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/marshal"
4
+ require "active_support/core_ext/file/atomic"
5
+ require "active_support/core_ext/string/conversions"
6
+ require "uri/common"
5
7
 
6
8
  module ActiveSupport
7
9
  module Cache
@@ -10,34 +12,35 @@ module ActiveSupport
10
12
  # FileStore implements the Strategy::LocalCache strategy which implements
11
13
  # an in-memory cache inside of a block.
12
14
  class FileStore < Store
15
+ prepend Strategy::LocalCache
13
16
  attr_reader :cache_path
14
17
 
15
18
  DIR_FORMATTER = "%03X"
16
19
  FILENAME_MAX_SIZE = 228 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write)
17
20
  FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room
18
- EXCLUDED_DIRS = ['.', '..'].freeze
21
+ EXCLUDED_DIRS = [".", ".."].freeze
22
+ GITKEEP_FILES = [".gitkeep", ".keep"].freeze
19
23
 
20
24
  def initialize(cache_path, options = nil)
21
25
  super(options)
22
26
  @cache_path = cache_path.to_s
23
- extend Strategy::LocalCache
24
27
  end
25
28
 
26
29
  # Deletes all items from the cache. In this case it deletes all the entries in the specified
27
- # file store directory except for .gitkeep. Be careful which directory is specified in your
30
+ # file store directory except for .keep or .gitkeep. Be careful which directory is specified in your
28
31
  # config file when using +FileStore+ because everything in that directory will be deleted.
29
32
  def clear(options = nil)
30
- root_dirs = Dir.entries(cache_path).reject {|f| (EXCLUDED_DIRS + [".gitkeep"]).include?(f)}
31
- FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)})
33
+ root_dirs = exclude_from(cache_path, EXCLUDED_DIRS + GITKEEP_FILES)
34
+ FileUtils.rm_r(root_dirs.collect { |f| File.join(cache_path, f) })
35
+ rescue Errno::ENOENT
32
36
  end
33
37
 
34
38
  # Preemptively iterates through all stored keys and removes the ones which have expired.
35
39
  def cleanup(options = nil)
36
40
  options = merged_options(options)
37
41
  search_dir(cache_path) do |fname|
38
- key = file_path_key(fname)
39
- entry = read_entry(key, options)
40
- delete_entry(key, options) if entry && entry.expired?
42
+ entry = read_entry(fname, options)
43
+ delete_entry(fname, options) if entry && entry.expired?
41
44
  end
42
45
  end
43
46
 
@@ -59,17 +62,16 @@ module ActiveSupport
59
62
  matcher = key_matcher(matcher, options)
60
63
  search_dir(cache_path) do |path|
61
64
  key = file_path_key(path)
62
- delete_entry(key, options) if key.match(matcher)
65
+ delete_entry(path, options) if key.match(matcher)
63
66
  end
64
67
  end
65
68
  end
66
69
 
67
- protected
70
+ private
68
71
 
69
72
  def read_entry(key, options)
70
- file_name = key_file_path(key)
71
- if File.exist?(file_name)
72
- File.open(file_name) { |f| Marshal.load(f) }
73
+ if File.exist?(key)
74
+ File.open(key) { |f| Marshal.load(f) }
73
75
  end
74
76
  rescue => e
75
77
  logger.error("FileStoreError (#{e}): #{e.message}") if logger
@@ -77,33 +79,30 @@ module ActiveSupport
77
79
  end
78
80
 
79
81
  def write_entry(key, entry, options)
80
- file_name = key_file_path(key)
81
- return false if options[:unless_exist] && File.exist?(file_name)
82
- ensure_cache_path(File.dirname(file_name))
83
- File.atomic_write(file_name, cache_path) {|f| Marshal.dump(entry, f)}
82
+ return false if options[:unless_exist] && File.exist?(key)
83
+ ensure_cache_path(File.dirname(key))
84
+ File.atomic_write(key, cache_path) { |f| Marshal.dump(entry, f) }
84
85
  true
85
86
  end
86
87
 
87
88
  def delete_entry(key, options)
88
- file_name = key_file_path(key)
89
- if File.exist?(file_name)
89
+ if File.exist?(key)
90
90
  begin
91
- File.delete(file_name)
92
- delete_empty_directories(File.dirname(file_name))
91
+ File.delete(key)
92
+ delete_empty_directories(File.dirname(key))
93
93
  true
94
94
  rescue => e
95
95
  # Just in case the error was caused by another process deleting the file first.
96
- raise e if File.exist?(file_name)
96
+ raise e if File.exist?(key)
97
97
  false
98
98
  end
99
99
  end
100
100
  end
101
101
 
102
- private
103
102
  # Lock a file for a block so only one process can modify it at a time.
104
- def lock_file(file_name, &block) # :nodoc:
103
+ def lock_file(file_name, &block)
105
104
  if File.exist?(file_name)
106
- File.open(file_name, 'r+') do |f|
105
+ File.open(file_name, "r+") do |f|
107
106
  begin
108
107
  f.flock File::LOCK_EX
109
108
  yield
@@ -117,12 +116,14 @@ module ActiveSupport
117
116
  end
118
117
 
119
118
  # Translate a key into a file path.
120
- def key_file_path(key)
121
- if key.size > FILEPATH_MAX_SIZE
122
- key = Digest::MD5.hexdigest(key)
119
+ def normalize_key(key, options)
120
+ key = super
121
+ fname = URI.encode_www_form_component(key)
122
+
123
+ if fname.size > FILEPATH_MAX_SIZE
124
+ fname = ActiveSupport::Digest.hexdigest(key)
123
125
  end
124
126
 
125
- fname = URI.encode_www_form_component(key)
126
127
  hash = Zlib.adler32(fname)
127
128
  hash, dir_1 = hash.divmod(0x1000)
128
129
  dir_2 = hash.modulo(0x1000)
@@ -146,7 +147,7 @@ module ActiveSupport
146
147
  # Delete empty directories in the cache.
147
148
  def delete_empty_directories(dir)
148
149
  return if File.realpath(dir) == File.realpath(cache_path)
149
- if Dir.entries(dir).reject {|f| EXCLUDED_DIRS.include?(f)}.empty?
150
+ if exclude_from(dir, EXCLUDED_DIRS).empty?
150
151
  Dir.delete(dir) rescue nil
151
152
  delete_empty_directories(File.dirname(dir))
152
153
  end
@@ -173,7 +174,7 @@ module ActiveSupport
173
174
  # Modifies the amount of an already existing integer value that is stored in the cache.
174
175
  # If the key is not found nothing is done.
175
176
  def modify_value(name, amount, options)
176
- file_name = key_file_path(namespaced_key(name, options))
177
+ file_name = normalize_key(name, options)
177
178
 
178
179
  lock_file(file_name) do
179
180
  options = merged_options(options)
@@ -185,6 +186,11 @@ module ActiveSupport
185
186
  end
186
187
  end
187
188
  end
189
+
190
+ # Exclude entries from source directory
191
+ def exclude_from(source, excludes)
192
+ Dir.entries(source).reject { |f| excludes.include?(f) }
193
+ end
188
194
  end
189
195
  end
190
196
  end
@@ -1,18 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
- require 'dalli'
4
+ require "dalli"
3
5
  rescue LoadError => e
4
6
  $stderr.puts "You don't have dalli installed in your application. Please add it to your Gemfile and run bundle install"
5
7
  raise e
6
8
  end
7
9
 
8
- require 'digest/md5'
9
- require 'active_support/core_ext/marshal'
10
- require 'active_support/core_ext/array/extract_options'
10
+ require "active_support/core_ext/marshal"
11
+ require "active_support/core_ext/array/extract_options"
11
12
 
12
13
  module ActiveSupport
13
14
  module Cache
14
15
  # A cache store implementation which stores data in Memcached:
15
- # http://memcached.org/
16
+ # https://memcached.org
16
17
  #
17
18
  # This is currently the most popular cache store for production websites.
18
19
  #
@@ -24,13 +25,44 @@ module ActiveSupport
24
25
  # MemCacheStore implements the Strategy::LocalCache strategy which implements
25
26
  # an in-memory cache inside of a block.
26
27
  class MemCacheStore < Store
28
+ # Provide support for raw values in the local cache strategy.
29
+ module LocalCacheWithRaw # :nodoc:
30
+ private
31
+ def write_entry(key, entry, options)
32
+ if options[:raw] && local_cache
33
+ raw_entry = Entry.new(entry.value.to_s)
34
+ raw_entry.expires_at = entry.expires_at
35
+ super(key, raw_entry, options)
36
+ else
37
+ super
38
+ end
39
+ end
40
+ end
41
+
42
+ prepend Strategy::LocalCache
43
+ prepend LocalCacheWithRaw
44
+
27
45
  ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/n
28
46
 
29
- def self.build_mem_cache(*addresses)
47
+ # Creates a new Dalli::Client instance with specified addresses and options.
48
+ # By default address is equal localhost:11211.
49
+ #
50
+ # ActiveSupport::Cache::MemCacheStore.build_mem_cache
51
+ # # => #<Dalli::Client:0x007f98a47d2028 @servers=["localhost:11211"], @options={}, @ring=nil>
52
+ # ActiveSupport::Cache::MemCacheStore.build_mem_cache('localhost:10290')
53
+ # # => #<Dalli::Client:0x007f98a47b3a60 @servers=["localhost:10290"], @options={}, @ring=nil>
54
+ def self.build_mem_cache(*addresses) # :nodoc:
30
55
  addresses = addresses.flatten
31
56
  options = addresses.extract_options!
32
57
  addresses = ["localhost:11211"] if addresses.empty?
33
- Dalli::Client.new(addresses, options)
58
+ pool_options = retrieve_pool_options(options)
59
+
60
+ if pool_options.empty?
61
+ Dalli::Client.new(addresses, options)
62
+ else
63
+ ensure_connection_pool_added!
64
+ ConnectionPool.new(pool_options) { Dalli::Client.new(addresses, options.merge(threadsafe: false)) }
65
+ end
34
66
  end
35
67
 
36
68
  # Creates a new MemCacheStore object, with the given memcached server
@@ -53,82 +85,56 @@ module ActiveSupport
53
85
  @data = addresses.first
54
86
  else
55
87
  mem_cache_options = options.dup
56
- UNIVERSAL_OPTIONS.each{|name| mem_cache_options.delete(name)}
88
+ UNIVERSAL_OPTIONS.each { |name| mem_cache_options.delete(name) }
57
89
  @data = self.class.build_mem_cache(*(addresses + [mem_cache_options]))
58
90
  end
59
-
60
- extend Strategy::LocalCache
61
- extend LocalCacheWithRaw
62
- end
63
-
64
- # Reads multiple values from the cache using a single call to the
65
- # servers for all keys. Options can be passed in the last argument.
66
- def read_multi(*names)
67
- options = names.extract_options!
68
- options = merged_options(options)
69
- keys_to_names = Hash[names.map{|name| [escape_key(namespaced_key(name, options)), name]}]
70
- raw_values = @data.get_multi(keys_to_names.keys)
71
- values = {}
72
- raw_values.each do |key, value|
73
- entry = deserialize_entry(value)
74
- values[keys_to_names[key]] = entry.value unless entry.expired?
75
- end
76
- values
77
91
  end
78
92
 
79
93
  # Increment a cached value. This method uses the memcached incr atomic
80
94
  # operator and can only be used on values written with the :raw option.
81
95
  # Calling it on a value not stored with :raw will initialize that value
82
96
  # to zero.
83
- def increment(name, amount = 1, options = nil) # :nodoc:
97
+ def increment(name, amount = 1, options = nil)
84
98
  options = merged_options(options)
85
- instrument(:increment, name, :amount => amount) do
86
- @data.incr(escape_key(namespaced_key(name, options)), amount)
99
+ instrument(:increment, name, amount: amount) do
100
+ rescue_error_with nil do
101
+ @data.with { |c| c.incr(normalize_key(name, options), amount, options[:expires_in]) }
102
+ end
87
103
  end
88
- rescue Dalli::DalliError => e
89
- logger.error("DalliError (#{e}): #{e.message}") if logger
90
- nil
91
104
  end
92
105
 
93
106
  # Decrement a cached value. This method uses the memcached decr atomic
94
107
  # operator and can only be used on values written with the :raw option.
95
108
  # Calling it on a value not stored with :raw will initialize that value
96
109
  # to zero.
97
- def decrement(name, amount = 1, options = nil) # :nodoc:
110
+ def decrement(name, amount = 1, options = nil)
98
111
  options = merged_options(options)
99
- instrument(:decrement, name, :amount => amount) do
100
- @data.decr(escape_key(namespaced_key(name, options)), amount)
112
+ instrument(:decrement, name, amount: amount) do
113
+ rescue_error_with nil do
114
+ @data.with { |c| c.decr(normalize_key(name, options), amount, options[:expires_in]) }
115
+ end
101
116
  end
102
- rescue Dalli::DalliError => e
103
- logger.error("DalliError (#{e}): #{e.message}") if logger
104
- nil
105
117
  end
106
118
 
107
119
  # Clear the entire cache on all memcached servers. This method should
108
120
  # be used with care when shared cache is being used.
109
121
  def clear(options = nil)
110
- @data.flush_all
111
- rescue Dalli::DalliError => e
112
- logger.error("DalliError (#{e}): #{e.message}") if logger
113
- nil
122
+ rescue_error_with(nil) { @data.with { |c| c.flush_all } }
114
123
  end
115
124
 
116
125
  # Get the statistics from the memcached servers.
117
126
  def stats
118
- @data.stats
127
+ @data.with { |c| c.stats }
119
128
  end
120
129
 
121
- protected
130
+ private
122
131
  # Read an entry from the cache.
123
- def read_entry(key, options) # :nodoc:
124
- deserialize_entry(@data.get(escape_key(key), options))
125
- rescue Dalli::DalliError => e
126
- logger.error("DalliError (#{e}): #{e.message}") if logger
127
- nil
132
+ def read_entry(key, options)
133
+ rescue_error_with(nil) { deserialize_entry(@data.with { |c| c.get(key, options) }) }
128
134
  end
129
135
 
130
136
  # Write an entry to the cache.
131
- def write_entry(key, entry, options) # :nodoc:
137
+ def write_entry(key, entry, options)
132
138
  method = options && options[:unless_exist] ? :add : :set
133
139
  value = options[:raw] ? entry.value.to_s : entry
134
140
  expires_in = options[:expires_in].to_i
@@ -136,63 +142,57 @@ module ActiveSupport
136
142
  # Set the memcache expire a few minutes in the future to support race condition ttls on read
137
143
  expires_in += 5.minutes
138
144
  end
139
- @data.send(method, escape_key(key), value, expires_in, options)
140
- rescue Dalli::DalliError => e
141
- logger.error("DalliError (#{e}): #{e.message}") if logger
142
- false
145
+ rescue_error_with false do
146
+ @data.with { |c| c.send(method, key, value, expires_in, options) }
147
+ end
143
148
  end
144
149
 
145
- # Delete an entry from the cache.
146
- def delete_entry(key, options) # :nodoc:
147
- @data.delete(escape_key(key))
148
- rescue Dalli::DalliError => e
149
- logger.error("DalliError (#{e}): #{e.message}") if logger
150
- false
150
+ # Reads multiple entries from the cache implementation.
151
+ def read_multi_entries(names, options)
152
+ keys_to_names = Hash[names.map { |name| [normalize_key(name, options), name] }]
153
+
154
+ raw_values = @data.with { |c| c.get_multi(keys_to_names.keys) }
155
+ values = {}
156
+
157
+ raw_values.each do |key, value|
158
+ entry = deserialize_entry(value)
159
+
160
+ unless entry.expired? || entry.mismatched?(normalize_version(keys_to_names[key], options))
161
+ values[keys_to_names[key]] = entry.value
162
+ end
163
+ end
164
+
165
+ values
151
166
  end
152
167
 
153
- private
168
+ # Delete an entry from the cache.
169
+ def delete_entry(key, options)
170
+ rescue_error_with(false) { @data.with { |c| c.delete(key) } }
171
+ end
154
172
 
155
173
  # Memcache keys are binaries. So we need to force their encoding to binary
156
174
  # before applying the regular expression to ensure we are escaping all
157
175
  # characters properly.
158
- def escape_key(key)
159
- key = key.to_s.dup
176
+ def normalize_key(key, options)
177
+ key = super.dup
160
178
  key = key.force_encoding(Encoding::ASCII_8BIT)
161
- key = key.gsub(ESCAPE_KEY_CHARS){ |match| "%#{match.getbyte(0).to_s(16).upcase}" }
162
- key = "#{key[0, 213]}:md5:#{Digest::MD5.hexdigest(key)}" if key.size > 250
179
+ key = key.gsub(ESCAPE_KEY_CHARS) { |match| "%#{match.getbyte(0).to_s(16).upcase}" }
180
+ key = "#{key[0, 213]}:md5:#{ActiveSupport::Digest.hexdigest(key)}" if key.size > 250
163
181
  key
164
182
  end
165
183
 
166
- def deserialize_entry(raw_value)
167
- if raw_value
168
- entry = Marshal.load(raw_value) rescue raw_value
184
+ def deserialize_entry(entry)
185
+ if entry
169
186
  entry.is_a?(Entry) ? entry : Entry.new(entry)
170
- else
171
- nil
172
187
  end
173
188
  end
174
189
 
175
- # Provide support for raw values in the local cache strategy.
176
- module LocalCacheWithRaw # :nodoc:
177
- protected
178
- def read_entry(key, options)
179
- entry = super
180
- if options[:raw] && local_cache && entry
181
- entry = deserialize_entry(entry.value)
182
- end
183
- entry
184
- end
185
-
186
- def write_entry(key, entry, options) # :nodoc:
187
- retval = super
188
- if options[:raw] && local_cache && retval
189
- raw_entry = Entry.new(entry.value.to_s)
190
- raw_entry.expires_at = entry.expires_at
191
- local_cache.write_entry(key, raw_entry, options)
192
- end
193
- retval
194
- end
195
- end
190
+ def rescue_error_with(fallback)
191
+ yield
192
+ rescue Dalli::DalliError => e
193
+ logger.error("DalliError (#{e}): #{e.message}") if logger
194
+ fallback
195
+ end
196
196
  end
197
197
  end
198
198
  end