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,58 +1,103 @@
1
1
  require 'active_support/xml_mini'
2
2
  require 'active_support/core_ext/hash/keys'
3
- require 'active_support/core_ext/hash/reverse_merge'
4
3
  require 'active_support/core_ext/string/inflections'
4
+ require 'active_support/core_ext/object/to_param'
5
+ require 'active_support/core_ext/object/to_query'
5
6
 
6
7
  class Array
7
- # Converts the array to a comma-separated sentence where the last element is joined by the connector word. Options:
8
- # * <tt>:words_connector</tt> - The sign or word used to join the elements in arrays with two or more elements (default: ", ")
9
- # * <tt>:two_words_connector</tt> - The sign or word used to join the elements in arrays with two elements (default: " and ")
10
- # * <tt>:last_word_connector</tt> - The sign or word used to join the last element in arrays with three or more elements (default: ", and ")
8
+ # Converts the array to a comma-separated sentence where the last element is
9
+ # joined by the connector word.
10
+ #
11
+ # You can pass the following options to change the default behavior. If you
12
+ # pass an option key that doesn't exist in the list below, it will raise an
13
+ # <tt>ArgumentError</tt>.
14
+ #
15
+ # ==== Options
16
+ #
17
+ # * <tt>:words_connector</tt> - The sign or word used to join the elements
18
+ # in arrays with two or more elements (default: ", ").
19
+ # * <tt>:two_words_connector</tt> - The sign or word used to join the elements
20
+ # in arrays with two elements (default: " and ").
21
+ # * <tt>:last_word_connector</tt> - The sign or word used to join the last element
22
+ # in arrays with three or more elements (default: ", and ").
23
+ # * <tt>:locale</tt> - If +i18n+ is available, you can set a locale and use
24
+ # the connector options defined on the 'support.array' namespace in the
25
+ # corresponding dictionary file.
26
+ #
27
+ # ==== Examples
28
+ #
29
+ # [].to_sentence # => ""
30
+ # ['one'].to_sentence # => "one"
31
+ # ['one', 'two'].to_sentence # => "one and two"
32
+ # ['one', 'two', 'three'].to_sentence # => "one, two, and three"
33
+ #
34
+ # ['one', 'two'].to_sentence(passing: 'invalid option')
35
+ # # => ArgumentError: Unknown key: :passing. Valid keys are: :words_connector, :two_words_connector, :last_word_connector, :locale
36
+ #
37
+ # ['one', 'two'].to_sentence(two_words_connector: '-')
38
+ # # => "one-two"
39
+ #
40
+ # ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
41
+ # # => "one or two or at least three"
42
+ #
43
+ # Using <tt>:locale</tt> option:
44
+ #
45
+ # # Given this locale dictionary:
46
+ # #
47
+ # # es:
48
+ # # support:
49
+ # # array:
50
+ # # words_connector: " o "
51
+ # # two_words_connector: " y "
52
+ # # last_word_connector: " o al menos "
53
+ #
54
+ # ['uno', 'dos'].to_sentence(locale: :es)
55
+ # # => "uno y dos"
56
+ #
57
+ # ['uno', 'dos', 'tres'].to_sentence(locale: :es)
58
+ # # => "uno o dos o al menos tres"
11
59
  def to_sentence(options = {})
60
+ options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
61
+
62
+ default_connectors = {
63
+ :words_connector => ', ',
64
+ :two_words_connector => ' and ',
65
+ :last_word_connector => ', and '
66
+ }
12
67
  if defined?(I18n)
13
- default_words_connector = I18n.translate(:'support.array.words_connector', :locale => options[:locale])
14
- default_two_words_connector = I18n.translate(:'support.array.two_words_connector', :locale => options[:locale])
15
- default_last_word_connector = I18n.translate(:'support.array.last_word_connector', :locale => options[:locale])
16
- else
17
- default_words_connector = ", "
18
- default_two_words_connector = " and "
19
- default_last_word_connector = ", and "
68
+ i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
69
+ default_connectors.merge!(i18n_connectors)
20
70
  end
21
-
22
- options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
23
- options.reverse_merge! :words_connector => default_words_connector, :two_words_connector => default_two_words_connector, :last_word_connector => default_last_word_connector
71
+ options = default_connectors.merge!(options)
24
72
 
25
73
  case length
26
- when 0
27
- ""
28
- when 1
29
- self[0].to_s.dup
30
- when 2
31
- "#{self[0]}#{options[:two_words_connector]}#{self[1]}"
32
- else
33
- "#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
74
+ when 0
75
+ ''
76
+ when 1
77
+ "#{self[0]}"
78
+ when 2
79
+ "#{self[0]}#{options[:two_words_connector]}#{self[1]}"
80
+ else
81
+ "#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
34
82
  end
35
83
  end
36
84
 
37
- # Converts a collection of elements into a formatted string by calling
38
- # <tt>to_s</tt> on all elements and joining them:
39
- #
40
- # Blog.all.to_formatted_s # => "First PostSecond PostThird Post"
41
- #
42
- # Adding in the <tt>:db</tt> argument as the format yields a prettier
43
- # output:
85
+ # Extends <tt>Array#to_s</tt> to convert a collection of elements into a
86
+ # comma separated id list if <tt>:db</tt> argument is given as the format.
44
87
  #
45
- # Blog.all.to_formatted_s(:db) # => "First Post,Second Post,Third Post"
88
+ # Blog.all.to_formatted_s(:db) # => "1,2,3"
89
+ # Blog.none.to_formatted_s(:db) # => "null"
90
+ # [1,2].to_formatted_s # => "[1, 2]"
46
91
  def to_formatted_s(format = :default)
47
92
  case format
48
- when :db
49
- if respond_to?(:empty?) && self.empty?
50
- "null"
51
- else
52
- collect { |element| element.id }.join(",")
53
- end
93
+ when :db
94
+ if empty?
95
+ 'null'
54
96
  else
55
- to_default_s
97
+ collect(&:id).join(',')
98
+ end
99
+ else
100
+ to_default_s
56
101
  end
57
102
  end
58
103
  alias_method :to_default_s, :to_s
@@ -86,20 +131,20 @@ class Array
86
131
  # </project>
87
132
  # </projects>
88
133
  #
89
- # Otherwise the root element is "records":
134
+ # Otherwise the root element is "objects":
90
135
  #
91
- # [{:foo => 1, :bar => 2}, {:baz => 3}].to_xml
136
+ # [{ foo: 1, bar: 2}, { baz: 3}].to_xml
92
137
  #
93
138
  # <?xml version="1.0" encoding="UTF-8"?>
94
- # <records type="array">
95
- # <record>
139
+ # <objects type="array">
140
+ # <object>
96
141
  # <bar type="integer">2</bar>
97
142
  # <foo type="integer">1</foo>
98
- # </record>
99
- # <record>
143
+ # </object>
144
+ # <object>
100
145
  # <baz type="integer">3</baz>
101
- # </record>
102
- # </records>
146
+ # </object>
147
+ # </objects>
103
148
  #
104
149
  # If the collection is empty the root element is "nil-classes" by default:
105
150
  #
@@ -110,7 +155,7 @@ class Array
110
155
  #
111
156
  # To ensure a meaningful root element use the <tt>:root</tt> option:
112
157
  #
113
- # customer_with_no_projects.projects.to_xml(:root => "projects")
158
+ # customer_with_no_projects.projects.to_xml(root: 'projects')
114
159
  #
115
160
  # <?xml version="1.0" encoding="UTF-8"?>
116
161
  # <projects type="array"/>
@@ -120,7 +165,7 @@ class Array
120
165
  #
121
166
  # The +options+ hash is passed downwards:
122
167
  #
123
- # Message.all.to_xml(:skip_types => true)
168
+ # Message.all.to_xml(skip_types: true)
124
169
  #
125
170
  # <?xml version="1.0" encoding="UTF-8"?>
126
171
  # <messages>
@@ -138,27 +183,29 @@ class Array
138
183
 
139
184
  options = options.dup
140
185
  options[:indent] ||= 2
141
- options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
142
- options[:root] ||= if first.class.to_s != "Hash" && all? { |e| e.is_a?(first.class) }
143
- underscored = ActiveSupport::Inflector.underscore(first.class.name)
144
- ActiveSupport::Inflector.pluralize(underscored).tr('/', '_')
145
- else
146
- "objects"
147
- end
186
+ options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
187
+ options[:root] ||= \
188
+ if first.class != Hash && all? { |e| e.is_a?(first.class) }
189
+ underscored = ActiveSupport::Inflector.underscore(first.class.name)
190
+ ActiveSupport::Inflector.pluralize(underscored).tr('/', '_')
191
+ else
192
+ 'objects'
193
+ end
148
194
 
149
195
  builder = options[:builder]
150
196
  builder.instruct! unless options.delete(:skip_instruct)
151
197
 
152
198
  root = ActiveSupport::XmlMini.rename_key(options[:root].to_s, options)
153
199
  children = options.delete(:children) || root.singularize
200
+ attributes = options[:skip_types] ? {} : { type: 'array' }
154
201
 
155
- attributes = options[:skip_types] ? {} : {:type => "array"}
156
- return builder.tag!(root, attributes) if empty?
157
-
158
- builder.__send__(:method_missing, root, attributes) do
159
- each { |value| ActiveSupport::XmlMini.to_tag(children, value, options) }
160
- yield builder if block_given?
202
+ if empty?
203
+ builder.tag!(root, attributes)
204
+ else
205
+ builder.tag!(root, attributes) do
206
+ each { |value| ActiveSupport::XmlMini.to_tag(children, value, options) }
207
+ yield builder if block_given?
208
+ end
161
209
  end
162
210
  end
163
-
164
211
  end
@@ -17,8 +17,8 @@ class Array
17
17
  # args.extract_options!
18
18
  # end
19
19
  #
20
- # options(1, 2) # => {}
21
- # options(1, 2, :a => :b) # => {:a=>:b}
20
+ # options(1, 2) # => {}
21
+ # options(1, 2, a: :b) # => {:a=>:b}
22
22
  def extract_options!
23
23
  if last.is_a?(Hash) && last.extractable_options?
24
24
  pop
@@ -1,22 +1,28 @@
1
- require 'enumerator'
2
-
3
1
  class Array
4
2
  # Splits or iterates over the array in groups of size +number+,
5
3
  # padding any remaining slots with +fill_with+ unless it is +false+.
6
4
  #
7
- # %w(1 2 3 4 5 6 7).in_groups_of(3) {|group| p group}
5
+ # %w(1 2 3 4 5 6 7 8 9 10).in_groups_of(3) {|group| p group}
8
6
  # ["1", "2", "3"]
9
7
  # ["4", "5", "6"]
10
- # ["7", nil, nil]
8
+ # ["7", "8", "9"]
9
+ # ["10", nil, nil]
11
10
  #
12
- # %w(1 2 3).in_groups_of(2, '&nbsp;') {|group| p group}
11
+ # %w(1 2 3 4 5).in_groups_of(2, '&nbsp;') {|group| p group}
13
12
  # ["1", "2"]
14
- # ["3", "&nbsp;"]
13
+ # ["3", "4"]
14
+ # ["5", "&nbsp;"]
15
15
  #
16
- # %w(1 2 3).in_groups_of(2, false) {|group| p group}
16
+ # %w(1 2 3 4 5).in_groups_of(2, false) {|group| p group}
17
17
  # ["1", "2"]
18
- # ["3"]
18
+ # ["3", "4"]
19
+ # ["5"]
19
20
  def in_groups_of(number, fill_with = nil)
21
+ if number.to_i <= 0
22
+ raise ArgumentError,
23
+ "Group size must be a positive integer, was #{number.inspect}"
24
+ end
25
+
20
26
  if fill_with == false
21
27
  collection = self
22
28
  else
@@ -24,15 +30,13 @@ class Array
24
30
  # subtracting from number gives how many to add;
25
31
  # modulo number ensures we don't add group of just fill.
26
32
  padding = (number - size % number) % number
27
- collection = dup.concat([fill_with] * padding)
33
+ collection = dup.concat(Array.new(padding, fill_with))
28
34
  end
29
35
 
30
36
  if block_given?
31
37
  collection.each_slice(number) { |slice| yield(slice) }
32
38
  else
33
- groups = []
34
- collection.each_slice(number) { |group| groups << group }
35
- groups
39
+ collection.each_slice(number).to_a
36
40
  end
37
41
  end
38
42
 
@@ -44,20 +48,20 @@ class Array
44
48
  # ["5", "6", "7", nil]
45
49
  # ["8", "9", "10", nil]
46
50
  #
47
- # %w(1 2 3 4 5 6 7).in_groups(3, '&nbsp;') {|group| p group}
48
- # ["1", "2", "3"]
49
- # ["4", "5", "&nbsp;"]
50
- # ["6", "7", "&nbsp;"]
51
+ # %w(1 2 3 4 5 6 7 8 9 10).in_groups(3, '&nbsp;') {|group| p group}
52
+ # ["1", "2", "3", "4"]
53
+ # ["5", "6", "7", "&nbsp;"]
54
+ # ["8", "9", "10", "&nbsp;"]
51
55
  #
52
56
  # %w(1 2 3 4 5 6 7).in_groups(3, false) {|group| p group}
53
57
  # ["1", "2", "3"]
54
58
  # ["4", "5"]
55
59
  # ["6", "7"]
56
60
  def in_groups(number, fill_with = nil)
57
- # size / number gives minor group size;
61
+ # size.div number gives minor group size;
58
62
  # size % number gives how many objects need extra accommodation;
59
63
  # each group hold either division or division + 1 items.
60
- division = size / number
64
+ division = size.div number
61
65
  modulo = size % number
62
66
 
63
67
  # create a new array avoiding dup
@@ -66,9 +70,9 @@ class Array
66
70
 
67
71
  number.times do |index|
68
72
  length = division + (modulo > 0 && modulo > index ? 1 : 0)
69
- padding = fill_with != false &&
70
- modulo > 0 && length == division ? 1 : 0
71
- groups << slice(start, length).concat([fill_with] * padding)
73
+ groups << last_group = slice(start, length)
74
+ last_group << fill_with if fill_with != false &&
75
+ modulo > 0 && length == division
72
76
  start += length
73
77
  end
74
78
 
@@ -82,19 +86,22 @@ class Array
82
86
  # Divides the array into one or more subarrays based on a delimiting +value+
83
87
  # or the result of an optional block.
84
88
  #
85
- # [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
86
- # (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
89
+ # [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
90
+ # (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
87
91
  def split(value = nil)
88
- using_block = block_given?
89
-
90
- inject([[]]) do |results, element|
91
- if (using_block && yield(element)) || (value == element)
92
- results << []
93
- else
94
- results.last << element
92
+ arr = self.dup
93
+ result = []
94
+ if block_given?
95
+ while (idx = arr.index { |i| yield i })
96
+ result << arr.shift(idx)
97
+ arr.shift
98
+ end
99
+ else
100
+ while (idx = arr.index(value))
101
+ result << arr.shift(idx)
102
+ arr.shift
95
103
  end
96
-
97
- results
98
104
  end
105
+ result << arr
99
106
  end
100
107
  end
@@ -0,0 +1,17 @@
1
+ require 'active_support/array_inquirer'
2
+
3
+ class Array
4
+ # Wraps the array in an +ArrayInquirer+ object, which gives a friendlier way
5
+ # to check its string-like contents.
6
+ #
7
+ # pets = [:cat, :dog].inquiry
8
+ #
9
+ # pets.cat? # => true
10
+ # pets.ferret? # => false
11
+ #
12
+ # pets.any?(:cat, :ferret) # => true
13
+ # pets.any?(:ferret, :alligator) # => false
14
+ def inquiry
15
+ ActiveSupport::ArrayInquirer.new(self)
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ class Array
2
+ # The human way of thinking about adding stuff to the end of a list is with append.
3
+ alias_method :append, :<<
4
+
5
+ # The human way of thinking about adding stuff to the beginning of a list is with prepend.
6
+ alias_method :prepend, :unshift
7
+ end
@@ -3,44 +3,42 @@ class Array
3
3
  #
4
4
  # Specifically:
5
5
  #
6
- # * If the argument is +nil+ an empty list is returned.
6
+ # * If the argument is +nil+ an empty array is returned.
7
7
  # * Otherwise, if the argument responds to +to_ary+ it is invoked, and its result returned.
8
8
  # * Otherwise, returns an array with the argument as its single element.
9
9
  #
10
- # Array.wrap(nil) # => []
11
- # Array.wrap([1, 2, 3]) # => [1, 2, 3]
12
- # Array.wrap(0) # => [0]
10
+ # Array.wrap(nil) # => []
11
+ # Array.wrap([1, 2, 3]) # => [1, 2, 3]
12
+ # Array.wrap(0) # => [0]
13
13
  #
14
14
  # This method is similar in purpose to <tt>Kernel#Array</tt>, but there are some differences:
15
15
  #
16
16
  # * If the argument responds to +to_ary+ the method is invoked. <tt>Kernel#Array</tt>
17
- # moves on to try +to_a+ if the returned value is +nil+, but <tt>Array.wrap</tt> returns
18
- # such a +nil+ right away.
17
+ # moves on to try +to_a+ if the returned value is +nil+, but <tt>Array.wrap</tt> returns
18
+ # an array with the argument as its single element right away.
19
19
  # * If the returned value from +to_ary+ is neither +nil+ nor an +Array+ object, <tt>Kernel#Array</tt>
20
- # raises an exception, while <tt>Array.wrap</tt> does not, it just returns the value.
21
- # * It does not call +to_a+ on the argument, though special-cases +nil+ to return an empty array.
20
+ # raises an exception, while <tt>Array.wrap</tt> does not, it just returns the value.
21
+ # * It does not call +to_a+ on the argument, if the argument does not respond to +to_ary+
22
+ # it returns an array with the argument as its single element.
22
23
  #
23
- # The last point is particularly worth comparing for some enumerables:
24
+ # The last point is easily explained with some enumerables:
24
25
  #
25
- # Array(:foo => :bar) # => [[:foo, :bar]]
26
- # Array.wrap(:foo => :bar) # => [{:foo => :bar}]
27
- #
28
- # Array("foo\nbar") # => ["foo\n", "bar"], in Ruby 1.8
29
- # Array.wrap("foo\nbar") # => ["foo\nbar"]
26
+ # Array(foo: :bar) # => [[:foo, :bar]]
27
+ # Array.wrap(foo: :bar) # => [{:foo=>:bar}]
30
28
  #
31
29
  # There's also a related idiom that uses the splat operator:
32
30
  #
33
31
  # [*object]
34
32
  #
35
- # which returns <tt>[nil]</tt> for +nil+, and calls to <tt>Array(object)</tt> otherwise.
33
+ # which returns <tt>[]</tt> for +nil+, but calls to <tt>Array(object)</tt> otherwise.
36
34
  #
37
- # Thus, in this case the behavior is different for +nil+, and the differences with
38
- # <tt>Kernel#Array</tt> explained above apply to the rest of +object+s.
35
+ # The differences with <tt>Kernel#Array</tt> explained above
36
+ # apply to the rest of <tt>object</tt>s.
39
37
  def self.wrap(object)
40
38
  if object.nil?
41
39
  []
42
40
  elsif object.respond_to?(:to_ary)
43
- object.to_ary
41
+ object.to_ary || [object]
44
42
  else
45
43
  [object]
46
44
  end
@@ -1,7 +1,7 @@
1
1
  require 'active_support/core_ext/array/wrap'
2
2
  require 'active_support/core_ext/array/access'
3
- require 'active_support/core_ext/array/uniq_by'
4
3
  require 'active_support/core_ext/array/conversions'
5
4
  require 'active_support/core_ext/array/extract_options'
6
5
  require 'active_support/core_ext/array/grouping'
7
- require 'active_support/core_ext/array/random_access'
6
+ require 'active_support/core_ext/array/prepend_and_append'
7
+ require 'active_support/core_ext/array/inquiry'
@@ -1,6 +1,13 @@
1
1
  require 'benchmark'
2
2
 
3
3
  class << Benchmark
4
+ # Benchmark realtime in milliseconds.
5
+ #
6
+ # Benchmark.realtime { User.all }
7
+ # # => 8.0e-05
8
+ #
9
+ # Benchmark.ms { User.all }
10
+ # # => 0.074
4
11
  def ms
5
12
  1000 * realtime { yield }
6
13
  end
@@ -1,42 +1,14 @@
1
1
  require 'bigdecimal'
2
+ require 'bigdecimal/util'
2
3
 
3
- begin
4
- require 'psych'
5
- rescue LoadError
6
- end
7
-
8
- require 'yaml'
9
-
10
- class BigDecimal
11
- YAML_TAG = 'tag:yaml.org,2002:float'
12
- YAML_MAPPING = { 'Infinity' => '.Inf', '-Infinity' => '-.Inf', 'NaN' => '.NaN' }
4
+ module ActiveSupport
5
+ module BigDecimalWithDefaultFormat #:nodoc:
6
+ DEFAULT_STRING_FORMAT = 'F'
13
7
 
14
- # This emits the number without any scientific notation.
15
- # This is better than self.to_f.to_s since it doesn't lose precision.
16
- #
17
- # Note that reconstituting YAML floats to native floats may lose precision.
18
- def to_yaml(opts = {})
19
- return super if defined?(YAML::ENGINE) && !YAML::ENGINE.syck?
20
-
21
- YAML.quick_emit(nil, opts) do |out|
22
- string = to_s
23
- out.scalar(YAML_TAG, YAML_MAPPING[string] || string, :plain)
8
+ def to_s(format = nil)
9
+ super(format || DEFAULT_STRING_FORMAT)
24
10
  end
25
11
  end
26
-
27
- def encode_with(coder)
28
- string = to_s
29
- coder.represent_scalar(nil, YAML_MAPPING[string] || string)
30
- end
31
-
32
- def to_d
33
- self
34
- end
35
-
36
- DEFAULT_STRING_FORMAT = 'F'
37
- def to_formatted_s(format = DEFAULT_STRING_FORMAT)
38
- _original_to_s(format)
39
- end
40
- alias_method :_original_to_s, :to_s
41
- alias_method :to_s, :to_formatted_s
42
12
  end
13
+
14
+ BigDecimal.prepend(ActiveSupport::BigDecimalWithDefaultFormat)
@@ -44,7 +44,8 @@ class Class
44
44
  # Base.setting # => []
45
45
  # Subclass.setting # => [:foo]
46
46
  #
47
- # For convenience, a query method is defined as well:
47
+ # For convenience, an instance predicate method is defined as well.
48
+ # To skip it, pass <tt>instance_predicate: false</tt>.
48
49
  #
49
50
  # Subclass.setting? # => false
50
51
  #
@@ -57,59 +58,71 @@ class Class
57
58
  # object.setting # => false
58
59
  # Base.setting # => true
59
60
  #
60
- # To opt out of the instance reader method, pass :instance_reader => false.
61
+ # To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
61
62
  #
62
63
  # object.setting # => NoMethodError
63
64
  # object.setting? # => NoMethodError
64
65
  #
65
- # To opt out of the instance writer method, pass :instance_writer => false.
66
+ # To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
66
67
  #
67
68
  # object.setting = false # => NoMethodError
69
+ #
70
+ # To opt out of both instance methods, pass <tt>instance_accessor: false</tt>.
68
71
  def class_attribute(*attrs)
69
72
  options = attrs.extract_options!
70
- instance_reader = options.fetch(:instance_reader, true)
71
- instance_writer = options.fetch(:instance_writer, true)
73
+ instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
74
+ instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
75
+ instance_predicate = options.fetch(:instance_predicate, true)
72
76
 
73
77
  attrs.each do |name|
74
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
75
- def self.#{name}() nil end
76
- def self.#{name}?() !!#{name} end
78
+ remove_possible_singleton_method(name)
79
+ define_singleton_method(name) { nil }
77
80
 
78
- def self.#{name}=(val)
79
- singleton_class.class_eval do
80
- remove_possible_method(:#{name})
81
- define_method(:#{name}) { val }
82
- end
81
+ remove_possible_singleton_method("#{name}?")
82
+ define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
83
+
84
+ ivar = "@#{name}"
85
+
86
+ remove_possible_singleton_method("#{name}=")
87
+ define_singleton_method("#{name}=") do |val|
88
+ singleton_class.class_eval do
89
+ remove_possible_method(name)
90
+ define_method(name) { val }
91
+ end
83
92
 
84
- if singleton_class?
85
- class_eval do
86
- remove_possible_method(:#{name})
87
- def #{name}
88
- defined?(@#{name}) ? @#{name} : singleton_class.#{name}
93
+ if singleton_class?
94
+ class_eval do
95
+ remove_possible_method(name)
96
+ define_method(name) do
97
+ if instance_variable_defined? ivar
98
+ instance_variable_get ivar
99
+ else
100
+ singleton_class.send name
89
101
  end
90
102
  end
91
103
  end
92
- val
93
104
  end
105
+ val
106
+ end
94
107
 
95
- if instance_reader
96
- remove_possible_method :#{name}
97
- def #{name}
98
- defined?(@#{name}) ? @#{name} : self.class.#{name}
99
- end
100
-
101
- def #{name}?
102
- !!#{name}
108
+ if instance_reader
109
+ remove_possible_method name
110
+ define_method(name) do
111
+ if instance_variable_defined?(ivar)
112
+ instance_variable_get ivar
113
+ else
114
+ self.class.public_send name
103
115
  end
104
116
  end
105
- RUBY
106
117
 
107
- attr_writer name if instance_writer
108
- end
109
- end
118
+ remove_possible_method "#{name}?"
119
+ define_method("#{name}?") { !!public_send(name) } if instance_predicate
120
+ end
110
121
 
111
- private
112
- def singleton_class?
113
- !name || '' == name
122
+ if instance_writer
123
+ remove_possible_method "#{name}="
124
+ attr_writer name
125
+ end
126
+ end
114
127
  end
115
128
  end