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
@@ -4,20 +4,18 @@ module ActiveSupport
4
4
  # module M
5
5
  # def self.included(base)
6
6
  # base.extend ClassMethods
7
- # base.send(:include, InstanceMethods)
8
- # scope :disabled, where(:disabled => true)
7
+ # base.class_eval do
8
+ # scope :disabled, -> { where(disabled: true) }
9
+ # end
9
10
  # end
10
11
  #
11
12
  # module ClassMethods
12
13
  # ...
13
14
  # end
14
- #
15
- # module InstanceMethods
16
- # ...
17
- # end
18
15
  # end
19
16
  #
20
- # By using <tt>ActiveSupport::Concern</tt> the above module could instead be written as:
17
+ # By using <tt>ActiveSupport::Concern</tt> the above module could instead be
18
+ # written as:
21
19
  #
22
20
  # require 'active_support/concern'
23
21
  #
@@ -25,20 +23,17 @@ module ActiveSupport
25
23
  # extend ActiveSupport::Concern
26
24
  #
27
25
  # included do
28
- # scope :disabled, where(:disabled => true)
26
+ # scope :disabled, -> { where(disabled: true) }
29
27
  # end
30
28
  #
31
- # module ClassMethods
32
- # ...
33
- # end
34
- #
35
- # module InstanceMethods
29
+ # class_methods do
36
30
  # ...
37
31
  # end
38
32
  # end
39
33
  #
40
- # Moreover, it gracefully handles module dependencies. Given a +Foo+ module and a +Bar+
41
- # module which depends on the former, we would typically write the following:
34
+ # Moreover, it gracefully handles module dependencies. Given a +Foo+ module
35
+ # and a +Bar+ module which depends on the former, we would typically write the
36
+ # following:
42
37
  #
43
38
  # module Foo
44
39
  # def self.included(base)
@@ -61,11 +56,11 @@ module ActiveSupport
61
56
  # include Bar # Bar is the module that Host really needs
62
57
  # end
63
58
  #
64
- # But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We could try to hide
65
- # these from +Host+ directly including +Foo+ in +Bar+:
59
+ # But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We
60
+ # could try to hide these from +Host+ directly including +Foo+ in +Bar+:
66
61
  #
67
62
  # module Bar
68
- # include Foo
63
+ # include Foo
69
64
  # def self.included(base)
70
65
  # base.method_injected_by_foo
71
66
  # end
@@ -75,18 +70,17 @@ module ActiveSupport
75
70
  # include Bar
76
71
  # end
77
72
  #
78
- # Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt> is the +Bar+ module,
79
- # not the +Host+ class. With <tt>ActiveSupport::Concern</tt>, module dependencies are properly resolved:
73
+ # Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
74
+ # is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
75
+ # module dependencies are properly resolved:
80
76
  #
81
77
  # require 'active_support/concern'
82
78
  #
83
79
  # module Foo
84
80
  # extend ActiveSupport::Concern
85
81
  # included do
86
- # class_eval do
87
- # def self.method_injected_by_foo
88
- # ...
89
- # end
82
+ # def self.method_injected_by_foo
83
+ # ...
90
84
  # end
91
85
  # end
92
86
  # end
@@ -101,34 +95,48 @@ module ActiveSupport
101
95
  # end
102
96
  #
103
97
  # class Host
104
- # include Bar # works, Bar takes care now of its dependencies
98
+ # include Bar # It works, now Bar takes care of its dependencies
105
99
  # end
106
- #
107
100
  module Concern
108
- def self.extended(base)
109
- base.instance_variable_set("@_dependencies", [])
101
+ class MultipleIncludedBlocks < StandardError #:nodoc:
102
+ def initialize
103
+ super "Cannot define multiple 'included' blocks for a Concern"
104
+ end
105
+ end
106
+
107
+ def self.extended(base) #:nodoc:
108
+ base.instance_variable_set(:@_dependencies, [])
110
109
  end
111
110
 
112
111
  def append_features(base)
113
- if base.instance_variable_defined?("@_dependencies")
114
- base.instance_variable_get("@_dependencies") << self
112
+ if base.instance_variable_defined?(:@_dependencies)
113
+ base.instance_variable_get(:@_dependencies) << self
115
114
  return false
116
115
  else
117
116
  return false if base < self
118
- @_dependencies.each { |dep| base.send(:include, dep) }
117
+ @_dependencies.each { |dep| base.include(dep) }
119
118
  super
120
- base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
121
- base.send :include, const_get("InstanceMethods") if const_defined?("InstanceMethods")
122
- base.class_eval(&@_included_block) if instance_variable_defined?("@_included_block")
119
+ base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)
120
+ base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block)
123
121
  end
124
122
  end
125
123
 
126
124
  def included(base = nil, &block)
127
125
  if base.nil?
126
+ raise MultipleIncludedBlocks if instance_variable_defined?(:@_included_block)
127
+
128
128
  @_included_block = block
129
129
  else
130
130
  super
131
131
  end
132
132
  end
133
+
134
+ def class_methods(&class_methods_module_definition)
135
+ mod = const_defined?(:ClassMethods, false) ?
136
+ const_get(:ClassMethods) :
137
+ const_set(:ClassMethods, Module.new)
138
+
139
+ mod.module_eval(&class_methods_module_definition)
140
+ end
133
141
  end
134
142
  end
@@ -0,0 +1,19 @@
1
+ require 'concurrent/atomic/count_down_latch'
2
+
3
+ module ActiveSupport
4
+ module Concurrency
5
+ class Latch < Concurrent::CountDownLatch
6
+
7
+ def initialize(count = 1)
8
+ ActiveSupport::Deprecation.warn("ActiveSupport::Concurrency::Latch is deprecated. Please use Concurrent::CountDownLatch instead.")
9
+ super(count)
10
+ end
11
+
12
+ alias_method :release, :count_down
13
+
14
+ def await
15
+ wait(nil)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,186 @@
1
+ require 'thread'
2
+ require 'monitor'
3
+
4
+ module ActiveSupport
5
+ module Concurrency
6
+ # A share/exclusive lock, otherwise known as a read/write lock.
7
+ #
8
+ # https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock
9
+ class ShareLock
10
+ include MonitorMixin
11
+
12
+ # We track Thread objects, instead of just using counters, because
13
+ # we need exclusive locks to be reentrant, and we need to be able
14
+ # to upgrade share locks to exclusive.
15
+
16
+
17
+ def initialize
18
+ super()
19
+
20
+ @cv = new_cond
21
+
22
+ @sharing = Hash.new(0)
23
+ @waiting = {}
24
+ @exclusive_thread = nil
25
+ @exclusive_depth = 0
26
+ end
27
+
28
+ # Returns false if +no_wait+ is set and the lock is not
29
+ # immediately available. Otherwise, returns true after the lock
30
+ # has been acquired.
31
+ #
32
+ # +purpose+ and +compatible+ work together; while this thread is
33
+ # waiting for the exclusive lock, it will yield its share (if any)
34
+ # to any other attempt whose +purpose+ appears in this attempt's
35
+ # +compatible+ list. This allows a "loose" upgrade, which, being
36
+ # less strict, prevents some classes of deadlocks.
37
+ #
38
+ # For many resources, loose upgrades are sufficient: if a thread
39
+ # is awaiting a lock, it is not running any other code. With
40
+ # +purpose+ matching, it is possible to yield only to other
41
+ # threads whose activity will not interfere.
42
+ def start_exclusive(purpose: nil, compatible: [], no_wait: false)
43
+ synchronize do
44
+ unless @exclusive_thread == Thread.current
45
+ if busy_for_exclusive?(purpose)
46
+ return false if no_wait
47
+
48
+ yield_shares(purpose: purpose, compatible: compatible, block_share: true) do
49
+ @cv.wait_while { busy_for_exclusive?(purpose) }
50
+ end
51
+ end
52
+ @exclusive_thread = Thread.current
53
+ end
54
+ @exclusive_depth += 1
55
+
56
+ true
57
+ end
58
+ end
59
+
60
+ # Relinquish the exclusive lock. Must only be called by the thread
61
+ # that called start_exclusive (and currently holds the lock).
62
+ def stop_exclusive(compatible: [])
63
+ synchronize do
64
+ raise "invalid unlock" if @exclusive_thread != Thread.current
65
+
66
+ @exclusive_depth -= 1
67
+ if @exclusive_depth == 0
68
+ @exclusive_thread = nil
69
+
70
+ if eligible_waiters?(compatible)
71
+ yield_shares(compatible: compatible, block_share: true) do
72
+ @cv.wait_while { @exclusive_thread || eligible_waiters?(compatible) }
73
+ end
74
+ end
75
+ @cv.broadcast
76
+ end
77
+ end
78
+ end
79
+
80
+ def start_sharing
81
+ synchronize do
82
+ if @sharing[Thread.current] > 0 || @exclusive_thread == Thread.current
83
+ # We already hold a lock; nothing to wait for
84
+ elsif @waiting[Thread.current]
85
+ # We're nested inside a +yield_shares+ call: we'll resume as
86
+ # soon as there isn't an exclusive lock in our way
87
+ @cv.wait_while { @exclusive_thread }
88
+ else
89
+ # This is an initial / outermost share call: any outstanding
90
+ # requests for an exclusive lock get to go first
91
+ @cv.wait_while { busy_for_sharing?(false) }
92
+ end
93
+ @sharing[Thread.current] += 1
94
+ end
95
+ end
96
+
97
+ def stop_sharing
98
+ synchronize do
99
+ if @sharing[Thread.current] > 1
100
+ @sharing[Thread.current] -= 1
101
+ else
102
+ @sharing.delete Thread.current
103
+ @cv.broadcast
104
+ end
105
+ end
106
+ end
107
+
108
+ # Execute the supplied block while holding the Exclusive lock. If
109
+ # +no_wait+ is set and the lock is not immediately available,
110
+ # returns +nil+ without yielding. Otherwise, returns the result of
111
+ # the block.
112
+ #
113
+ # See +start_exclusive+ for other options.
114
+ def exclusive(purpose: nil, compatible: [], after_compatible: [], no_wait: false)
115
+ if start_exclusive(purpose: purpose, compatible: compatible, no_wait: no_wait)
116
+ begin
117
+ yield
118
+ ensure
119
+ stop_exclusive(compatible: after_compatible)
120
+ end
121
+ end
122
+ end
123
+
124
+ # Execute the supplied block while holding the Share lock.
125
+ def sharing
126
+ start_sharing
127
+ begin
128
+ yield
129
+ ensure
130
+ stop_sharing
131
+ end
132
+ end
133
+
134
+ # Temporarily give up all held Share locks while executing the
135
+ # supplied block, allowing any +compatible+ exclusive lock request
136
+ # to proceed.
137
+ def yield_shares(purpose: nil, compatible: [], block_share: false)
138
+ loose_shares = previous_wait = nil
139
+ synchronize do
140
+ if loose_shares = @sharing.delete(Thread.current)
141
+ if previous_wait = @waiting[Thread.current]
142
+ purpose = nil unless purpose == previous_wait[0]
143
+ compatible &= previous_wait[1]
144
+ end
145
+ compatible |= [false] unless block_share
146
+ @waiting[Thread.current] = [purpose, compatible]
147
+ end
148
+
149
+ @cv.broadcast
150
+ end
151
+
152
+ begin
153
+ yield
154
+ ensure
155
+ synchronize do
156
+ @cv.wait_while { @exclusive_thread && @exclusive_thread != Thread.current }
157
+
158
+ if previous_wait
159
+ @waiting[Thread.current] = previous_wait
160
+ else
161
+ @waiting.delete Thread.current
162
+ end
163
+ @sharing[Thread.current] = loose_shares if loose_shares
164
+ end
165
+ end
166
+ end
167
+
168
+ private
169
+
170
+ # Must be called within synchronize
171
+ def busy_for_exclusive?(purpose)
172
+ busy_for_sharing?(purpose) ||
173
+ @sharing.size > (@sharing[Thread.current] > 0 ? 1 : 0)
174
+ end
175
+
176
+ def busy_for_sharing?(purpose)
177
+ (@exclusive_thread && @exclusive_thread != Thread.current) ||
178
+ @waiting.any? { |t, (_, c)| t != Thread.current && !c.include?(purpose) }
179
+ end
180
+
181
+ def eligible_waiters?(compatible)
182
+ @waiting.any? { |t, (p, _)| compatible.include?(p) && @waiting.all? { |t2, (_, c2)| t == t2 || c2.include?(p) } }
183
+ end
184
+ end
185
+ end
186
+ end
@@ -1,7 +1,5 @@
1
1
  require 'active_support/concern'
2
2
  require 'active_support/ordered_options'
3
- require 'active_support/core_ext/kernel/singleton_class'
4
- require 'active_support/core_ext/module/delegation'
5
3
  require 'active_support/core_ext/array/extract_options'
6
4
 
7
5
  module ActiveSupport
@@ -15,7 +13,7 @@ module ActiveSupport
15
13
  self.class.compile_methods!(keys)
16
14
  end
17
15
 
18
- # compiles reader methods so we don't have to go through method_missing
16
+ # Compiles reader methods so we don't have to go through method_missing.
19
17
  def self.compile_methods!(keys)
20
18
  keys.reject { |m| method_defined?(m) }.each do |key|
21
19
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
@@ -39,31 +37,92 @@ module ActiveSupport
39
37
  yield config
40
38
  end
41
39
 
42
- # Allows you to add shortcut so that you don't have to refer to attribute through config.
43
- # Also look at the example for config to contrast.
40
+ # Allows you to add shortcut so that you don't have to refer to attribute
41
+ # through config. Also look at the example for config to contrast.
42
+ #
43
+ # Defines both class and instance config accessors.
44
44
  #
45
45
  # class User
46
46
  # include ActiveSupport::Configurable
47
47
  # config_accessor :allowed_access
48
48
  # end
49
49
  #
50
+ # User.allowed_access # => nil
51
+ # User.allowed_access = false
52
+ # User.allowed_access # => false
53
+ #
50
54
  # user = User.new
55
+ # user.allowed_access # => false
51
56
  # user.allowed_access = true
52
57
  # user.allowed_access # => true
53
58
  #
59
+ # User.allowed_access # => false
60
+ #
61
+ # The attribute name must be a valid method name in Ruby.
62
+ #
63
+ # class User
64
+ # include ActiveSupport::Configurable
65
+ # config_accessor :"1_Badname"
66
+ # end
67
+ # # => NameError: invalid config attribute name
68
+ #
69
+ # To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
70
+ # To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
71
+ #
72
+ # class User
73
+ # include ActiveSupport::Configurable
74
+ # config_accessor :allowed_access, instance_reader: false, instance_writer: false
75
+ # end
76
+ #
77
+ # User.allowed_access = false
78
+ # User.allowed_access # => false
79
+ #
80
+ # User.new.allowed_access = true # => NoMethodError
81
+ # User.new.allowed_access # => NoMethodError
82
+ #
83
+ # Or pass <tt>instance_accessor: false</tt>, to opt out both instance methods.
84
+ #
85
+ # class User
86
+ # include ActiveSupport::Configurable
87
+ # config_accessor :allowed_access, instance_accessor: false
88
+ # end
89
+ #
90
+ # User.allowed_access = false
91
+ # User.allowed_access # => false
92
+ #
93
+ # User.new.allowed_access = true # => NoMethodError
94
+ # User.new.allowed_access # => NoMethodError
95
+ #
96
+ # Also you can pass a block to set up the attribute with a default value.
97
+ #
98
+ # class User
99
+ # include ActiveSupport::Configurable
100
+ # config_accessor :hair_colors do
101
+ # [:brown, :black, :blonde, :red]
102
+ # end
103
+ # end
104
+ #
105
+ # User.hair_colors # => [:brown, :black, :blonde, :red]
54
106
  def config_accessor(*names)
55
107
  options = names.extract_options!
56
108
 
57
109
  names.each do |name|
58
- reader, line = "def #{name}; config.#{name}; end", __LINE__
59
- writer, line = "def #{name}=(value); config.#{name} = value; end", __LINE__
110
+ raise NameError.new('invalid config attribute name') unless name =~ /\A[_A-Za-z]\w*\z/
60
111
 
61
- singleton_class.class_eval reader, __FILE__, line
62
- singleton_class.class_eval writer, __FILE__, line
63
- class_eval reader, __FILE__, line unless options[:instance_reader] == false
64
- class_eval writer, __FILE__, line unless options[:instance_writer] == false
112
+ reader, reader_line = "def #{name}; config.#{name}; end", __LINE__
113
+ writer, writer_line = "def #{name}=(value); config.#{name} = value; end", __LINE__
114
+
115
+ singleton_class.class_eval reader, __FILE__, reader_line
116
+ singleton_class.class_eval writer, __FILE__, writer_line
117
+
118
+ unless options[:instance_accessor] == false
119
+ class_eval reader, __FILE__, reader_line unless options[:instance_reader] == false
120
+ class_eval writer, __FILE__, writer_line unless options[:instance_writer] == false
121
+ end
122
+ send("#{name}=", yield) if block_given?
65
123
  end
66
124
  end
125
+ private :config_accessor
67
126
  end
68
127
 
69
128
  # Reads and writes attributes from a configuration <tt>OrderedHash</tt>.
@@ -81,7 +140,6 @@ module ActiveSupport
81
140
  #
82
141
  # user.config.allowed_access # => true
83
142
  # user.config.level # => 1
84
- #
85
143
  def config
86
144
  @_config ||= self.class.config.inheritable_copy
87
145
  end
@@ -1,46 +1,90 @@
1
1
  class Array
2
2
  # Returns the tail of the array from +position+.
3
3
  #
4
- # %w( a b c d ).from(0) # => %w( a b c d )
5
- # %w( a b c d ).from(2) # => %w( c d )
6
- # %w( a b c d ).from(10) # => %w()
7
- # %w().from(0) # => %w()
4
+ # %w( a b c d ).from(0) # => ["a", "b", "c", "d"]
5
+ # %w( a b c d ).from(2) # => ["c", "d"]
6
+ # %w( a b c d ).from(10) # => []
7
+ # %w().from(0) # => []
8
+ # %w( a b c d ).from(-2) # => ["c", "d"]
9
+ # %w( a b c ).from(-10) # => []
8
10
  def from(position)
9
11
  self[position, length] || []
10
12
  end
11
13
 
12
14
  # Returns the beginning of the array up to +position+.
13
15
  #
14
- # %w( a b c d ).to(0) # => %w( a )
15
- # %w( a b c d ).to(2) # => %w( a b c )
16
- # %w( a b c d ).to(10) # => %w( a b c d )
17
- # %w().to(0) # => %w()
16
+ # %w( a b c d ).to(0) # => ["a"]
17
+ # %w( a b c d ).to(2) # => ["a", "b", "c"]
18
+ # %w( a b c d ).to(10) # => ["a", "b", "c", "d"]
19
+ # %w().to(0) # => []
20
+ # %w( a b c d ).to(-2) # => ["a", "b", "c"]
21
+ # %w( a b c ).to(-10) # => []
18
22
  def to(position)
19
- self[0..position]
23
+ if position >= 0
24
+ take position + 1
25
+ else
26
+ self[0..position]
27
+ end
28
+ end
29
+
30
+ # Returns a copy of the Array without the specified elements.
31
+ #
32
+ # people = ["David", "Rafael", "Aaron", "Todd"]
33
+ # people.without "Aaron", "Todd"
34
+ # => ["David", "Rafael"]
35
+ #
36
+ # Note: This is an optimization of `Enumerable#without` that uses `Array#-`
37
+ # instead of `Array#reject` for performance reasons.
38
+ def without(*elements)
39
+ self - elements
20
40
  end
21
41
 
22
42
  # Equal to <tt>self[1]</tt>.
43
+ #
44
+ # %w( a b c d e ).second # => "b"
23
45
  def second
24
46
  self[1]
25
47
  end
26
48
 
27
49
  # Equal to <tt>self[2]</tt>.
50
+ #
51
+ # %w( a b c d e ).third # => "c"
28
52
  def third
29
53
  self[2]
30
54
  end
31
55
 
32
56
  # Equal to <tt>self[3]</tt>.
57
+ #
58
+ # %w( a b c d e ).fourth # => "d"
33
59
  def fourth
34
60
  self[3]
35
61
  end
36
62
 
37
63
  # Equal to <tt>self[4]</tt>.
64
+ #
65
+ # %w( a b c d e ).fifth # => "e"
38
66
  def fifth
39
67
  self[4]
40
68
  end
41
69
 
42
70
  # Equal to <tt>self[41]</tt>. Also known as accessing "the reddit".
71
+ #
72
+ # (1..42).to_a.forty_two # => 42
43
73
  def forty_two
44
74
  self[41]
45
75
  end
76
+
77
+ # Equal to <tt>self[-3]</tt>.
78
+ #
79
+ # %w( a b c d e ).third_to_last # => "c"
80
+ def third_to_last
81
+ self[-3]
82
+ end
83
+
84
+ # Equal to <tt>self[-2]</tt>.
85
+ #
86
+ # %w( a b c d e ).second_to_last # => "d"
87
+ def second_to_last
88
+ self[-2]
89
+ end
46
90
  end