actionpack 2.1.2 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (200) hide show
  1. data/CHANGELOG +223 -7
  2. data/README +6 -12
  3. data/Rakefile +11 -11
  4. data/lib/action_controller.rb +9 -9
  5. data/lib/action_controller/assertions/response_assertions.rb +29 -78
  6. data/lib/action_controller/assertions/routing_assertions.rb +33 -33
  7. data/lib/action_controller/assertions/selector_assertions.rb +9 -5
  8. data/lib/action_controller/base.rb +227 -161
  9. data/lib/action_controller/benchmarking.rb +37 -24
  10. data/lib/action_controller/caching/actions.rb +53 -21
  11. data/lib/action_controller/caching/fragments.rb +10 -36
  12. data/lib/action_controller/caching/sweeping.rb +3 -3
  13. data/lib/action_controller/cgi_ext/session.rb +2 -22
  14. data/lib/action_controller/cgi_process.rb +8 -46
  15. data/lib/action_controller/components.rb +4 -1
  16. data/lib/action_controller/cookies.rb +10 -0
  17. data/lib/action_controller/dispatcher.rb +49 -15
  18. data/lib/action_controller/filters.rb +48 -10
  19. data/lib/action_controller/headers.rb +16 -14
  20. data/lib/action_controller/helpers.rb +2 -2
  21. data/lib/action_controller/http_authentication.rb +1 -1
  22. data/lib/action_controller/integration.rb +57 -60
  23. data/lib/action_controller/layout.rb +27 -53
  24. data/lib/action_controller/mime_responds.rb +5 -1
  25. data/lib/action_controller/mime_type.rb +64 -42
  26. data/lib/action_controller/mime_types.rb +2 -1
  27. data/lib/action_controller/performance_test.rb +16 -0
  28. data/lib/action_controller/polymorphic_routes.rb +16 -9
  29. data/lib/action_controller/rack_process.rb +303 -0
  30. data/lib/action_controller/request.rb +205 -97
  31. data/lib/action_controller/request_forgery_protection.rb +2 -2
  32. data/lib/action_controller/request_profiler.rb +0 -0
  33. data/lib/action_controller/rescue.rb +20 -115
  34. data/lib/action_controller/resources.rb +186 -83
  35. data/lib/action_controller/response.rb +140 -26
  36. data/lib/action_controller/routing.rb +28 -30
  37. data/lib/action_controller/routing/builder.rb +45 -54
  38. data/lib/action_controller/routing/optimisations.rb +31 -21
  39. data/lib/action_controller/routing/recognition_optimisation.rb +33 -27
  40. data/lib/action_controller/routing/route.rb +162 -147
  41. data/lib/action_controller/routing/route_set.rb +8 -7
  42. data/lib/action_controller/routing/routing_ext.rb +4 -1
  43. data/lib/action_controller/routing/segments.rb +50 -21
  44. data/lib/action_controller/session/cookie_store.rb +3 -2
  45. data/lib/action_controller/session/drb_server.rb +7 -7
  46. data/lib/action_controller/session_management.rb +6 -2
  47. data/lib/action_controller/streaming.rb +15 -8
  48. data/lib/action_controller/templates/rescues/diagnostics.erb +2 -2
  49. data/lib/action_controller/templates/rescues/template_error.erb +2 -2
  50. data/lib/action_controller/test_case.rb +66 -2
  51. data/lib/action_controller/test_process.rb +71 -66
  52. data/lib/action_controller/translation.rb +13 -0
  53. data/lib/action_controller/url_rewriter.rb +90 -13
  54. data/lib/action_controller/vendor/html-scanner/html/node.rb +9 -2
  55. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +1 -1
  56. data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -2
  57. data/lib/action_controller/verification.rb +2 -2
  58. data/lib/action_pack/version.rb +1 -1
  59. data/lib/action_view.rb +19 -11
  60. data/lib/action_view/base.rb +184 -150
  61. data/lib/action_view/helpers.rb +38 -0
  62. data/lib/action_view/helpers/active_record_helper.rb +56 -27
  63. data/lib/action_view/helpers/asset_tag_helper.rb +356 -153
  64. data/lib/action_view/helpers/atom_feed_helper.rb +74 -19
  65. data/lib/action_view/helpers/benchmark_helper.rb +3 -3
  66. data/lib/action_view/helpers/cache_helper.rb +1 -2
  67. data/lib/action_view/helpers/capture_helper.rb +19 -44
  68. data/lib/action_view/helpers/date_helper.rb +486 -296
  69. data/lib/action_view/helpers/debug_helper.rb +20 -13
  70. data/lib/action_view/helpers/form_helper.rb +71 -30
  71. data/lib/action_view/helpers/form_options_helper.rb +15 -85
  72. data/lib/action_view/helpers/form_tag_helper.rb +61 -38
  73. data/lib/action_view/helpers/javascript_helper.rb +80 -89
  74. data/lib/action_view/helpers/number_helper.rb +179 -74
  75. data/lib/action_view/helpers/prototype_helper.rb +216 -201
  76. data/lib/action_view/helpers/record_tag_helper.rb +4 -5
  77. data/lib/action_view/helpers/sanitize_helper.rb +65 -33
  78. data/lib/action_view/helpers/scriptaculous_helper.rb +2 -2
  79. data/lib/action_view/helpers/tag_helper.rb +39 -22
  80. data/lib/action_view/helpers/text_helper.rb +212 -118
  81. data/lib/action_view/helpers/translation_helper.rb +21 -0
  82. data/lib/action_view/helpers/url_helper.rb +100 -58
  83. data/lib/action_view/inline_template.rb +13 -14
  84. data/lib/action_view/locale/en.yml +91 -0
  85. data/lib/action_view/partials.rb +100 -55
  86. data/lib/action_view/paths.rb +125 -0
  87. data/lib/action_view/renderable.rb +102 -0
  88. data/lib/action_view/renderable_partial.rb +48 -0
  89. data/lib/action_view/template.rb +90 -101
  90. data/lib/action_view/template_error.rb +11 -21
  91. data/lib/action_view/template_handler.rb +8 -28
  92. data/lib/action_view/template_handlers.rb +45 -0
  93. data/lib/action_view/template_handlers/builder.rb +5 -15
  94. data/lib/action_view/template_handlers/erb.rb +9 -6
  95. data/lib/action_view/template_handlers/rjs.rb +2 -17
  96. data/lib/action_view/test_case.rb +7 -4
  97. data/test/abstract_unit.rb +4 -1
  98. data/test/active_record_unit.rb +28 -30
  99. data/test/activerecord/render_partial_with_record_identification_test.rb +25 -12
  100. data/test/controller/action_pack_assertions_test.rb +8 -37
  101. data/test/controller/addresses_render_test.rb +0 -3
  102. data/test/controller/assert_select_test.rb +51 -24
  103. data/test/controller/base_test.rb +4 -4
  104. data/test/controller/caching_test.rb +136 -66
  105. data/test/controller/capture_test.rb +1 -21
  106. data/test/controller/cgi_test.rb +157 -10
  107. data/test/controller/components_test.rb +41 -25
  108. data/test/controller/content_type_test.rb +49 -17
  109. data/test/controller/cookie_test.rb +1 -1
  110. data/test/controller/deprecation/deprecated_base_methods_test.rb +0 -3
  111. data/test/controller/dispatcher_test.rb +9 -1
  112. data/test/controller/filter_params_test.rb +2 -2
  113. data/test/controller/filters_test.rb +13 -13
  114. data/test/controller/html-scanner/cdata_node_test.rb +15 -0
  115. data/test/controller/html-scanner/node_test.rb +21 -0
  116. data/test/controller/html-scanner/sanitizer_test.rb +14 -0
  117. data/test/controller/integration_test.rb +167 -6
  118. data/test/controller/layout_test.rb +11 -68
  119. data/test/controller/logging_test.rb +46 -0
  120. data/test/controller/mime_responds_test.rb +61 -59
  121. data/test/controller/mime_type_test.rb +6 -6
  122. data/test/controller/polymorphic_routes_test.rb +37 -2
  123. data/test/controller/rack_test.rb +323 -0
  124. data/test/controller/redirect_test.rb +72 -71
  125. data/test/controller/render_test.rb +1120 -108
  126. data/test/controller/request_forgery_protection_test.rb +66 -52
  127. data/test/controller/request_test.rb +103 -146
  128. data/test/controller/rescue_test.rb +20 -24
  129. data/test/controller/resources_test.rb +408 -25
  130. data/test/controller/routing_test.rb +1774 -1774
  131. data/test/controller/send_file_test.rb +0 -4
  132. data/test/controller/session/cookie_store_test.rb +53 -1
  133. data/test/controller/test_test.rb +15 -37
  134. data/test/controller/translation_test.rb +26 -0
  135. data/test/controller/url_rewriter_test.rb +27 -28
  136. data/test/controller/view_paths_test.rb +48 -47
  137. data/test/fixtures/_top_level_partial.html.erb +1 -0
  138. data/test/fixtures/_top_level_partial_only.erb +1 -0
  139. data/test/fixtures/developers/_developer.erb +1 -0
  140. data/test/fixtures/fun/games/_game.erb +1 -0
  141. data/test/fixtures/fun/serious/games/_game.erb +1 -0
  142. data/test/fixtures/functional_caching/formatted_fragment_cached.html.erb +3 -0
  143. data/test/fixtures/functional_caching/formatted_fragment_cached.js.rjs +6 -0
  144. data/test/fixtures/functional_caching/formatted_fragment_cached.xml.builder +5 -0
  145. data/test/fixtures/functional_caching/inline_fragment_cached.html.erb +2 -0
  146. data/test/fixtures/layouts/_column.html.erb +2 -0
  147. data/test/fixtures/projects/_project.erb +1 -0
  148. data/test/fixtures/public/javascripts/subdir/subdir.js +1 -0
  149. data/test/fixtures/public/stylesheets/subdir/subdir.css +1 -0
  150. data/test/fixtures/replies/_reply.erb +1 -0
  151. data/test/fixtures/test/_counter.html.erb +1 -0
  152. data/test/fixtures/test/_customer.erb +1 -1
  153. data/test/fixtures/test/_customer_with_var.erb +1 -0
  154. data/test/fixtures/test/_layout_for_block_with_args.html.erb +3 -0
  155. data/test/fixtures/test/_local_inspector.html.erb +1 -0
  156. data/test/fixtures/test/_partial_with_only_html_version.html.erb +1 -0
  157. data/test/fixtures/test/hello.builder +1 -1
  158. data/test/fixtures/test/hyphen-ated.erb +1 -0
  159. data/test/fixtures/test/implicit_content_type.atom.builder +2 -0
  160. data/test/fixtures/test/nested_layout.erb +3 -0
  161. data/test/fixtures/test/non_erb_block_content_for.builder +1 -1
  162. data/test/fixtures/test/sub_template_raise.html.erb +1 -0
  163. data/test/fixtures/test/template.erb +1 -0
  164. data/test/fixtures/test/using_layout_around_block_with_args.html.erb +1 -0
  165. data/test/template/active_record_helper_i18n_test.rb +46 -0
  166. data/test/template/active_record_helper_test.rb +24 -24
  167. data/test/template/asset_tag_helper_test.rb +161 -29
  168. data/test/template/atom_feed_helper_test.rb +114 -5
  169. data/test/template/compiled_templates_test.rb +59 -0
  170. data/test/template/date_helper_i18n_test.rb +113 -0
  171. data/test/template/date_helper_test.rb +403 -109
  172. data/test/template/form_helper_test.rb +213 -154
  173. data/test/template/form_options_helper_test.rb +249 -897
  174. data/test/template/form_tag_helper_test.rb +80 -32
  175. data/test/template/javascript_helper_test.rb +17 -18
  176. data/test/template/number_helper_i18n_test.rb +54 -0
  177. data/test/template/number_helper_test.rb +43 -13
  178. data/test/template/prototype_helper_test.rb +101 -84
  179. data/test/template/record_tag_helper_test.rb +24 -20
  180. data/test/template/render_test.rb +193 -0
  181. data/test/template/sanitize_helper_test.rb +3 -3
  182. data/test/template/tag_helper_test.rb +34 -14
  183. data/test/template/text_helper_test.rb +83 -9
  184. data/test/template/translation_helper_test.rb +28 -0
  185. data/test/template/url_helper_test.rb +55 -18
  186. metadata +57 -18
  187. data/lib/action_view/helpers/javascripts/controls.js +0 -963
  188. data/lib/action_view/helpers/javascripts/dragdrop.js +0 -972
  189. data/lib/action_view/helpers/javascripts/effects.js +0 -1120
  190. data/lib/action_view/helpers/javascripts/prototype.js +0 -4225
  191. data/lib/action_view/partial_template.rb +0 -70
  192. data/lib/action_view/template_finder.rb +0 -177
  193. data/lib/action_view/template_handlers/compilable.rb +0 -128
  194. data/test/controller/custom_handler_test.rb +0 -45
  195. data/test/controller/new_render_test.rb +0 -945
  196. data/test/fixtures/test/block_content_for.erb +0 -2
  197. data/test/fixtures/test/erb_content_for.erb +0 -2
  198. data/test/template/deprecated_erb_variable_test.rb +0 -9
  199. data/test/template/template_finder_test.rb +0 -73
  200. data/test/template/template_object_test.rb +0 -95
@@ -4,10 +4,10 @@ require 'action_view/helpers/prototype_helper'
4
4
  module ActionView
5
5
  module Helpers
6
6
  # Provides functionality for working with JavaScript in your views.
7
- #
7
+ #
8
8
  # == Ajax, controls and visual effects
9
- #
10
- # * For information on using Ajax, see
9
+ #
10
+ # * For information on using Ajax, see
11
11
  # ActionView::Helpers::PrototypeHelper.
12
12
  # * For information on using controls and visual effects, see
13
13
  # ActionView::Helpers::ScriptaculousHelper.
@@ -20,22 +20,19 @@ module ActionView
20
20
  # and ActionView::Helpers::ScriptaculousHelper), you must do one of the
21
21
  # following:
22
22
  #
23
- # * Use <tt><%= javascript_include_tag :defaults %></tt> in the HEAD
24
- # section of your page (recommended): This function will return
23
+ # * Use <tt><%= javascript_include_tag :defaults %></tt> in the HEAD
24
+ # section of your page (recommended): This function will return
25
25
  # references to the JavaScript files created by the +rails+ command in
26
26
  # your <tt>public/javascripts</tt> directory. Using it is recommended as
27
- # the browser can then cache the libraries instead of fetching all the
27
+ # the browser can then cache the libraries instead of fetching all the
28
28
  # functions anew on every request.
29
- # * Use <tt><%= javascript_include_tag 'prototype' %></tt>: As above, but
29
+ # * Use <tt><%= javascript_include_tag 'prototype' %></tt>: As above, but
30
30
  # will only include the Prototype core library, which means you are able
31
- # to use all basic AJAX functionality. For the Scriptaculous-based
32
- # JavaScript helpers, like visual effects, autocompletion, drag and drop
31
+ # to use all basic AJAX functionality. For the Scriptaculous-based
32
+ # JavaScript helpers, like visual effects, autocompletion, drag and drop
33
33
  # and so on, you should use the method described above.
34
- # * Use <tt><%= define_javascript_functions %></tt>: this will copy all the
35
- # JavaScript support functions within a single script block. Not
36
- # recommended.
37
34
  #
38
- # For documentation on +javascript_include_tag+ see
35
+ # For documentation on +javascript_include_tag+ see
39
36
  # ActionView::Helpers::AssetTagHelper.
40
37
  module JavaScriptHelper
41
38
  unless const_defined? :JAVASCRIPT_PATH
@@ -43,13 +40,22 @@ module ActionView
43
40
  end
44
41
 
45
42
  include PrototypeHelper
46
-
47
- # Returns a link that will trigger a JavaScript +function+ using the
43
+
44
+ # Returns a link of the given +name+ that will trigger a JavaScript +function+ using the
48
45
  # onclick handler and return false after the fact.
49
46
  #
47
+ # The first argument +name+ is used as the link text.
48
+ #
49
+ # The next arguments are optional and may include the javascript function definition and a hash of html_options.
50
+ #
50
51
  # The +function+ argument can be omitted in favor of an +update_page+
51
52
  # block, which evaluates to a string when the template is rendered
52
- # (instead of making an Ajax request first).
53
+ # (instead of making an Ajax request first).
54
+ #
55
+ # The +html_options+ will accept a hash of html attributes for the link tag. Some examples are :class => "nav_button", :id => "articles_nav_button"
56
+ #
57
+ # Note: if you choose to specify the javascript function in a block, but would like to pass html_options, set the +function+ parameter to nil
58
+ #
53
59
  #
54
60
  # Examples:
55
61
  # link_to_function "Greeting", "alert('Hello world!')"
@@ -70,35 +76,39 @@ module ActionView
70
76
  # <a href="#" id="more_link" onclick="try {
71
77
  # $(&quot;details&quot;).visualEffect(&quot;toggle_blind&quot;);
72
78
  # $(&quot;more_link&quot;).update(&quot;Show me less&quot;);
73
- # }
74
- # catch (e) {
75
- # alert('RJS error:\n\n' + e.toString());
79
+ # }
80
+ # catch (e) {
81
+ # alert('RJS error:\n\n' + e.toString());
76
82
  # alert('$(\&quot;details\&quot;).visualEffect(\&quot;toggle_blind\&quot;);
77
83
  # \n$(\&quot;more_link\&quot;).update(\&quot;Show me less\&quot;);');
78
- # throw e
84
+ # throw e
79
85
  # };
80
86
  # return false;">Show me more</a>
81
87
  #
82
88
  def link_to_function(name, *args, &block)
83
89
  html_options = args.extract_options!.symbolize_keys
84
- function = args[0] || ''
85
-
86
- function = update_page(&block) if block_given?
87
- content_tag(
88
- "a", name,
89
- html_options.merge({
90
- :href => html_options[:href] || "#",
91
- :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function}; return false;"
92
- })
93
- )
90
+
91
+ function = block_given? ? update_page(&block) : args[0] || ''
92
+ onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;"
93
+ href = html_options[:href] || '#'
94
+
95
+ content_tag(:a, name, html_options.merge(:href => href, :onclick => onclick))
94
96
  end
95
-
96
- # Returns a button that'll trigger a JavaScript +function+ using the
97
+
98
+ # Returns a button with the given +name+ text that'll trigger a JavaScript +function+ using the
97
99
  # onclick handler.
98
100
  #
101
+ # The first argument +name+ is used as the button's value or display text.
102
+ #
103
+ # The next arguments are optional and may include the javascript function definition and a hash of html_options.
104
+ #
99
105
  # The +function+ argument can be omitted in favor of an +update_page+
100
106
  # block, which evaluates to a string when the template is rendered
101
- # (instead of making an Ajax request first).
107
+ # (instead of making an Ajax request first).
108
+ #
109
+ # The +html_options+ will accept a hash of html attributes for the link tag. Some examples are :class => "nav_button", :id => "articles_nav_button"
110
+ #
111
+ # Note: if you choose to specify the javascript function in a block, but would like to pass html_options, set the +function+ parameter to nil
102
112
  #
103
113
  # Examples:
104
114
  # button_to_function "Greeting", "alert('Hello world!')"
@@ -111,45 +121,29 @@ module ActionView
111
121
  # end
112
122
  def button_to_function(name, *args, &block)
113
123
  html_options = args.extract_options!.symbolize_keys
114
- function = args[0] || ''
115
124
 
116
- function = update_page(&block) if block_given?
117
- tag(:input, html_options.merge({
118
- :type => "button", :value => name,
119
- :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
120
- }))
121
- end
125
+ function = block_given? ? update_page(&block) : args[0] || ''
126
+ onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};"
122
127
 
123
- # Includes the Action Pack JavaScript libraries inside a single <script>
124
- # tag. The function first includes prototype.js and then its core extensions,
125
- # (determined by filenames starting with "prototype").
126
- # Afterwards, any additional scripts will be included in undefined order.
127
- #
128
- # Note: The recommended approach is to copy the contents of
129
- # lib/action_view/helpers/javascripts/ into your application's
130
- # public/javascripts/ directory, and use +javascript_include_tag+ to
131
- # create remote <script> links.
132
- def define_javascript_functions
133
- javascript = "<script type=\"#{Mime::JS}\">"
134
-
135
- # load prototype.js and its extensions first
136
- prototype_libs = Dir.glob(File.join(JAVASCRIPT_PATH, 'prototype*')).sort.reverse
137
- prototype_libs.each do |filename|
138
- javascript << "\n" << IO.read(filename)
139
- end
140
-
141
- # load other libraries
142
- (Dir.glob(File.join(JAVASCRIPT_PATH, '*')) - prototype_libs).each do |filename|
143
- javascript << "\n" << IO.read(filename)
144
- end
145
- javascript << '</script>'
128
+ tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick))
146
129
  end
147
130
 
148
- deprecate :define_javascript_functions=>"use javascript_include_tag instead"
131
+ JS_ESCAPE_MAP = {
132
+ '\\' => '\\\\',
133
+ '</' => '<\/',
134
+ "\r\n" => '\n',
135
+ "\n" => '\n',
136
+ "\r" => '\n',
137
+ '"' => '\\"',
138
+ "'" => "\\'" }
149
139
 
150
140
  # Escape carrier returns and single and double quotes for JavaScript segments.
151
141
  def escape_javascript(javascript)
152
- (javascript || '').gsub('\\','\0\0').gsub('</','<\/').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
142
+ if javascript
143
+ javascript.gsub(/(\\|<\/|\r\n|[\n\r"'])/) { JS_ESCAPE_MAP[$1] }
144
+ else
145
+ ''
146
+ end
153
147
  end
154
148
 
155
149
  # Returns a JavaScript tag with the +content+ inside. Example:
@@ -163,7 +157,7 @@ module ActionView
163
157
  # </script>
164
158
  #
165
159
  # +html_options+ may be a hash of attributes for the <script> tag. Example:
166
- # javascript_tag "alert('All is good')", :defer => 'defer'
160
+ # javascript_tag "alert('All is good')", :defer => 'defer'
167
161
  # # => <script defer="defer" type="text/javascript">alert('All is good')</script>
168
162
  #
169
163
  # Instead of passing the content as an argument, you can also use a block
@@ -172,46 +166,43 @@ module ActionView
172
166
  # alert('All is good')
173
167
  # <% end -%>
174
168
  def javascript_tag(content_or_options_with_block = nil, html_options = {}, &block)
175
- if block_given?
176
- html_options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
177
- content = capture(&block)
178
- else
179
- content = content_or_options_with_block
180
- end
169
+ content =
170
+ if block_given?
171
+ html_options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
172
+ capture(&block)
173
+ else
174
+ content_or_options_with_block
175
+ end
181
176
 
182
- javascript_tag = content_tag("script", javascript_cdata_section(content), html_options.merge(:type => Mime::JS))
183
-
184
- if block_given? && block_is_within_action_view?(block)
185
- concat(javascript_tag, block.binding)
177
+ tag = content_tag(:script, javascript_cdata_section(content), html_options.merge(:type => Mime::JS))
178
+
179
+ if block_called_from_erb?(block)
180
+ concat(tag)
186
181
  else
187
- javascript_tag
182
+ tag
188
183
  end
189
184
  end
190
185
 
191
186
  def javascript_cdata_section(content) #:nodoc:
192
187
  "\n//#{cdata_section("\n#{content}\n//")}\n"
193
188
  end
194
-
189
+
195
190
  protected
196
191
  def options_for_javascript(options)
197
- '{' + options.map {|k, v| "#{k}:#{v}"}.sort.join(', ') + '}'
192
+ if options.empty?
193
+ '{}'
194
+ else
195
+ "{#{options.keys.map { |k| "#{k}:#{options[k]}" }.sort.join(', ')}}"
196
+ end
198
197
  end
199
-
198
+
200
199
  def array_or_string_for_javascript(option)
201
- js_option = if option.kind_of?(Array)
200
+ if option.kind_of?(Array)
202
201
  "['#{option.join('\',\'')}']"
203
202
  elsif !option.nil?
204
203
  "'#{option}'"
205
204
  end
206
- js_option
207
- end
208
-
209
- private
210
- def block_is_within_action_view?(block)
211
- eval("defined? _erbout", block.binding)
212
205
  end
213
206
  end
214
-
215
- JavascriptHelper = JavaScriptHelper unless const_defined? :JavascriptHelper
216
207
  end
217
208
  end
@@ -22,14 +22,14 @@ module ActionView
22
22
  # number_to_phone(1235551234, :country_code => 1) # => +1-123-555-1234
23
23
  #
24
24
  # number_to_phone(1235551234, :country_code => 1, :extension => 1343, :delimiter => ".")
25
- # => +1.123.555.1234 x 1343
25
+ # => +1.123.555.1234 x 1343
26
26
  def number_to_phone(number, options = {})
27
27
  number = number.to_s.strip unless number.nil?
28
- options = options.stringify_keys
29
- area_code = options["area_code"] || nil
30
- delimiter = options["delimiter"] || "-"
31
- extension = options["extension"].to_s.strip || nil
32
- country_code = options["country_code"] || nil
28
+ options = options.symbolize_keys
29
+ area_code = options[:area_code] || nil
30
+ delimiter = options[:delimiter] || "-"
31
+ extension = options[:extension].to_s.strip || nil
32
+ country_code = options[:country_code] || nil
33
33
 
34
34
  begin
35
35
  str = ""
@@ -51,10 +51,10 @@ module ActionView
51
51
  #
52
52
  # ==== Options
53
53
  # * <tt>:precision</tt> - Sets the level of precision (defaults to 2).
54
- # * <tt>:unit</tt> - Sets the denomination of the currency (defaults to "$").
54
+ # * <tt>:unit</tt> - Sets the denomination of the currency (defaults to "$").
55
55
  # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
56
56
  # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ",").
57
- # * <tt>:format</tt> - Sets the format of the output string (defaults to "%u%n"). The field types are:
57
+ # * <tt>:format</tt> - Sets the format of the output string (defaults to "%u%n"). The field types are:
58
58
  #
59
59
  # %u The currency unit
60
60
  # %n The number
@@ -69,16 +69,25 @@ module ActionView
69
69
  # number_to_currency(1234567890.50, :unit => "&pound;", :separator => ",", :delimiter => "", :format => "%n %u")
70
70
  # # => 1234567890,50 &pound;
71
71
  def number_to_currency(number, options = {})
72
- options = options.stringify_keys
73
- precision = options["precision"] || 2
74
- unit = options["unit"] || "$"
75
- separator = precision > 0 ? options["separator"] || "." : ""
76
- delimiter = options["delimiter"] || ","
77
- format = options["format"] || "%u%n"
72
+ options.symbolize_keys!
73
+
74
+ defaults = I18n.translate(:'number.format', :locale => options[:locale], :raise => true) rescue {}
75
+ currency = I18n.translate(:'number.currency.format', :locale => options[:locale], :raise => true) rescue {}
76
+ defaults = defaults.merge(currency)
77
+
78
+ precision = options[:precision] || defaults[:precision]
79
+ unit = options[:unit] || defaults[:unit]
80
+ separator = options[:separator] || defaults[:separator]
81
+ delimiter = options[:delimiter] || defaults[:delimiter]
82
+ format = options[:format] || defaults[:format]
83
+ separator = '' if precision == 0
78
84
 
79
85
  begin
80
- parts = number_with_precision(number, precision).split('.')
81
- format.gsub(/%n/, number_with_delimiter(parts[0], delimiter) + separator + parts[1].to_s).gsub(/%u/, unit)
86
+ format.gsub(/%n/, number_with_precision(number,
87
+ :precision => precision,
88
+ :delimiter => delimiter,
89
+ :separator => separator)
90
+ ).gsub(/%u/, unit)
82
91
  rescue
83
92
  number
84
93
  end
@@ -90,96 +99,192 @@ module ActionView
90
99
  # ==== Options
91
100
  # * <tt>:precision</tt> - Sets the level of precision (defaults to 3).
92
101
  # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
102
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
93
103
  #
94
104
  # ==== Examples
95
- # number_to_percentage(100) # => 100.000%
96
- # number_to_percentage(100, :precision => 0) # => 100%
97
- #
98
- # number_to_percentage(302.24398923423, :precision => 5)
99
- # # => 302.24399%
105
+ # number_to_percentage(100) # => 100.000%
106
+ # number_to_percentage(100, :precision => 0) # => 100%
107
+ # number_to_percentage(1000, :delimiter => '.', :separator => ',') # => 1.000,000%
108
+ # number_to_percentage(302.24398923423, :precision => 5) # => 302.24399%
100
109
  def number_to_percentage(number, options = {})
101
- options = options.stringify_keys
102
- precision = options["precision"] || 3
103
- separator = options["separator"] || "."
110
+ options.symbolize_keys!
111
+
112
+ defaults = I18n.translate(:'number.format', :locale => options[:locale], :raise => true) rescue {}
113
+ percentage = I18n.translate(:'number.percentage.format', :locale => options[:locale], :raise => true) rescue {}
114
+ defaults = defaults.merge(percentage)
115
+
116
+ precision = options[:precision] || defaults[:precision]
117
+ separator = options[:separator] || defaults[:separator]
118
+ delimiter = options[:delimiter] || defaults[:delimiter]
104
119
 
105
120
  begin
106
- number = number_with_precision(number, precision)
107
- parts = number.split('.')
108
- if parts.at(1).nil?
109
- parts[0] + "%"
110
- else
111
- parts[0] + separator + parts[1].to_s + "%"
112
- end
121
+ number_with_precision(number,
122
+ :precision => precision,
123
+ :separator => separator,
124
+ :delimiter => delimiter) + "%"
113
125
  rescue
114
126
  number
115
127
  end
116
128
  end
117
129
 
118
- # Formats a +number+ with grouped thousands using +delimiter+ (e.g., 12,324). You
119
- # can customize the format using optional <em>delimiter</em> and <em>separator</em> parameters.
130
+ # Formats a +number+ with grouped thousands using +delimiter+ (e.g., 12,324). You can
131
+ # customize the format in the +options+ hash.
120
132
  #
121
133
  # ==== Options
122
- # * <tt>delimiter</tt> - Sets the thousands delimiter (defaults to ",").
123
- # * <tt>separator</tt> - Sets the separator between the units (defaults to ".").
134
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ",").
135
+ # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
124
136
  #
125
137
  # ==== Examples
126
- # number_with_delimiter(12345678) # => 12,345,678
127
- # number_with_delimiter(12345678.05) # => 12,345,678.05
128
- # number_with_delimiter(12345678, ".") # => 12.345.678
129
- #
130
- # number_with_delimiter(98765432.98, " ", ",")
138
+ # number_with_delimiter(12345678) # => 12,345,678
139
+ # number_with_delimiter(12345678.05) # => 12,345,678.05
140
+ # number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678
141
+ # number_with_delimiter(12345678, :seperator => ",") # => 12,345,678
142
+ # number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",")
131
143
  # # => 98 765 432,98
132
- def number_with_delimiter(number, delimiter=",", separator=".")
144
+ #
145
+ # You can still use <tt>number_with_delimiter</tt> with the old API that accepts the
146
+ # +delimiter+ as its optional second and the +separator+ as its
147
+ # optional third parameter:
148
+ # number_with_delimiter(12345678, " ") # => 12 345.678
149
+ # number_with_delimiter(12345678.05, ".", ",") # => 12.345.678,05
150
+ def number_with_delimiter(number, *args)
151
+ options = args.extract_options!
152
+ options.symbolize_keys!
153
+
154
+ defaults = I18n.translate(:'number.format', :locale => options[:locale], :raise => true) rescue {}
155
+
156
+ unless args.empty?
157
+ ActiveSupport::Deprecation.warn('number_with_delimiter takes an option hash ' +
158
+ 'instead of separate delimiter and precision arguments.', caller)
159
+ delimiter = args[0] || defaults[:delimiter]
160
+ separator = args[1] || defaults[:separator]
161
+ end
162
+
163
+ delimiter ||= (options[:delimiter] || defaults[:delimiter])
164
+ separator ||= (options[:separator] || defaults[:separator])
165
+
133
166
  begin
134
167
  parts = number.to_s.split('.')
135
168
  parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")
136
- parts.join separator
169
+ parts.join(separator)
137
170
  rescue
138
171
  number
139
172
  end
140
173
  end
141
174
 
142
- # Formats a +number+ with the specified level of +precision+ (e.g., 112.32 has a precision of 2). The default
143
- # level of precision is 3.
175
+ # Formats a +number+ with the specified level of <tt>:precision</tt> (e.g., 112.32 has a precision of 2).
176
+ # You can customize the format in the +options+ hash.
177
+ #
178
+ # ==== Options
179
+ # * <tt>:precision</tt> - Sets the level of precision (defaults to 3).
180
+ # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
181
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
144
182
  #
145
183
  # ==== Examples
146
- # number_with_precision(111.2345) # => 111.235
147
- # number_with_precision(111.2345, 2) # => 111.23
148
- # number_with_precision(13, 5) # => 13.00000
149
- # number_with_precision(389.32314, 0) # => 389
150
- def number_with_precision(number, precision=3)
151
- "%01.#{precision}f" % ((Float(number) * (10 ** precision)).round.to_f / 10 ** precision)
152
- rescue
153
- number
184
+ # number_with_precision(111.2345) # => 111.235
185
+ # number_with_precision(111.2345, :precision => 2) # => 111.23
186
+ # number_with_precision(13, :precision => 5) # => 13.00000
187
+ # number_with_precision(389.32314, :precision => 0) # => 389
188
+ # number_with_precision(1111.2345, :precision => 2, :separator => ',', :delimiter => '.')
189
+ # # => 1.111,23
190
+ #
191
+ # You can still use <tt>number_with_precision</tt> with the old API that accepts the
192
+ # +precision+ as its optional second parameter:
193
+ # number_with_precision(number_with_precision(111.2345, 2) # => 111.23
194
+ def number_with_precision(number, *args)
195
+ options = args.extract_options!
196
+ options.symbolize_keys!
197
+
198
+ defaults = I18n.translate(:'number.format', :locale => options[:locale], :raise => true) rescue {}
199
+ precision_defaults = I18n.translate(:'number.precision.format', :locale => options[:locale],
200
+ :raise => true) rescue {}
201
+ defaults = defaults.merge(precision_defaults)
202
+
203
+ unless args.empty?
204
+ ActiveSupport::Deprecation.warn('number_with_precision takes an option hash ' +
205
+ 'instead of a separate precision argument.', caller)
206
+ precision = args[0] || defaults[:precision]
207
+ end
208
+
209
+ precision ||= (options[:precision] || defaults[:precision])
210
+ separator ||= (options[:separator] || defaults[:separator])
211
+ delimiter ||= (options[:delimiter] || defaults[:delimiter])
212
+
213
+ begin
214
+ rounded_number = (Float(number) * (10 ** precision)).round.to_f / 10 ** precision
215
+ number_with_delimiter("%01.#{precision}f" % rounded_number,
216
+ :separator => separator,
217
+ :delimiter => delimiter)
218
+ rescue
219
+ number
220
+ end
154
221
  end
155
222
 
223
+ STORAGE_UNITS = %w( Bytes KB MB GB TB ).freeze
224
+
156
225
  # Formats the bytes in +size+ into a more understandable representation
157
- # (e.g., giving it 1500 yields 1.5 KB). This method is useful for
226
+ # (e.g., giving it 1500 yields 1.5 KB). This method is useful for
158
227
  # reporting file sizes to users. This method returns nil if
159
- # +size+ cannot be converted into a number. You can change the default
160
- # precision of 1 using the precision parameter +precision+.
228
+ # +size+ cannot be converted into a number. You can customize the
229
+ # format in the +options+ hash.
230
+ #
231
+ # ==== Options
232
+ # * <tt>:precision</tt> - Sets the level of precision (defaults to 1).
233
+ # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
234
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
161
235
  #
162
236
  # ==== Examples
163
- # number_to_human_size(123) # => 123 Bytes
164
- # number_to_human_size(1234) # => 1.2 KB
165
- # number_to_human_size(12345) # => 12.1 KB
166
- # number_to_human_size(1234567) # => 1.2 MB
167
- # number_to_human_size(1234567890) # => 1.1 GB
168
- # number_to_human_size(1234567890123) # => 1.1 TB
237
+ # number_to_human_size(123) # => 123 Bytes
238
+ # number_to_human_size(1234) # => 1.2 KB
239
+ # number_to_human_size(12345) # => 12.1 KB
240
+ # number_to_human_size(1234567) # => 1.2 MB
241
+ # number_to_human_size(1234567890) # => 1.1 GB
242
+ # number_to_human_size(1234567890123) # => 1.1 TB
243
+ # number_to_human_size(1234567, :precision => 2) # => 1.18 MB
244
+ # number_to_human_size(483989, :precision => 0) # => 473 KB
245
+ # number_to_human_size(1234567, :precision => 2, :separator => ',') # => 1,18 MB
246
+ #
247
+ # You can still use <tt>number_to_human_size</tt> with the old API that accepts the
248
+ # +precision+ as its optional second parameter:
169
249
  # number_to_human_size(1234567, 2) # => 1.18 MB
170
- # number_to_human_size(483989, 0) # => 4 MB
171
- def number_to_human_size(size, precision=1)
172
- size = Kernel.Float(size)
173
- case
174
- when size.to_i == 1; "1 Byte"
175
- when size < 1.kilobyte; "%d Bytes" % size
176
- when size < 1.megabyte; "%.#{precision}f KB" % (size / 1.0.kilobyte)
177
- when size < 1.gigabyte; "%.#{precision}f MB" % (size / 1.0.megabyte)
178
- when size < 1.terabyte; "%.#{precision}f GB" % (size / 1.0.gigabyte)
179
- else "%.#{precision}f TB" % (size / 1.0.terabyte)
180
- end.sub(/([0-9]\.\d*?)0+ /, '\1 ' ).sub(/\. /,' ')
181
- rescue
182
- nil
250
+ # number_to_human_size(483989, 0) # => 473 KB
251
+ def number_to_human_size(number, *args)
252
+ return number.nil? ? nil : pluralize(number.to_i, "Byte") if number.to_i < 1024
253
+
254
+ options = args.extract_options!
255
+ options.symbolize_keys!
256
+
257
+ defaults = I18n.translate(:'number.format', :locale => options[:locale], :raise => true) rescue {}
258
+ human = I18n.translate(:'number.human.format', :locale => options[:locale], :raise => true) rescue {}
259
+ defaults = defaults.merge(human)
260
+
261
+ unless args.empty?
262
+ ActiveSupport::Deprecation.warn('number_to_human_size takes an option hash ' +
263
+ 'instead of a separate precision argument.', caller)
264
+ precision = args[0] || defaults[:precision]
265
+ end
266
+
267
+ precision ||= (options[:precision] || defaults[:precision])
268
+ separator ||= (options[:separator] || defaults[:separator])
269
+ delimiter ||= (options[:delimiter] || defaults[:delimiter])
270
+
271
+ max_exp = STORAGE_UNITS.size - 1
272
+ number = Float(number)
273
+ exponent = (Math.log(number) / Math.log(1024)).to_i # Convert to base 1024
274
+ exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit
275
+ number /= 1024 ** exponent
276
+ unit = STORAGE_UNITS[exponent]
277
+
278
+ begin
279
+ escaped_separator = Regexp.escape(separator)
280
+ number_with_precision(number,
281
+ :precision => precision,
282
+ :separator => separator,
283
+ :delimiter => delimiter
284
+ ).sub(/(\d)(#{escaped_separator}[1-9]*)?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '') + " #{unit}"
285
+ rescue
286
+ number
287
+ end
183
288
  end
184
289
  end
185
290
  end