actionpack 3.2.19 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +850 -401
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -288
  5. data/lib/abstract_controller/asset_paths.rb +2 -2
  6. data/lib/abstract_controller/base.rb +39 -37
  7. data/lib/abstract_controller/callbacks.rb +101 -82
  8. data/lib/abstract_controller/collector.rb +7 -3
  9. data/lib/abstract_controller/helpers.rb +25 -13
  10. data/lib/abstract_controller/layouts.rb +74 -74
  11. data/lib/abstract_controller/logger.rb +1 -2
  12. data/lib/abstract_controller/rendering.rb +30 -13
  13. data/lib/abstract_controller/translation.rb +16 -1
  14. data/lib/abstract_controller/url_for.rb +6 -6
  15. data/lib/abstract_controller/view_paths.rb +1 -1
  16. data/lib/abstract_controller.rb +1 -8
  17. data/lib/action_controller/base.rb +46 -22
  18. data/lib/action_controller/caching/fragments.rb +23 -53
  19. data/lib/action_controller/caching.rb +46 -33
  20. data/lib/action_controller/deprecated/integration_test.rb +3 -0
  21. data/lib/action_controller/deprecated.rb +5 -1
  22. data/lib/action_controller/log_subscriber.rb +16 -8
  23. data/lib/action_controller/metal/conditional_get.rb +76 -32
  24. data/lib/action_controller/metal/data_streaming.rb +20 -26
  25. data/lib/action_controller/metal/exceptions.rb +19 -6
  26. data/lib/action_controller/metal/flash.rb +24 -9
  27. data/lib/action_controller/metal/force_ssl.rb +70 -12
  28. data/lib/action_controller/metal/head.rb +25 -4
  29. data/lib/action_controller/metal/helpers.rb +5 -9
  30. data/lib/action_controller/metal/hide_actions.rb +0 -1
  31. data/lib/action_controller/metal/http_authentication.rb +107 -83
  32. data/lib/action_controller/metal/implicit_render.rb +1 -1
  33. data/lib/action_controller/metal/instrumentation.rb +2 -1
  34. data/lib/action_controller/metal/live.rb +175 -0
  35. data/lib/action_controller/metal/mime_responds.rb +161 -47
  36. data/lib/action_controller/metal/params_wrapper.rb +112 -74
  37. data/lib/action_controller/metal/rack_delegation.rb +9 -3
  38. data/lib/action_controller/metal/redirecting.rb +15 -20
  39. data/lib/action_controller/metal/renderers.rb +11 -9
  40. data/lib/action_controller/metal/rendering.rb +9 -1
  41. data/lib/action_controller/metal/request_forgery_protection.rb +112 -19
  42. data/lib/action_controller/metal/responder.rb +20 -19
  43. data/lib/action_controller/metal/streaming.rb +12 -18
  44. data/lib/action_controller/metal/strong_parameters.rb +520 -0
  45. data/lib/action_controller/metal/testing.rb +13 -18
  46. data/lib/action_controller/metal/url_for.rb +28 -25
  47. data/lib/action_controller/metal.rb +17 -32
  48. data/lib/action_controller/model_naming.rb +12 -0
  49. data/lib/action_controller/railtie.rb +33 -17
  50. data/lib/action_controller/railties/helpers.rb +22 -0
  51. data/lib/action_controller/record_identifier.rb +18 -72
  52. data/lib/action_controller/test_case.rb +251 -131
  53. data/lib/action_controller/vendor/html-scanner.rb +4 -19
  54. data/lib/action_controller.rb +15 -6
  55. data/lib/action_dispatch/http/cache.rb +63 -11
  56. data/lib/action_dispatch/http/filter_parameters.rb +18 -8
  57. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  58. data/lib/action_dispatch/http/headers.rb +49 -17
  59. data/lib/action_dispatch/http/mime_negotiation.rb +24 -1
  60. data/lib/action_dispatch/http/mime_type.rb +154 -100
  61. data/lib/action_dispatch/http/mime_types.rb +1 -1
  62. data/lib/action_dispatch/http/parameter_filter.rb +44 -46
  63. data/lib/action_dispatch/http/parameters.rb +28 -28
  64. data/lib/action_dispatch/http/rack_cache.rb +2 -3
  65. data/lib/action_dispatch/http/request.rb +64 -18
  66. data/lib/action_dispatch/http/response.rb +130 -35
  67. data/lib/action_dispatch/http/upload.rb +63 -20
  68. data/lib/action_dispatch/http/url.rb +98 -35
  69. data/lib/action_dispatch/journey/backwards.rb +5 -0
  70. data/lib/action_dispatch/journey/formatter.rb +146 -0
  71. data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
  72. data/lib/action_dispatch/journey/gtg/simulator.rb +44 -0
  73. data/lib/action_dispatch/journey/gtg/transition_table.rb +156 -0
  74. data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
  75. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  76. data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
  77. data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
  78. data/lib/action_dispatch/journey/nodes/node.rb +124 -0
  79. data/lib/action_dispatch/journey/parser.rb +206 -0
  80. data/lib/action_dispatch/journey/parser.y +47 -0
  81. data/lib/action_dispatch/journey/parser_extras.rb +23 -0
  82. data/lib/action_dispatch/journey/path/pattern.rb +196 -0
  83. data/lib/action_dispatch/journey/route.rb +124 -0
  84. data/lib/action_dispatch/journey/router/strexp.rb +24 -0
  85. data/lib/action_dispatch/journey/router/utils.rb +54 -0
  86. data/lib/action_dispatch/journey/router.rb +166 -0
  87. data/lib/action_dispatch/journey/routes.rb +75 -0
  88. data/lib/action_dispatch/journey/scanner.rb +61 -0
  89. data/lib/action_dispatch/journey/visitors.rb +197 -0
  90. data/lib/action_dispatch/journey/visualizer/fsm.css +34 -0
  91. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  92. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  93. data/lib/action_dispatch/journey.rb +5 -0
  94. data/lib/action_dispatch/middleware/callbacks.rb +9 -4
  95. data/lib/action_dispatch/middleware/cookies.rb +259 -114
  96. data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -17
  97. data/lib/action_dispatch/middleware/exception_wrapper.rb +29 -3
  98. data/lib/action_dispatch/middleware/flash.rb +58 -58
  99. data/lib/action_dispatch/middleware/params_parser.rb +14 -29
  100. data/lib/action_dispatch/middleware/public_exceptions.rb +30 -14
  101. data/lib/action_dispatch/middleware/reloader.rb +6 -6
  102. data/lib/action_dispatch/middleware/remote_ip.rb +145 -39
  103. data/lib/action_dispatch/middleware/request_id.rb +2 -6
  104. data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
  105. data/lib/action_dispatch/middleware/session/cookie_store.rb +82 -28
  106. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
  107. data/lib/action_dispatch/middleware/show_exceptions.rb +12 -45
  108. data/lib/action_dispatch/middleware/ssl.rb +70 -0
  109. data/lib/action_dispatch/middleware/stack.rb +6 -1
  110. data/lib/action_dispatch/middleware/static.rb +2 -1
  111. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +14 -11
  112. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +25 -0
  113. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +7 -9
  114. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +15 -9
  115. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +127 -5
  116. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +7 -2
  117. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +30 -15
  118. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +39 -13
  119. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +6 -2
  120. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  121. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +144 -0
  122. data/lib/action_dispatch/railtie.rb +16 -6
  123. data/lib/action_dispatch/request/session.rb +181 -0
  124. data/lib/action_dispatch/routing/inspector.rb +240 -0
  125. data/lib/action_dispatch/routing/mapper.rb +540 -291
  126. data/lib/action_dispatch/routing/polymorphic_routes.rb +16 -20
  127. data/lib/action_dispatch/routing/redirection.rb +46 -29
  128. data/lib/action_dispatch/routing/route_set.rb +207 -164
  129. data/lib/action_dispatch/routing/routes_proxy.rb +2 -0
  130. data/lib/action_dispatch/routing/url_for.rb +48 -33
  131. data/lib/action_dispatch/routing.rb +48 -83
  132. data/lib/action_dispatch/testing/assertions/dom.rb +3 -13
  133. data/lib/action_dispatch/testing/assertions/response.rb +32 -40
  134. data/lib/action_dispatch/testing/assertions/routing.rb +42 -41
  135. data/lib/action_dispatch/testing/assertions/selector.rb +17 -22
  136. data/lib/action_dispatch/testing/assertions/tag.rb +20 -23
  137. data/lib/action_dispatch/testing/integration.rb +65 -51
  138. data/lib/action_dispatch/testing/test_process.rb +9 -6
  139. data/lib/action_dispatch/testing/test_request.rb +7 -3
  140. data/lib/action_dispatch.rb +21 -15
  141. data/lib/action_pack/version.rb +7 -6
  142. data/lib/action_pack.rb +1 -1
  143. data/lib/action_view/base.rb +15 -34
  144. data/lib/action_view/buffers.rb +7 -1
  145. data/lib/action_view/context.rb +4 -4
  146. data/lib/action_view/dependency_tracker.rb +93 -0
  147. data/lib/action_view/digestor.rb +85 -0
  148. data/lib/action_view/flows.rb +1 -4
  149. data/lib/action_view/helpers/active_model_helper.rb +3 -4
  150. data/lib/action_view/helpers/asset_tag_helper.rb +215 -352
  151. data/lib/action_view/helpers/asset_url_helper.rb +355 -0
  152. data/lib/action_view/helpers/atom_feed_helper.rb +13 -10
  153. data/lib/action_view/helpers/cache_helper.rb +150 -18
  154. data/lib/action_view/helpers/capture_helper.rb +44 -31
  155. data/lib/action_view/helpers/csrf_helper.rb +0 -2
  156. data/lib/action_view/helpers/date_helper.rb +269 -248
  157. data/lib/action_view/helpers/debug_helper.rb +10 -11
  158. data/lib/action_view/helpers/form_helper.rb +931 -537
  159. data/lib/action_view/helpers/form_options_helper.rb +341 -166
  160. data/lib/action_view/helpers/form_tag_helper.rb +190 -90
  161. data/lib/action_view/helpers/javascript_helper.rb +23 -16
  162. data/lib/action_view/helpers/number_helper.rb +148 -329
  163. data/lib/action_view/helpers/output_safety_helper.rb +3 -3
  164. data/lib/action_view/helpers/record_tag_helper.rb +17 -22
  165. data/lib/action_view/helpers/rendering_helper.rb +2 -2
  166. data/lib/action_view/helpers/sanitize_helper.rb +3 -6
  167. data/lib/action_view/helpers/tag_helper.rb +46 -33
  168. data/lib/action_view/helpers/tags/base.rb +147 -0
  169. data/lib/action_view/helpers/tags/check_box.rb +64 -0
  170. data/lib/action_view/helpers/tags/checkable.rb +16 -0
  171. data/lib/action_view/helpers/tags/collection_check_boxes.rb +43 -0
  172. data/lib/action_view/helpers/tags/collection_helpers.rb +83 -0
  173. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
  174. data/lib/action_view/helpers/tags/collection_select.rb +28 -0
  175. data/lib/action_view/helpers/tags/color_field.rb +25 -0
  176. data/lib/action_view/helpers/tags/date_field.rb +13 -0
  177. data/lib/action_view/helpers/tags/date_select.rb +72 -0
  178. data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
  179. data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
  180. data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
  181. data/lib/action_view/helpers/tags/email_field.rb +8 -0
  182. data/lib/action_view/helpers/tags/file_field.rb +8 -0
  183. data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
  184. data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
  185. data/lib/action_view/helpers/tags/label.rb +65 -0
  186. data/lib/action_view/helpers/tags/month_field.rb +13 -0
  187. data/lib/action_view/helpers/tags/number_field.rb +18 -0
  188. data/lib/action_view/helpers/tags/password_field.rb +12 -0
  189. data/lib/action_view/helpers/tags/radio_button.rb +31 -0
  190. data/lib/action_view/helpers/tags/range_field.rb +8 -0
  191. data/lib/action_view/helpers/tags/search_field.rb +24 -0
  192. data/lib/action_view/helpers/tags/select.rb +40 -0
  193. data/lib/action_view/helpers/tags/tel_field.rb +8 -0
  194. data/lib/action_view/helpers/tags/text_area.rb +18 -0
  195. data/lib/action_view/helpers/tags/text_field.rb +29 -0
  196. data/lib/action_view/helpers/tags/time_field.rb +13 -0
  197. data/lib/action_view/helpers/tags/time_select.rb +8 -0
  198. data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
  199. data/lib/action_view/helpers/tags/url_field.rb +8 -0
  200. data/lib/action_view/helpers/tags/week_field.rb +13 -0
  201. data/lib/action_view/helpers/tags.rb +39 -0
  202. data/lib/action_view/helpers/text_helper.rb +130 -114
  203. data/lib/action_view/helpers/translation_helper.rb +32 -16
  204. data/lib/action_view/helpers/url_helper.rb +211 -270
  205. data/lib/action_view/helpers.rb +2 -4
  206. data/lib/action_view/locale/en.yml +1 -105
  207. data/lib/action_view/log_subscriber.rb +6 -4
  208. data/lib/action_view/lookup_context.rb +15 -28
  209. data/lib/action_view/model_naming.rb +12 -0
  210. data/lib/action_view/path_set.rb +8 -20
  211. data/lib/action_view/railtie.rb +6 -22
  212. data/lib/action_view/record_identifier.rb +84 -0
  213. data/lib/action_view/renderer/abstract_renderer.rb +25 -19
  214. data/lib/action_view/renderer/partial_renderer.rb +158 -81
  215. data/lib/action_view/renderer/renderer.rb +8 -12
  216. data/lib/action_view/renderer/streaming_template_renderer.rb +2 -5
  217. data/lib/action_view/renderer/template_renderer.rb +12 -10
  218. data/lib/action_view/routing_url_for.rb +107 -0
  219. data/lib/action_view/template/error.rb +22 -12
  220. data/lib/action_view/template/handlers/builder.rb +1 -1
  221. data/lib/action_view/template/handlers/erb.rb +40 -19
  222. data/lib/action_view/template/handlers/raw.rb +11 -0
  223. data/lib/action_view/template/handlers.rb +12 -9
  224. data/lib/action_view/template/resolver.rb +107 -53
  225. data/lib/action_view/template/text.rb +12 -8
  226. data/lib/action_view/template/types.rb +57 -0
  227. data/lib/action_view/template.rb +25 -23
  228. data/lib/action_view/test_case.rb +67 -42
  229. data/lib/{action_controller → action_view}/vendor/html-scanner/html/document.rb +0 -0
  230. data/lib/{action_controller → action_view}/vendor/html-scanner/html/node.rb +12 -12
  231. data/lib/{action_controller → action_view}/vendor/html-scanner/html/sanitizer.rb +13 -2
  232. data/lib/{action_controller → action_view}/vendor/html-scanner/html/selector.rb +9 -9
  233. data/lib/{action_controller → action_view}/vendor/html-scanner/html/tokenizer.rb +1 -1
  234. data/lib/{action_controller → action_view}/vendor/html-scanner/html/version.rb +0 -0
  235. data/lib/action_view/vendor/html-scanner.rb +20 -0
  236. data/lib/action_view.rb +17 -8
  237. metadata +184 -214
  238. data/lib/action_controller/caching/actions.rb +0 -185
  239. data/lib/action_controller/caching/pages.rb +0 -187
  240. data/lib/action_controller/caching/sweeping.rb +0 -97
  241. data/lib/action_controller/deprecated/performance_test.rb +0 -1
  242. data/lib/action_controller/metal/compatibility.rb +0 -65
  243. data/lib/action_controller/metal/session_management.rb +0 -14
  244. data/lib/action_controller/railties/paths.rb +0 -25
  245. data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
  246. data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
  247. data/lib/action_dispatch/middleware/head.rb +0 -18
  248. data/lib/action_dispatch/middleware/rescue.rb +0 -26
  249. data/lib/action_dispatch/testing/performance_test.rb +0 -10
  250. data/lib/action_view/asset_paths.rb +0 -142
  251. data/lib/action_view/helpers/asset_paths.rb +0 -7
  252. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
  253. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
  254. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
  255. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
  256. data/lib/sprockets/assets.rake +0 -99
  257. data/lib/sprockets/bootstrap.rb +0 -37
  258. data/lib/sprockets/compressors.rb +0 -83
  259. data/lib/sprockets/helpers/isolated_helper.rb +0 -13
  260. data/lib/sprockets/helpers/rails_helper.rb +0 -182
  261. data/lib/sprockets/helpers.rb +0 -6
  262. data/lib/sprockets/railtie.rb +0 -62
  263. data/lib/sprockets/static_compiler.rb +0 -56
@@ -1,11 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'active_support/core_ext/hash/keys'
4
- require 'active_support/core_ext/hash/reverse_merge'
5
- require 'active_support/core_ext/big_decimal/conversions'
6
- require 'active_support/core_ext/float/rounding'
7
- require 'active_support/core_ext/object/blank'
8
4
  require 'active_support/core_ext/string/output_safety'
5
+ require 'active_support/number_helper'
9
6
 
10
7
  module ActionView
11
8
  # = Action View Number Helpers
@@ -19,9 +16,6 @@ module ActionView
19
16
  # unchanged if can't be converted into a valid number.
20
17
  module NumberHelper
21
18
 
22
- DEFAULT_CURRENCY_VALUES = { :format => "%u%n", :negative_format => "-%u%n", :unit => "$", :separator => ".", :delimiter => ",",
23
- :precision => 2, :significant => false, :strip_insignificant_zeros => false }
24
-
25
19
  # Raised when argument +number+ param given to the helpers is invalid and
26
20
  # the option :raise is set to +true+.
27
21
  class InvalidNumberError < StandardError
@@ -48,47 +42,24 @@ module ActionView
48
42
  #
49
43
  # ==== Examples
50
44
  #
51
- # number_to_phone(5551234) # => 555-1234
52
- # number_to_phone("5551234") # => 555-1234
53
- # number_to_phone(1235551234) # => 123-555-1234
54
- # number_to_phone(1235551234, :area_code => true) # => (123) 555-1234
55
- # number_to_phone(1235551234, :delimiter => " ") # => 123 555 1234
56
- # number_to_phone(1235551234, :area_code => true, :extension => 555) # => (123) 555-1234 x 555
57
- # number_to_phone(1235551234, :country_code => 1) # => +1-123-555-1234
58
- # number_to_phone("123a456") # => 123a456
59
- #
60
- # number_to_phone("1234a567", :raise => true) # => InvalidNumberError
61
- #
62
- # number_to_phone(1235551234, :country_code => 1, :extension => 1343, :delimiter => ".")
63
- # # => +1.123.555.1234 x 1343
45
+ # number_to_phone(5551234) # => 555-1234
46
+ # number_to_phone("5551234") # => 555-1234
47
+ # number_to_phone(1235551234) # => 123-555-1234
48
+ # number_to_phone(1235551234, area_code: true) # => (123) 555-1234
49
+ # number_to_phone(1235551234, delimiter: " ") # => 123 555 1234
50
+ # number_to_phone(1235551234, area_code: true, extension: 555) # => (123) 555-1234 x 555
51
+ # number_to_phone(1235551234, country_code: 1) # => +1-123-555-1234
52
+ # number_to_phone("123a456") # => 123a456
53
+ # number_to_phone("1234a567", raise: true) # => InvalidNumberError
54
+ #
55
+ # number_to_phone(1235551234, country_code: 1, extension: 1343, delimiter: ".")
56
+ # # => +1.123.555.1234 x 1343
64
57
  def number_to_phone(number, options = {})
65
58
  return unless number
59
+ options = options.symbolize_keys
66
60
 
67
- begin
68
- Float(number)
69
- rescue ArgumentError, TypeError
70
- raise InvalidNumberError, number
71
- end if options[:raise]
72
-
73
- number = number.to_s.strip
74
- options = options.symbolize_keys
75
- area_code = options[:area_code]
76
- delimiter = options[:delimiter] || "-"
77
- extension = options[:extension]
78
- country_code = options[:country_code]
79
-
80
- if area_code
81
- number.gsub!(/(\d{1,3})(\d{3})(\d{4}$)/,"(\\1) \\2#{delimiter}\\3")
82
- else
83
- number.gsub!(/(\d{0,3})(\d{3})(\d{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3")
84
- number.slice!(0, 1) if number.starts_with?(delimiter) && !delimiter.blank?
85
- end
86
-
87
- str = []
88
- str << "+#{country_code}#{delimiter}" unless country_code.blank?
89
- str << number
90
- str << " x #{extension}" unless extension.blank?
91
- ERB::Util.html_escape(str.join)
61
+ parse_float(number, true) if options.delete(:raise)
62
+ ERB::Util.html_escape(ActiveSupport::NumberHelper.number_to_phone(number, options))
92
63
  end
93
64
 
94
65
  # Formats a +number+ into a currency string (e.g., $13.65). You
@@ -119,59 +90,27 @@ module ActionView
119
90
  #
120
91
  # ==== Examples
121
92
  #
122
- # number_to_currency(1234567890.50) # => $1,234,567,890.50
123
- # number_to_currency(1234567890.506) # => $1,234,567,890.51
124
- # number_to_currency(1234567890.506, :precision => 3) # => $1,234,567,890.506
125
- # number_to_currency(1234567890.506, :locale => :fr) # => 1 234 567 890,51 €
126
- # number_to_currency("123a456") # => $123a456
93
+ # number_to_currency(1234567890.50) # => $1,234,567,890.50
94
+ # number_to_currency(1234567890.506) # => $1,234,567,890.51
95
+ # number_to_currency(1234567890.506, precision: 3) # => $1,234,567,890.506
96
+ # number_to_currency(1234567890.506, locale: :fr) # => 1 234 567 890,51 €
97
+ # number_to_currency("123a456") # => $123a456
127
98
  #
128
- # number_to_currency("123a456", :raise => true) # => InvalidNumberError
99
+ # number_to_currency("123a456", raise: true) # => InvalidNumberError
129
100
  #
130
- # number_to_currency(-1234567890.50, :negative_format => "(%u%n)")
131
- # # => ($1,234,567,890.50)
132
- # number_to_currency(1234567890.50, :unit => "R$", :separator => ",", :delimiter => "")
133
- # # => R$1234567890,50
134
- # number_to_currency(1234567890.50, :unit => "R$", :separator => ",", :delimiter => "", :format => "%n %u")
135
- # # => 1234567890,50 R$
101
+ # number_to_currency(-1234567890.50, negative_format: "(%u%n)")
102
+ # # => ($1,234,567,890.50)
103
+ # number_to_currency(1234567890.50, unit: "&pound;", separator: ",", delimiter: "")
104
+ # # => &pound;1234567890,50
105
+ # number_to_currency(1234567890.50, unit: "&pound;", separator: ",", delimiter: "", format: "%n %u")
106
+ # # => 1234567890,50 &pound;
136
107
  def number_to_currency(number, options = {})
137
108
  return unless number
109
+ options = escape_unsafe_delimiters_and_separators(options.symbolize_keys)
138
110
 
139
- options.symbolize_keys!
140
-
141
- options[:delimiter] = ERB::Util.html_escape(options[:delimiter]) if options[:delimiter]
142
- options[:separator] = ERB::Util.html_escape(options[:separator]) if options[:separator]
143
- options[:format] = ERB::Util.html_escape(options[:format]) if options[:format]
144
- options[:negative_format] = ERB::Util.html_escape(options[:negative_format]) if options[:negative_format]
145
-
146
- defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
147
- currency = I18n.translate(:'number.currency.format', :locale => options[:locale], :default => {})
148
- currency[:negative_format] ||= "-" + currency[:format] if currency[:format]
149
-
150
- defaults = DEFAULT_CURRENCY_VALUES.merge(defaults).merge!(currency)
151
- defaults[:negative_format] = "-" + options[:format] if options[:format]
152
-
153
- options = defaults.merge!(options)
154
-
155
- unit = options.delete(:unit)
156
- format = options.delete(:format)
157
-
158
- if number.to_f < 0
159
- format = options.delete(:negative_format)
160
- number = number.respond_to?("abs") ? number.abs : number.sub(/^-/, '')
161
- end
162
-
163
- begin
164
- value = number_with_precision(number, options.merge(:raise => true))
165
- format.gsub(/%n/, ERB::Util.html_escape(value)).gsub(/%u/, ERB::Util.html_escape(unit)).html_safe
166
- rescue InvalidNumberError => e
167
- if options[:raise]
168
- raise
169
- else
170
- formatted_number = format.gsub(/%n/, e.number).gsub(/%u/, unit)
171
- e.number.to_s.html_safe? ? formatted_number.html_safe : formatted_number
172
- end
173
- end
174
-
111
+ wrap_with_output_safety_handling(number, options.delete(:raise)) {
112
+ ActiveSupport::NumberHelper.number_to_currency(number, options)
113
+ }
175
114
  end
176
115
 
177
116
  # Formats a +number+ as a percentage string (e.g., 65%). You can
@@ -193,43 +132,30 @@ module ActionView
193
132
  # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
194
133
  # insignificant zeros after the decimal separator (defaults to
195
134
  # +false+).
135
+ # * <tt>:format</tt> - Specifies the format of the percentage
136
+ # string The number field is <tt>%n</tt> (defaults to "%n%").
196
137
  # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
197
138
  # the argument is invalid.
198
139
  #
199
140
  # ==== Examples
200
141
  #
201
- # number_to_percentage(100) # => 100.000%
202
- # number_to_percentage("98") # => 98.000%
203
- # number_to_percentage(100, :precision => 0) # => 100%
204
- # number_to_percentage(1000, :delimiter => '.', :separator => ',') # => 1.000,000%
205
- # number_to_percentage(302.24398923423, :precision => 5) # => 302.24399%
206
- # number_to_percentage(1000, :locale => :fr) # => 1 000,000%
207
- # number_to_percentage("98a") # => 98a%
142
+ # number_to_percentage(100) # => 100.000%
143
+ # number_to_percentage("98") # => 98.000%
144
+ # number_to_percentage(100, precision: 0) # => 100%
145
+ # number_to_percentage(1000, delimiter: '.', separator: ',') # => 1.000,000%
146
+ # number_to_percentage(302.24398923423, precision: 5) # => 302.24399%
147
+ # number_to_percentage(1000, locale: :fr) # => 1 000,000%
148
+ # number_to_percentage("98a") # => 98a%
149
+ # number_to_percentage(100, format: "%n %") # => 100 %
208
150
  #
209
- # number_to_percentage("98a", :raise => true) # => InvalidNumberError
151
+ # number_to_percentage("98a", raise: true) # => InvalidNumberError
210
152
  def number_to_percentage(number, options = {})
211
153
  return unless number
154
+ options = escape_unsafe_delimiters_and_separators(options.symbolize_keys)
212
155
 
213
- options.symbolize_keys!
214
-
215
- options[:delimiter] = ERB::Util.html_escape(options[:delimiter]) if options[:delimiter]
216
- options[:separator] = ERB::Util.html_escape(options[:separator]) if options[:separator]
217
-
218
- defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
219
- percentage = I18n.translate(:'number.percentage.format', :locale => options[:locale], :default => {})
220
- defaults = defaults.merge(percentage)
221
-
222
- options = options.reverse_merge(defaults)
223
-
224
- begin
225
- "#{number_with_precision(number, options.merge(:raise => true))}%".html_safe
226
- rescue InvalidNumberError => e
227
- if options[:raise]
228
- raise
229
- else
230
- e.number.to_s.html_safe? ? "#{e.number}%".html_safe : "#{e.number}%"
231
- end
232
- end
156
+ wrap_with_output_safety_handling(number, options.delete(:raise)) {
157
+ ActiveSupport::NumberHelper.number_to_percentage(number, options)
158
+ }
233
159
  end
234
160
 
235
161
  # Formats a +number+ with grouped thousands using +delimiter+
@@ -249,41 +175,24 @@ module ActionView
249
175
  #
250
176
  # ==== Examples
251
177
  #
252
- # number_with_delimiter(12345678) # => 12,345,678
253
- # number_with_delimiter("123456") # => 123,456
254
- # number_with_delimiter(12345678.05) # => 12,345,678.05
255
- # number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678
256
- # number_with_delimiter(12345678, :delimiter => ",") # => 12,345,678
257
- # number_with_delimiter(12345678.05, :separator => " ") # => 12,345,678 05
258
- # number_with_delimiter(12345678.05, :locale => :fr) # => 12 345 678,05
259
- # number_with_delimiter("112a") # => 112a
260
- # number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",")
261
- # # => 98 765 432,98
262
- #
263
- # number_with_delimiter("112a", :raise => true) # => raise InvalidNumberError
178
+ # number_with_delimiter(12345678) # => 12,345,678
179
+ # number_with_delimiter("123456") # => 123,456
180
+ # number_with_delimiter(12345678.05) # => 12,345,678.05
181
+ # number_with_delimiter(12345678, delimiter: ".") # => 12.345.678
182
+ # number_with_delimiter(12345678, delimiter: ",") # => 12,345,678
183
+ # number_with_delimiter(12345678.05, separator: " ") # => 12,345,678 05
184
+ # number_with_delimiter(12345678.05, locale: :fr) # => 12 345 678,05
185
+ # number_with_delimiter("112a") # => 112a
186
+ # number_with_delimiter(98765432.98, delimiter: " ", separator: ",")
187
+ # # => 98 765 432,98
188
+ #
189
+ # number_with_delimiter("112a", raise: true) # => raise InvalidNumberError
264
190
  def number_with_delimiter(number, options = {})
265
- options.symbolize_keys!
266
-
267
- options[:delimiter] = ERB::Util.html_escape(options[:delimiter]) if options[:delimiter]
268
- options[:separator] = ERB::Util.html_escape(options[:separator]) if options[:separator]
269
-
270
- begin
271
- Float(number)
272
- rescue ArgumentError, TypeError
273
- if options[:raise]
274
- raise InvalidNumberError, number
275
- else
276
- return number
277
- end
278
- end
279
-
280
- defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
281
- options = options.reverse_merge(defaults)
282
-
283
- parts = number.to_s.to_str.split('.')
284
- parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
285
- parts.join(options[:separator]).html_safe
191
+ options = escape_unsafe_delimiters_and_separators(options.symbolize_keys)
286
192
 
193
+ wrap_with_output_safety_handling(number, options.delete(:raise)) {
194
+ ActiveSupport::NumberHelper.number_to_delimited(number, options)
195
+ }
287
196
  end
288
197
 
289
198
  # Formats a +number+ with the specified level of
@@ -312,68 +221,29 @@ module ActionView
312
221
  #
313
222
  # ==== Examples
314
223
  #
315
- # number_with_precision(111.2345) # => 111.235
316
- # number_with_precision(111.2345, :precision => 2) # => 111.23
317
- # number_with_precision(13, :precision => 5) # => 13.00000
318
- # number_with_precision(389.32314, :precision => 0) # => 389
319
- # number_with_precision(111.2345, :significant => true) # => 111
320
- # number_with_precision(111.2345, :precision => 1, :significant => true) # => 100
321
- # number_with_precision(13, :precision => 5, :significant => true) # => 13.000
322
- # number_with_precision(111.234, :locale => :fr) # => 111,234
323
- #
324
- # number_with_precision(13, :precision => 5, :significant => true, :strip_insignificant_zeros => true)
325
- # # => 13
326
- #
327
- # number_with_precision(389.32314, :precision => 4, :significant => true) # => 389.3
328
- # number_with_precision(1111.2345, :precision => 2, :separator => ',', :delimiter => '.')
329
- # # => 1.111,23
224
+ # number_with_precision(111.2345) # => 111.235
225
+ # number_with_precision(111.2345, precision: 2) # => 111.23
226
+ # number_with_precision(13, precision: 5) # => 13.00000
227
+ # number_with_precision(389.32314, precision: 0) # => 389
228
+ # number_with_precision(111.2345, significant: true) # => 111
229
+ # number_with_precision(111.2345, precision: 1, significant: true) # => 100
230
+ # number_with_precision(13, precision: 5, significant: true) # => 13.000
231
+ # number_with_precision(111.234, locale: :fr) # => 111,234
232
+ #
233
+ # number_with_precision(13, precision: 5, significant: true, strip_insignificant_zeros: true)
234
+ # # => 13
235
+ #
236
+ # number_with_precision(389.32314, precision: 4, significant: true) # => 389.3
237
+ # number_with_precision(1111.2345, precision: 2, separator: ',', delimiter: '.')
238
+ # # => 1.111,23
330
239
  def number_with_precision(number, options = {})
331
- options.symbolize_keys!
332
-
333
- number = begin
334
- Float(number)
335
- rescue ArgumentError, TypeError
336
- if options[:raise]
337
- raise InvalidNumberError, number
338
- else
339
- return number
340
- end
341
- end
342
-
343
- defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
344
- precision_defaults = I18n.translate(:'number.precision.format', :locale => options[:locale], :default => {})
345
- defaults = defaults.merge(precision_defaults)
346
-
347
- options = options.reverse_merge(defaults) # Allow the user to unset default values: Eg.: :significant => false
348
- precision = options.delete :precision
349
- significant = options.delete :significant
350
- strip_insignificant_zeros = options.delete :strip_insignificant_zeros
351
-
352
- if significant and precision > 0
353
- if number == 0
354
- digits, rounded_number = 1, 0
355
- else
356
- digits = (Math.log10(number.abs) + 1).floor
357
- rounded_number = (BigDecimal.new(number.to_s) / BigDecimal.new((10 ** (digits - precision)).to_f.to_s)).round.to_f * 10 ** (digits - precision)
358
- digits = (Math.log10(rounded_number.abs) + 1).floor # After rounding, the number of digits may have changed
359
- end
360
- precision -= digits
361
- precision = precision > 0 ? precision : 0 #don't let it be negative
362
- else
363
- rounded_number = BigDecimal.new(number.to_s).round(precision).to_f
364
- end
365
- formatted_number = number_with_delimiter("%01.#{precision}f" % rounded_number, options)
366
- if strip_insignificant_zeros
367
- escaped_separator = Regexp.escape(options[:separator])
368
- formatted_number.sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '').html_safe
369
- else
370
- formatted_number
371
- end
240
+ options = escape_unsafe_delimiters_and_separators(options.symbolize_keys)
372
241
 
242
+ wrap_with_output_safety_handling(number, options.delete(:raise)) {
243
+ ActiveSupport::NumberHelper.number_to_rounded(number, options)
244
+ }
373
245
  end
374
246
 
375
- STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb]
376
-
377
247
  # Formats the bytes in +number+ into a more understandable
378
248
  # representation (e.g., giving it 1500 yields 1.5 KB). This
379
249
  # method is useful for reporting file sizes to users. You can
@@ -405,67 +275,31 @@ module ActionView
405
275
  #
406
276
  # ==== Examples
407
277
  #
408
- # number_to_human_size(123) # => 123 Bytes
409
- # number_to_human_size(1234) # => 1.21 KB
410
- # number_to_human_size(12345) # => 12.1 KB
411
- # number_to_human_size(1234567) # => 1.18 MB
412
- # number_to_human_size(1234567890) # => 1.15 GB
413
- # number_to_human_size(1234567890123) # => 1.12 TB
414
- # number_to_human_size(1234567, :precision => 2) # => 1.2 MB
415
- # number_to_human_size(483989, :precision => 2) # => 470 KB
416
- # number_to_human_size(1234567, :precision => 2, :separator => ',') # => 1,2 MB
278
+ # number_to_human_size(123) # => 123 Bytes
279
+ # number_to_human_size(1234) # => 1.21 KB
280
+ # number_to_human_size(12345) # => 12.1 KB
281
+ # number_to_human_size(1234567) # => 1.18 MB
282
+ # number_to_human_size(1234567890) # => 1.15 GB
283
+ # number_to_human_size(1234567890123) # => 1.12 TB
284
+ # number_to_human_size(1234567, precision: 2) # => 1.2 MB
285
+ # number_to_human_size(483989, precision: 2) # => 470 KB
286
+ # number_to_human_size(1234567, precision: 2, separator: ',') # => 1,2 MB
417
287
  #
418
288
  # Non-significant zeros after the fractional separator are
419
289
  # stripped out by default (set
420
290
  # <tt>:strip_insignificant_zeros</tt> to +false+ to change
421
291
  # that):
422
- # number_to_human_size(1234567890123, :precision => 5) # => "1.1229 TB"
423
- # number_to_human_size(524288000, :precision => 5) # => "500 MB"
292
+ #
293
+ # number_to_human_size(1234567890123, precision: 5) # => "1.1229 TB"
294
+ # number_to_human_size(524288000, precision: 5) # => "500 MB"
424
295
  def number_to_human_size(number, options = {})
425
- options.symbolize_keys!
426
-
427
- number = begin
428
- Float(number)
429
- rescue ArgumentError, TypeError
430
- if options[:raise]
431
- raise InvalidNumberError, number
432
- else
433
- return number
434
- end
435
- end
436
-
437
- defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
438
- human = I18n.translate(:'number.human.format', :locale => options[:locale], :default => {})
439
- defaults = defaults.merge(human)
440
-
441
- options = options.reverse_merge(defaults)
442
- #for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
443
- options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
444
-
445
- storage_units_format = I18n.translate(:'number.human.storage_units.format', :locale => options[:locale], :raise => true)
296
+ options = escape_unsafe_delimiters_and_separators(options.symbolize_keys)
446
297
 
447
- base = options[:prefix] == :si ? 1000 : 1024
448
-
449
- if number.to_i < base
450
- unit = I18n.translate(:'number.human.storage_units.units.byte', :locale => options[:locale], :count => number.to_i, :raise => true)
451
- storage_units_format.gsub(/%n/, number.to_i.to_s).gsub(/%u/, unit).html_safe
452
- else
453
- max_exp = STORAGE_UNITS.size - 1
454
- exponent = (Math.log(number) / Math.log(base)).to_i # Convert to base
455
- exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit
456
- number /= base ** exponent
457
-
458
- unit_key = STORAGE_UNITS[exponent]
459
- unit = I18n.translate(:"number.human.storage_units.units.#{unit_key}", :locale => options[:locale], :count => number, :raise => true)
460
-
461
- formatted_number = number_with_precision(number, options)
462
- storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit).html_safe
463
- end
298
+ wrap_with_output_safety_handling(number, options.delete(:raise)) {
299
+ ActiveSupport::NumberHelper.number_to_human_size(number, options)
300
+ }
464
301
  end
465
302
 
466
- DECIMAL_UNITS = {0 => :unit, 1 => :ten, 2 => :hundred, 3 => :thousand, 6 => :million, 9 => :billion, 12 => :trillion, 15 => :quadrillion,
467
- -1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto}
468
-
469
303
  # Pretty prints (formats and approximates) a number in a way it
470
304
  # is more readable by humans (eg.: 1200000000 becomes "1.2
471
305
  # Billion"). This is useful for numbers that can get very large
@@ -515,32 +349,32 @@ module ActionView
515
349
  #
516
350
  # ==== Examples
517
351
  #
518
- # number_to_human(123) # => "123"
519
- # number_to_human(1234) # => "1.23 Thousand"
520
- # number_to_human(12345) # => "12.3 Thousand"
521
- # number_to_human(1234567) # => "1.23 Million"
522
- # number_to_human(1234567890) # => "1.23 Billion"
523
- # number_to_human(1234567890123) # => "1.23 Trillion"
524
- # number_to_human(1234567890123456) # => "1.23 Quadrillion"
525
- # number_to_human(1234567890123456789) # => "1230 Quadrillion"
526
- # number_to_human(489939, :precision => 2) # => "490 Thousand"
527
- # number_to_human(489939, :precision => 4) # => "489.9 Thousand"
528
- # number_to_human(1234567, :precision => 4,
529
- # :significant => false) # => "1.2346 Million"
530
- # number_to_human(1234567, :precision => 1,
531
- # :separator => ',',
532
- # :significant => false) # => "1,2 Million"
352
+ # number_to_human(123) # => "123"
353
+ # number_to_human(1234) # => "1.23 Thousand"
354
+ # number_to_human(12345) # => "12.3 Thousand"
355
+ # number_to_human(1234567) # => "1.23 Million"
356
+ # number_to_human(1234567890) # => "1.23 Billion"
357
+ # number_to_human(1234567890123) # => "1.23 Trillion"
358
+ # number_to_human(1234567890123456) # => "1.23 Quadrillion"
359
+ # number_to_human(1234567890123456789) # => "1230 Quadrillion"
360
+ # number_to_human(489939, precision: 2) # => "490 Thousand"
361
+ # number_to_human(489939, precision: 4) # => "489.9 Thousand"
362
+ # number_to_human(1234567, precision: 4,
363
+ # significant: false) # => "1.2346 Million"
364
+ # number_to_human(1234567, precision: 1,
365
+ # separator: ',',
366
+ # significant: false) # => "1,2 Million"
533
367
  #
534
368
  # Non-significant zeros after the decimal separator are stripped
535
369
  # out by default (set <tt>:strip_insignificant_zeros</tt> to
536
370
  # +false+ to change that):
537
- # number_to_human(12345012345, :significant_digits => 6) # => "12.345 Billion"
538
- # number_to_human(500000000, :precision => 5) # => "500 Million"
371
+ # number_to_human(12345012345, significant_digits: 6) # => "12.345 Billion"
372
+ # number_to_human(500000000, precision: 5) # => "500 Million"
539
373
  #
540
374
  # ==== Custom Unit Quantifiers
541
375
  #
542
376
  # You can also use your own custom unit quantifiers:
543
- # number_to_human(500000, :units => {:unit => "ml", :thousand => "lt"}) # => "500 lt"
377
+ # number_to_human(500000, units: {unit: "ml", thousand: "lt"}) # => "500 lt"
544
378
  #
545
379
  # If in your I18n locale you have:
546
380
  # distance:
@@ -557,66 +391,51 @@ module ActionView
557
391
  #
558
392
  # Then you could do:
559
393
  #
560
- # number_to_human(543934, :units => :distance) # => "544 kilometers"
561
- # number_to_human(54393498, :units => :distance) # => "54400 kilometers"
562
- # number_to_human(54393498000, :units => :distance) # => "54.4 gazillion-distance"
563
- # number_to_human(343, :units => :distance, :precision => 1) # => "300 meters"
564
- # number_to_human(1, :units => :distance) # => "1 meter"
565
- # number_to_human(0.34, :units => :distance) # => "34 centimeters"
394
+ # number_to_human(543934, units: :distance) # => "544 kilometers"
395
+ # number_to_human(54393498, units: :distance) # => "54400 kilometers"
396
+ # number_to_human(54393498000, units: :distance) # => "54.4 gazillion-distance"
397
+ # number_to_human(343, units: :distance, precision: 1) # => "300 meters"
398
+ # number_to_human(1, units: :distance) # => "1 meter"
399
+ # number_to_human(0.34, units: :distance) # => "34 centimeters"
566
400
  #
567
401
  def number_to_human(number, options = {})
568
- options.symbolize_keys!
569
-
570
- number = begin
571
- Float(number)
572
- rescue ArgumentError, TypeError
573
- if options[:raise]
574
- raise InvalidNumberError, number
575
- else
576
- return number
577
- end
578
- end
402
+ options = escape_unsafe_delimiters_and_separators(options.symbolize_keys)
579
403
 
580
- defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
581
- human = I18n.translate(:'number.human.format', :locale => options[:locale], :default => {})
582
- defaults = defaults.merge(human)
404
+ wrap_with_output_safety_handling(number, options.delete(:raise)) {
405
+ ActiveSupport::NumberHelper.number_to_human(number, options)
406
+ }
407
+ end
583
408
 
584
- options = options.reverse_merge(defaults)
585
- #for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
586
- options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
409
+ private
587
410
 
588
- inverted_du = DECIMAL_UNITS.invert
411
+ def escape_unsafe_delimiters_and_separators(options)
412
+ options[:separator] = ERB::Util.html_escape(options[:separator]) if options[:separator] && !options[:separator].html_safe?
413
+ options[:delimiter] = ERB::Util.html_escape(options[:delimiter]) if options[:delimiter] && !options[:delimiter].html_safe?
414
+ options
415
+ end
589
416
 
590
- units = options.delete :units
591
- unit_exponents = case units
592
- when Hash
593
- units = Hash[units.map { |k, v| [k, ERB::Util.html_escape(v)] }]
594
- when String, Symbol
595
- I18n.translate(:"#{units}", :locale => options[:locale], :raise => true)
596
- when nil
597
- I18n.translate(:"number.human.decimal_units.units", :locale => options[:locale], :raise => true)
598
- else
599
- raise ArgumentError, ":units must be a Hash or String translation scope."
600
- end.keys.map{|e_name| inverted_du[e_name] }.sort_by{|e| -e}
417
+ def wrap_with_output_safety_handling(number, raise_on_invalid, &block)
418
+ valid_float = valid_float?(number)
419
+ raise InvalidNumberError, number if raise_on_invalid && !valid_float
601
420
 
602
- number_exponent = number != 0 ? Math.log10(number.abs).floor : 0
603
- display_exponent = unit_exponents.find{ |e| number_exponent >= e } || 0
604
- number /= 10 ** display_exponent
421
+ formatted_number = yield
605
422
 
606
- unit = case units
607
- when Hash
608
- units[DECIMAL_UNITS[display_exponent]] || ''
609
- when String, Symbol
610
- I18n.translate(:"#{units}.#{DECIMAL_UNITS[display_exponent]}", :locale => options[:locale], :count => number.to_i)
423
+ if valid_float || number.html_safe?
424
+ formatted_number.html_safe
611
425
  else
612
- I18n.translate(:"number.human.decimal_units.units.#{DECIMAL_UNITS[display_exponent]}", :locale => options[:locale], :count => number.to_i)
426
+ formatted_number
613
427
  end
428
+ end
614
429
 
615
- decimal_format = options[:format] || I18n.translate(:'number.human.decimal_units.format', :locale => options[:locale], :default => "%n %u")
616
- formatted_number = number_with_precision(number, options)
617
- decimal_format.gsub(/%n/, formatted_number).gsub(/%u/, unit).strip.html_safe
430
+ def valid_float?(number)
431
+ !parse_float(number, false).nil?
618
432
  end
619
433
 
434
+ def parse_float(number, raise_error)
435
+ Float(number)
436
+ rescue ArgumentError, TypeError
437
+ raise InvalidNumberError, number if raise_error
438
+ end
620
439
  end
621
440
  end
622
441
  end
@@ -11,7 +11,8 @@ module ActionView #:nodoc:
11
11
  #
12
12
  # For example:
13
13
  #
14
- # <%=raw @user.name %>
14
+ # raw @user.name
15
+ # # => 'Jimmy <alert>Tables</alert>'
15
16
  def raw(stringish)
16
17
  stringish.to_s.html_safe
17
18
  end
@@ -28,11 +29,10 @@ module ActionView #:nodoc:
28
29
  # # => "<p>foo</p><br /><p>bar</p>"
29
30
  #
30
31
  def safe_join(array, sep=$,)
31
- sep ||= "".html_safe
32
32
  sep = ERB::Util.html_escape(sep)
33
33
 
34
34
  array.map { |i| ERB::Util.html_escape(i) }.join(sep).html_safe
35
35
  end
36
36
  end
37
37
  end
38
- end
38
+ end