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
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2005-2016 David Heinemeier Hansson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
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.
data/README.rdoc CHANGED
@@ -8,26 +8,32 @@ outside of Rails.
8
8
 
9
9
  == Download and installation
10
10
 
11
- The latest version of Active Support can be installed with Rubygems:
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
- Source code can be downloaded as part of the Rails project on GitHub
15
+ Source code can be downloaded as part of the Rails project on GitHub:
16
16
 
17
17
  * https://github.com/rails/rails/tree/master/activesupport
18
18
 
19
19
 
20
20
  == License
21
21
 
22
- Active Support is released under the MIT license.
22
+ Active Support is released under the MIT license:
23
+
24
+ * http://www.opensource.org/licenses/MIT
23
25
 
24
26
 
25
27
  == Support
26
28
 
27
- API documentation is at
29
+ API documentation is at:
28
30
 
29
- * http://api.rubyonrails.com
31
+ * http://api.rubyonrails.org
30
32
 
31
- Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
33
+ Bug reports can be filed for the Ruby on Rails project here:
32
34
 
33
35
  * https://github.com/rails/rails/issues
36
+
37
+ Feature requests should be discussed on the rails-core mailing list here:
38
+
39
+ * https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
@@ -0,0 +1,44 @@
1
+ module ActiveSupport
2
+ # Wrapping an array in an +ArrayInquirer+ gives a friendlier way to check
3
+ # its string-like contents:
4
+ #
5
+ # variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
6
+ #
7
+ # variants.phone? # => true
8
+ # variants.tablet? # => true
9
+ # variants.desktop? # => false
10
+ class ArrayInquirer < Array
11
+ # Passes each element of +candidates+ collection to ArrayInquirer collection.
12
+ # The method returns true if at least one element is the same. If +candidates+
13
+ # collection is not given, method returns true.
14
+ #
15
+ # variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
16
+ #
17
+ # variants.any? # => true
18
+ # variants.any?(:phone, :tablet) # => true
19
+ # variants.any?('phone', 'desktop') # => true
20
+ # variants.any?(:desktop, :watch) # => false
21
+ def any?(*candidates, &block)
22
+ if candidates.none?
23
+ super
24
+ else
25
+ candidates.any? do |candidate|
26
+ include?(candidate.to_sym) || include?(candidate.to_s)
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+ def respond_to_missing?(name, include_private = false)
33
+ name[-1] == '?'
34
+ end
35
+
36
+ def method_missing(name, *args)
37
+ if name[-1] == '?'
38
+ any?(name[0..-2])
39
+ else
40
+ super
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,34 +1,40 @@
1
1
  module ActiveSupport
2
- # Backtraces often include many lines that are not relevant for the context under review. This makes it hard to find the
3
- # signal amongst the backtrace noise, and adds debugging time. With a BacktraceCleaner, filters and silencers are used to
4
- # remove the noisy lines, so that only the most relevant lines remain.
2
+ # Backtraces often include many lines that are not relevant for the context
3
+ # under review. This makes it hard to find the signal amongst the backtrace
4
+ # noise, and adds debugging time. With a BacktraceCleaner, filters and
5
+ # silencers are used to remove the noisy lines, so that only the most relevant
6
+ # lines remain.
5
7
  #
6
- # Filters are used to modify lines of data, while silencers are used to remove lines entirely. The typical filter use case
7
- # is to remove lengthy path information from the start of each line, and view file paths relevant to the app directory
8
- # instead of the file system root. The typical silencer use case is to exclude the output of a noisy library from the
9
- # backtrace, so that you can focus on the rest.
10
- #
11
- # ==== Example:
8
+ # Filters are used to modify lines of data, while silencers are used to remove
9
+ # lines entirely. The typical filter use case is to remove lengthy path
10
+ # information from the start of each line, and view file paths relevant to the
11
+ # app directory instead of the file system root. The typical silencer use case
12
+ # is to exclude the output of a noisy library from the backtrace, so that you
13
+ # can focus on the rest.
12
14
  #
13
15
  # bc = BacktraceCleaner.new
14
- # bc.add_filter { |line| line.gsub(Rails.root, '') }
15
- # bc.add_silencer { |line| line =~ /mongrel|rubygems/ }
16
- # bc.clean(exception.backtrace) # will strip the Rails.root prefix and skip any lines from mongrel or rubygems
16
+ # 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
18
+ # bc.clean(exception.backtrace) # perform the cleanup
17
19
  #
18
- # To reconfigure an existing BacktraceCleaner (like the default one in Rails) and show as much data as possible, you can
19
- # always call <tt>BacktraceCleaner#remove_silencers!</tt>, which will restore the backtrace to a pristine state. If you
20
- # need to reconfigure an existing BacktraceCleaner so that it does not filter or modify the paths of any lines of the
21
- # backtrace, you can call BacktraceCleaner#remove_filters! These two methods will give you a completely untouched backtrace.
20
+ # To reconfigure an existing BacktraceCleaner (like the default one in Rails)
21
+ # and show as much data as possible, you can always call
22
+ # <tt>BacktraceCleaner#remove_silencers!</tt>, which will restore the
23
+ # backtrace to a pristine state. If you need to reconfigure an existing
24
+ # BacktraceCleaner so that it does not filter or modify the paths of any lines
25
+ # of the backtrace, you can call <tt>BacktraceCleaner#remove_filters!</tt>
26
+ # These two methods will give you a completely untouched backtrace.
22
27
  #
23
- # Inspired by the Quiet Backtrace gem by Thoughtbot.
28
+ # Inspired by the Quiet Backtrace gem by thoughtbot.
24
29
  class BacktraceCleaner
25
30
  def initialize
26
31
  @filters, @silencers = [], []
27
32
  end
28
33
 
29
- # Returns the backtrace after all filters and silencers have been run against it. Filters run first, then silencers.
34
+ # Returns the backtrace after all filters and silencers have been run
35
+ # against it. Filters run first, then silencers.
30
36
  def clean(backtrace, kind = :silent)
31
- filtered = filter(backtrace)
37
+ filtered = filter_backtrace(backtrace)
32
38
 
33
39
  case kind
34
40
  when :silent
@@ -39,10 +45,10 @@ module ActiveSupport
39
45
  filtered
40
46
  end
41
47
  end
48
+ alias :filter :clean
42
49
 
43
- # Adds a filter from the block provided. Each line in the backtrace will be mapped against this filter.
44
- #
45
- # Example:
50
+ # Adds a filter from the block provided. Each line in the backtrace will be
51
+ # mapped against this filter.
46
52
  #
47
53
  # # Will turn "/my/rails/root/app/models/person.rb" into "/app/models/person.rb"
48
54
  # backtrace_cleaner.add_filter { |line| line.gsub(Rails.root, '') }
@@ -50,10 +56,8 @@ module ActiveSupport
50
56
  @filters << block
51
57
  end
52
58
 
53
- # Adds a silencer from the block provided. If the silencer returns true for a given line, it will be excluded from
54
- # the clean backtrace.
55
- #
56
- # Example:
59
+ # Adds a silencer from the block provided. If the silencer returns +true+
60
+ # for a given line, it will be excluded from the clean backtrace.
57
61
  #
58
62
  # # Will reject all lines that include the word "mongrel", like "/gems/mongrel/server.rb" or "/app/my_mongrel_server/rb"
59
63
  # backtrace_cleaner.add_silencer { |line| line =~ /mongrel/ }
@@ -61,18 +65,22 @@ module ActiveSupport
61
65
  @silencers << block
62
66
  end
63
67
 
64
- # Will remove all silencers, but leave in the filters. This is useful if your context of debugging suddenly expands as
65
- # you suspect a bug in one of the libraries you use.
68
+ # Removes all silencers, but leaves in the filters. Useful if your
69
+ # context of debugging suddenly expands as you suspect a bug in one of
70
+ # the libraries you use.
66
71
  def remove_silencers!
67
72
  @silencers = []
68
73
  end
69
74
 
75
+ # Removes all filters, but leaves in the silencers. Useful if you suddenly
76
+ # need to see entire filepaths in the backtrace that you had already
77
+ # filtered out.
70
78
  def remove_filters!
71
79
  @filters = []
72
80
  end
73
81
 
74
82
  private
75
- def filter(backtrace)
83
+ def filter_backtrace(backtrace)
76
84
  @filters.each do |f|
77
85
  backtrace = backtrace.map { |line| f.call(line) }
78
86
  end
@@ -89,11 +97,7 @@ module ActiveSupport
89
97
  end
90
98
 
91
99
  def noise(backtrace)
92
- @silencers.each do |s|
93
- backtrace = backtrace.select { |line| s.call(line) }
94
- end
95
-
96
- backtrace
100
+ backtrace - silence(backtrace)
97
101
  end
98
102
  end
99
103
  end
@@ -3,41 +3,39 @@ require 'active_support/core_ext/hash/keys'
3
3
 
4
4
  module ActiveSupport
5
5
  module Benchmarkable
6
- # Allows you to measure the execution time of a block
7
- # in a template and records the result to the log. Wrap this block around
8
- # expensive operations or possible bottlenecks to get a time reading
9
- # for the operation. For example, let's say you thought your file
10
- # processing method was taking too long; you could wrap it in a benchmark block.
6
+ # Allows you to measure the execution time of a block in a template and
7
+ # records the result to the log. Wrap this block around expensive operations
8
+ # or possible bottlenecks to get a time reading for the operation. For
9
+ # example, let's say you thought your file processing method was taking too
10
+ # long; you could wrap it in a benchmark block.
11
11
  #
12
- # <% benchmark "Process data files" do %>
12
+ # <% benchmark 'Process data files' do %>
13
13
  # <%= expensive_files_operation %>
14
14
  # <% end %>
15
15
  #
16
16
  # That would add something like "Process data files (345.2ms)" to the log,
17
17
  # which you can then use to compare timings when optimizing your code.
18
18
  #
19
- # You may give an optional logger level as the :level option.
20
- # (:debug, :info, :warn, :error); the default value is :info.
19
+ # You may give an optional logger level (<tt>:debug</tt>, <tt>:info</tt>,
20
+ # <tt>:warn</tt>, <tt>:error</tt>) as the <tt>:level</tt> option. The
21
+ # default logger level value is <tt>:info</tt>.
21
22
  #
22
- # <% benchmark "Low-level files", :level => :debug do %>
23
+ # <% benchmark 'Low-level files', level: :debug do %>
23
24
  # <%= lowlevel_files_operation %>
24
25
  # <% end %>
25
26
  #
26
- # Finally, you can pass true as the third argument to silence all log activity
27
- # inside the block. This is great for boiling down a noisy block to just a single statement:
27
+ # Finally, you can pass true as the third argument to silence all log
28
+ # activity (other than the timing information) from inside the block. This
29
+ # is great for boiling down a noisy block to just a single statement that
30
+ # produces one log line:
28
31
  #
29
- # <% benchmark "Process data files", :level => :info, :silence => true do %>
32
+ # <% benchmark 'Process data files', level: :info, silence: true do %>
30
33
  # <%= expensive_and_chatty_files_operation %>
31
34
  # <% end %>
32
35
  def benchmark(message = "Benchmarking", options = {})
33
36
  if logger
34
- if options.is_a?(Symbol)
35
- ActiveSupport::Deprecation.warn("use benchmark('#{message}', :level => :#{options}) instead", caller)
36
- options = { :level => options, :silence => false }
37
- else
38
- options.assert_valid_keys(:level, :silence)
39
- options[:level] ||= :info
40
- end
37
+ options.assert_valid_keys(:level, :silence)
38
+ options[:level] ||= :info
41
39
 
42
40
  result = nil
43
41
  ms = Benchmark.ms { result = options[:silence] ? logger.silence { yield } : yield }
@@ -47,14 +45,5 @@ module ActiveSupport
47
45
  yield
48
46
  end
49
47
  end
50
-
51
- # Silence the logger during the execution of the block.
52
- #
53
- def silence
54
- old_logger_level, logger.level = logger.level, ::Logger::ERROR if logger
55
- yield
56
- ensure
57
- logger.level = old_logger_level if logger
58
- end
59
48
  end
60
49
  end
@@ -1,64 +1,58 @@
1
+ require 'active_support/core_ext/marshal'
1
2
  require 'active_support/core_ext/file/atomic'
2
3
  require 'active_support/core_ext/string/conversions'
3
- require 'active_support/core_ext/object/inclusion'
4
- require 'rack/utils'
4
+ require 'uri/common'
5
5
 
6
6
  module ActiveSupport
7
7
  module Cache
8
8
  # A cache store implementation which stores everything on the filesystem.
9
9
  #
10
10
  # FileStore implements the Strategy::LocalCache strategy which implements
11
- # an in memory cache inside of a block.
11
+ # an in-memory cache inside of a block.
12
12
  class FileStore < Store
13
+ prepend Strategy::LocalCache
13
14
  attr_reader :cache_path
14
15
 
15
16
  DIR_FORMATTER = "%03X"
17
+ 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)
18
+ FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room
19
+ EXCLUDED_DIRS = ['.', '..'].freeze
20
+ GITKEEP_FILES = ['.gitkeep', '.keep'].freeze
16
21
 
17
22
  def initialize(cache_path, options = nil)
18
23
  super(options)
19
24
  @cache_path = cache_path.to_s
20
- extend Strategy::LocalCache
21
25
  end
22
26
 
27
+ # Deletes all items from the cache. In this case it deletes all the entries in the specified
28
+ # file store directory except for .keep or .gitkeep. Be careful which directory is specified in your
29
+ # config file when using +FileStore+ because everything in that directory will be deleted.
23
30
  def clear(options = nil)
24
- root_dirs = Dir.entries(cache_path).reject{|f| f.in?(['.', '..'])}
31
+ root_dirs = exclude_from(cache_path, EXCLUDED_DIRS + GITKEEP_FILES)
25
32
  FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)})
33
+ rescue Errno::ENOENT
26
34
  end
27
35
 
36
+ # Preemptively iterates through all stored keys and removes the ones which have expired.
28
37
  def cleanup(options = nil)
29
38
  options = merged_options(options)
30
- each_key(options) do |key|
39
+ search_dir(cache_path) do |fname|
40
+ key = file_path_key(fname)
31
41
  entry = read_entry(key, options)
32
42
  delete_entry(key, options) if entry && entry.expired?
33
43
  end
34
44
  end
35
45
 
46
+ # Increments an already existing integer value that is stored in the cache.
47
+ # If the key is not found nothing is done.
36
48
  def increment(name, amount = 1, options = nil)
37
- file_name = key_file_path(namespaced_key(name, options))
38
- lock_file(file_name) do
39
- options = merged_options(options)
40
- if num = read(name, options)
41
- num = num.to_i + amount
42
- write(name, num, options)
43
- num
44
- else
45
- nil
46
- end
47
- end
49
+ modify_value(name, amount, options)
48
50
  end
49
51
 
52
+ # Decrements an already existing integer value that is stored in the cache.
53
+ # If the key is not found nothing is done.
50
54
  def decrement(name, amount = 1, options = nil)
51
- file_name = key_file_path(namespaced_key(name, options))
52
- lock_file(file_name) do
53
- options = merged_options(options)
54
- if num = read(name, options)
55
- num = num.to_i - amount
56
- write(name, num, options)
57
- num
58
- else
59
- nil
60
- end
61
- end
55
+ modify_value(name, -amount, options)
62
56
  end
63
57
 
64
58
  def delete_matched(matcher, options = nil)
@@ -67,7 +61,7 @@ module ActiveSupport
67
61
  matcher = key_matcher(matcher, options)
68
62
  search_dir(cache_path) do |path|
69
63
  key = file_path_key(path)
70
- delete_entry(key, options) if key.match(matcher)
64
+ delete_entry(path, options) if key.match(matcher)
71
65
  end
72
66
  end
73
67
  end
@@ -75,43 +69,30 @@ module ActiveSupport
75
69
  protected
76
70
 
77
71
  def read_entry(key, options)
78
- file_name = key_file_path(key)
79
- if File.exist?(file_name)
80
- entry = File.open(file_name) { |f| Marshal.load(f) }
81
- if entry && !entry.expired? && !entry.expires_in && !self.options[:expires_in]
82
- # Check for deprecated use of +:expires_in+ option from versions < 3.0
83
- deprecated_expires_in = options[:expires_in]
84
- if deprecated_expires_in
85
- ActiveSupport::Deprecation.warn('Setting :expires_in on read has been deprecated in favor of setting it on write.', caller)
86
- if entry.created_at + deprecated_expires_in.to_f <= Time.now.to_f
87
- delete_entry(key, options)
88
- entry = nil
89
- end
90
- end
91
- end
92
- entry
72
+ if File.exist?(key)
73
+ File.open(key) { |f| Marshal.load(f) }
93
74
  end
94
- rescue
75
+ rescue => e
76
+ logger.error("FileStoreError (#{e}): #{e.message}") if logger
95
77
  nil
96
78
  end
97
79
 
98
80
  def write_entry(key, entry, options)
99
- file_name = key_file_path(key)
100
- ensure_cache_path(File.dirname(file_name))
101
- File.atomic_write(file_name, cache_path) {|f| Marshal.dump(entry, f)}
81
+ return false if options[:unless_exist] && File.exist?(key)
82
+ ensure_cache_path(File.dirname(key))
83
+ File.atomic_write(key, cache_path) {|f| Marshal.dump(entry, f)}
102
84
  true
103
85
  end
104
86
 
105
87
  def delete_entry(key, options)
106
- file_name = key_file_path(key)
107
- if File.exist?(file_name)
88
+ if File.exist?(key)
108
89
  begin
109
- File.delete(file_name)
110
- delete_empty_directories(File.dirname(file_name))
90
+ File.delete(key)
91
+ delete_empty_directories(File.dirname(key))
111
92
  true
112
93
  rescue => e
113
94
  # Just in case the error was caused by another process deleting the file first.
114
- raise e if File.exist?(file_name)
95
+ raise e if File.exist?(key)
115
96
  false
116
97
  end
117
98
  end
@@ -135,35 +116,47 @@ module ActiveSupport
135
116
  end
136
117
 
137
118
  # Translate a key into a file path.
138
- def key_file_path(key)
139
- fname = Rack::Utils.escape(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 = Digest::MD5.hexdigest(key)
125
+ end
126
+
140
127
  hash = Zlib.adler32(fname)
141
128
  hash, dir_1 = hash.divmod(0x1000)
142
129
  dir_2 = hash.modulo(0x1000)
143
130
  fname_paths = []
144
- # Make sure file name is < 255 characters so it doesn't exceed file system limits.
145
- if fname.size <= 255
146
- fname_paths << fname
147
- else
148
- while fname.size <= 255
149
- fname_path << fname[0, 255]
150
- fname = fname[255, -1]
151
- end
152
- end
131
+
132
+ # Make sure file name doesn't exceed file system limits.
133
+ begin
134
+ fname_paths << fname[0, FILENAME_MAX_SIZE]
135
+ fname = fname[FILENAME_MAX_SIZE..-1]
136
+ end until fname.blank?
137
+
153
138
  File.join(cache_path, DIR_FORMATTER % dir_1, DIR_FORMATTER % dir_2, *fname_paths)
154
139
  end
155
140
 
141
+ def key_file_path(key)
142
+ ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
143
+ `key_file_path` is deprecated and will be removed from Rails 5.1.
144
+ Please use `normalize_key` which will return a fully resolved key or nothing.
145
+ MESSAGE
146
+ key
147
+ end
148
+
156
149
  # Translate a file path into a key.
157
150
  def file_path_key(path)
158
- fname = path[cache_path.size, path.size].split(File::SEPARATOR, 4).last
159
- Rack::Utils.unescape(fname)
151
+ fname = path[cache_path.to_s.size..-1].split(File::SEPARATOR, 4).last
152
+ URI.decode_www_form_component(fname, Encoding::UTF_8)
160
153
  end
161
154
 
162
155
  # Delete empty directories in the cache.
163
156
  def delete_empty_directories(dir)
164
- return if dir == cache_path
165
- if Dir.entries(dir).reject{|f| f.in?(['.', '..'])}.empty?
166
- File.delete(dir) rescue nil
157
+ return if File.realpath(dir) == File.realpath(cache_path)
158
+ if exclude_from(dir, EXCLUDED_DIRS).empty?
159
+ Dir.delete(dir) rescue nil
167
160
  delete_empty_directories(File.dirname(dir))
168
161
  end
169
162
  end
@@ -174,8 +167,9 @@ module ActiveSupport
174
167
  end
175
168
 
176
169
  def search_dir(dir, &callback)
170
+ return if !File.exist?(dir)
177
171
  Dir.foreach(dir) do |d|
178
- next if d == "." || d == ".."
172
+ next if EXCLUDED_DIRS.include?(d)
179
173
  name = File.join(dir, d)
180
174
  if File.directory?(name)
181
175
  search_dir(name, &callback)
@@ -184,6 +178,27 @@ module ActiveSupport
184
178
  end
185
179
  end
186
180
  end
181
+
182
+ # Modifies the amount of an already existing integer value that is stored in the cache.
183
+ # If the key is not found nothing is done.
184
+ def modify_value(name, amount, options)
185
+ file_name = normalize_key(name, options)
186
+
187
+ lock_file(file_name) do
188
+ options = merged_options(options)
189
+
190
+ if num = read(name, options)
191
+ num = num.to_i + amount
192
+ write(name, num, options)
193
+ num
194
+ end
195
+ end
196
+ end
197
+
198
+ # Exclude entries from source directory
199
+ def exclude_from(source, excludes)
200
+ Dir.entries(source).reject { |f| excludes.include?(f) }
201
+ end
187
202
  end
188
203
  end
189
204
  end