activesupport 3.1.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (276) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +798 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +13 -7
  5. data/lib/active_support/array_inquirer.rb +44 -0
  6. data/lib/active_support/backtrace_cleaner.rb +38 -34
  7. data/lib/active_support/benchmarkable.rb +17 -28
  8. data/lib/active_support/cache/file_store.rb +85 -70
  9. data/lib/active_support/cache/mem_cache_store.rb +75 -66
  10. data/lib/active_support/cache/memory_store.rb +31 -23
  11. data/lib/active_support/cache/null_store.rb +41 -0
  12. data/lib/active_support/cache/strategy/local_cache.rb +73 -70
  13. data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
  14. data/lib/active_support/cache.rb +360 -294
  15. data/lib/active_support/callbacks.rb +563 -393
  16. data/lib/active_support/concern.rb +42 -34
  17. data/lib/active_support/concurrency/latch.rb +19 -0
  18. data/lib/active_support/concurrency/share_lock.rb +186 -0
  19. data/lib/active_support/configurable.rb +70 -12
  20. data/lib/active_support/core_ext/array/access.rb +53 -9
  21. data/lib/active_support/core_ext/array/conversions.rb +109 -62
  22. data/lib/active_support/core_ext/array/extract_options.rb +2 -2
  23. data/lib/active_support/core_ext/array/grouping.rb +39 -32
  24. data/lib/active_support/core_ext/array/inquiry.rb +17 -0
  25. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
  26. data/lib/active_support/core_ext/array/wrap.rb +16 -18
  27. data/lib/active_support/core_ext/array.rb +2 -2
  28. data/lib/active_support/core_ext/benchmark.rb +7 -0
  29. data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -36
  30. data/lib/active_support/core_ext/class/attribute.rb +47 -34
  31. data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -79
  32. data/lib/active_support/core_ext/class/subclasses.rb +12 -7
  33. data/lib/active_support/core_ext/class.rb +0 -3
  34. data/lib/active_support/core_ext/date/blank.rb +12 -0
  35. data/lib/active_support/core_ext/date/calculations.rb +57 -167
  36. data/lib/active_support/core_ext/date/conversions.rb +31 -42
  37. data/lib/active_support/core_ext/date/zones.rb +2 -10
  38. data/lib/active_support/core_ext/date.rb +5 -0
  39. data/lib/active_support/core_ext/date_and_time/calculations.rb +335 -0
  40. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -0
  41. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  42. data/lib/active_support/core_ext/date_time/acts_like.rb +1 -0
  43. data/lib/active_support/core_ext/date_time/blank.rb +12 -0
  44. data/lib/active_support/core_ext/date_time/calculations.rb +132 -65
  45. data/lib/active_support/core_ext/date_time/compatibility.rb +5 -0
  46. data/lib/active_support/core_ext/date_time/conversions.rb +36 -34
  47. data/lib/active_support/core_ext/date_time.rb +5 -0
  48. data/lib/active_support/core_ext/digest/uuid.rb +51 -0
  49. data/lib/active_support/core_ext/enumerable.rb +81 -74
  50. data/lib/active_support/core_ext/file/atomic.rb +53 -26
  51. data/lib/active_support/core_ext/file.rb +0 -1
  52. data/lib/active_support/core_ext/hash/compact.rb +20 -0
  53. data/lib/active_support/core_ext/hash/conversions.rb +175 -70
  54. data/lib/active_support/core_ext/hash/deep_merge.rb +30 -8
  55. data/lib/active_support/core_ext/hash/except.rb +11 -12
  56. data/lib/active_support/core_ext/hash/indifferent_access.rb +7 -8
  57. data/lib/active_support/core_ext/hash/keys.rb +147 -24
  58. data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
  59. data/lib/active_support/core_ext/hash/slice.rb +22 -14
  60. data/lib/active_support/core_ext/hash/transform_values.rb +29 -0
  61. data/lib/active_support/core_ext/hash.rb +2 -2
  62. data/lib/active_support/core_ext/integer/inflections.rb +13 -1
  63. data/lib/active_support/core_ext/integer/multiple.rb +4 -0
  64. data/lib/active_support/core_ext/integer/time.rb +12 -22
  65. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -2
  66. data/lib/active_support/core_ext/kernel/concern.rb +12 -0
  67. data/lib/active_support/core_ext/kernel/debugger.rb +2 -15
  68. data/lib/active_support/core_ext/kernel/reporting.rb +12 -62
  69. data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
  70. data/lib/active_support/core_ext/kernel.rb +2 -3
  71. data/lib/active_support/core_ext/load_error.rb +14 -7
  72. data/lib/active_support/core_ext/marshal.rb +22 -0
  73. data/lib/active_support/core_ext/module/aliasing.rb +16 -12
  74. data/lib/active_support/core_ext/module/anonymous.rb +12 -8
  75. data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
  76. data/lib/active_support/core_ext/module/attribute_accessors.rb +165 -13
  77. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
  78. data/lib/active_support/core_ext/module/concerning.rb +135 -0
  79. data/lib/active_support/core_ext/module/delegation.rb +141 -68
  80. data/lib/active_support/core_ext/module/deprecation.rb +17 -3
  81. data/lib/active_support/core_ext/module/introspection.rb +9 -31
  82. data/lib/active_support/core_ext/module/method_transplanting.rb +3 -0
  83. data/lib/active_support/core_ext/module/qualified_const.rb +70 -0
  84. data/lib/active_support/core_ext/module/reachable.rb +1 -3
  85. data/lib/active_support/core_ext/module/remove_method.rb +24 -5
  86. data/lib/active_support/core_ext/module.rb +3 -3
  87. data/lib/active_support/core_ext/name_error.rb +15 -2
  88. data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
  89. data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
  90. data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
  91. data/lib/active_support/core_ext/numeric/time.rb +31 -36
  92. data/lib/active_support/core_ext/numeric.rb +2 -0
  93. data/lib/active_support/core_ext/object/acts_like.rb +4 -4
  94. data/lib/active_support/core_ext/object/blank.rb +52 -18
  95. data/lib/active_support/core_ext/object/deep_dup.rb +53 -0
  96. data/lib/active_support/core_ext/object/duplicable.rb +12 -20
  97. data/lib/active_support/core_ext/object/inclusion.rb +13 -1
  98. data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
  99. data/lib/active_support/core_ext/object/json.rb +205 -0
  100. data/lib/active_support/core_ext/object/to_param.rb +1 -55
  101. data/lib/active_support/core_ext/object/to_query.rb +66 -9
  102. data/lib/active_support/core_ext/object/try.rb +124 -33
  103. data/lib/active_support/core_ext/object/with_options.rb +37 -11
  104. data/lib/active_support/core_ext/object.rb +2 -1
  105. data/lib/active_support/core_ext/range/conversions.rb +17 -7
  106. data/lib/active_support/core_ext/range/each.rb +21 -0
  107. data/lib/active_support/core_ext/range/include_range.rb +20 -18
  108. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  109. data/lib/active_support/core_ext/range.rb +1 -2
  110. data/lib/active_support/core_ext/securerandom.rb +23 -0
  111. data/lib/active_support/core_ext/string/access.rb +95 -90
  112. data/lib/active_support/core_ext/string/behavior.rb +1 -1
  113. data/lib/active_support/core_ext/string/conversions.rb +41 -38
  114. data/lib/active_support/core_ext/string/exclude.rb +6 -1
  115. data/lib/active_support/core_ext/string/filters.rb +70 -17
  116. data/lib/active_support/core_ext/string/indent.rb +43 -0
  117. data/lib/active_support/core_ext/string/inflections.rb +139 -59
  118. data/lib/active_support/core_ext/string/inquiry.rb +2 -2
  119. data/lib/active_support/core_ext/string/multibyte.rb +46 -65
  120. data/lib/active_support/core_ext/string/output_safety.rb +153 -56
  121. data/lib/active_support/core_ext/string/strip.rb +3 -6
  122. data/lib/active_support/core_ext/string/zones.rb +14 -0
  123. data/lib/active_support/core_ext/string.rb +2 -3
  124. data/lib/active_support/core_ext/struct.rb +3 -0
  125. data/lib/active_support/core_ext/time/calculations.rb +173 -173
  126. data/lib/active_support/core_ext/time/compatibility.rb +5 -0
  127. data/lib/active_support/core_ext/time/conversions.rb +33 -29
  128. data/lib/active_support/core_ext/time/marshal.rb +2 -56
  129. data/lib/active_support/core_ext/time/zones.rb +57 -32
  130. data/lib/active_support/core_ext/time.rb +5 -0
  131. data/lib/active_support/core_ext/uri.rb +13 -19
  132. data/lib/active_support/core_ext.rb +3 -2
  133. data/lib/active_support/dependencies/autoload.rb +47 -20
  134. data/lib/active_support/dependencies/interlock.rb +51 -0
  135. data/lib/active_support/dependencies.rb +315 -265
  136. data/lib/active_support/deprecation/behaviors.rb +71 -30
  137. data/lib/active_support/deprecation/instance_delegator.rb +24 -0
  138. data/lib/active_support/deprecation/method_wrappers.rb +59 -18
  139. data/lib/active_support/deprecation/proxy_wrappers.rb +82 -14
  140. data/lib/active_support/deprecation/reporting.rb +61 -14
  141. data/lib/active_support/deprecation.rb +38 -13
  142. data/lib/active_support/descendants_tracker.rb +34 -19
  143. data/lib/active_support/duration/iso8601_parser.rb +122 -0
  144. data/lib/active_support/duration/iso8601_serializer.rb +51 -0
  145. data/lib/active_support/duration.rb +85 -14
  146. data/lib/active_support/evented_file_update_checker.rb +194 -0
  147. data/lib/active_support/execution_wrapper.rb +117 -0
  148. data/lib/active_support/executor.rb +6 -0
  149. data/lib/active_support/file_update_checker.rb +138 -17
  150. data/lib/active_support/gem_version.rb +15 -0
  151. data/lib/active_support/gzip.rb +11 -5
  152. data/lib/active_support/hash_with_indifferent_access.rb +199 -49
  153. data/lib/active_support/i18n.rb +6 -2
  154. data/lib/active_support/i18n_railtie.rb +40 -21
  155. data/lib/active_support/inflections.rb +22 -13
  156. data/lib/active_support/inflector/inflections.rb +175 -144
  157. data/lib/active_support/inflector/methods.rb +328 -91
  158. data/lib/active_support/inflector/transliterate.rb +51 -37
  159. data/lib/active_support/json/decoding.rb +31 -22
  160. data/lib/active_support/json/encoding.rb +88 -248
  161. data/lib/active_support/key_generator.rb +71 -0
  162. data/lib/active_support/lazy_load_hooks.rb +27 -25
  163. data/lib/active_support/locale/en.yml +102 -3
  164. data/lib/active_support/log_subscriber/test_helper.rb +24 -21
  165. data/lib/active_support/log_subscriber.rb +36 -49
  166. data/lib/active_support/logger.rb +106 -0
  167. data/lib/active_support/logger_silence.rb +28 -0
  168. data/lib/active_support/logger_thread_safe_level.rb +31 -0
  169. data/lib/active_support/message_encryptor.rb +72 -36
  170. data/lib/active_support/message_verifier.rb +96 -24
  171. data/lib/active_support/multibyte/chars.rb +88 -333
  172. data/lib/active_support/multibyte/unicode.rb +156 -136
  173. data/lib/active_support/multibyte.rb +5 -28
  174. data/lib/active_support/notifications/fanout.rb +115 -19
  175. data/lib/active_support/notifications/instrumenter.rb +52 -15
  176. data/lib/active_support/notifications.rb +168 -33
  177. data/lib/active_support/number_helper/number_converter.rb +182 -0
  178. data/lib/active_support/number_helper/number_to_currency_converter.rb +44 -0
  179. data/lib/active_support/number_helper/number_to_delimited_converter.rb +28 -0
  180. data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
  181. data/lib/active_support/number_helper/number_to_human_size_converter.rb +62 -0
  182. data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
  183. data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
  184. data/lib/active_support/number_helper/number_to_rounded_converter.rb +92 -0
  185. data/lib/active_support/number_helper.rb +368 -0
  186. data/lib/active_support/option_merger.rb +1 -1
  187. data/lib/active_support/ordered_hash.rb +18 -183
  188. data/lib/active_support/ordered_options.rb +44 -24
  189. data/lib/active_support/per_thread_registry.rb +58 -0
  190. data/lib/active_support/proxy_object.rb +13 -0
  191. data/lib/active_support/rails.rb +27 -0
  192. data/lib/active_support/railtie.rb +25 -34
  193. data/lib/active_support/reloader.rb +129 -0
  194. data/lib/active_support/rescuable.rb +98 -48
  195. data/lib/active_support/security_utils.rb +27 -0
  196. data/lib/active_support/string_inquirer.rb +14 -9
  197. data/lib/active_support/subscriber.rb +120 -0
  198. data/lib/active_support/tagged_logging.rb +78 -0
  199. data/lib/active_support/test_case.rb +69 -17
  200. data/lib/active_support/testing/assertions.rb +43 -41
  201. data/lib/active_support/testing/autorun.rb +12 -0
  202. data/lib/active_support/testing/constant_lookup.rb +50 -0
  203. data/lib/active_support/testing/declarative.rb +7 -21
  204. data/lib/active_support/testing/deprecation.rb +14 -33
  205. data/lib/active_support/testing/file_fixtures.rb +34 -0
  206. data/lib/active_support/testing/isolation.rb +53 -95
  207. data/lib/active_support/testing/method_call_assertions.rb +41 -0
  208. data/lib/active_support/testing/setup_and_teardown.rb +21 -82
  209. data/lib/active_support/testing/stream.rb +42 -0
  210. data/lib/active_support/testing/tagged_logging.rb +25 -0
  211. data/lib/active_support/testing/time_helpers.rb +134 -0
  212. data/lib/active_support/time.rb +6 -23
  213. data/lib/active_support/time_with_zone.rb +239 -92
  214. data/lib/active_support/values/time_zone.rb +236 -160
  215. data/lib/active_support/values/unicode_tables.dat +0 -0
  216. data/lib/active_support/version.rb +5 -7
  217. data/lib/active_support/xml_mini/jdom.rb +19 -13
  218. data/lib/active_support/xml_mini/libxml.rb +3 -4
  219. data/lib/active_support/xml_mini/libxmlsax.rb +2 -3
  220. data/lib/active_support/xml_mini/nokogiri.rb +3 -4
  221. data/lib/active_support/xml_mini/nokogirisax.rb +2 -3
  222. data/lib/active_support/xml_mini/rexml.rb +8 -10
  223. data/lib/active_support/xml_mini.rb +66 -34
  224. data/lib/active_support.rb +40 -23
  225. metadata +185 -134
  226. data/CHANGELOG +0 -1534
  227. data/lib/active_support/base64.rb +0 -42
  228. data/lib/active_support/basic_object.rb +0 -21
  229. data/lib/active_support/buffered_logger.rb +0 -137
  230. data/lib/active_support/cache/compressed_mem_cache_store.rb +0 -13
  231. data/lib/active_support/cache/synchronized_memory_store.rb +0 -11
  232. data/lib/active_support/core_ext/array/random_access.rb +0 -30
  233. data/lib/active_support/core_ext/array/uniq_by.rb +0 -16
  234. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -44
  235. data/lib/active_support/core_ext/class/inheritable_attributes.rb +0 -178
  236. data/lib/active_support/core_ext/date/freeze.rb +0 -31
  237. data/lib/active_support/core_ext/date_time/zones.rb +0 -21
  238. data/lib/active_support/core_ext/exception.rb +0 -3
  239. data/lib/active_support/core_ext/file/path.rb +0 -5
  240. data/lib/active_support/core_ext/float/rounding.rb +0 -19
  241. data/lib/active_support/core_ext/float.rb +0 -1
  242. data/lib/active_support/core_ext/hash/deep_dup.rb +0 -11
  243. data/lib/active_support/core_ext/hash/diff.rb +0 -13
  244. data/lib/active_support/core_ext/kernel/requires.rb +0 -28
  245. data/lib/active_support/core_ext/logger.rb +0 -81
  246. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +0 -31
  247. data/lib/active_support/core_ext/module/method_names.rb +0 -14
  248. data/lib/active_support/core_ext/module/synchronization.rb +0 -43
  249. data/lib/active_support/core_ext/object/to_json.rb +0 -19
  250. data/lib/active_support/core_ext/proc.rb +0 -14
  251. data/lib/active_support/core_ext/process/daemon.rb +0 -23
  252. data/lib/active_support/core_ext/process.rb +0 -1
  253. data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
  254. data/lib/active_support/core_ext/range/cover.rb +0 -3
  255. data/lib/active_support/core_ext/rexml.rb +0 -46
  256. data/lib/active_support/core_ext/string/encoding.rb +0 -11
  257. data/lib/active_support/core_ext/string/interpolation.rb +0 -2
  258. data/lib/active_support/core_ext/string/xchar.rb +0 -18
  259. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
  260. data/lib/active_support/file_watcher.rb +0 -36
  261. data/lib/active_support/json/variable.rb +0 -9
  262. data/lib/active_support/memoizable.rb +0 -105
  263. data/lib/active_support/multibyte/exceptions.rb +0 -8
  264. data/lib/active_support/multibyte/utils.rb +0 -60
  265. data/lib/active_support/ruby/shim.rb +0 -22
  266. data/lib/active_support/secure_random.rb +0 -6
  267. data/lib/active_support/testing/mochaing.rb +0 -7
  268. data/lib/active_support/testing/pending.rb +0 -52
  269. data/lib/active_support/testing/performance/jruby.rb +0 -115
  270. data/lib/active_support/testing/performance/rubinius.rb +0 -113
  271. data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
  272. data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
  273. data/lib/active_support/testing/performance/ruby.rb +0 -152
  274. data/lib/active_support/testing/performance.rb +0 -317
  275. data/lib/active_support/time/autoload.rb +0 -5
  276. data/lib/active_support/whiny_nil.rb +0 -60
@@ -1,36 +1,157 @@
1
+ require 'active_support/core_ext/time/calculations'
2
+
1
3
  module ActiveSupport
2
- # This class is responsible to track files and invoke the given block
3
- # whenever one of these files are changed. For example, this class
4
- # is used by Rails to reload the I18n framework whenever they are
5
- # changed upon a new request.
4
+ # FileUpdateChecker specifies the API used by Rails to watch files
5
+ # and control reloading. The API depends on four methods:
6
+ #
7
+ # * +initialize+ which expects two parameters and one block as
8
+ # described below.
9
+ #
10
+ # * +updated?+ which returns a boolean if there were updates in
11
+ # the filesystem or not.
12
+ #
13
+ # * +execute+ which executes the given block on initialization
14
+ # and updates the latest watched files and timestamp.
15
+ #
16
+ # * +execute_if_updated+ which just executes the block if it was updated.
17
+ #
18
+ # After initialization, a call to +execute_if_updated+ must execute
19
+ # the block only if there was really a change in the filesystem.
20
+ #
21
+ # This class is used by Rails to reload the I18n framework whenever
22
+ # they are changed upon a new request.
6
23
  #
7
24
  # i18n_reloader = ActiveSupport::FileUpdateChecker.new(paths) do
8
25
  # I18n.reload!
9
26
  # end
10
27
  #
11
- # ActionDispatch::Reloader.to_prepare do
28
+ # ActiveSupport::Reloader.to_prepare do
12
29
  # i18n_reloader.execute_if_updated
13
30
  # end
14
- #
15
31
  class FileUpdateChecker
16
- attr_reader :paths, :last_update_at
17
-
18
- def initialize(paths, calculate=false, &block)
19
- @paths = paths
32
+ # It accepts two parameters on initialization. The first is an array
33
+ # of files and the second is an optional hash of directories. The hash must
34
+ # have directories as keys and the value is an array of extensions to be
35
+ # watched under that directory.
36
+ #
37
+ # This method must also receive a block that will be called once a path
38
+ # changes. The array of files and list of directories cannot be changed
39
+ # after FileUpdateChecker has been initialized.
40
+ def initialize(files, dirs = {}, &block)
41
+ @files = files.freeze
42
+ @glob = compile_glob(dirs)
20
43
  @block = block
21
- @last_update_at = calculate ? updated_at : nil
44
+
45
+ @watched = nil
46
+ @updated_at = nil
47
+
48
+ @last_watched = watched
49
+ @last_update_at = updated_at(@last_watched)
50
+ end
51
+
52
+ # Check if any of the entries were updated. If so, the watched and/or
53
+ # updated_at values are cached until the block is executed via +execute+
54
+ # or +execute_if_updated+.
55
+ def updated?
56
+ current_watched = watched
57
+ if @last_watched.size != current_watched.size
58
+ @watched = current_watched
59
+ true
60
+ else
61
+ current_updated_at = updated_at(current_watched)
62
+ if @last_update_at < current_updated_at
63
+ @watched = current_watched
64
+ @updated_at = current_updated_at
65
+ true
66
+ else
67
+ false
68
+ end
69
+ end
22
70
  end
23
71
 
24
- def updated_at
25
- paths.map { |path| File.stat(path).mtime }.max
72
+ # Executes the given block and updates the latest watched files and
73
+ # timestamp.
74
+ def execute
75
+ @last_watched = watched
76
+ @last_update_at = updated_at(@last_watched)
77
+ @block.call
78
+ ensure
79
+ @watched = nil
80
+ @updated_at = nil
26
81
  end
27
82
 
83
+ # Execute the block given if updated.
28
84
  def execute_if_updated
29
- current_update_at = self.updated_at
30
- if @last_update_at != current_update_at
31
- @last_update_at = current_update_at
32
- @block.call
85
+ if updated?
86
+ yield if block_given?
87
+ execute
88
+ true
89
+ else
90
+ false
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def watched
97
+ @watched || begin
98
+ all = @files.select { |f| File.exist?(f) }
99
+ all.concat(Dir[@glob]) if @glob
100
+ all
33
101
  end
34
102
  end
103
+
104
+ def updated_at(paths)
105
+ @updated_at || max_mtime(paths) || Time.at(0)
106
+ end
107
+
108
+ # This method returns the maximum mtime of the files in +paths+, or +nil+
109
+ # if the array is empty.
110
+ #
111
+ # Files with a mtime in the future are ignored. Such abnormal situation
112
+ # can happen for example if the user changes the clock by hand. It is
113
+ # healthy to consider this edge case because with mtimes in the future
114
+ # reloading is not triggered.
115
+ def max_mtime(paths)
116
+ time_now = Time.now
117
+ max_mtime = nil
118
+
119
+ # Time comparisons are performed with #compare_without_coercion because
120
+ # AS redefines these operators in a way that is much slower and does not
121
+ # bring any benefit in this particular code.
122
+ #
123
+ # Read t1.compare_without_coercion(t2) < 0 as t1 < t2.
124
+ paths.each do |path|
125
+ mtime = File.mtime(path)
126
+
127
+ next if time_now.compare_without_coercion(mtime) < 0
128
+
129
+ if max_mtime.nil? || max_mtime.compare_without_coercion(mtime) < 0
130
+ max_mtime = mtime
131
+ end
132
+ end
133
+
134
+ max_mtime
135
+ end
136
+
137
+ def compile_glob(hash)
138
+ hash.freeze # Freeze so changes aren't accidentally pushed
139
+ return if hash.empty?
140
+
141
+ globs = hash.map do |key, value|
142
+ "#{escape(key)}/**/*#{compile_ext(value)}"
143
+ end
144
+ "{#{globs.join(",")}}"
145
+ end
146
+
147
+ def escape(key)
148
+ key.gsub(',','\,')
149
+ end
150
+
151
+ def compile_ext(array)
152
+ array = Array(array)
153
+ return if array.empty?
154
+ ".{#{array.join(",")}}"
155
+ end
35
156
  end
36
157
  end
@@ -0,0 +1,15 @@
1
+ module ActiveSupport
2
+ # Returns the version of the currently loaded Active Support as a <tt>Gem::Version</tt>.
3
+ def self.gem_version
4
+ Gem::Version.new VERSION::STRING
5
+ end
6
+
7
+ module VERSION
8
+ MAJOR = 5
9
+ MINOR = 0
10
+ TINY = 0
11
+ PRE = nil
12
+
13
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
+ end
15
+ end
@@ -1,14 +1,20 @@
1
1
  require 'zlib'
2
2
  require 'stringio'
3
- require 'active_support/core_ext/string/encoding'
4
3
 
5
4
  module ActiveSupport
6
- # A convenient wrapper for the zlib standard library that allows compression/decompression of strings with gzip.
5
+ # A convenient wrapper for the zlib standard library that allows
6
+ # compression/decompression of strings with gzip.
7
+ #
8
+ # gzip = ActiveSupport::Gzip.compress('compress me!')
9
+ # # => "\x1F\x8B\b\x00o\x8D\xCDO\x00\x03K\xCE\xCF-(J-.V\xC8MU\x04\x00R>n\x83\f\x00\x00\x00"
10
+ #
11
+ # ActiveSupport::Gzip.decompress(gzip)
12
+ # # => "compress me!"
7
13
  module Gzip
8
14
  class Stream < StringIO
9
15
  def initialize(*)
10
16
  super
11
- set_encoding "BINARY" if "".encoding_aware?
17
+ set_encoding "BINARY"
12
18
  end
13
19
  def close; rewind; end
14
20
  end
@@ -19,9 +25,9 @@ module ActiveSupport
19
25
  end
20
26
 
21
27
  # Compresses a string using gzip.
22
- def self.compress(source)
28
+ def self.compress(source, level=Zlib::DEFAULT_COMPRESSION, strategy=Zlib::DEFAULT_STRATEGY)
23
29
  output = Stream.new
24
- gz = Zlib::GzipWriter.new(output)
30
+ gz = Zlib::GzipWriter.new(output, level, strategy)
25
31
  gz.write(source)
26
32
  gz.close
27
33
  output.string
@@ -1,13 +1,48 @@
1
1
  require 'active_support/core_ext/hash/keys'
2
-
3
- # This class has dubious semantics and we only have it so that
4
- # people can write <tt>params[:key]</tt> instead of <tt>params['key']</tt>
5
- # and they get the same value for both keys.
2
+ require 'active_support/core_ext/hash/reverse_merge'
6
3
 
7
4
  module ActiveSupport
5
+ # Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
6
+ # to be the same.
7
+ #
8
+ # rgb = ActiveSupport::HashWithIndifferentAccess.new
9
+ #
10
+ # rgb[:black] = '#000000'
11
+ # rgb[:black] # => '#000000'
12
+ # rgb['black'] # => '#000000'
13
+ #
14
+ # rgb['white'] = '#FFFFFF'
15
+ # rgb[:white] # => '#FFFFFF'
16
+ # rgb['white'] # => '#FFFFFF'
17
+ #
18
+ # Internally symbols are mapped to strings when used as keys in the entire
19
+ # writing interface (calling <tt>[]=</tt>, <tt>merge</tt>, etc). This
20
+ # mapping belongs to the public interface. For example, given:
21
+ #
22
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
23
+ #
24
+ # You are guaranteed that the key is returned as a string:
25
+ #
26
+ # hash.keys # => ["a"]
27
+ #
28
+ # Technically other types of keys are accepted:
29
+ #
30
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
31
+ # hash[0] = 0
32
+ # hash # => {"a"=>1, 0=>0}
33
+ #
34
+ # but this class is intended for use cases where strings or symbols are the
35
+ # expected keys and it is convenient to understand both as the same. For
36
+ # example the +params+ hash in Ruby on Rails.
37
+ #
38
+ # Note that core extensions define <tt>Hash#with_indifferent_access</tt>:
39
+ #
40
+ # rgb = { black: '#000000', white: '#FFFFFF' }.with_indifferent_access
41
+ #
42
+ # which may be handy.
8
43
  class HashWithIndifferentAccess < Hash
9
-
10
- # Always returns true, so that <tt>Array#extract_options!</tt> finds members of this class.
44
+ # Returns +true+ so that <tt>Array#extract_options!</tt> finds members of
45
+ # this class.
11
46
  def extractable_options?
12
47
  true
13
48
  end
@@ -16,17 +51,27 @@ module ActiveSupport
16
51
  dup
17
52
  end
18
53
 
54
+ def nested_under_indifferent_access
55
+ self
56
+ end
57
+
19
58
  def initialize(constructor = {})
20
- if constructor.is_a?(Hash)
59
+ if constructor.respond_to?(:to_hash)
21
60
  super()
22
61
  update(constructor)
62
+
63
+ hash = constructor.to_hash
64
+ self.default = hash.default if hash.default
65
+ self.default_proc = hash.default_proc if hash.default_proc
23
66
  else
24
67
  super(constructor)
25
68
  end
26
69
  end
27
70
 
28
- def default(key = nil)
29
- if key.is_a?(Symbol) && include?(key = key.to_s)
71
+ def default(*args)
72
+ arg_key = args.first
73
+
74
+ if include?(key = convert_key(arg_key))
30
75
  self[key]
31
76
  else
32
77
  super
@@ -34,9 +79,16 @@ module ActiveSupport
34
79
  end
35
80
 
36
81
  def self.new_from_hash_copying_default(hash)
37
- new(hash).tap do |new_hash|
38
- new_hash.default = hash.default
39
- end
82
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
83
+ `ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default`
84
+ has been deprecated, and will be removed in Rails 5.1. The behavior of
85
+ this method is now identical to the behavior of `.new`.
86
+ MSG
87
+ new(hash)
88
+ end
89
+
90
+ def self.[](*args)
91
+ new.merge!(Hash[*args])
40
92
  end
41
93
 
42
94
  alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
@@ -44,30 +96,51 @@ module ActiveSupport
44
96
 
45
97
  # Assigns a new value to the hash:
46
98
  #
47
- # hash = HashWithIndifferentAccess.new
48
- # hash[:key] = "value"
99
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
100
+ # hash[:key] = 'value'
49
101
  #
102
+ # This value can be later fetched using either +:key+ or <tt>'key'</tt>.
50
103
  def []=(key, value)
51
- regular_writer(convert_key(key), convert_value(value))
104
+ regular_writer(convert_key(key), convert_value(value, for: :assignment))
52
105
  end
53
106
 
54
107
  alias_method :store, :[]=
55
108
 
56
- # Updates the instantized hash with values from the second:
109
+ # Updates the receiver in-place, merging in the hash passed as argument:
57
110
  #
58
- # hash_1 = HashWithIndifferentAccess.new
59
- # hash_1[:key] = "value"
111
+ # hash_1 = ActiveSupport::HashWithIndifferentAccess.new
112
+ # hash_1[:key] = 'value'
60
113
  #
61
- # hash_2 = HashWithIndifferentAccess.new
62
- # hash_2[:key] = "New Value!"
114
+ # hash_2 = ActiveSupport::HashWithIndifferentAccess.new
115
+ # hash_2[:key] = 'New Value!'
63
116
  #
64
117
  # hash_1.update(hash_2) # => {"key"=>"New Value!"}
65
118
  #
119
+ # The argument can be either an
120
+ # <tt>ActiveSupport::HashWithIndifferentAccess</tt> or a regular +Hash+.
121
+ # In either case the merge respects the semantics of indifferent access.
122
+ #
123
+ # If the argument is a regular hash with keys +:key+ and +"key"+ only one
124
+ # of the values end up in the receiver, but which one is unspecified.
125
+ #
126
+ # When given a block, the value for duplicated keys will be determined
127
+ # by the result of invoking the block with the duplicated key, the value
128
+ # in the receiver, and the value in +other_hash+. The rules for duplicated
129
+ # keys follow the semantics of indifferent access:
130
+ #
131
+ # hash_1[:key] = 10
132
+ # hash_2['key'] = 12
133
+ # hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
66
134
  def update(other_hash)
67
135
  if other_hash.is_a? HashWithIndifferentAccess
68
136
  super(other_hash)
69
137
  else
70
- other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
138
+ other_hash.to_hash.each_pair do |key, value|
139
+ if block_given? && key?(key)
140
+ value = yield(convert_key(key), self[key], value)
141
+ end
142
+ regular_writer(convert_key(key), convert_value(value))
143
+ end
71
144
  self
72
145
  end
73
146
  end
@@ -76,11 +149,10 @@ module ActiveSupport
76
149
 
77
150
  # Checks the hash for a key matching the argument passed in:
78
151
  #
79
- # hash = HashWithIndifferentAccess.new
80
- # hash["key"] = "value"
81
- # hash.key? :key # => true
82
- # hash.key? "key" # => true
83
- #
152
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
153
+ # hash['key'] = 'value'
154
+ # hash.key?(:key) # => true
155
+ # hash.key?('key') # => true
84
156
  def key?(key)
85
157
  super(convert_key(key))
86
158
  end
@@ -89,59 +161,122 @@ module ActiveSupport
89
161
  alias_method :has_key?, :key?
90
162
  alias_method :member?, :key?
91
163
 
92
- # Fetches the value for the specified key, same as doing hash[key]
164
+
165
+ # Same as <tt>Hash#[]</tt> where the key passed as argument can be
166
+ # either a string or a symbol:
167
+ #
168
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
169
+ # counters[:foo] = 1
170
+ #
171
+ # counters['foo'] # => 1
172
+ # counters[:foo] # => 1
173
+ # counters[:zoo] # => nil
174
+ def [](key)
175
+ super(convert_key(key))
176
+ end
177
+
178
+ # Same as <tt>Hash#fetch</tt> where the key passed as argument can be
179
+ # either a string or a symbol:
180
+ #
181
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
182
+ # counters[:foo] = 1
183
+ #
184
+ # counters.fetch('foo') # => 1
185
+ # counters.fetch(:bar, 0) # => 0
186
+ # counters.fetch(:bar) { |key| 0 } # => 0
187
+ # counters.fetch(:zoo) # => KeyError: key not found: "zoo"
93
188
  def fetch(key, *extras)
94
189
  super(convert_key(key), *extras)
95
190
  end
96
191
 
97
192
  # Returns an array of the values at the specified indices:
98
193
  #
99
- # hash = HashWithIndifferentAccess.new
100
- # hash[:a] = "x"
101
- # hash[:b] = "y"
102
- # hash.values_at("a", "b") # => ["x", "y"]
103
- #
194
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
195
+ # hash[:a] = 'x'
196
+ # hash[:b] = 'y'
197
+ # hash.values_at('a', 'b') # => ["x", "y"]
104
198
  def values_at(*indices)
105
- indices.collect {|key| self[convert_key(key)]}
199
+ indices.collect { |key| self[convert_key(key)] }
106
200
  end
107
201
 
108
- # Returns an exact copy of the hash.
202
+ # Returns a shallow copy of the hash.
203
+ #
204
+ # hash = ActiveSupport::HashWithIndifferentAccess.new({ a: { b: 'b' } })
205
+ # dup = hash.dup
206
+ # dup[:a][:c] = 'c'
207
+ #
208
+ # hash[:a][:c] # => nil
209
+ # dup[:a][:c] # => "c"
109
210
  def dup
110
211
  self.class.new(self).tap do |new_hash|
111
- new_hash.default = default
212
+ set_defaults(new_hash)
112
213
  end
113
214
  end
114
215
 
115
- # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
116
- # Does not overwrite the existing hash.
117
- def merge(hash)
118
- self.dup.update(hash)
216
+ # This method has the same semantics of +update+, except it does not
217
+ # modify the receiver but rather returns a new hash with indifferent
218
+ # access with the result of the merge.
219
+ def merge(hash, &block)
220
+ self.dup.update(hash, &block)
119
221
  end
120
222
 
121
- # Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.
122
- # This overloaded definition prevents returning a regular hash, if reverse_merge is called on a <tt>HashWithDifferentAccess</tt>.
223
+ # Like +merge+ but the other way around: Merges the receiver into the
224
+ # argument and returns a new hash with indifferent access as result:
225
+ #
226
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
227
+ # hash['a'] = nil
228
+ # hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}
123
229
  def reverse_merge(other_hash)
124
- super self.class.new_from_hash_copying_default(other_hash)
230
+ super(self.class.new(other_hash))
125
231
  end
126
232
 
233
+ # Same semantics as +reverse_merge+ but modifies the receiver in-place.
127
234
  def reverse_merge!(other_hash)
128
235
  replace(reverse_merge( other_hash ))
129
236
  end
130
237
 
131
- # Removes a specified key from the hash.
238
+ # Replaces the contents of this hash with other_hash.
239
+ #
240
+ # h = { "a" => 100, "b" => 200 }
241
+ # h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400}
242
+ def replace(other_hash)
243
+ super(self.class.new(other_hash))
244
+ end
245
+
246
+ # Removes the specified key from the hash.
132
247
  def delete(key)
133
248
  super(convert_key(key))
134
249
  end
135
250
 
136
251
  def stringify_keys!; self end
252
+ def deep_stringify_keys!; self end
137
253
  def stringify_keys; dup end
254
+ def deep_stringify_keys; dup end
138
255
  undef :symbolize_keys!
139
- def symbolize_keys; to_hash.symbolize_keys end
256
+ undef :deep_symbolize_keys!
257
+ def symbolize_keys; to_hash.symbolize_keys! end
258
+ def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
140
259
  def to_options!; self end
141
260
 
142
- # Convert to a Hash with String keys.
261
+ def select(*args, &block)
262
+ return to_enum(:select) unless block_given?
263
+ dup.tap { |hash| hash.select!(*args, &block) }
264
+ end
265
+
266
+ def reject(*args, &block)
267
+ return to_enum(:reject) unless block_given?
268
+ dup.tap { |hash| hash.reject!(*args, &block) }
269
+ end
270
+
271
+ # Convert to a regular hash with string keys.
143
272
  def to_hash
144
- Hash.new(default).merge!(self)
273
+ _new_hash = Hash.new
274
+ set_defaults(_new_hash)
275
+
276
+ each do |key, value|
277
+ _new_hash[key] = convert_value(value, for: :to_hash)
278
+ end
279
+ _new_hash
145
280
  end
146
281
 
147
282
  protected
@@ -149,15 +284,30 @@ module ActiveSupport
149
284
  key.kind_of?(Symbol) ? key.to_s : key
150
285
  end
151
286
 
152
- def convert_value(value)
287
+ def convert_value(value, options = {})
153
288
  if value.is_a? Hash
154
- value.nested_under_indifferent_access
289
+ if options[:for] == :to_hash
290
+ value.to_hash
291
+ else
292
+ value.nested_under_indifferent_access
293
+ end
155
294
  elsif value.is_a?(Array)
156
- value.dup.replace(value.map { |e| convert_value(e) })
295
+ if options[:for] != :assignment || value.frozen?
296
+ value = value.dup
297
+ end
298
+ value.map! { |e| convert_value(e, options) }
157
299
  else
158
300
  value
159
301
  end
160
302
  end
303
+
304
+ def set_defaults(target)
305
+ if default_proc
306
+ target.default_proc = default_proc.dup
307
+ else
308
+ target.default = default
309
+ end
310
+ end
161
311
  end
162
312
  end
163
313
 
@@ -1,9 +1,13 @@
1
+ require 'active_support/core_ext/hash/deep_merge'
2
+ require 'active_support/core_ext/hash/except'
3
+ require 'active_support/core_ext/hash/slice'
1
4
  begin
2
5
  require 'i18n'
3
- require 'active_support/lazy_load_hooks'
4
6
  rescue LoadError => e
5
- $stderr.puts "You don't have i18n installed in your application. Please add it to your Gemfile and run bundle install"
7
+ $stderr.puts "The i18n gem is not available. Please add it to your Gemfile and run bundle install"
6
8
  raise e
7
9
  end
10
+ require 'active_support/lazy_load_hooks'
8
11
 
12
+ ActiveSupport.run_load_hooks(:i18n)
9
13
  I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml"