activesupport 5.0.7.1

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 (236) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1013 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +39 -0
  5. data/lib/active_support.rb +99 -0
  6. data/lib/active_support/all.rb +3 -0
  7. data/lib/active_support/array_inquirer.rb +44 -0
  8. data/lib/active_support/backtrace_cleaner.rb +103 -0
  9. data/lib/active_support/benchmarkable.rb +49 -0
  10. data/lib/active_support/builder.rb +6 -0
  11. data/lib/active_support/cache.rb +701 -0
  12. data/lib/active_support/cache/file_store.rb +204 -0
  13. data/lib/active_support/cache/mem_cache_store.rb +207 -0
  14. data/lib/active_support/cache/memory_store.rb +167 -0
  15. data/lib/active_support/cache/null_store.rb +41 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +172 -0
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
  18. data/lib/active_support/callbacks.rb +791 -0
  19. data/lib/active_support/concern.rb +142 -0
  20. data/lib/active_support/concurrency/latch.rb +26 -0
  21. data/lib/active_support/concurrency/share_lock.rb +226 -0
  22. data/lib/active_support/configurable.rb +148 -0
  23. data/lib/active_support/core_ext.rb +4 -0
  24. data/lib/active_support/core_ext/array.rb +7 -0
  25. data/lib/active_support/core_ext/array/access.rb +90 -0
  26. data/lib/active_support/core_ext/array/conversions.rb +211 -0
  27. data/lib/active_support/core_ext/array/extract_options.rb +29 -0
  28. data/lib/active_support/core_ext/array/grouping.rb +107 -0
  29. data/lib/active_support/core_ext/array/inquiry.rb +17 -0
  30. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
  31. data/lib/active_support/core_ext/array/wrap.rb +46 -0
  32. data/lib/active_support/core_ext/benchmark.rb +14 -0
  33. data/lib/active_support/core_ext/big_decimal.rb +1 -0
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
  35. data/lib/active_support/core_ext/class.rb +2 -0
  36. data/lib/active_support/core_ext/class/attribute.rb +128 -0
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -0
  38. data/lib/active_support/core_ext/class/subclasses.rb +41 -0
  39. data/lib/active_support/core_ext/date.rb +5 -0
  40. data/lib/active_support/core_ext/date/acts_like.rb +8 -0
  41. data/lib/active_support/core_ext/date/blank.rb +12 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +143 -0
  43. data/lib/active_support/core_ext/date/conversions.rb +95 -0
  44. data/lib/active_support/core_ext/date/zones.rb +6 -0
  45. data/lib/active_support/core_ext/date_and_time/calculations.rb +335 -0
  46. data/lib/active_support/core_ext/date_and_time/compatibility.rb +14 -0
  47. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  48. data/lib/active_support/core_ext/date_time.rb +5 -0
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +14 -0
  50. data/lib/active_support/core_ext/date_time/blank.rb +12 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +199 -0
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
  53. data/lib/active_support/core_ext/date_time/conversions.rb +105 -0
  54. data/lib/active_support/core_ext/digest/uuid.rb +51 -0
  55. data/lib/active_support/core_ext/enumerable.rb +146 -0
  56. data/lib/active_support/core_ext/file.rb +1 -0
  57. data/lib/active_support/core_ext/file/atomic.rb +68 -0
  58. data/lib/active_support/core_ext/hash.rb +9 -0
  59. data/lib/active_support/core_ext/hash/compact.rb +24 -0
  60. data/lib/active_support/core_ext/hash/conversions.rb +262 -0
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +38 -0
  62. data/lib/active_support/core_ext/hash/except.rb +22 -0
  63. data/lib/active_support/core_ext/hash/indifferent_access.rb +23 -0
  64. data/lib/active_support/core_ext/hash/keys.rb +170 -0
  65. data/lib/active_support/core_ext/hash/reverse_merge.rb +22 -0
  66. data/lib/active_support/core_ext/hash/slice.rb +48 -0
  67. data/lib/active_support/core_ext/hash/transform_values.rb +29 -0
  68. data/lib/active_support/core_ext/integer.rb +3 -0
  69. data/lib/active_support/core_ext/integer/inflections.rb +29 -0
  70. data/lib/active_support/core_ext/integer/multiple.rb +10 -0
  71. data/lib/active_support/core_ext/integer/time.rb +29 -0
  72. data/lib/active_support/core_ext/kernel.rb +4 -0
  73. data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
  74. data/lib/active_support/core_ext/kernel/concern.rb +12 -0
  75. data/lib/active_support/core_ext/kernel/debugger.rb +3 -0
  76. data/lib/active_support/core_ext/kernel/reporting.rb +43 -0
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +6 -0
  78. data/lib/active_support/core_ext/load_error.rb +31 -0
  79. data/lib/active_support/core_ext/marshal.rb +22 -0
  80. data/lib/active_support/core_ext/module.rb +12 -0
  81. data/lib/active_support/core_ext/module/aliasing.rb +74 -0
  82. data/lib/active_support/core_ext/module/anonymous.rb +28 -0
  83. data/lib/active_support/core_ext/module/attr_internal.rb +36 -0
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +212 -0
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +135 -0
  87. data/lib/active_support/core_ext/module/delegation.rb +216 -0
  88. data/lib/active_support/core_ext/module/deprecation.rb +23 -0
  89. data/lib/active_support/core_ext/module/introspection.rb +68 -0
  90. data/lib/active_support/core_ext/module/method_transplanting.rb +3 -0
  91. data/lib/active_support/core_ext/module/qualified_const.rb +70 -0
  92. data/lib/active_support/core_ext/module/reachable.rb +8 -0
  93. data/lib/active_support/core_ext/module/remove_method.rb +35 -0
  94. data/lib/active_support/core_ext/name_error.rb +31 -0
  95. data/lib/active_support/core_ext/numeric.rb +4 -0
  96. data/lib/active_support/core_ext/numeric/bytes.rb +64 -0
  97. data/lib/active_support/core_ext/numeric/conversions.rb +144 -0
  98. data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
  99. data/lib/active_support/core_ext/numeric/time.rb +74 -0
  100. data/lib/active_support/core_ext/object.rb +14 -0
  101. data/lib/active_support/core_ext/object/acts_like.rb +10 -0
  102. data/lib/active_support/core_ext/object/blank.rb +143 -0
  103. data/lib/active_support/core_ext/object/conversions.rb +4 -0
  104. data/lib/active_support/core_ext/object/deep_dup.rb +53 -0
  105. data/lib/active_support/core_ext/object/duplicable.rb +124 -0
  106. data/lib/active_support/core_ext/object/inclusion.rb +27 -0
  107. data/lib/active_support/core_ext/object/instance_variables.rb +28 -0
  108. data/lib/active_support/core_ext/object/json.rb +205 -0
  109. data/lib/active_support/core_ext/object/to_param.rb +1 -0
  110. data/lib/active_support/core_ext/object/to_query.rb +84 -0
  111. data/lib/active_support/core_ext/object/try.rb +146 -0
  112. data/lib/active_support/core_ext/object/with_options.rb +69 -0
  113. data/lib/active_support/core_ext/range.rb +4 -0
  114. data/lib/active_support/core_ext/range/conversions.rb +31 -0
  115. data/lib/active_support/core_ext/range/each.rb +21 -0
  116. data/lib/active_support/core_ext/range/include_range.rb +23 -0
  117. data/lib/active_support/core_ext/range/overlaps.rb +8 -0
  118. data/lib/active_support/core_ext/regexp.rb +5 -0
  119. data/lib/active_support/core_ext/securerandom.rb +23 -0
  120. data/lib/active_support/core_ext/string.rb +13 -0
  121. data/lib/active_support/core_ext/string/access.rb +104 -0
  122. data/lib/active_support/core_ext/string/behavior.rb +6 -0
  123. data/lib/active_support/core_ext/string/conversions.rb +57 -0
  124. data/lib/active_support/core_ext/string/exclude.rb +11 -0
  125. data/lib/active_support/core_ext/string/filters.rb +102 -0
  126. data/lib/active_support/core_ext/string/indent.rb +43 -0
  127. data/lib/active_support/core_ext/string/inflections.rb +244 -0
  128. data/lib/active_support/core_ext/string/inquiry.rb +13 -0
  129. data/lib/active_support/core_ext/string/multibyte.rb +53 -0
  130. data/lib/active_support/core_ext/string/output_safety.rb +260 -0
  131. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -0
  132. data/lib/active_support/core_ext/string/strip.rb +23 -0
  133. data/lib/active_support/core_ext/string/zones.rb +14 -0
  134. data/lib/active_support/core_ext/struct.rb +3 -0
  135. data/lib/active_support/core_ext/time.rb +5 -0
  136. data/lib/active_support/core_ext/time/acts_like.rb +8 -0
  137. data/lib/active_support/core_ext/time/calculations.rb +290 -0
  138. data/lib/active_support/core_ext/time/compatibility.rb +14 -0
  139. data/lib/active_support/core_ext/time/conversions.rb +67 -0
  140. data/lib/active_support/core_ext/time/marshal.rb +3 -0
  141. data/lib/active_support/core_ext/time/zones.rb +111 -0
  142. data/lib/active_support/core_ext/uri.rb +24 -0
  143. data/lib/active_support/dependencies.rb +755 -0
  144. data/lib/active_support/dependencies/autoload.rb +77 -0
  145. data/lib/active_support/dependencies/interlock.rb +55 -0
  146. data/lib/active_support/deprecation.rb +43 -0
  147. data/lib/active_support/deprecation/behaviors.rb +90 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +37 -0
  149. data/lib/active_support/deprecation/method_wrappers.rb +70 -0
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +149 -0
  151. data/lib/active_support/deprecation/reporting.rb +112 -0
  152. data/lib/active_support/descendants_tracker.rb +60 -0
  153. data/lib/active_support/duration.rb +235 -0
  154. data/lib/active_support/duration/iso8601_parser.rb +122 -0
  155. data/lib/active_support/duration/iso8601_serializer.rb +51 -0
  156. data/lib/active_support/evented_file_update_checker.rb +199 -0
  157. data/lib/active_support/execution_wrapper.rb +126 -0
  158. data/lib/active_support/executor.rb +6 -0
  159. data/lib/active_support/file_update_checker.rb +157 -0
  160. data/lib/active_support/gem_version.rb +15 -0
  161. data/lib/active_support/gzip.rb +36 -0
  162. data/lib/active_support/hash_with_indifferent_access.rb +329 -0
  163. data/lib/active_support/i18n.rb +13 -0
  164. data/lib/active_support/i18n_railtie.rb +115 -0
  165. data/lib/active_support/inflections.rb +70 -0
  166. data/lib/active_support/inflector.rb +7 -0
  167. data/lib/active_support/inflector/inflections.rb +242 -0
  168. data/lib/active_support/inflector/methods.rb +390 -0
  169. data/lib/active_support/inflector/transliterate.rb +112 -0
  170. data/lib/active_support/json.rb +2 -0
  171. data/lib/active_support/json/decoding.rb +74 -0
  172. data/lib/active_support/json/encoding.rb +127 -0
  173. data/lib/active_support/key_generator.rb +71 -0
  174. data/lib/active_support/lazy_load_hooks.rb +76 -0
  175. data/lib/active_support/locale/en.yml +135 -0
  176. data/lib/active_support/log_subscriber.rb +109 -0
  177. data/lib/active_support/log_subscriber/test_helper.rb +104 -0
  178. data/lib/active_support/logger.rb +106 -0
  179. data/lib/active_support/logger_silence.rb +28 -0
  180. data/lib/active_support/logger_thread_safe_level.rb +31 -0
  181. data/lib/active_support/message_encryptor.rb +114 -0
  182. data/lib/active_support/message_verifier.rb +134 -0
  183. data/lib/active_support/multibyte.rb +21 -0
  184. data/lib/active_support/multibyte/chars.rb +231 -0
  185. data/lib/active_support/multibyte/unicode.rb +413 -0
  186. data/lib/active_support/notifications.rb +212 -0
  187. data/lib/active_support/notifications/fanout.rb +157 -0
  188. data/lib/active_support/notifications/instrumenter.rb +91 -0
  189. data/lib/active_support/number_helper.rb +368 -0
  190. data/lib/active_support/number_helper/number_converter.rb +182 -0
  191. data/lib/active_support/number_helper/number_to_currency_converter.rb +44 -0
  192. data/lib/active_support/number_helper/number_to_delimited_converter.rb +28 -0
  193. data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
  194. data/lib/active_support/number_helper/number_to_human_size_converter.rb +62 -0
  195. data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
  196. data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
  197. data/lib/active_support/number_helper/number_to_rounded_converter.rb +92 -0
  198. data/lib/active_support/option_merger.rb +25 -0
  199. data/lib/active_support/ordered_hash.rb +48 -0
  200. data/lib/active_support/ordered_options.rb +81 -0
  201. data/lib/active_support/per_thread_registry.rb +58 -0
  202. data/lib/active_support/proxy_object.rb +13 -0
  203. data/lib/active_support/rails.rb +27 -0
  204. data/lib/active_support/railtie.rb +51 -0
  205. data/lib/active_support/reloader.rb +129 -0
  206. data/lib/active_support/rescuable.rb +173 -0
  207. data/lib/active_support/security_utils.rb +27 -0
  208. data/lib/active_support/string_inquirer.rb +26 -0
  209. data/lib/active_support/subscriber.rb +120 -0
  210. data/lib/active_support/tagged_logging.rb +77 -0
  211. data/lib/active_support/test_case.rb +88 -0
  212. data/lib/active_support/testing/assertions.rb +99 -0
  213. data/lib/active_support/testing/autorun.rb +5 -0
  214. data/lib/active_support/testing/constant_lookup.rb +50 -0
  215. data/lib/active_support/testing/declarative.rb +26 -0
  216. data/lib/active_support/testing/deprecation.rb +36 -0
  217. data/lib/active_support/testing/file_fixtures.rb +34 -0
  218. data/lib/active_support/testing/isolation.rb +115 -0
  219. data/lib/active_support/testing/method_call_assertions.rb +41 -0
  220. data/lib/active_support/testing/setup_and_teardown.rb +50 -0
  221. data/lib/active_support/testing/stream.rb +42 -0
  222. data/lib/active_support/testing/tagged_logging.rb +25 -0
  223. data/lib/active_support/testing/time_helpers.rb +136 -0
  224. data/lib/active_support/time.rb +18 -0
  225. data/lib/active_support/time_with_zone.rb +511 -0
  226. data/lib/active_support/values/time_zone.rb +484 -0
  227. data/lib/active_support/values/unicode_tables.dat +0 -0
  228. data/lib/active_support/version.rb +8 -0
  229. data/lib/active_support/xml_mini.rb +209 -0
  230. data/lib/active_support/xml_mini/jdom.rb +181 -0
  231. data/lib/active_support/xml_mini/libxml.rb +77 -0
  232. data/lib/active_support/xml_mini/libxmlsax.rb +82 -0
  233. data/lib/active_support/xml_mini/nokogiri.rb +81 -0
  234. data/lib/active_support/xml_mini/nokogirisax.rb +85 -0
  235. data/lib/active_support/xml_mini/rexml.rb +128 -0
  236. metadata +350 -0
@@ -0,0 +1,69 @@
1
+ require 'active_support/option_merger'
2
+
3
+ class Object
4
+ # An elegant way to factor duplication out of options passed to a series of
5
+ # method calls. Each method called in the block, with the block variable as
6
+ # the receiver, will have its options merged with the default +options+ hash
7
+ # provided. Each method called on the block variable must take an options
8
+ # hash as its final argument.
9
+ #
10
+ # Without <tt>with_options</tt>, this code contains duplication:
11
+ #
12
+ # class Account < ActiveRecord::Base
13
+ # has_many :customers, dependent: :destroy
14
+ # has_many :products, dependent: :destroy
15
+ # has_many :invoices, dependent: :destroy
16
+ # has_many :expenses, dependent: :destroy
17
+ # end
18
+ #
19
+ # Using <tt>with_options</tt>, we can remove the duplication:
20
+ #
21
+ # class Account < ActiveRecord::Base
22
+ # with_options dependent: :destroy do |assoc|
23
+ # assoc.has_many :customers
24
+ # assoc.has_many :products
25
+ # assoc.has_many :invoices
26
+ # assoc.has_many :expenses
27
+ # end
28
+ # end
29
+ #
30
+ # It can also be used with an explicit receiver:
31
+ #
32
+ # I18n.with_options locale: user.locale, scope: 'newsletter' do |i18n|
33
+ # subject i18n.t :subject
34
+ # body i18n.t :body, user_name: user.name
35
+ # end
36
+ #
37
+ # When you don't pass an explicit receiver, it executes the whole block
38
+ # in merging options context:
39
+ #
40
+ # class Account < ActiveRecord::Base
41
+ # with_options dependent: :destroy do
42
+ # has_many :customers
43
+ # has_many :products
44
+ # has_many :invoices
45
+ # has_many :expenses
46
+ # end
47
+ # end
48
+ #
49
+ # <tt>with_options</tt> can also be nested since the call is forwarded to its receiver.
50
+ #
51
+ # NOTE: Each nesting level will merge inherited defaults in addition to their own.
52
+ #
53
+ # class Post < ActiveRecord::Base
54
+ # with_options if: :persisted?, length: { minimum: 50 } do
55
+ # validates :content, if: -> { content.present? }
56
+ # end
57
+ # end
58
+ #
59
+ # The code is equivalent to:
60
+ #
61
+ # validates :content, length: { minimum: 50 }, if: -> { content.present? }
62
+ #
63
+ # Hence the inherited default for `if` key is ignored.
64
+ #
65
+ def with_options(options, &block)
66
+ option_merger = ActiveSupport::OptionMerger.new(self, options)
67
+ block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
68
+ end
69
+ end
@@ -0,0 +1,4 @@
1
+ require 'active_support/core_ext/range/conversions'
2
+ require 'active_support/core_ext/range/include_range'
3
+ require 'active_support/core_ext/range/overlaps'
4
+ require 'active_support/core_ext/range/each'
@@ -0,0 +1,31 @@
1
+ module ActiveSupport::RangeWithFormat
2
+ RANGE_FORMATS = {
3
+ :db => Proc.new { |start, stop| "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'" }
4
+ }
5
+
6
+ # Convert range to a formatted string. See RANGE_FORMATS for predefined formats.
7
+ #
8
+ # range = (1..100) # => 1..100
9
+ #
10
+ # range.to_s # => "1..100"
11
+ # range.to_s(:db) # => "BETWEEN '1' AND '100'"
12
+ #
13
+ # == Adding your own range formats to to_s
14
+ # You can add your own formats to the Range::RANGE_FORMATS hash.
15
+ # Use the format name as the hash key and a Proc instance.
16
+ #
17
+ # # config/initializers/range_formats.rb
18
+ # Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_s(:db)} and #{stop.to_s(:db)}" }
19
+ def to_s(format = :default)
20
+ if formatter = RANGE_FORMATS[format]
21
+ formatter.call(first, last)
22
+ else
23
+ super()
24
+ end
25
+ end
26
+
27
+ alias_method :to_default_s, :to_s
28
+ alias_method :to_formatted_s, :to_s
29
+ end
30
+
31
+ Range.prepend(ActiveSupport::RangeWithFormat)
@@ -0,0 +1,21 @@
1
+ module ActiveSupport
2
+ module EachTimeWithZone #:nodoc:
3
+ def each(&block)
4
+ ensure_iteration_allowed
5
+ super
6
+ end
7
+
8
+ def step(n = 1, &block)
9
+ ensure_iteration_allowed
10
+ super
11
+ end
12
+
13
+ private
14
+
15
+ def ensure_iteration_allowed
16
+ raise TypeError, "can't iterate from #{first.class}" if first.is_a?(Time)
17
+ end
18
+ end
19
+ end
20
+
21
+ Range.prepend(ActiveSupport::EachTimeWithZone)
@@ -0,0 +1,23 @@
1
+ module ActiveSupport
2
+ module IncludeWithRange #:nodoc:
3
+ # Extends the default Range#include? to support range comparisons.
4
+ # (1..5).include?(1..5) # => true
5
+ # (1..5).include?(2..3) # => true
6
+ # (1..5).include?(2..6) # => false
7
+ #
8
+ # The native Range#include? behavior is untouched.
9
+ # ('a'..'f').include?('c') # => true
10
+ # (5..9).include?(11) # => false
11
+ def include?(value)
12
+ if value.is_a?(::Range)
13
+ # 1...10 includes 1..9 but it does not include 1..10.
14
+ operator = exclude_end? && !value.exclude_end? ? :< : :<=
15
+ super(value.first) && value.last.send(operator, last)
16
+ else
17
+ super
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ Range.prepend(ActiveSupport::IncludeWithRange)
@@ -0,0 +1,8 @@
1
+ class Range
2
+ # Compare two ranges and see if they overlap each other
3
+ # (1..5).overlaps?(4..6) # => true
4
+ # (1..5).overlaps?(7..9) # => false
5
+ def overlaps?(other)
6
+ cover?(other.first) || other.cover?(first)
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ class Regexp #:nodoc:
2
+ def multiline?
3
+ options & MULTILINE == MULTILINE
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ require 'securerandom'
2
+
3
+ module SecureRandom
4
+ BASE58_ALPHABET = ('0'..'9').to_a + ('A'..'Z').to_a + ('a'..'z').to_a - ['0', 'O', 'I', 'l']
5
+ # SecureRandom.base58 generates a random base58 string.
6
+ #
7
+ # The argument _n_ specifies the length, of the random string to be generated.
8
+ #
9
+ # If _n_ is not specified or is nil, 16 is assumed. It may be larger in the future.
10
+ #
11
+ # The result may contain alphanumeric characters except 0, O, I and l
12
+ #
13
+ # p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
14
+ # p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"
15
+ #
16
+ def self.base58(n = 16)
17
+ SecureRandom.random_bytes(n).unpack("C*").map do |byte|
18
+ idx = byte % 64
19
+ idx = SecureRandom.random_number(58) if idx >= 58
20
+ BASE58_ALPHABET[idx]
21
+ end.join
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ require 'active_support/core_ext/string/conversions'
2
+ require 'active_support/core_ext/string/filters'
3
+ require 'active_support/core_ext/string/multibyte'
4
+ require 'active_support/core_ext/string/starts_ends_with'
5
+ require 'active_support/core_ext/string/inflections'
6
+ require 'active_support/core_ext/string/access'
7
+ require 'active_support/core_ext/string/behavior'
8
+ require 'active_support/core_ext/string/output_safety'
9
+ require 'active_support/core_ext/string/exclude'
10
+ require 'active_support/core_ext/string/strip'
11
+ require 'active_support/core_ext/string/inquiry'
12
+ require 'active_support/core_ext/string/indent'
13
+ require 'active_support/core_ext/string/zones'
@@ -0,0 +1,104 @@
1
+ class String
2
+ # If you pass a single integer, returns a substring of one character at that
3
+ # position. The first character of the string is at position 0, the next at
4
+ # position 1, and so on. If a range is supplied, a substring containing
5
+ # characters at offsets given by the range is returned. In both cases, if an
6
+ # offset is negative, it is counted from the end of the string. Returns nil
7
+ # if the initial offset falls outside the string. Returns an empty string if
8
+ # the beginning of the range is greater than the end of the string.
9
+ #
10
+ # str = "hello"
11
+ # str.at(0) # => "h"
12
+ # str.at(1..3) # => "ell"
13
+ # str.at(-2) # => "l"
14
+ # str.at(-2..-1) # => "lo"
15
+ # str.at(5) # => nil
16
+ # str.at(5..-1) # => ""
17
+ #
18
+ # If a Regexp is given, the matching portion of the string is returned.
19
+ # If a String is given, that given string is returned if it occurs in
20
+ # the string. In both cases, nil is returned if there is no match.
21
+ #
22
+ # str = "hello"
23
+ # str.at(/lo/) # => "lo"
24
+ # str.at(/ol/) # => nil
25
+ # str.at("lo") # => "lo"
26
+ # str.at("ol") # => nil
27
+ def at(position)
28
+ self[position]
29
+ end
30
+
31
+ # Returns a substring from the given position to the end of the string.
32
+ # If the position is negative, it is counted from the end of the string.
33
+ #
34
+ # str = "hello"
35
+ # str.from(0) # => "hello"
36
+ # str.from(3) # => "lo"
37
+ # str.from(-2) # => "lo"
38
+ #
39
+ # You can mix it with +to+ method and do fun things like:
40
+ #
41
+ # str = "hello"
42
+ # str.from(0).to(-1) # => "hello"
43
+ # str.from(1).to(-2) # => "ell"
44
+ def from(position)
45
+ self[position..-1]
46
+ end
47
+
48
+ # Returns a substring from the beginning of the string to the given position.
49
+ # If the position is negative, it is counted from the end of the string.
50
+ #
51
+ # str = "hello"
52
+ # str.to(0) # => "h"
53
+ # str.to(3) # => "hell"
54
+ # str.to(-2) # => "hell"
55
+ #
56
+ # You can mix it with +from+ method and do fun things like:
57
+ #
58
+ # str = "hello"
59
+ # str.from(0).to(-1) # => "hello"
60
+ # str.from(1).to(-2) # => "ell"
61
+ def to(position)
62
+ self[0..position]
63
+ end
64
+
65
+ # Returns the first character. If a limit is supplied, returns a substring
66
+ # from the beginning of the string until it reaches the limit value. If the
67
+ # given limit is greater than or equal to the string length, returns a copy of self.
68
+ #
69
+ # str = "hello"
70
+ # str.first # => "h"
71
+ # str.first(1) # => "h"
72
+ # str.first(2) # => "he"
73
+ # str.first(0) # => ""
74
+ # str.first(6) # => "hello"
75
+ def first(limit = 1)
76
+ if limit == 0
77
+ ''
78
+ elsif limit >= size
79
+ self.dup
80
+ else
81
+ to(limit - 1)
82
+ end
83
+ end
84
+
85
+ # Returns the last character of the string. If a limit is supplied, returns a substring
86
+ # from the end of the string until it reaches the limit value (counting backwards). If
87
+ # the given limit is greater than or equal to the string length, returns a copy of self.
88
+ #
89
+ # str = "hello"
90
+ # str.last # => "o"
91
+ # str.last(1) # => "o"
92
+ # str.last(2) # => "lo"
93
+ # str.last(0) # => ""
94
+ # str.last(6) # => "hello"
95
+ def last(limit = 1)
96
+ if limit == 0
97
+ ''
98
+ elsif limit >= size
99
+ self.dup
100
+ else
101
+ from(-limit)
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,6 @@
1
+ class String
2
+ # Enables more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>.
3
+ def acts_like_string?
4
+ true
5
+ end
6
+ end
@@ -0,0 +1,57 @@
1
+ require 'date'
2
+ require 'active_support/core_ext/time/calculations'
3
+
4
+ class String
5
+ # Converts a string to a Time value.
6
+ # The +form+ can be either :utc or :local (default :local).
7
+ #
8
+ # The time is parsed using Time.parse method.
9
+ # If +form+ is :local, then the time is in the system timezone.
10
+ # If the date part is missing then the current date is used and if
11
+ # the time part is missing then it is assumed to be 00:00:00.
12
+ #
13
+ # "13-12-2012".to_time # => 2012-12-13 00:00:00 +0100
14
+ # "06:12".to_time # => 2012-12-13 06:12:00 +0100
15
+ # "2012-12-13 06:12".to_time # => 2012-12-13 06:12:00 +0100
16
+ # "2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
17
+ # "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 06:12:00 UTC
18
+ # "12/13/2012".to_time # => ArgumentError: argument out of range
19
+ def to_time(form = :local)
20
+ parts = Date._parse(self, false)
21
+ used_keys = %i(year mon mday hour min sec sec_fraction offset)
22
+ return if (parts.keys & used_keys).empty?
23
+
24
+ now = Time.now
25
+ time = Time.new(
26
+ parts.fetch(:year, now.year),
27
+ parts.fetch(:mon, now.month),
28
+ parts.fetch(:mday, now.day),
29
+ parts.fetch(:hour, 0),
30
+ parts.fetch(:min, 0),
31
+ parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
32
+ parts.fetch(:offset, form == :utc ? 0 : nil)
33
+ )
34
+
35
+ form == :utc ? time.utc : time.to_time
36
+ end
37
+
38
+ # Converts a string to a Date value.
39
+ #
40
+ # "1-1-2012".to_date # => Sun, 01 Jan 2012
41
+ # "01/01/2012".to_date # => Sun, 01 Jan 2012
42
+ # "2012-12-13".to_date # => Thu, 13 Dec 2012
43
+ # "12/13/2012".to_date # => ArgumentError: invalid date
44
+ def to_date
45
+ ::Date.parse(self, false) unless blank?
46
+ end
47
+
48
+ # Converts a string to a DateTime value.
49
+ #
50
+ # "1-1-2012".to_datetime # => Sun, 01 Jan 2012 00:00:00 +0000
51
+ # "01/01/2012 23:59:59".to_datetime # => Sun, 01 Jan 2012 23:59:59 +0000
52
+ # "2012-12-13 12:50".to_datetime # => Thu, 13 Dec 2012 12:50:00 +0000
53
+ # "12/13/2012".to_datetime # => ArgumentError: invalid date
54
+ def to_datetime
55
+ ::DateTime.parse(self, false) unless blank?
56
+ end
57
+ end
@@ -0,0 +1,11 @@
1
+ class String
2
+ # The inverse of <tt>String#include?</tt>. Returns true if the string
3
+ # does not include the other string.
4
+ #
5
+ # "hello".exclude? "lo" # => false
6
+ # "hello".exclude? "ol" # => true
7
+ # "hello".exclude? ?h # => false
8
+ def exclude?(string)
9
+ !include?(string)
10
+ end
11
+ end
@@ -0,0 +1,102 @@
1
+ class String
2
+ # Returns the string, first removing all whitespace on both ends of
3
+ # the string, and then changing remaining consecutive whitespace
4
+ # groups into one space each.
5
+ #
6
+ # Note that it handles both ASCII and Unicode whitespace.
7
+ #
8
+ # %{ Multi-line
9
+ # string }.squish # => "Multi-line string"
10
+ # " foo bar \n \t boo".squish # => "foo bar boo"
11
+ def squish
12
+ dup.squish!
13
+ end
14
+
15
+ # Performs a destructive squish. See String#squish.
16
+ # str = " foo bar \n \t boo"
17
+ # str.squish! # => "foo bar boo"
18
+ # str # => "foo bar boo"
19
+ def squish!
20
+ gsub!(/[[:space:]]+/, ' ')
21
+ strip!
22
+ self
23
+ end
24
+
25
+ # Returns a new string with all occurrences of the patterns removed.
26
+ # str = "foo bar test"
27
+ # str.remove(" test") # => "foo bar"
28
+ # str.remove(" test", /bar/) # => "foo "
29
+ # str # => "foo bar test"
30
+ def remove(*patterns)
31
+ dup.remove!(*patterns)
32
+ end
33
+
34
+ # Alters the string by removing all occurrences of the patterns.
35
+ # str = "foo bar test"
36
+ # str.remove!(" test", /bar/) # => "foo "
37
+ # str # => "foo "
38
+ def remove!(*patterns)
39
+ patterns.each do |pattern|
40
+ gsub! pattern, ""
41
+ end
42
+
43
+ self
44
+ end
45
+
46
+ # Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>:
47
+ #
48
+ # 'Once upon a time in a world far far away'.truncate(27)
49
+ # # => "Once upon a time in a wo..."
50
+ #
51
+ # Pass a string or regexp <tt>:separator</tt> to truncate +text+ at a natural break:
52
+ #
53
+ # 'Once upon a time in a world far far away'.truncate(27, separator: ' ')
54
+ # # => "Once upon a time in a..."
55
+ #
56
+ # 'Once upon a time in a world far far away'.truncate(27, separator: /\s/)
57
+ # # => "Once upon a time in a..."
58
+ #
59
+ # The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
60
+ # for a total length not exceeding <tt>length</tt>:
61
+ #
62
+ # 'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
63
+ # # => "And they f... (continued)"
64
+ def truncate(truncate_at, options = {})
65
+ return dup unless length > truncate_at
66
+
67
+ omission = options[:omission] || '...'
68
+ length_with_room_for_omission = truncate_at - omission.length
69
+ stop = \
70
+ if options[:separator]
71
+ rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission
72
+ else
73
+ length_with_room_for_omission
74
+ end
75
+
76
+ "#{self[0, stop]}#{omission}"
77
+ end
78
+
79
+ # Truncates a given +text+ after a given number of words (<tt>words_count</tt>):
80
+ #
81
+ # 'Once upon a time in a world far far away'.truncate_words(4)
82
+ # # => "Once upon a time..."
83
+ #
84
+ # Pass a string or regexp <tt>:separator</tt> to specify a different separator of words:
85
+ #
86
+ # 'Once<br>upon<br>a<br>time<br>in<br>a<br>world'.truncate_words(5, separator: '<br>')
87
+ # # => "Once<br>upon<br>a<br>time<br>in..."
88
+ #
89
+ # The last characters will be replaced with the <tt>:omission</tt> string (defaults to "..."):
90
+ #
91
+ # 'And they found that many people were sleeping better.'.truncate_words(5, omission: '... (continued)')
92
+ # # => "And they found that many... (continued)"
93
+ def truncate_words(words_count, options = {})
94
+ sep = options[:separator] || /\s+/
95
+ sep = Regexp.escape(sep.to_s) unless Regexp === sep
96
+ if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
97
+ $1 + (options[:omission] || '...')
98
+ else
99
+ dup
100
+ end
101
+ end
102
+ end