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.
- data/CHANGELOG +223 -7
- data/README +6 -12
- data/Rakefile +11 -11
- data/lib/action_controller.rb +9 -9
- data/lib/action_controller/assertions/response_assertions.rb +29 -78
- data/lib/action_controller/assertions/routing_assertions.rb +33 -33
- data/lib/action_controller/assertions/selector_assertions.rb +9 -5
- data/lib/action_controller/base.rb +227 -161
- data/lib/action_controller/benchmarking.rb +37 -24
- data/lib/action_controller/caching/actions.rb +53 -21
- data/lib/action_controller/caching/fragments.rb +10 -36
- data/lib/action_controller/caching/sweeping.rb +3 -3
- data/lib/action_controller/cgi_ext/session.rb +2 -22
- data/lib/action_controller/cgi_process.rb +8 -46
- data/lib/action_controller/components.rb +4 -1
- data/lib/action_controller/cookies.rb +10 -0
- data/lib/action_controller/dispatcher.rb +49 -15
- data/lib/action_controller/filters.rb +48 -10
- data/lib/action_controller/headers.rb +16 -14
- data/lib/action_controller/helpers.rb +2 -2
- data/lib/action_controller/http_authentication.rb +1 -1
- data/lib/action_controller/integration.rb +57 -60
- data/lib/action_controller/layout.rb +27 -53
- data/lib/action_controller/mime_responds.rb +5 -1
- data/lib/action_controller/mime_type.rb +64 -42
- data/lib/action_controller/mime_types.rb +2 -1
- data/lib/action_controller/performance_test.rb +16 -0
- data/lib/action_controller/polymorphic_routes.rb +16 -9
- data/lib/action_controller/rack_process.rb +303 -0
- data/lib/action_controller/request.rb +205 -97
- data/lib/action_controller/request_forgery_protection.rb +2 -2
- data/lib/action_controller/request_profiler.rb +0 -0
- data/lib/action_controller/rescue.rb +20 -115
- data/lib/action_controller/resources.rb +186 -83
- data/lib/action_controller/response.rb +140 -26
- data/lib/action_controller/routing.rb +28 -30
- data/lib/action_controller/routing/builder.rb +45 -54
- data/lib/action_controller/routing/optimisations.rb +31 -21
- data/lib/action_controller/routing/recognition_optimisation.rb +33 -27
- data/lib/action_controller/routing/route.rb +162 -147
- data/lib/action_controller/routing/route_set.rb +8 -7
- data/lib/action_controller/routing/routing_ext.rb +4 -1
- data/lib/action_controller/routing/segments.rb +50 -21
- data/lib/action_controller/session/cookie_store.rb +3 -2
- data/lib/action_controller/session/drb_server.rb +7 -7
- data/lib/action_controller/session_management.rb +6 -2
- data/lib/action_controller/streaming.rb +15 -8
- data/lib/action_controller/templates/rescues/diagnostics.erb +2 -2
- data/lib/action_controller/templates/rescues/template_error.erb +2 -2
- data/lib/action_controller/test_case.rb +66 -2
- data/lib/action_controller/test_process.rb +71 -66
- data/lib/action_controller/translation.rb +13 -0
- data/lib/action_controller/url_rewriter.rb +90 -13
- data/lib/action_controller/vendor/html-scanner/html/node.rb +9 -2
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +1 -1
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -2
- data/lib/action_controller/verification.rb +2 -2
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_view.rb +19 -11
- data/lib/action_view/base.rb +184 -150
- data/lib/action_view/helpers.rb +38 -0
- data/lib/action_view/helpers/active_record_helper.rb +56 -27
- data/lib/action_view/helpers/asset_tag_helper.rb +356 -153
- data/lib/action_view/helpers/atom_feed_helper.rb +74 -19
- data/lib/action_view/helpers/benchmark_helper.rb +3 -3
- data/lib/action_view/helpers/cache_helper.rb +1 -2
- data/lib/action_view/helpers/capture_helper.rb +19 -44
- data/lib/action_view/helpers/date_helper.rb +486 -296
- data/lib/action_view/helpers/debug_helper.rb +20 -13
- data/lib/action_view/helpers/form_helper.rb +71 -30
- data/lib/action_view/helpers/form_options_helper.rb +15 -85
- data/lib/action_view/helpers/form_tag_helper.rb +61 -38
- data/lib/action_view/helpers/javascript_helper.rb +80 -89
- data/lib/action_view/helpers/number_helper.rb +179 -74
- data/lib/action_view/helpers/prototype_helper.rb +216 -201
- data/lib/action_view/helpers/record_tag_helper.rb +4 -5
- data/lib/action_view/helpers/sanitize_helper.rb +65 -33
- data/lib/action_view/helpers/scriptaculous_helper.rb +2 -2
- data/lib/action_view/helpers/tag_helper.rb +39 -22
- data/lib/action_view/helpers/text_helper.rb +212 -118
- data/lib/action_view/helpers/translation_helper.rb +21 -0
- data/lib/action_view/helpers/url_helper.rb +100 -58
- data/lib/action_view/inline_template.rb +13 -14
- data/lib/action_view/locale/en.yml +91 -0
- data/lib/action_view/partials.rb +100 -55
- data/lib/action_view/paths.rb +125 -0
- data/lib/action_view/renderable.rb +102 -0
- data/lib/action_view/renderable_partial.rb +48 -0
- data/lib/action_view/template.rb +90 -101
- data/lib/action_view/template_error.rb +11 -21
- data/lib/action_view/template_handler.rb +8 -28
- data/lib/action_view/template_handlers.rb +45 -0
- data/lib/action_view/template_handlers/builder.rb +5 -15
- data/lib/action_view/template_handlers/erb.rb +9 -6
- data/lib/action_view/template_handlers/rjs.rb +2 -17
- data/lib/action_view/test_case.rb +7 -4
- data/test/abstract_unit.rb +4 -1
- data/test/active_record_unit.rb +28 -30
- data/test/activerecord/render_partial_with_record_identification_test.rb +25 -12
- data/test/controller/action_pack_assertions_test.rb +8 -37
- data/test/controller/addresses_render_test.rb +0 -3
- data/test/controller/assert_select_test.rb +51 -24
- data/test/controller/base_test.rb +4 -4
- data/test/controller/caching_test.rb +136 -66
- data/test/controller/capture_test.rb +1 -21
- data/test/controller/cgi_test.rb +157 -10
- data/test/controller/components_test.rb +41 -25
- data/test/controller/content_type_test.rb +49 -17
- data/test/controller/cookie_test.rb +1 -1
- data/test/controller/deprecation/deprecated_base_methods_test.rb +0 -3
- data/test/controller/dispatcher_test.rb +9 -1
- data/test/controller/filter_params_test.rb +2 -2
- data/test/controller/filters_test.rb +13 -13
- data/test/controller/html-scanner/cdata_node_test.rb +15 -0
- data/test/controller/html-scanner/node_test.rb +21 -0
- data/test/controller/html-scanner/sanitizer_test.rb +14 -0
- data/test/controller/integration_test.rb +167 -6
- data/test/controller/layout_test.rb +11 -68
- data/test/controller/logging_test.rb +46 -0
- data/test/controller/mime_responds_test.rb +61 -59
- data/test/controller/mime_type_test.rb +6 -6
- data/test/controller/polymorphic_routes_test.rb +37 -2
- data/test/controller/rack_test.rb +323 -0
- data/test/controller/redirect_test.rb +72 -71
- data/test/controller/render_test.rb +1120 -108
- data/test/controller/request_forgery_protection_test.rb +66 -52
- data/test/controller/request_test.rb +103 -146
- data/test/controller/rescue_test.rb +20 -24
- data/test/controller/resources_test.rb +408 -25
- data/test/controller/routing_test.rb +1774 -1774
- data/test/controller/send_file_test.rb +0 -4
- data/test/controller/session/cookie_store_test.rb +53 -1
- data/test/controller/test_test.rb +15 -37
- data/test/controller/translation_test.rb +26 -0
- data/test/controller/url_rewriter_test.rb +27 -28
- data/test/controller/view_paths_test.rb +48 -47
- data/test/fixtures/_top_level_partial.html.erb +1 -0
- data/test/fixtures/_top_level_partial_only.erb +1 -0
- data/test/fixtures/developers/_developer.erb +1 -0
- data/test/fixtures/fun/games/_game.erb +1 -0
- data/test/fixtures/fun/serious/games/_game.erb +1 -0
- data/test/fixtures/functional_caching/formatted_fragment_cached.html.erb +3 -0
- data/test/fixtures/functional_caching/formatted_fragment_cached.js.rjs +6 -0
- data/test/fixtures/functional_caching/formatted_fragment_cached.xml.builder +5 -0
- data/test/fixtures/functional_caching/inline_fragment_cached.html.erb +2 -0
- data/test/fixtures/layouts/_column.html.erb +2 -0
- data/test/fixtures/projects/_project.erb +1 -0
- data/test/fixtures/public/javascripts/subdir/subdir.js +1 -0
- data/test/fixtures/public/stylesheets/subdir/subdir.css +1 -0
- data/test/fixtures/replies/_reply.erb +1 -0
- data/test/fixtures/test/_counter.html.erb +1 -0
- data/test/fixtures/test/_customer.erb +1 -1
- data/test/fixtures/test/_customer_with_var.erb +1 -0
- data/test/fixtures/test/_layout_for_block_with_args.html.erb +3 -0
- data/test/fixtures/test/_local_inspector.html.erb +1 -0
- data/test/fixtures/test/_partial_with_only_html_version.html.erb +1 -0
- data/test/fixtures/test/hello.builder +1 -1
- data/test/fixtures/test/hyphen-ated.erb +1 -0
- data/test/fixtures/test/implicit_content_type.atom.builder +2 -0
- data/test/fixtures/test/nested_layout.erb +3 -0
- data/test/fixtures/test/non_erb_block_content_for.builder +1 -1
- data/test/fixtures/test/sub_template_raise.html.erb +1 -0
- data/test/fixtures/test/template.erb +1 -0
- data/test/fixtures/test/using_layout_around_block_with_args.html.erb +1 -0
- data/test/template/active_record_helper_i18n_test.rb +46 -0
- data/test/template/active_record_helper_test.rb +24 -24
- data/test/template/asset_tag_helper_test.rb +161 -29
- data/test/template/atom_feed_helper_test.rb +114 -5
- data/test/template/compiled_templates_test.rb +59 -0
- data/test/template/date_helper_i18n_test.rb +113 -0
- data/test/template/date_helper_test.rb +403 -109
- data/test/template/form_helper_test.rb +213 -154
- data/test/template/form_options_helper_test.rb +249 -897
- data/test/template/form_tag_helper_test.rb +80 -32
- data/test/template/javascript_helper_test.rb +17 -18
- data/test/template/number_helper_i18n_test.rb +54 -0
- data/test/template/number_helper_test.rb +43 -13
- data/test/template/prototype_helper_test.rb +101 -84
- data/test/template/record_tag_helper_test.rb +24 -20
- data/test/template/render_test.rb +193 -0
- data/test/template/sanitize_helper_test.rb +3 -3
- data/test/template/tag_helper_test.rb +34 -14
- data/test/template/text_helper_test.rb +83 -9
- data/test/template/translation_helper_test.rb +28 -0
- data/test/template/url_helper_test.rb +55 -18
- metadata +57 -18
- data/lib/action_view/helpers/javascripts/controls.js +0 -963
- data/lib/action_view/helpers/javascripts/dragdrop.js +0 -972
- data/lib/action_view/helpers/javascripts/effects.js +0 -1120
- data/lib/action_view/helpers/javascripts/prototype.js +0 -4225
- data/lib/action_view/partial_template.rb +0 -70
- data/lib/action_view/template_finder.rb +0 -177
- data/lib/action_view/template_handlers/compilable.rb +0 -128
- data/test/controller/custom_handler_test.rb +0 -45
- data/test/controller/new_render_test.rb +0 -945
- data/test/fixtures/test/block_content_for.erb +0 -2
- data/test/fixtures/test/erb_content_for.erb +0 -2
- data/test/template/deprecated_erb_variable_test.rb +0 -9
- data/test/template/template_finder_test.rb +0 -73
- 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
|
# $("details").visualEffect("toggle_blind");
|
72
78
|
# $("more_link").update("Show me less");
|
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('$(\"details\").visualEffect(\"toggle_blind\");
|
77
83
|
# \n$(\"more_link\").update(\"Show me less\");');
|
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
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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)
|
117
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
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
|
-
|
183
|
-
|
184
|
-
if
|
185
|
-
concat(
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
29
|
-
area_code = options[
|
30
|
-
delimiter = options[
|
31
|
-
extension = options[
|
32
|
-
country_code = options[
|
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>
|
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>
|
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 => "£", :separator => ",", :delimiter => "", :format => "%n %u")
|
70
70
|
# # => 1234567890,50 £
|
71
71
|
def number_to_currency(number, options = {})
|
72
|
-
options
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
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
|
-
|
81
|
-
|
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)
|
96
|
-
# number_to_percentage(100, :precision => 0)
|
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
|
102
|
-
|
103
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
-
#
|
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
|
123
|
-
# * <tt
|
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)
|
127
|
-
# number_with_delimiter(12345678.05)
|
128
|
-
# number_with_delimiter(12345678, ".")
|
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
|
-
|
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
|
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
|
143
|
-
#
|
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)
|
147
|
-
# number_with_precision(111.2345, 2)
|
148
|
-
# number_with_precision(13, 5)
|
149
|
-
# number_with_precision(389.32314, 0)
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
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
|
160
|
-
#
|
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)
|
164
|
-
# number_to_human_size(1234)
|
165
|
-
# number_to_human_size(12345)
|
166
|
-
# number_to_human_size(1234567)
|
167
|
-
# number_to_human_size(1234567890)
|
168
|
-
# number_to_human_size(1234567890123)
|
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) # =>
|
171
|
-
def number_to_human_size(
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
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
|