activesupport 4.2.11.3 → 5.0.7.2

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 (182) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +678 -348
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +2 -3
  5. data/lib/active_support/array_inquirer.rb +44 -0
  6. data/lib/active_support/backtrace_cleaner.rb +1 -1
  7. data/lib/active_support/benchmarkable.rb +1 -1
  8. data/lib/active_support/cache/file_store.rb +36 -22
  9. data/lib/active_support/cache/mem_cache_store.rb +63 -54
  10. data/lib/active_support/cache/memory_store.rb +16 -21
  11. data/lib/active_support/cache/null_store.rb +1 -4
  12. data/lib/active_support/cache/strategy/local_cache.rb +31 -20
  13. data/lib/active_support/cache/strategy/local_cache_middleware.rb +4 -4
  14. data/lib/active_support/cache.rb +71 -87
  15. data/lib/active_support/callbacks.rb +109 -113
  16. data/lib/active_support/concern.rb +1 -1
  17. data/lib/active_support/concurrency/latch.rb +11 -12
  18. data/lib/active_support/concurrency/share_lock.rb +226 -0
  19. data/lib/active_support/configurable.rb +1 -0
  20. data/lib/active_support/core_ext/array/access.rb +27 -1
  21. data/lib/active_support/core_ext/array/conversions.rb +6 -4
  22. data/lib/active_support/core_ext/array/grouping.rb +9 -18
  23. data/lib/active_support/core_ext/array/inquiry.rb +17 -0
  24. data/lib/active_support/core_ext/array/wrap.rb +5 -4
  25. data/lib/active_support/core_ext/array.rb +1 -0
  26. data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -10
  27. data/lib/active_support/core_ext/class/attribute.rb +10 -9
  28. data/lib/active_support/core_ext/class/subclasses.rb +3 -2
  29. data/lib/active_support/core_ext/class.rb +0 -1
  30. data/lib/active_support/core_ext/date/blank.rb +12 -0
  31. data/lib/active_support/core_ext/date/calculations.rb +1 -1
  32. data/lib/active_support/core_ext/date/conversions.rb +7 -6
  33. data/lib/active_support/core_ext/date.rb +1 -1
  34. data/lib/active_support/core_ext/date_and_time/calculations.rb +100 -27
  35. data/lib/active_support/core_ext/date_and_time/compatibility.rb +0 -1
  36. data/lib/active_support/core_ext/date_and_time/zones.rb +3 -4
  37. data/lib/active_support/core_ext/date_time/blank.rb +12 -0
  38. data/lib/active_support/core_ext/date_time/calculations.rb +14 -8
  39. data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
  40. data/lib/active_support/core_ext/date_time.rb +1 -1
  41. data/lib/active_support/core_ext/enumerable.rb +75 -25
  42. data/lib/active_support/core_ext/file/atomic.rb +30 -25
  43. data/lib/active_support/core_ext/hash/conversions.rb +22 -2
  44. data/lib/active_support/core_ext/hash/deep_merge.rb +1 -1
  45. data/lib/active_support/core_ext/hash/except.rb +9 -8
  46. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
  47. data/lib/active_support/core_ext/hash/keys.rb +25 -21
  48. data/lib/active_support/core_ext/hash/slice.rb +1 -1
  49. data/lib/active_support/core_ext/hash/transform_values.rb +11 -5
  50. data/lib/active_support/core_ext/integer/time.rb +2 -2
  51. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  52. data/lib/active_support/core_ext/kernel/debugger.rb +3 -10
  53. data/lib/active_support/core_ext/kernel/reporting.rb +2 -84
  54. data/lib/active_support/core_ext/kernel.rb +0 -1
  55. data/lib/active_support/core_ext/load_error.rb +5 -2
  56. data/lib/active_support/core_ext/marshal.rb +7 -9
  57. data/lib/active_support/core_ext/module/aliasing.rb +6 -1
  58. data/lib/active_support/core_ext/module/anonymous.rb +10 -1
  59. data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
  60. data/lib/active_support/core_ext/module/attribute_accessors.rb +15 -15
  61. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
  62. data/lib/active_support/core_ext/module/concerning.rb +4 -4
  63. data/lib/active_support/core_ext/module/delegation.rb +11 -20
  64. data/lib/active_support/core_ext/module/deprecation.rb +2 -2
  65. data/lib/active_support/core_ext/module/introspection.rb +8 -2
  66. data/lib/active_support/core_ext/module/method_transplanting.rb +3 -13
  67. data/lib/active_support/core_ext/module/qualified_const.rb +30 -12
  68. data/lib/active_support/core_ext/module/remove_method.rb +23 -0
  69. data/lib/active_support/core_ext/module.rb +1 -0
  70. data/lib/active_support/core_ext/name_error.rb +15 -2
  71. data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
  72. data/lib/active_support/core_ext/numeric/conversions.rb +78 -77
  73. data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
  74. data/lib/active_support/core_ext/numeric/time.rb +26 -6
  75. data/lib/active_support/core_ext/numeric.rb +1 -0
  76. data/lib/active_support/core_ext/object/blank.rb +15 -3
  77. data/lib/active_support/core_ext/object/deep_dup.rb +10 -3
  78. data/lib/active_support/core_ext/object/duplicable.rb +7 -12
  79. data/lib/active_support/core_ext/object/inclusion.rb +2 -2
  80. data/lib/active_support/core_ext/object/instance_variables.rb +1 -1
  81. data/lib/active_support/core_ext/object/json.rb +15 -7
  82. data/lib/active_support/core_ext/object/to_query.rb +1 -1
  83. data/lib/active_support/core_ext/object/try.rb +67 -21
  84. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  85. data/lib/active_support/core_ext/object.rb +0 -1
  86. data/lib/active_support/core_ext/range/conversions.rb +18 -6
  87. data/lib/active_support/core_ext/range/each.rb +16 -18
  88. data/lib/active_support/core_ext/range/include_range.rb +20 -20
  89. data/lib/active_support/core_ext/securerandom.rb +23 -0
  90. data/lib/active_support/core_ext/string/behavior.rb +1 -1
  91. data/lib/active_support/core_ext/string/conversions.rb +3 -2
  92. data/lib/active_support/core_ext/string/filters.rb +1 -2
  93. data/lib/active_support/core_ext/string/inflections.rb +32 -5
  94. data/lib/active_support/core_ext/string/multibyte.rb +11 -7
  95. data/lib/active_support/core_ext/string/output_safety.rb +12 -14
  96. data/lib/active_support/core_ext/string/strip.rb +3 -6
  97. data/lib/active_support/core_ext/struct.rb +3 -6
  98. data/lib/active_support/core_ext/time/calculations.rb +18 -9
  99. data/lib/active_support/core_ext/time/conversions.rb +4 -2
  100. data/lib/active_support/core_ext/time/marshal.rb +2 -29
  101. data/lib/active_support/core_ext/time/zones.rb +36 -4
  102. data/lib/active_support/core_ext/time.rb +0 -1
  103. data/lib/active_support/core_ext/uri.rb +1 -3
  104. data/lib/active_support/core_ext.rb +2 -1
  105. data/lib/active_support/dependencies/interlock.rb +55 -0
  106. data/lib/active_support/dependencies.rb +88 -95
  107. data/lib/active_support/deprecation/behaviors.rb +15 -1
  108. data/lib/active_support/deprecation/instance_delegator.rb +13 -0
  109. data/lib/active_support/deprecation/method_wrappers.rb +42 -16
  110. data/lib/active_support/deprecation/proxy_wrappers.rb +47 -24
  111. data/lib/active_support/deprecation/reporting.rb +23 -5
  112. data/lib/active_support/deprecation.rb +1 -1
  113. data/lib/active_support/duration/iso8601_parser.rb +122 -0
  114. data/lib/active_support/duration/iso8601_serializer.rb +51 -0
  115. data/lib/active_support/duration.rb +90 -15
  116. data/lib/active_support/evented_file_update_checker.rb +199 -0
  117. data/lib/active_support/execution_wrapper.rb +126 -0
  118. data/lib/active_support/executor.rb +6 -0
  119. data/lib/active_support/file_update_checker.rb +23 -3
  120. data/lib/active_support/gem_version.rb +5 -5
  121. data/lib/active_support/gzip.rb +1 -1
  122. data/lib/active_support/hash_with_indifferent_access.rb +40 -11
  123. data/lib/active_support/i18n_railtie.rb +25 -4
  124. data/lib/active_support/inflector/inflections.rb +36 -5
  125. data/lib/active_support/inflector/methods.rb +97 -90
  126. data/lib/active_support/inflector/transliterate.rb +36 -21
  127. data/lib/active_support/json/decoding.rb +11 -10
  128. data/lib/active_support/json/encoding.rb +1 -51
  129. data/lib/active_support/key_generator.rb +7 -9
  130. data/lib/active_support/lazy_load_hooks.rb +46 -18
  131. data/lib/active_support/locale/en.yml +2 -0
  132. data/lib/active_support/log_subscriber/test_helper.rb +3 -3
  133. data/lib/active_support/log_subscriber.rb +1 -1
  134. data/lib/active_support/logger.rb +3 -4
  135. data/lib/active_support/logger_silence.rb +2 -1
  136. data/lib/active_support/logger_thread_safe_level.rb +2 -3
  137. data/lib/active_support/message_encryptor.rb +7 -7
  138. data/lib/active_support/message_verifier.rb +70 -8
  139. data/lib/active_support/multibyte/chars.rb +12 -3
  140. data/lib/active_support/multibyte/unicode.rb +44 -21
  141. data/lib/active_support/notifications/fanout.rb +5 -5
  142. data/lib/active_support/notifications/instrumenter.rb +20 -2
  143. data/lib/active_support/notifications.rb +2 -2
  144. data/lib/active_support/number_helper/number_to_currency_converter.rb +7 -9
  145. data/lib/active_support/number_helper/number_to_delimited_converter.rb +8 -3
  146. data/lib/active_support/number_helper/number_to_human_converter.rb +6 -4
  147. data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -2
  148. data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
  149. data/lib/active_support/number_helper/number_to_phone_converter.rb +11 -2
  150. data/lib/active_support/number_helper/number_to_rounded_converter.rb +30 -25
  151. data/lib/active_support/number_helper.rb +90 -67
  152. data/lib/active_support/ordered_hash.rb +1 -1
  153. data/lib/active_support/ordered_options.rb +15 -1
  154. data/lib/active_support/per_thread_registry.rb +3 -0
  155. data/lib/active_support/rails.rb +2 -2
  156. data/lib/active_support/railtie.rb +6 -1
  157. data/lib/active_support/reloader.rb +129 -0
  158. data/lib/active_support/rescuable.rb +101 -47
  159. data/lib/active_support/string_inquirer.rb +1 -1
  160. data/lib/active_support/subscriber.rb +5 -10
  161. data/lib/active_support/tagged_logging.rb +8 -7
  162. data/lib/active_support/test_case.rb +17 -29
  163. data/lib/active_support/testing/assertions.rb +15 -13
  164. data/lib/active_support/testing/deprecation.rb +9 -8
  165. data/lib/active_support/testing/file_fixtures.rb +34 -0
  166. data/lib/active_support/testing/isolation.rb +22 -8
  167. data/lib/active_support/testing/method_call_assertions.rb +41 -0
  168. data/lib/active_support/testing/stream.rb +42 -0
  169. data/lib/active_support/testing/time_helpers.rb +3 -1
  170. data/lib/active_support/time_with_zone.rb +123 -33
  171. data/lib/active_support/values/time_zone.rb +101 -47
  172. data/lib/active_support/values/unicode_tables.dat +0 -0
  173. data/lib/active_support/xml_mini/jdom.rb +1 -1
  174. data/lib/active_support/xml_mini/libxml.rb +2 -2
  175. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  176. data/lib/active_support.rb +11 -6
  177. metadata +36 -17
  178. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  179. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  180. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  181. data/lib/active_support/core_ext/object/itself.rb +0 -15
  182. data/lib/active_support/core_ext/thread.rb +0 -86
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require 'active_support/inflections'
4
2
 
5
3
  module ActiveSupport
@@ -22,58 +20,58 @@ module ActiveSupport
22
20
  # pluralized using rules defined for that language. By default,
23
21
  # this parameter is set to <tt>:en</tt>.
24
22
  #
25
- # 'post'.pluralize # => "posts"
26
- # 'octopus'.pluralize # => "octopi"
27
- # 'sheep'.pluralize # => "sheep"
28
- # 'words'.pluralize # => "words"
29
- # 'CamelOctopus'.pluralize # => "CamelOctopi"
30
- # 'ley'.pluralize(:es) # => "leyes"
23
+ # pluralize('post') # => "posts"
24
+ # pluralize('octopus') # => "octopi"
25
+ # pluralize('sheep') # => "sheep"
26
+ # pluralize('words') # => "words"
27
+ # pluralize('CamelOctopus') # => "CamelOctopi"
28
+ # pluralize('ley', :es) # => "leyes"
31
29
  def pluralize(word, locale = :en)
32
30
  apply_inflections(word, inflections(locale).plurals)
33
31
  end
34
32
 
35
- # The reverse of +pluralize+, returns the singular form of a word in a
33
+ # The reverse of #pluralize, returns the singular form of a word in a
36
34
  # string.
37
35
  #
38
36
  # If passed an optional +locale+ parameter, the word will be
39
37
  # singularized using rules defined for that language. By default,
40
38
  # this parameter is set to <tt>:en</tt>.
41
39
  #
42
- # 'posts'.singularize # => "post"
43
- # 'octopi'.singularize # => "octopus"
44
- # 'sheep'.singularize # => "sheep"
45
- # 'word'.singularize # => "word"
46
- # 'CamelOctopi'.singularize # => "CamelOctopus"
47
- # 'leyes'.singularize(:es) # => "ley"
40
+ # singularize('posts') # => "post"
41
+ # singularize('octopi') # => "octopus"
42
+ # singularize('sheep') # => "sheep"
43
+ # singularize('word') # => "word"
44
+ # singularize('CamelOctopi') # => "CamelOctopus"
45
+ # singularize('leyes', :es) # => "ley"
48
46
  def singularize(word, locale = :en)
49
47
  apply_inflections(word, inflections(locale).singulars)
50
48
  end
51
49
 
52
- # By default, +camelize+ converts strings to UpperCamelCase. If the argument
53
- # to +camelize+ is set to <tt>:lower</tt> then +camelize+ produces
50
+ # Converts strings to UpperCamelCase.
51
+ # If the +uppercase_first_letter+ parameter is set to false, then produces
54
52
  # lowerCamelCase.
55
53
  #
56
- # +camelize+ will also convert '/' to '::' which is useful for converting
54
+ # Also converts '/' to '::' which is useful for converting
57
55
  # paths to namespaces.
58
56
  #
59
- # 'active_model'.camelize # => "ActiveModel"
60
- # 'active_model'.camelize(:lower) # => "activeModel"
61
- # 'active_model/errors'.camelize # => "ActiveModel::Errors"
62
- # 'active_model/errors'.camelize(:lower) # => "activeModel::Errors"
57
+ # camelize('active_model') # => "ActiveModel"
58
+ # camelize('active_model', false) # => "activeModel"
59
+ # camelize('active_model/errors') # => "ActiveModel::Errors"
60
+ # camelize('active_model/errors', false) # => "activeModel::Errors"
63
61
  #
64
62
  # As a rule of thumb you can think of +camelize+ as the inverse of
65
- # +underscore+, though there are cases where that does not hold:
63
+ # #underscore, though there are cases where that does not hold:
66
64
  #
67
- # 'SSLError'.underscore.camelize # => "SslError"
65
+ # camelize(underscore('SSLError')) # => "SslError"
68
66
  def camelize(term, uppercase_first_letter = true)
69
67
  string = term.to_s
70
68
  if uppercase_first_letter
71
- string = string.sub(/^[a-z\d]*/) { inflections.acronyms[$&] || $&.capitalize }
69
+ string = string.sub(/^[a-z\d]*/) { |match| inflections.acronyms[match] || match.capitalize }
72
70
  else
73
- string = string.sub(/^(?:#{inflections.acronym_regex}(?=\b|[A-Z_])|\w)/) { $&.downcase }
71
+ string = string.sub(/^(?:#{inflections.acronym_regex}(?=\b|[A-Z_])|\w)/) { |match| match.downcase }
74
72
  end
75
73
  string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }
76
- string.gsub!(/\//, '::')
74
+ string.gsub!('/'.freeze, '::'.freeze)
77
75
  string
78
76
  end
79
77
 
@@ -81,34 +79,34 @@ module ActiveSupport
81
79
  #
82
80
  # Changes '::' to '/' to convert namespaces to paths.
83
81
  #
84
- # 'ActiveModel'.underscore # => "active_model"
85
- # 'ActiveModel::Errors'.underscore # => "active_model/errors"
82
+ # underscore('ActiveModel') # => "active_model"
83
+ # underscore('ActiveModel::Errors') # => "active_model/errors"
86
84
  #
87
85
  # As a rule of thumb you can think of +underscore+ as the inverse of
88
- # +camelize+, though there are cases where that does not hold:
86
+ # #camelize, though there are cases where that does not hold:
89
87
  #
90
- # 'SSLError'.underscore.camelize # => "SslError"
88
+ # camelize(underscore('SSLError')) # => "SslError"
91
89
  def underscore(camel_cased_word)
92
90
  return camel_cased_word unless camel_cased_word =~ /[A-Z-]|::/
93
- word = camel_cased_word.to_s.gsub(/::/, '/')
94
- word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1 && '_'}#{$2.downcase}" }
95
- word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
96
- word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
97
- word.tr!("-", "_")
91
+ word = camel_cased_word.to_s.gsub('::'.freeze, '/'.freeze)
92
+ word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1 && '_'.freeze }#{$2.downcase}" }
93
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'.freeze)
94
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2'.freeze)
95
+ word.tr!("-".freeze, "_".freeze)
98
96
  word.downcase!
99
97
  word
100
98
  end
101
99
 
102
100
  # Tweaks an attribute name for display to end users.
103
101
  #
104
- # Specifically, +humanize+ performs these transformations:
102
+ # Specifically, performs these transformations:
105
103
  #
106
- # * Applies human inflection rules to the argument.
107
- # * Deletes leading underscores, if any.
108
- # * Removes a "_id" suffix if present.
109
- # * Replaces underscores with spaces, if any.
110
- # * Downcases all words except acronyms.
111
- # * Capitalizes the first word.
104
+ # * Applies human inflection rules to the argument.
105
+ # * Deletes leading underscores, if any.
106
+ # * Removes a "_id" suffix if present.
107
+ # * Replaces underscores with spaces, if any.
108
+ # * Downcases all words except acronyms.
109
+ # * Capitalizes the first word.
112
110
  #
113
111
  # The capitalization of the first word can be turned off by setting the
114
112
  # +:capitalize+ option to false (default is true).
@@ -127,9 +125,9 @@ module ActiveSupport
127
125
 
128
126
  inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
129
127
 
130
- result.sub!(/\A_+/, '')
131
- result.sub!(/_id\z/, '')
132
- result.tr!('_', ' ')
128
+ result.sub!(/\A_+/, ''.freeze)
129
+ result.sub!(/_id\z/, ''.freeze)
130
+ result.tr!('_'.freeze, ' '.freeze)
133
131
 
134
132
  result.gsub!(/([a-z\d]*)/i) do |match|
135
133
  "#{inflections.acronyms[match] || match.downcase}"
@@ -142,60 +140,69 @@ module ActiveSupport
142
140
  result
143
141
  end
144
142
 
143
+ # Converts just the first character to uppercase.
144
+ #
145
+ # upcase_first('what a Lovely Day') # => "What a Lovely Day"
146
+ # upcase_first('w') # => "W"
147
+ # upcase_first('') # => ""
148
+ def upcase_first(string)
149
+ string.length > 0 ? string[0].upcase.concat(string[1..-1]) : ''
150
+ end
151
+
145
152
  # Capitalizes all the words and replaces some characters in the string to
146
153
  # create a nicer looking title. +titleize+ is meant for creating pretty
147
154
  # output. It is not used in the Rails internals.
148
155
  #
149
156
  # +titleize+ is also aliased as +titlecase+.
150
157
  #
151
- # 'man from the boondocks'.titleize # => "Man From The Boondocks"
152
- # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
153
- # 'TheManWithoutAPast'.titleize # => "The Man Without A Past"
154
- # 'raiders_of_the_lost_ark'.titleize # => "Raiders Of The Lost Ark"
158
+ # titleize('man from the boondocks') # => "Man From The Boondocks"
159
+ # titleize('x-men: the last stand') # => "X Men: The Last Stand"
160
+ # titleize('TheManWithoutAPast') # => "The Man Without A Past"
161
+ # titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark"
155
162
  def titleize(word)
156
163
  humanize(underscore(word)).gsub(/\b(?<!['’`])[a-z]/) { |match| match.capitalize }
157
164
  end
158
165
 
159
- # Create the name of a table like Rails does for models to table names. This
160
- # method uses the +pluralize+ method on the last word in the string.
166
+ # Creates the name of a table like Rails does for models to table names.
167
+ # This method uses the #pluralize method on the last word in the string.
161
168
  #
162
- # 'RawScaledScorer'.tableize # => "raw_scaled_scorers"
163
- # 'egg_and_ham'.tableize # => "egg_and_hams"
164
- # 'fancyCategory'.tableize # => "fancy_categories"
169
+ # tableize('RawScaledScorer') # => "raw_scaled_scorers"
170
+ # tableize('ham_and_egg') # => "ham_and_eggs"
171
+ # tableize('fancyCategory') # => "fancy_categories"
165
172
  def tableize(class_name)
166
173
  pluralize(underscore(class_name))
167
174
  end
168
175
 
169
- # Create a class name from a plural table name like Rails does for table
176
+ # Creates a class name from a plural table name like Rails does for table
170
177
  # names to models. Note that this returns a string and not a Class (To
171
- # convert to an actual class follow +classify+ with +constantize+).
178
+ # convert to an actual class follow +classify+ with #constantize).
172
179
  #
173
- # 'egg_and_hams'.classify # => "EggAndHam"
174
- # 'posts'.classify # => "Post"
180
+ # classify('ham_and_eggs') # => "HamAndEgg"
181
+ # classify('posts') # => "Post"
175
182
  #
176
183
  # Singular names are not handled correctly:
177
184
  #
178
- # 'calculus'.classify # => "Calculu"
185
+ # classify('calculus') # => "Calculus"
179
186
  def classify(table_name)
180
187
  # strip out any leading schema name
181
- camelize(singularize(table_name.to_s.sub(/.*\./, '')))
188
+ camelize(singularize(table_name.to_s.sub(/.*\./, ''.freeze)))
182
189
  end
183
190
 
184
191
  # Replaces underscores with dashes in the string.
185
192
  #
186
- # 'puni_puni'.dasherize # => "puni-puni"
193
+ # dasherize('puni_puni') # => "puni-puni"
187
194
  def dasherize(underscored_word)
188
- underscored_word.tr('_', '-')
195
+ underscored_word.tr('_'.freeze, '-'.freeze)
189
196
  end
190
197
 
191
198
  # Removes the module part from the expression in the string.
192
199
  #
193
- # 'ActiveRecord::CoreExtensions::String::Inflections'.demodulize # => "Inflections"
194
- # 'Inflections'.demodulize # => "Inflections"
195
- # '::Inflections'.demodulize # => "Inflections"
196
- # ''.demodulize # => ""
200
+ # demodulize('ActiveRecord::CoreExtensions::String::Inflections') # => "Inflections"
201
+ # demodulize('Inflections') # => "Inflections"
202
+ # demodulize('::Inflections') # => "Inflections"
203
+ # demodulize('') # => ""
197
204
  #
198
- # See also +deconstantize+.
205
+ # See also #deconstantize.
199
206
  def demodulize(path)
200
207
  path = path.to_s
201
208
  if i = path.rindex('::')
@@ -207,13 +214,13 @@ module ActiveSupport
207
214
 
208
215
  # Removes the rightmost segment from the constant expression in the string.
209
216
  #
210
- # 'Net::HTTP'.deconstantize # => "Net"
211
- # '::Net::HTTP'.deconstantize # => "::Net"
212
- # 'String'.deconstantize # => ""
213
- # '::String'.deconstantize # => ""
214
- # ''.deconstantize # => ""
217
+ # deconstantize('Net::HTTP') # => "Net"
218
+ # deconstantize('::Net::HTTP') # => "::Net"
219
+ # deconstantize('String') # => ""
220
+ # deconstantize('::String') # => ""
221
+ # deconstantize('') # => ""
215
222
  #
216
- # See also +demodulize+.
223
+ # See also #demodulize.
217
224
  def deconstantize(path)
218
225
  path.to_s[0, path.rindex('::') || 0] # implementation based on the one in facets' Module#spacename
219
226
  end
@@ -222,17 +229,17 @@ module ActiveSupport
222
229
  # +separate_class_name_and_id_with_underscore+ sets whether
223
230
  # the method should put '_' between the name and 'id'.
224
231
  #
225
- # 'Message'.foreign_key # => "message_id"
226
- # 'Message'.foreign_key(false) # => "messageid"
227
- # 'Admin::Post'.foreign_key # => "post_id"
232
+ # foreign_key('Message') # => "message_id"
233
+ # foreign_key('Message', false) # => "messageid"
234
+ # foreign_key('Admin::Post') # => "post_id"
228
235
  def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
229
236
  underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id")
230
237
  end
231
238
 
232
239
  # Tries to find a constant with the name specified in the argument string.
233
240
  #
234
- # 'Module'.constantize # => Module
235
- # 'Test::Unit'.constantize # => Test::Unit
241
+ # 'Module'.constantize # => Module
242
+ # 'Foo::Bar'.constantize # => Foo::Bar
236
243
  #
237
244
  # The name is assumed to be the one of a top-level constant, no matter
238
245
  # whether it starts with "::" or not. No lexical context is taken into
@@ -248,7 +255,7 @@ module ActiveSupport
248
255
  # NameError is raised when the name is not in CamelCase or the constant is
249
256
  # unknown.
250
257
  def constantize(camel_cased_word)
251
- names = camel_cased_word.split('::')
258
+ names = camel_cased_word.split('::'.freeze)
252
259
 
253
260
  # Trigger a built-in NameError exception including the ill-formed constant in the message.
254
261
  Object.const_get(camel_cased_word) if names.empty?
@@ -266,7 +273,7 @@ module ActiveSupport
266
273
 
267
274
  # Go down the ancestors to check if it is owned directly. The check
268
275
  # stops when we reach Object or the end of ancestors tree.
269
- constant = constant.ancestors.inject do |const, ancestor|
276
+ constant = constant.ancestors.inject(constant) do |const, ancestor|
270
277
  break const if ancestor == Object
271
278
  break ancestor if ancestor.const_defined?(name, false)
272
279
  const
@@ -280,8 +287,8 @@ module ActiveSupport
280
287
 
281
288
  # Tries to find a constant with the name specified in the argument string.
282
289
  #
283
- # 'Module'.safe_constantize # => Module
284
- # 'Test::Unit'.safe_constantize # => Test::Unit
290
+ # safe_constantize('Module') # => Module
291
+ # safe_constantize('Foo::Bar') # => Foo::Bar
285
292
  #
286
293
  # The name is assumed to be the one of a top-level constant, no matter
287
294
  # whether it starts with "::" or not. No lexical context is taken into
@@ -290,16 +297,16 @@ module ActiveSupport
290
297
  # C = 'outside'
291
298
  # module M
292
299
  # C = 'inside'
293
- # C # => 'inside'
294
- # 'C'.safe_constantize # => 'outside', same as ::C
300
+ # C # => 'inside'
301
+ # safe_constantize('C') # => 'outside', same as ::C
295
302
  # end
296
303
  #
297
304
  # +nil+ is returned when the name is not in CamelCase or the constant (or
298
305
  # part of it) is unknown.
299
306
  #
300
- # 'blargle'.safe_constantize # => nil
301
- # 'UnknownModule'.safe_constantize # => nil
302
- # 'UnknownModule::Foo::Bar'.safe_constantize # => nil
307
+ # safe_constantize('blargle') # => nil
308
+ # safe_constantize('UnknownModule') # => nil
309
+ # safe_constantize('UnknownModule::Foo::Bar') # => nil
303
310
  def safe_constantize(camel_cased_word)
304
311
  constantize(camel_cased_word)
305
312
  rescue NameError => e
@@ -354,7 +361,7 @@ module ActiveSupport
354
361
  # const_regexp("Foo::Bar::Baz") # => "Foo(::Bar(::Baz)?)?"
355
362
  # const_regexp("::") # => "::"
356
363
  def const_regexp(camel_cased_word) #:nodoc:
357
- parts = camel_cased_word.split("::")
364
+ parts = camel_cased_word.split("::".freeze)
358
365
 
359
366
  return Regexp.escape(camel_cased_word) if parts.blank?
360
367
 
@@ -372,7 +379,7 @@ module ActiveSupport
372
379
  def apply_inflections(word, rules)
373
380
  result = word.to_s.dup
374
381
 
375
- if word.empty? || inflections.uncountables.include?(result.downcase[/\b\w+\Z/])
382
+ if word.empty? || inflections.uncountables.uncountable?(result)
376
383
  result
377
384
  else
378
385
  rules.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  require 'active_support/core_ext/string/multibyte'
3
2
  require 'active_support/i18n'
4
3
 
@@ -58,7 +57,7 @@ module ActiveSupport
58
57
  # I18n.locale = :de
59
58
  # transliterate('Jürgen')
60
59
  # # => "Juergen"
61
- def transliterate(string, replacement = "?")
60
+ def transliterate(string, replacement = "?".freeze)
62
61
  I18n.transliterate(ActiveSupport::Multibyte::Unicode.normalize(
63
62
  ActiveSupport::Multibyte::Unicode.tidy_bytes(string), :c),
64
63
  :replacement => replacement)
@@ -67,31 +66,47 @@ module ActiveSupport
67
66
  # Replaces special characters in a string so that it may be used as part of
68
67
  # a 'pretty' URL.
69
68
  #
70
- # class Person
71
- # def to_param
72
- # "#{id}-#{name.parameterize}"
73
- # end
74
- # end
69
+ # parameterize("Donald E. Knuth") # => "donald-e-knuth"
70
+ # parameterize("^trés|Jolie-- ") # => "tres-jolie"
75
71
  #
76
- # @person = Person.find(1)
77
- # # => #<Person id: 1, name: "Donald E. Knuth">
72
+ # To use a custom separator, override the `separator` argument.
78
73
  #
79
- # <%= link_to(@person.name, person_path(@person)) %>
80
- # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
81
- def parameterize(string, sep = '-')
82
- # replace accented chars with their ascii equivalents
74
+ # parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth"
75
+ # parameterize("^trés|Jolie-- ", separator: '_') # => "tres_jolie"
76
+ #
77
+ # To preserve the case of the characters in a string, use the `preserve_case` argument.
78
+ #
79
+ # parameterize("Donald E. Knuth", preserve_case: true) # => "Donald-E-Knuth"
80
+ # parameterize("^trés|Jolie-- ", preserve_case: true) # => "tres-Jolie"
81
+ #
82
+ def parameterize(string, sep = :unused, separator: '-', preserve_case: false)
83
+ unless sep == :unused
84
+ ActiveSupport::Deprecation.warn("Passing the separator argument as a positional parameter is deprecated and will soon be removed. Use `separator: '#{sep}'` instead.")
85
+ separator = sep
86
+ end
87
+ # Replace accented chars with their ASCII equivalents.
83
88
  parameterized_string = transliterate(string)
84
- # Turn unwanted chars into the separator
85
- parameterized_string.gsub!(/[^a-z0-9\-_]+/i, sep)
86
- unless sep.nil? || sep.empty?
87
- re_sep = Regexp.escape(sep)
89
+
90
+ # Turn unwanted chars into the separator.
91
+ parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator)
92
+
93
+ unless separator.nil? || separator.empty?
94
+ if separator == "-".freeze
95
+ re_duplicate_separator = /-{2,}/
96
+ re_leading_trailing_separator = /^-|-$/i
97
+ else
98
+ re_sep = Regexp.escape(separator)
99
+ re_duplicate_separator = /#{re_sep}{2,}/
100
+ re_leading_trailing_separator = /^#{re_sep}|#{re_sep}$/i
101
+ end
88
102
  # No more than one of the separator in a row.
89
- parameterized_string.gsub!(/#{re_sep}{2,}/, sep)
103
+ parameterized_string.gsub!(re_duplicate_separator, separator)
90
104
  # Remove leading/trailing separator.
91
- parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '')
105
+ parameterized_string.gsub!(re_leading_trailing_separator, ''.freeze)
92
106
  end
93
- parameterized_string.downcase
107
+
108
+ parameterized_string.downcase! unless preserve_case
109
+ parameterized_string
94
110
  end
95
-
96
111
  end
97
112
  end
@@ -8,21 +8,16 @@ module ActiveSupport
8
8
 
9
9
  module JSON
10
10
  # matches YAML-formatted dates
11
- DATE_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?))$/
12
-
11
+ DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/
12
+ DATETIME_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?)$/
13
+
13
14
  class << self
14
15
  # Parses a JSON string (JavaScript Object Notation) into a hash.
15
16
  # See http://www.json.org for more info.
16
17
  #
17
18
  # ActiveSupport::JSON.decode("{\"team\":\"rails\",\"players\":\"36\"}")
18
19
  # => {"team" => "rails", "players" => "36"}
19
- def decode(json, options = {})
20
- if options.present?
21
- raise ArgumentError, "In Rails 4.1, ActiveSupport::JSON.decode no longer " \
22
- "accepts an options hash for MultiJSON. MultiJSON reached its end of life " \
23
- "and has been removed."
24
- end
25
-
20
+ def decode(json)
26
21
  data = ::JSON.parse(json, quirks_mode: true)
27
22
 
28
23
  if ActiveSupport.parse_json_times
@@ -54,7 +49,13 @@ module ActiveSupport
54
49
  nil
55
50
  when DATE_REGEX
56
51
  begin
57
- DateTime.parse(data)
52
+ Date.parse(data)
53
+ rescue ArgumentError
54
+ data
55
+ end
56
+ when DATETIME_REGEX
57
+ begin
58
+ Time.zone.parse(data)
58
59
  rescue ArgumentError
59
60
  data
60
61
  end
@@ -1,13 +1,11 @@
1
1
  require 'active_support/core_ext/object/json'
2
2
  require 'active_support/core_ext/module/delegation'
3
- require 'active_support/deprecation'
4
3
 
5
4
  module ActiveSupport
6
5
  class << self
7
6
  delegate :use_standard_json_time_format, :use_standard_json_time_format=,
8
7
  :time_precision, :time_precision=,
9
8
  :escape_html_entities_in_json, :escape_html_entities_in_json=,
10
- :encode_big_decimal_as_string, :encode_big_decimal_as_string=,
11
9
  :json_encoder, :json_encoder=,
12
10
  :to => :'ActiveSupport::JSON::Encoding'
13
11
  end
@@ -86,7 +84,7 @@ module ActiveSupport
86
84
  when String
87
85
  EscapedString.new(value)
88
86
  when Numeric, NilClass, TrueClass, FalseClass
89
- value
87
+ value.as_json
90
88
  when Hash
91
89
  Hash[value.map { |k, v| [jsonify(k), jsonify(v)] }]
92
90
  when Array
@@ -118,54 +116,6 @@ module ActiveSupport
118
116
  # Sets the encoder used by Rails to encode Ruby objects into JSON strings
119
117
  # in +Object#to_json+ and +ActiveSupport::JSON.encode+.
120
118
  attr_accessor :json_encoder
121
-
122
- def encode_big_decimal_as_string=(as_string)
123
- message = \
124
- "The JSON encoder in Rails 4.1 no longer supports encoding BigDecimals as JSON numbers. Instead, " \
125
- "the new encoder will always encode them as strings.\n\n" \
126
- "You are seeing this error because you have 'active_support.encode_big_decimal_as_string' in " \
127
- "your configuration file. If you have been setting this to true, you can safely remove it from " \
128
- "your configuration. Otherwise, you should add the 'activesupport-json_encoder' gem to your " \
129
- "Gemfile in order to restore this functionality."
130
-
131
- raise NotImplementedError, message
132
- end
133
-
134
- def encode_big_decimal_as_string
135
- message = \
136
- "The JSON encoder in Rails 4.1 no longer supports encoding BigDecimals as JSON numbers. Instead, " \
137
- "the new encoder will always encode them as strings.\n\n" \
138
- "You are seeing this error because you are trying to check the value of the related configuration, " \
139
- "`active_support.encode_big_decimal_as_string`. If your application depends on this option, you should " \
140
- "add the 'activesupport-json_encoder' gem to your Gemfile. For now, this option will always be true. " \
141
- "In the future, it will be removed from Rails, so you should stop checking its value."
142
-
143
- ActiveSupport::Deprecation.warn message
144
-
145
- true
146
- end
147
-
148
- # Deprecate CircularReferenceError
149
- def const_missing(name)
150
- if name == :CircularReferenceError
151
- message = "The JSON encoder in Rails 4.1 no longer offers protection from circular references. " \
152
- "You are seeing this warning because you are rescuing from (or otherwise referencing) " \
153
- "ActiveSupport::Encoding::CircularReferenceError. In the future, this error will be " \
154
- "removed from Rails. You should remove these rescue blocks from your code and ensure " \
155
- "that your data structures are free of circular references so they can be properly " \
156
- "serialized into JSON.\n\n" \
157
- "For example, the following Hash contains a circular reference to itself:\n" \
158
- " h = {}\n" \
159
- " h['circular'] = h\n" \
160
- "In this case, calling h.to_json would not work properly."
161
-
162
- ActiveSupport::Deprecation.warn message
163
-
164
- SystemStackError
165
- else
166
- super
167
- end
168
- end
169
119
  end
170
120
 
171
121
  self.use_standard_json_time_format = true
@@ -1,8 +1,8 @@
1
- require 'thread_safe'
1
+ require 'concurrent/map'
2
2
  require 'openssl'
3
3
 
4
4
  module ActiveSupport
5
- # KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2
5
+ # KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2.
6
6
  # It can be used to derive a number of keys for various purposes from a given secret.
7
7
  # This lets Rails applications have a single secure secret, but avoid reusing that
8
8
  # key in multiple incompatible contexts.
@@ -24,18 +24,16 @@ module ActiveSupport
24
24
 
25
25
  # CachingKeyGenerator is a wrapper around KeyGenerator which allows users to avoid
26
26
  # re-executing the key generation process when it's called using the same salt and
27
- # key_size
27
+ # key_size.
28
28
  class CachingKeyGenerator
29
29
  def initialize(key_generator)
30
30
  @key_generator = key_generator
31
- @cache_keys = ThreadSafe::Cache.new
31
+ @cache_keys = Concurrent::Map.new
32
32
  end
33
33
 
34
- # Returns a derived key suitable for use. The default key_size is chosen
35
- # to be compatible with the default settings of ActiveSupport::MessageVerifier.
36
- # i.e. OpenSSL::Digest::SHA1#block_length
37
- def generate_key(salt, key_size=64)
38
- @cache_keys["#{salt}#{key_size}"] ||= @key_generator.generate_key(salt, key_size)
34
+ # Returns a derived key suitable for use.
35
+ def generate_key(*args)
36
+ @cache_keys[args.join] ||= @key_generator.generate_key(*args)
39
37
  end
40
38
  end
41
39