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,182 @@
1
+ require 'active_support/core_ext/big_decimal/conversions'
2
+ require 'active_support/core_ext/object/blank'
3
+ require 'active_support/core_ext/hash/keys'
4
+ require 'active_support/i18n'
5
+ require 'active_support/core_ext/class/attribute'
6
+
7
+ module ActiveSupport
8
+ module NumberHelper
9
+ class NumberConverter # :nodoc:
10
+ # Default and i18n option namespace per class
11
+ class_attribute :namespace
12
+
13
+ # Does the object need a number that is a valid float?
14
+ class_attribute :validate_float
15
+
16
+ attr_reader :number, :opts
17
+
18
+ DEFAULTS = {
19
+ # Used in number_to_delimited
20
+ # These are also the defaults for 'currency', 'percentage', 'precision', and 'human'
21
+ format: {
22
+ # Sets the separator between the units, for more precision (e.g. 1.0 / 2.0 == 0.5)
23
+ separator: ".",
24
+ # Delimits thousands (e.g. 1,000,000 is a million) (always in groups of three)
25
+ delimiter: ",",
26
+ # Number of decimals, behind the separator (the number 1 with a precision of 2 gives: 1.00)
27
+ precision: 3,
28
+ # If set to true, precision will mean the number of significant digits instead
29
+ # of the number of decimal digits (1234 with precision 2 becomes 1200, 1.23543 becomes 1.2)
30
+ significant: false,
31
+ # If set, the zeros after the decimal separator will always be stripped (eg.: 1.200 will be 1.2)
32
+ strip_insignificant_zeros: false
33
+ },
34
+
35
+ # Used in number_to_currency
36
+ currency: {
37
+ format: {
38
+ format: "%u%n",
39
+ negative_format: "-%u%n",
40
+ unit: "$",
41
+ # These five are to override number.format and are optional
42
+ separator: ".",
43
+ delimiter: ",",
44
+ precision: 2,
45
+ significant: false,
46
+ strip_insignificant_zeros: false
47
+ }
48
+ },
49
+
50
+ # Used in number_to_percentage
51
+ percentage: {
52
+ format: {
53
+ delimiter: "",
54
+ format: "%n%"
55
+ }
56
+ },
57
+
58
+ # Used in number_to_rounded
59
+ precision: {
60
+ format: {
61
+ delimiter: ""
62
+ }
63
+ },
64
+
65
+ # Used in number_to_human_size and number_to_human
66
+ human: {
67
+ format: {
68
+ # These five are to override number.format and are optional
69
+ delimiter: "",
70
+ precision: 3,
71
+ significant: true,
72
+ strip_insignificant_zeros: true
73
+ },
74
+ # Used in number_to_human_size
75
+ storage_units: {
76
+ # Storage units output formatting.
77
+ # %u is the storage unit, %n is the number (default: 2 MB)
78
+ format: "%n %u",
79
+ units: {
80
+ byte: "Bytes",
81
+ kb: "KB",
82
+ mb: "MB",
83
+ gb: "GB",
84
+ tb: "TB"
85
+ }
86
+ },
87
+ # Used in number_to_human
88
+ decimal_units: {
89
+ format: "%n %u",
90
+ # Decimal units output formatting
91
+ # By default we will only quantify some of the exponents
92
+ # but the commented ones might be defined or overridden
93
+ # by the user.
94
+ units: {
95
+ # femto: Quadrillionth
96
+ # pico: Trillionth
97
+ # nano: Billionth
98
+ # micro: Millionth
99
+ # mili: Thousandth
100
+ # centi: Hundredth
101
+ # deci: Tenth
102
+ unit: "",
103
+ # ten:
104
+ # one: Ten
105
+ # other: Tens
106
+ # hundred: Hundred
107
+ thousand: "Thousand",
108
+ million: "Million",
109
+ billion: "Billion",
110
+ trillion: "Trillion",
111
+ quadrillion: "Quadrillion"
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ def self.convert(number, options)
118
+ new(number, options).execute
119
+ end
120
+
121
+ def initialize(number, options)
122
+ @number = number
123
+ @opts = options.symbolize_keys
124
+ end
125
+
126
+ def execute
127
+ if !number
128
+ nil
129
+ elsif validate_float? && !valid_float?
130
+ number
131
+ else
132
+ convert
133
+ end
134
+ end
135
+
136
+ private
137
+
138
+ def options
139
+ @options ||= format_options.merge(opts)
140
+ end
141
+
142
+ def format_options #:nodoc:
143
+ default_format_options.merge!(i18n_format_options)
144
+ end
145
+
146
+ def default_format_options #:nodoc:
147
+ options = DEFAULTS[:format].dup
148
+ options.merge!(DEFAULTS[namespace][:format]) if namespace
149
+ options
150
+ end
151
+
152
+ def i18n_format_options #:nodoc:
153
+ locale = opts[:locale]
154
+ options = I18n.translate(:'number.format', locale: locale, default: {}).dup
155
+
156
+ if namespace
157
+ options.merge!(I18n.translate(:"number.#{namespace}.format", locale: locale, default: {}))
158
+ end
159
+
160
+ options
161
+ end
162
+
163
+ def translate_number_value_with_default(key, i18n_options = {}) #:nodoc:
164
+ I18n.translate(key, { default: default_value(key), scope: :number }.merge!(i18n_options))
165
+ end
166
+
167
+ def translate_in_locale(key, i18n_options = {})
168
+ translate_number_value_with_default(key, { locale: options[:locale] }.merge(i18n_options))
169
+ end
170
+
171
+ def default_value(key)
172
+ key.split('.').reduce(DEFAULTS) { |defaults, k| defaults[k.to_sym] }
173
+ end
174
+
175
+ def valid_float? #:nodoc:
176
+ Float(number)
177
+ rescue ArgumentError, TypeError
178
+ false
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,44 @@
1
+ require 'active_support/core_ext/numeric/inquiry'
2
+
3
+ module ActiveSupport
4
+ module NumberHelper
5
+ class NumberToCurrencyConverter < NumberConverter # :nodoc:
6
+ self.namespace = :currency
7
+
8
+ def convert
9
+ number = self.number.to_s.strip
10
+ format = options[:format]
11
+
12
+ if number.to_f.negative?
13
+ format = options[:negative_format]
14
+ number = absolute_value(number)
15
+ end
16
+
17
+ rounded_number = NumberToRoundedConverter.convert(number, options)
18
+ format.gsub('%n'.freeze, rounded_number).gsub('%u'.freeze, options[:unit])
19
+ end
20
+
21
+ private
22
+
23
+ def absolute_value(number)
24
+ number.respond_to?(:abs) ? number.abs : number.sub(/\A-/, '')
25
+ end
26
+
27
+ def options
28
+ @options ||= begin
29
+ defaults = default_format_options.merge(i18n_opts)
30
+ # Override negative format if format options are given
31
+ defaults[:negative_format] = "-#{opts[:format]}" if opts[:format]
32
+ defaults.merge!(opts)
33
+ end
34
+ end
35
+
36
+ def i18n_opts
37
+ # Set International negative format if it does not exist
38
+ i18n = i18n_format_options
39
+ i18n[:negative_format] ||= "-#{i18n[:format]}" if i18n[:format]
40
+ i18n
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,28 @@
1
+ module ActiveSupport
2
+ module NumberHelper
3
+ class NumberToDelimitedConverter < NumberConverter #:nodoc:
4
+ self.validate_float = true
5
+
6
+ DEFAULT_DELIMITER_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
7
+
8
+ def convert
9
+ parts.join(options[:separator])
10
+ end
11
+
12
+ private
13
+
14
+ def parts
15
+ left, right = number.to_s.split('.'.freeze)
16
+ left.gsub!(delimiter_pattern) do |digit_to_delimit|
17
+ "#{digit_to_delimit}#{options[:delimiter]}"
18
+ end
19
+ [left, right].compact
20
+ end
21
+
22
+ def delimiter_pattern
23
+ options.fetch(:delimiter_pattern, DEFAULT_DELIMITER_REGEX)
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,68 @@
1
+ module ActiveSupport
2
+ module NumberHelper
3
+ class NumberToHumanConverter < NumberConverter # :nodoc:
4
+ DECIMAL_UNITS = { 0 => :unit, 1 => :ten, 2 => :hundred, 3 => :thousand, 6 => :million, 9 => :billion, 12 => :trillion, 15 => :quadrillion,
5
+ -1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto }
6
+ INVERTED_DECIMAL_UNITS = DECIMAL_UNITS.invert
7
+
8
+ self.namespace = :human
9
+ self.validate_float = true
10
+
11
+ def convert # :nodoc:
12
+ @number = Float(number)
13
+
14
+ # for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
15
+ unless options.key?(:strip_insignificant_zeros)
16
+ options[:strip_insignificant_zeros] = true
17
+ end
18
+
19
+ units = opts[:units]
20
+ exponent = calculate_exponent(units)
21
+ @number = number / (10 ** exponent)
22
+
23
+ until (rounded_number = NumberToRoundedConverter.convert(number, options)) != NumberToRoundedConverter.convert(1000, options)
24
+ @number = number / 1000.0
25
+ exponent += 3
26
+ end
27
+ unit = determine_unit(units, exponent)
28
+ format.gsub('%n'.freeze, rounded_number).gsub('%u'.freeze, unit).strip
29
+ end
30
+
31
+ private
32
+
33
+ def format
34
+ options[:format] || translate_in_locale('human.decimal_units.format')
35
+ end
36
+
37
+ def determine_unit(units, exponent)
38
+ exp = DECIMAL_UNITS[exponent]
39
+ case units
40
+ when Hash
41
+ units[exp] || ''
42
+ when String, Symbol
43
+ I18n.translate("#{units}.#{exp}", :locale => options[:locale], :count => number.to_i)
44
+ else
45
+ translate_in_locale("human.decimal_units.units.#{exp}", count: number.to_i)
46
+ end
47
+ end
48
+
49
+ def calculate_exponent(units)
50
+ exponent = number != 0 ? Math.log10(number.abs).floor : 0
51
+ unit_exponents(units).find { |e| exponent >= e } || 0
52
+ end
53
+
54
+ def unit_exponents(units)
55
+ case units
56
+ when Hash
57
+ units
58
+ when String, Symbol
59
+ I18n.translate(units.to_s, :locale => options[:locale], :raise => true)
60
+ when nil
61
+ translate_in_locale("human.decimal_units.units", raise: true)
62
+ else
63
+ raise ArgumentError, ":units must be a Hash or String translation scope."
64
+ end.keys.map { |e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by(&:-@)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,62 @@
1
+ module ActiveSupport
2
+ module NumberHelper
3
+ class NumberToHumanSizeConverter < NumberConverter #:nodoc:
4
+ STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb, :pb, :eb]
5
+
6
+ self.namespace = :human
7
+ self.validate_float = true
8
+
9
+ def convert
10
+ if opts.key?(:prefix)
11
+ ActiveSupport::Deprecation.warn('The :prefix option of `number_to_human_size` is deprecated and will be removed in Rails 5.1 with no replacement.')
12
+ end
13
+
14
+ @number = Float(number)
15
+
16
+ # for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
17
+ unless options.key?(:strip_insignificant_zeros)
18
+ options[:strip_insignificant_zeros] = true
19
+ end
20
+
21
+ if smaller_than_base?
22
+ number_to_format = number.to_i.to_s
23
+ else
24
+ human_size = number / (base ** exponent)
25
+ number_to_format = NumberToRoundedConverter.convert(human_size, options)
26
+ end
27
+ conversion_format.gsub('%n'.freeze, number_to_format).gsub('%u'.freeze, unit)
28
+ end
29
+
30
+ private
31
+
32
+ def conversion_format
33
+ translate_number_value_with_default('human.storage_units.format', :locale => options[:locale], :raise => true)
34
+ end
35
+
36
+ def unit
37
+ translate_number_value_with_default(storage_unit_key, :locale => options[:locale], :count => number.to_i, :raise => true)
38
+ end
39
+
40
+ def storage_unit_key
41
+ key_end = smaller_than_base? ? 'byte' : STORAGE_UNITS[exponent]
42
+ "human.storage_units.units.#{key_end}"
43
+ end
44
+
45
+ def exponent
46
+ max = STORAGE_UNITS.size - 1
47
+ exp = (Math.log(number) / Math.log(base)).to_i
48
+ exp = max if exp > max # avoid overflow for the highest unit
49
+ exp
50
+ end
51
+
52
+ def smaller_than_base?
53
+ number.to_i < base
54
+ end
55
+
56
+ def base
57
+ opts[:prefix] == :si ? 1000 : 1024
58
+ end
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,12 @@
1
+ module ActiveSupport
2
+ module NumberHelper
3
+ class NumberToPercentageConverter < NumberConverter # :nodoc:
4
+ self.namespace = :percentage
5
+
6
+ def convert
7
+ rounded_number = NumberToRoundedConverter.convert(number, options)
8
+ options[:format].gsub('%n'.freeze, rounded_number)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,58 @@
1
+ module ActiveSupport
2
+ module NumberHelper
3
+ class NumberToPhoneConverter < NumberConverter #:nodoc:
4
+ def convert
5
+ str = country_code(opts[:country_code])
6
+ str << convert_to_phone_number(number.to_s.strip)
7
+ str << phone_ext(opts[:extension])
8
+ end
9
+
10
+ private
11
+
12
+ def convert_to_phone_number(number)
13
+ if opts[:area_code]
14
+ convert_with_area_code(number)
15
+ else
16
+ convert_without_area_code(number)
17
+ end
18
+ end
19
+
20
+ def convert_with_area_code(number)
21
+ default_pattern = /(\d{1,3})(\d{3})(\d{4}$)/
22
+ number.gsub!(regexp_pattern(default_pattern),
23
+ "(\\1) \\2#{delimiter}\\3")
24
+ number
25
+ end
26
+
27
+ def convert_without_area_code(number)
28
+ default_pattern = /(\d{0,3})(\d{3})(\d{4})$/
29
+ number.gsub!(regexp_pattern(default_pattern),
30
+ "\\1#{delimiter}\\2#{delimiter}\\3")
31
+ number.slice!(0, 1) if start_with_delimiter?(number)
32
+ number
33
+ end
34
+
35
+ def start_with_delimiter?(number)
36
+ delimiter.present? && number.start_with?(delimiter)
37
+ end
38
+
39
+ def delimiter
40
+ opts[:delimiter] || "-"
41
+ end
42
+
43
+ def country_code(code)
44
+ code.blank? ? "" : "+#{code}#{delimiter}"
45
+ end
46
+
47
+ def phone_ext(ext)
48
+ ext.blank? ? "" : " x #{ext}"
49
+ end
50
+
51
+ def regexp_pattern(default_pattern)
52
+ opts.fetch :pattern, default_pattern
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+