actionpack 1.8.1 → 1.9.0
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 +309 -16
- data/README +1 -1
- data/lib/action_controller.rb +5 -0
- data/lib/action_controller/assertions.rb +57 -12
- data/lib/action_controller/auto_complete.rb +47 -0
- data/lib/action_controller/base.rb +288 -258
- data/lib/action_controller/benchmarking.rb +8 -3
- data/lib/action_controller/caching.rb +88 -42
- data/lib/action_controller/cgi_ext/cgi_ext.rb +1 -1
- data/lib/action_controller/cgi_ext/cgi_methods.rb +41 -11
- data/lib/action_controller/cgi_ext/multipart_progress.rb +169 -0
- data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +30 -12
- data/lib/action_controller/cgi_process.rb +39 -11
- data/lib/action_controller/code_generation.rb +235 -0
- data/lib/action_controller/cookies.rb +14 -8
- data/lib/action_controller/deprecated_renders_and_redirects.rb +76 -0
- data/lib/action_controller/filters.rb +8 -7
- data/lib/action_controller/helpers.rb +41 -6
- data/lib/action_controller/layout.rb +45 -16
- data/lib/action_controller/request.rb +86 -23
- data/lib/action_controller/rescue.rb +1 -0
- data/lib/action_controller/response.rb +1 -1
- data/lib/action_controller/routing.rb +536 -272
- data/lib/action_controller/scaffolding.rb +30 -25
- data/lib/action_controller/session/active_record_store.rb +251 -50
- data/lib/action_controller/streaming.rb +133 -0
- data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -7
- data/lib/action_controller/templates/scaffolds/edit.rhtml +2 -2
- data/lib/action_controller/templates/scaffolds/layout.rhtml +22 -18
- data/lib/action_controller/templates/scaffolds/list.rhtml +3 -3
- data/lib/action_controller/templates/scaffolds/new.rhtml +2 -2
- data/lib/action_controller/templates/scaffolds/show.rhtml +1 -1
- data/lib/action_controller/test_process.rb +68 -47
- data/lib/action_controller/upload_progress.rb +421 -0
- data/lib/action_controller/url_rewriter.rb +8 -11
- data/lib/action_controller/vendor/html-scanner/html/document.rb +6 -5
- data/lib/action_controller/vendor/html-scanner/html/node.rb +70 -14
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +17 -10
- data/lib/action_controller/vendor/html-scanner/html/version.rb +3 -3
- data/lib/action_controller/vendor/xml_simple.rb +1019 -0
- data/lib/action_controller/verification.rb +36 -30
- data/lib/action_view/base.rb +21 -14
- data/lib/action_view/helpers/active_record_helper.rb +15 -13
- data/lib/action_view/helpers/asset_tag_helper.rb +26 -9
- data/lib/action_view/helpers/benchmark_helper.rb +24 -0
- data/lib/action_view/helpers/capture_helper.rb +7 -5
- data/lib/action_view/helpers/date_helper.rb +63 -46
- data/lib/action_view/helpers/form_helper.rb +7 -1
- data/lib/action_view/helpers/form_options_helper.rb +19 -11
- data/lib/action_view/helpers/form_tag_helper.rb +5 -1
- data/lib/action_view/helpers/javascript_helper.rb +403 -35
- data/lib/action_view/helpers/javascripts/controls.js +261 -0
- data/lib/action_view/helpers/javascripts/dragdrop.js +476 -0
- data/lib/action_view/helpers/javascripts/effects.js +570 -0
- data/lib/action_view/helpers/javascripts/prototype.js +633 -371
- data/lib/action_view/helpers/number_helper.rb +11 -13
- data/lib/action_view/helpers/tag_helper.rb +1 -2
- data/lib/action_view/helpers/text_helper.rb +69 -6
- data/lib/action_view/helpers/upload_progress_helper.rb +433 -0
- data/lib/action_view/helpers/url_helper.rb +98 -3
- data/lib/action_view/partials.rb +14 -8
- data/lib/action_view/vendor/builder/xmlmarkup.rb +11 -0
- data/rakefile +13 -5
- data/test/abstract_unit.rb +1 -1
- data/test/controller/action_pack_assertions_test.rb +52 -9
- data/test/controller/active_record_assertions_test.rb +119 -120
- data/test/controller/active_record_store_test.rb +111 -0
- data/test/controller/addresses_render_test.rb +45 -0
- data/test/controller/caching_filestore.rb +92 -0
- data/test/controller/capture_test.rb +39 -0
- data/test/controller/cgi_test.rb +40 -3
- data/test/controller/helper_test.rb +65 -13
- data/test/controller/multipart_progress_testx.rb +365 -0
- data/test/controller/new_render_test.rb +263 -0
- data/test/controller/redirect_test.rb +64 -0
- data/test/controller/render_test.rb +20 -21
- data/test/controller/request_test.rb +83 -3
- data/test/controller/routing_test.rb +702 -0
- data/test/controller/send_file_test.rb +2 -0
- data/test/controller/test_test.rb +44 -8
- data/test/controller/upload_progress_testx.rb +89 -0
- data/test/controller/verification_test.rb +94 -29
- data/test/fixtures/addresses/list.rhtml +1 -0
- data/test/fixtures/test/capturing.rhtml +4 -0
- data/test/fixtures/test/list.rhtml +1 -1
- data/test/fixtures/test/update_element_with_capture.rhtml +9 -0
- data/test/template/active_record_helper_test.rb +30 -15
- data/test/template/asset_tag_helper_test.rb +12 -5
- data/test/template/benchmark_helper_test.rb +72 -0
- data/test/template/date_helper_test.rb +69 -0
- data/test/template/form_helper_test.rb +18 -10
- data/test/template/form_options_helper_test.rb +40 -5
- data/test/template/javascript_helper.rb +149 -2
- data/test/template/number_helper_test.rb +2 -0
- data/test/template/tag_helper_test.rb +4 -0
- data/test/template/text_helper_test.rb +36 -0
- data/test/template/upload_progress_helper_testx.rb +272 -0
- data/test/template/url_helper_test.rb +30 -0
- metadata +30 -6
- data/test/controller/layout_test.rb +0 -49
- data/test/controller/routing_tests.rb +0 -543
@@ -1,37 +1,36 @@
|
|
1
1
|
module ActionController #:nodoc:
|
2
|
-
|
3
|
-
# This module provides a class-level method for specifying that certain
|
4
|
-
# actions are guarded against being called without certain prerequisites
|
5
|
-
# being met. This is essentially a special kind of before_filter.
|
6
|
-
#
|
7
|
-
# An action may be guarded against being invoked without certain request
|
8
|
-
# parameters being set, or without certain session values existing.
|
9
|
-
#
|
10
|
-
# When a verification is violated, values may be inserted into the flash, and
|
11
|
-
# a specified redirection is triggered.
|
12
|
-
#
|
13
|
-
# Usage:
|
14
|
-
#
|
15
|
-
# class GlobalController < ActionController::Base
|
16
|
-
# # prevent the #update_settings action from being invoked unless
|
17
|
-
# # the 'admin_privileges' request parameter exists.
|
18
|
-
# verify :params => "admin_privileges", :only => :update_post,
|
19
|
-
# :redirect_to => { :action => "settings" }
|
20
|
-
#
|
21
|
-
# # disallow a post from being updated if there was no information
|
22
|
-
# # submitted with the post, and if there is no active post in the
|
23
|
-
# # session, and if there is no "note" key in the flash.
|
24
|
-
# verify :params => "post", :session => "post", "flash" => "note",
|
25
|
-
# :only => :update_post,
|
26
|
-
# :add_flash => { "alert" => "Failed to create your message" },
|
27
|
-
# :redirect_to => :category_url
|
28
|
-
#
|
29
|
-
module Verification
|
2
|
+
module Verification #:nodoc:
|
30
3
|
def self.append_features(base) #:nodoc:
|
31
4
|
super
|
32
5
|
base.extend(ClassMethods)
|
33
6
|
end
|
34
7
|
|
8
|
+
# This module provides a class-level method for specifying that certain
|
9
|
+
# actions are guarded against being called without certain prerequisites
|
10
|
+
# being met. This is essentially a special kind of before_filter.
|
11
|
+
#
|
12
|
+
# An action may be guarded against being invoked without certain request
|
13
|
+
# parameters being set, or without certain session values existing.
|
14
|
+
#
|
15
|
+
# When a verification is violated, values may be inserted into the flash, and
|
16
|
+
# a specified redirection is triggered.
|
17
|
+
#
|
18
|
+
# Usage:
|
19
|
+
#
|
20
|
+
# class GlobalController < ActionController::Base
|
21
|
+
# # prevent the #update_settings action from being invoked unless
|
22
|
+
# # the 'admin_privileges' request parameter exists.
|
23
|
+
# verify :params => "admin_privileges", :only => :update_post,
|
24
|
+
# :redirect_to => { :action => "settings" }
|
25
|
+
#
|
26
|
+
# # disallow a post from being updated if there was no information
|
27
|
+
# # submitted with the post, and if there is no active post in the
|
28
|
+
# # session, and if there is no "note" key in the flash.
|
29
|
+
# verify :params => "post", :session => "post", "flash" => "note",
|
30
|
+
# :only => :update_post,
|
31
|
+
# :add_flash => { "alert" => "Failed to create your message" },
|
32
|
+
# :redirect_to => :category_url
|
33
|
+
#
|
35
34
|
module ClassMethods
|
36
35
|
# Verify the given actions so that if certain prerequisites are not met,
|
37
36
|
# the user is redirected to a different action. The +options+ parameter
|
@@ -52,6 +51,8 @@ module ActionController #:nodoc:
|
|
52
51
|
# into the session's flash if the prerequisites cannot be satisfied.
|
53
52
|
# * <tt>:redirect_to</tt>: the redirection parameters to be used when
|
54
53
|
# redirecting if the prerequisites cannot be satisfied.
|
54
|
+
# * <tt>:render</tt>: the render parameters to be used when
|
55
|
+
# the prerequisites cannot be satisfied.
|
55
56
|
# * <tt>:only</tt>: only apply this verification to the actions specified
|
56
57
|
# in the associated array (may also be a single value).
|
57
58
|
# * <tt>:except</tt>: do not apply this verification to the actions
|
@@ -74,10 +75,15 @@ module ActionController #:nodoc:
|
|
74
75
|
prereqs_invalid ||=
|
75
76
|
[*options[:method]].all? { |v| @request.method != v.to_sym }
|
76
77
|
end
|
77
|
-
|
78
|
+
|
79
|
+
prereqs_invalid ||= (request.xhr? != options[:xhr]) unless options[:xhr].nil?
|
80
|
+
|
78
81
|
if prereqs_invalid
|
79
82
|
flash.update(options[:add_flash]) if options[:add_flash]
|
80
|
-
|
83
|
+
unless performed?
|
84
|
+
render(options[:render]) if options[:render]
|
85
|
+
redirect_to(options[:redirect_to]) if options[:redirect_to]
|
86
|
+
end
|
81
87
|
return false
|
82
88
|
end
|
83
89
|
|
data/lib/action_view/base.rb
CHANGED
@@ -122,6 +122,8 @@ module ActionView #:nodoc:
|
|
122
122
|
attr_reader :first_render
|
123
123
|
attr_accessor :base_path, :assigns, :template_extension
|
124
124
|
attr_accessor :controller
|
125
|
+
|
126
|
+
attr_reader :logger, :params, :response, :session, :headers, :flash
|
125
127
|
|
126
128
|
# Turn on to cache the reading of templates from the file system. Doing so means that you have to restart the server
|
127
129
|
# when changing templates, but that rendering will be faster.
|
@@ -142,16 +144,6 @@ module ActionView #:nodoc:
|
|
142
144
|
end
|
143
145
|
end
|
144
146
|
|
145
|
-
def self.controller_delegate(*methods)#:nodoc:
|
146
|
-
methods.flatten.each do |method|
|
147
|
-
class_eval <<-end_eval
|
148
|
-
def #{method}(*args, &block)
|
149
|
-
controller.send(%(#{method}), *args, &block)
|
150
|
-
end
|
151
|
-
end_eval
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
147
|
def self.register_template_handler(extension, klass)
|
156
148
|
@@template_handlers[extension] = klass
|
157
149
|
end
|
@@ -191,8 +183,23 @@ module ActionView #:nodoc:
|
|
191
183
|
|
192
184
|
# Renders the template present at <tt>template_path</tt> (relative to the template_root).
|
193
185
|
# The hash in <tt>local_assigns</tt> is made available as local variables.
|
194
|
-
def render(
|
195
|
-
|
186
|
+
def render(options = {}, old_local_assigns = {})
|
187
|
+
if options.is_a?(String)
|
188
|
+
render_file(options, true, old_local_assigns)
|
189
|
+
elsif options.is_a?(Hash)
|
190
|
+
options[:locals] ||= {}
|
191
|
+
options[:use_full_path] = options[:use_full_path].nil? ? true : options[:use_full_path]
|
192
|
+
|
193
|
+
if options[:file]
|
194
|
+
render_file(options[:file], options[:use_full_path], options[:locals])
|
195
|
+
elsif options[:partial] && options[:collection]
|
196
|
+
render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals])
|
197
|
+
elsif options[:partial]
|
198
|
+
render_partial(options[:partial], options[:object], options[:locals])
|
199
|
+
elsif options[:inline]
|
200
|
+
render_template(options[:type] || :rhtml, options[:inline], options[:locals] || {})
|
201
|
+
end
|
202
|
+
end
|
196
203
|
end
|
197
204
|
|
198
205
|
# Renders the +template+ which is given as a string as either rhtml or rxml depending on <tt>template_extension</tt>.
|
@@ -218,7 +225,7 @@ module ActionView #:nodoc:
|
|
218
225
|
if @@template_handlers[template_extension]
|
219
226
|
"delegate_render"
|
220
227
|
else
|
221
|
-
(template_extension == "rxml" ? "rxml" : "rhtml") + "_render"
|
228
|
+
(template_extension.to_s == "rxml" ? "rxml" : "rhtml") + "_render"
|
222
229
|
end
|
223
230
|
end
|
224
231
|
|
@@ -290,4 +297,4 @@ module ActionView #:nodoc:
|
|
290
297
|
end
|
291
298
|
end
|
292
299
|
|
293
|
-
require 'action_view/template_error'
|
300
|
+
require 'action_view/template_error'
|
@@ -31,7 +31,7 @@ module ActionView
|
|
31
31
|
# </p>
|
32
32
|
# <p>
|
33
33
|
# <label for="post_body">Body</label><br />
|
34
|
-
# <textarea cols="40" id="post_body" name="post[body]" rows="20"
|
34
|
+
# <textarea cols="40" id="post_body" name="post[body]" rows="20">
|
35
35
|
# Back to the hill and over it again!
|
36
36
|
# </textarea>
|
37
37
|
# </p>
|
@@ -56,20 +56,22 @@ module ActionView
|
|
56
56
|
# form << content_tag("b", "Department")
|
57
57
|
# form << collection_select("department", "id", @departments, "id", "name")
|
58
58
|
# end
|
59
|
-
def form(record_name, options =
|
60
|
-
|
61
|
-
record = instance_eval("@#{record_name}")
|
59
|
+
def form(record_name, options = {})
|
60
|
+
record = instance_variable_get("@#{record_name}")
|
62
61
|
|
62
|
+
options = options.symbolize_keys
|
63
63
|
options[:action] ||= record.new_record? ? "create" : "update"
|
64
|
-
action = url_for(:action => options[:action])
|
64
|
+
action = url_for(:action => options[:action], :id => record)
|
65
65
|
|
66
66
|
submit_value = options[:submit_value] || options[:action].gsub(/[^\w]/, '').capitalize
|
67
67
|
|
68
|
-
|
68
|
+
contents = ''
|
69
|
+
contents << hidden_field(record_name, :id) unless record.new_record?
|
70
|
+
contents << all_input_tags(record, record_name, options)
|
71
|
+
yield contents if block_given?
|
72
|
+
contents << submit_tag(submit_value)
|
69
73
|
|
70
|
-
|
71
|
-
yield formtag if block_given?
|
72
|
-
formtag + %(<input type="submit" value="#{submit_value}" /></form>)
|
74
|
+
content_tag('form', contents, :action => action, :method => 'post')
|
73
75
|
end
|
74
76
|
|
75
77
|
# Returns a string containing the error message attached to the +method+ on the +object+, if one exists.
|
@@ -83,8 +85,8 @@ module ActionView
|
|
83
85
|
# <%= error_message_on "post", "title", "Title simply ", " (or it won't work)", "inputError" %> =>
|
84
86
|
# <div class="inputError">Title simply can't be empty (or it won't work)</div>
|
85
87
|
def error_message_on(object, method, prepend_text = "", append_text = "", css_class = "formError")
|
86
|
-
if errors =
|
87
|
-
"
|
88
|
+
if errors = instance_variable_get("@#{object}").errors.on(method)
|
89
|
+
content_tag("div", "#{prepend_text}#{errors.is_a?(Array) ? errors.first : errors}#{append_text}", :class => css_class)
|
88
90
|
end
|
89
91
|
end
|
90
92
|
|
@@ -96,7 +98,7 @@ module ActionView
|
|
96
98
|
# * <tt>class</tt> - The class of the error div (default: errorExplanation)
|
97
99
|
def error_messages_for(object_name, options = {})
|
98
100
|
options = options.symbolize_keys
|
99
|
-
object =
|
101
|
+
object = instance_variable_get("@#{object_name}")
|
100
102
|
unless object.errors.empty?
|
101
103
|
content_tag("div",
|
102
104
|
content_tag(
|
@@ -117,7 +119,7 @@ module ActionView
|
|
117
119
|
end
|
118
120
|
|
119
121
|
def default_input_block
|
120
|
-
Proc.new { |record, column|
|
122
|
+
Proc.new { |record, column| %(<p><label for="#{record}_#{column.name}">#{column.human_name}</label><br />#{input(record, column.name)}</p>) }
|
121
123
|
end
|
122
124
|
end
|
123
125
|
|
@@ -14,11 +14,16 @@ module ActionView
|
|
14
14
|
# <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.curenthost.com/controller/action" />
|
15
15
|
# auto_discovery_link_tag(:atom) # =>
|
16
16
|
# <link rel="alternate" type="application/atom+xml" title="ATOM" href="http://www.curenthost.com/controller/action" />
|
17
|
-
# auto_discovery_link_tag(:rss, :action => "feed") # =>
|
18
|
-
# <link rel="alternate" type="application/
|
19
|
-
|
17
|
+
# auto_discovery_link_tag(:rss, {:action => "feed"}) # =>
|
18
|
+
# <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.curenthost.com/controller/feed" />
|
19
|
+
# auto_discovery_link_tag(:rss, {:action => "feed"}, {:title => "My RSS"}) # =>
|
20
|
+
# <link rel="alternate" type="application/rss+xml" title="My RSS" href="http://www.curenthost.com/controller/feed" />
|
21
|
+
def auto_discovery_link_tag(type = :rss, options = {}, tag_options = {})
|
20
22
|
tag(
|
21
|
-
"link",
|
23
|
+
"link",
|
24
|
+
"rel" => tag_options[:rel] || "alternate",
|
25
|
+
"type" => tag_options[:type] || "application/#{type}+xml",
|
26
|
+
"title" => tag_options[:title] || type.to_s.upcase,
|
22
27
|
"href" => url_for(options.merge(:only_path => false))
|
23
28
|
)
|
24
29
|
end
|
@@ -38,10 +43,18 @@ module ActionView
|
|
38
43
|
# javascript_include_tag "common.javascript", "/elsewhere/cools" # =>
|
39
44
|
# <script type="text/javascript" src="/javascripts/common.javascript"></script>
|
40
45
|
# <script type="text/javascript" src="/elsewhere/cools.js"></script>
|
46
|
+
#
|
47
|
+
# javascript_include_tag :defaults # =>
|
48
|
+
# <script type="text/javascript" src="/javascripts/prototype.js"></script>
|
49
|
+
# <script type="text/javascript" src="/javascripts/effects.js"></script>
|
50
|
+
# <script type="text/javascript" src="/javascripts/controls.js"></script>
|
51
|
+
# <script type="text/javascript" src="/javascripts/dragdrop.js"></script>
|
41
52
|
def javascript_include_tag(*sources)
|
53
|
+
options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { }
|
54
|
+
sources = ['prototype', 'effects', 'controls', 'dragdrop'] if sources.first == :defaults
|
42
55
|
sources.collect { |source|
|
43
56
|
source = javascript_path(source)
|
44
|
-
content_tag("script", "", "type" => "text/javascript", "src" => source)
|
57
|
+
content_tag("script", "", { "type" => "text/javascript", "src" => source }.merge(options))
|
45
58
|
}.join("\n")
|
46
59
|
end
|
47
60
|
|
@@ -57,13 +70,17 @@ module ActionView
|
|
57
70
|
# stylesheet_link_tag "style" # =>
|
58
71
|
# <link href="/stylesheets/style.css" media="screen" rel="Stylesheet" type="text/css" />
|
59
72
|
#
|
73
|
+
# stylesheet_link_tag "style", :media => "all" # =>
|
74
|
+
# <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" />
|
75
|
+
#
|
60
76
|
# stylesheet_link_tag "random.styles", "/css/stylish" # =>
|
61
77
|
# <link href="/stylesheets/random.styles" media="screen" rel="Stylesheet" type="text/css" />
|
62
78
|
# <link href="/css/stylish.css" media="screen" rel="Stylesheet" type="text/css" />
|
63
79
|
def stylesheet_link_tag(*sources)
|
80
|
+
options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { }
|
64
81
|
sources.collect { |source|
|
65
82
|
source = stylesheet_path(source)
|
66
|
-
tag("link", "rel" => "Stylesheet", "type" => "text/css", "media" => "screen", "href" => source)
|
83
|
+
tag("link", { "rel" => "Stylesheet", "type" => "text/css", "media" => "screen", "href" => source }.merge(options))
|
67
84
|
}.join("\n")
|
68
85
|
end
|
69
86
|
|
@@ -90,7 +107,7 @@ module ActionView
|
|
90
107
|
options.symbolize_keys
|
91
108
|
|
92
109
|
options[:src] = image_path(source)
|
93
|
-
options[:alt] ||=
|
110
|
+
options[:alt] ||= File.basename(options[:src], '.*').split('.').first.capitalize
|
94
111
|
|
95
112
|
if options[:size]
|
96
113
|
options[:width], options[:height] = options[:size].split("x")
|
@@ -104,8 +121,8 @@ module ActionView
|
|
104
121
|
def compute_public_path(source, dir, ext)
|
105
122
|
source = "/#{dir}/#{source}" unless source.include?("/")
|
106
123
|
source = "#{source}.#{ext}" unless source.include?(".")
|
107
|
-
source = "#{@request.relative_url_root}#{source}"
|
108
|
-
source
|
124
|
+
source = "#{@request.relative_url_root}#{source}" unless %r{^[-a-z]+://} =~ source
|
125
|
+
ActionController::Base.asset_host + source
|
109
126
|
end
|
110
127
|
end
|
111
128
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
module Helpers
|
5
|
+
module BenchmarkHelper
|
6
|
+
# Measures the execution time of a block in a template and reports the result to the log. Example:
|
7
|
+
#
|
8
|
+
# <% benchmark "Notes section" do %>
|
9
|
+
# <%= expensive_notes_operation %>
|
10
|
+
# <% end %>
|
11
|
+
#
|
12
|
+
# Will add something like "Notes section (0.34523)" to the log.
|
13
|
+
#
|
14
|
+
# You may give an optional logger level as the second argument
|
15
|
+
# (:debug, :info, :warn, :error). The default is :info.
|
16
|
+
def benchmark(message = "Benchmarking", level = :info)
|
17
|
+
if @logger
|
18
|
+
real = Benchmark.realtime { yield }
|
19
|
+
@logger.send level, "#{message} (#{'%.5f' % real})"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -48,11 +48,11 @@ module ActionView
|
|
48
48
|
# <% @greeting = capture do %>
|
49
49
|
# Welcome To my shiny new web page!
|
50
50
|
# <% end %>
|
51
|
-
def capture(&block)
|
51
|
+
def capture(*args, &block)
|
52
52
|
# execute the block
|
53
53
|
buffer = eval("_erbout", block.binding)
|
54
54
|
pos = buffer.length
|
55
|
-
block.call
|
55
|
+
block.call(*args)
|
56
56
|
|
57
57
|
# extract the block
|
58
58
|
data = buffer[pos..-1]
|
@@ -77,7 +77,10 @@ module ActionView
|
|
77
77
|
# alert('hello world')
|
78
78
|
# <% end %>
|
79
79
|
#
|
80
|
-
# You can use @content_for_header anywhere in your templates
|
80
|
+
# You can use @content_for_header anywhere in your templates.
|
81
|
+
#
|
82
|
+
# NOTE: Beware that content_for is ignored in caches. So you shouldn't use it
|
83
|
+
# for elements that are going to be fragment cached.
|
81
84
|
def content_for(name, &block)
|
82
85
|
base = controller.instance_variable_get(instance_var_name(name)) || ""
|
83
86
|
data = capture(&block)
|
@@ -85,8 +88,7 @@ module ActionView
|
|
85
88
|
data
|
86
89
|
end
|
87
90
|
|
88
|
-
private
|
89
|
-
|
91
|
+
private
|
90
92
|
def instance_var_name(name) #:nodoc#
|
91
93
|
"@content_for_#{name}"
|
92
94
|
end
|
@@ -11,31 +11,38 @@ module ActionView
|
|
11
11
|
# * <tt>:discard_type</tt> - set to true if you want to discard the type part of the select name. If set to true, the select_month
|
12
12
|
# method would use simply "date" (which can be overwritten using <tt>:prefix</tt>) instead of "date[month]".
|
13
13
|
module DateHelper
|
14
|
-
DEFAULT_PREFIX =
|
14
|
+
DEFAULT_PREFIX = 'date' unless const_defined?('DEFAULT_PREFIX')
|
15
15
|
|
16
|
-
# Reports the approximate distance in time between to Time objects
|
16
|
+
# Reports the approximate distance in time between to Time objects or integers.
|
17
|
+
# For example, if the distance is 47 minutes, it'll return
|
17
18
|
# "about 1 hour". See the source for the complete wording list.
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
#
|
20
|
+
# Integers are interpreted as seconds. So,
|
21
|
+
# <tt>distance_of_time_in_words(50)</tt> returns "less than a minute".
|
22
|
+
#
|
23
|
+
# Set <tt>include_seconds</tt> to true if you want more detailed approximations if distance < 1 minute
|
24
|
+
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false)
|
25
|
+
from_time = from_time.to_time if from_time.respond_to?(:to_time)
|
26
|
+
to_time = to_time.to_time if to_time.respond_to?(:to_time)
|
27
|
+
distance_in_minutes = (((to_time - from_time).abs)/60).round
|
28
|
+
distance_in_seconds = ((to_time - from_time).abs).round
|
22
29
|
|
23
30
|
case distance_in_minutes
|
24
31
|
when 0..1
|
25
|
-
return (distance_in_minutes==0) ?
|
32
|
+
return (distance_in_minutes==0) ? 'less than a minute' : '1 minute' unless include_seconds
|
26
33
|
case distance_in_seconds
|
27
|
-
when 0..5 then
|
28
|
-
when 6..10 then
|
29
|
-
when 11..20 then
|
30
|
-
when 21..40 then
|
31
|
-
when 41..59 then
|
32
|
-
else
|
34
|
+
when 0..5 then 'less than 5 seconds'
|
35
|
+
when 6..10 then 'less than 10 seconds'
|
36
|
+
when 11..20 then 'less than 20 seconds'
|
37
|
+
when 21..40 then 'half a minute'
|
38
|
+
when 41..59 then 'less than a minute'
|
39
|
+
else '1 minute'
|
33
40
|
end
|
34
41
|
|
35
42
|
when 2..45 then "#{distance_in_minutes} minutes"
|
36
|
-
when 46..90 then
|
43
|
+
when 46..90 then 'about 1 hour'
|
37
44
|
when 90..1440 then "about #{(distance_in_minutes.to_f / 60.0).round} hours"
|
38
|
-
when 1441..2880 then
|
45
|
+
when 1441..2880 then '1 day'
|
39
46
|
else "#{(distance_in_minutes / 1440).round} days"
|
40
47
|
end
|
41
48
|
end
|
@@ -100,63 +107,67 @@ module ActionView
|
|
100
107
|
|
101
108
|
# Returns a select tag with options for each of the seconds 0 through 59 with the current second selected.
|
102
109
|
# The <tt>second</tt> can also be substituted for a second number.
|
110
|
+
# Override the field name using the <tt>:field_name</tt> option, 'second' by default.
|
103
111
|
def select_second(datetime, options = {})
|
104
112
|
second_options = []
|
105
113
|
|
106
114
|
0.upto(59) do |second|
|
107
115
|
second_options << ((datetime && (datetime.kind_of?(Fixnum) ? datetime : datetime.sec) == second) ?
|
108
|
-
|
109
|
-
|
116
|
+
%(<option value="#{leading_zero_on_single_digits(second)}" selected="selected">#{leading_zero_on_single_digits(second)}</option>\n) :
|
117
|
+
%(<option value="#{leading_zero_on_single_digits(second)}">#{leading_zero_on_single_digits(second)}</option>\n)
|
110
118
|
)
|
111
119
|
end
|
112
120
|
|
113
|
-
select_html(
|
121
|
+
select_html(options[:field_name] || 'second', second_options, options[:prefix], options[:include_blank], options[:discard_type])
|
114
122
|
end
|
115
123
|
|
116
124
|
# Returns a select tag with options for each of the minutes 0 through 59 with the current minute selected.
|
117
125
|
# Also can return a select tag with options by <tt>minute_step</tt> from 0 through 59 with the 00 minute selected
|
118
126
|
# The <tt>minute</tt> can also be substituted for a minute number.
|
127
|
+
# Override the field name using the <tt>:field_name</tt> option, 'minute' by default.
|
119
128
|
def select_minute(datetime, options = {})
|
120
129
|
minute_options = []
|
121
130
|
|
122
131
|
0.step(59, options[:minute_step] || 1) do |minute|
|
123
132
|
minute_options << ((datetime && (datetime.kind_of?(Fixnum) ? datetime : datetime.min) == minute) ?
|
124
|
-
|
125
|
-
|
133
|
+
%(<option value="#{leading_zero_on_single_digits(minute)}" selected="selected">#{leading_zero_on_single_digits(minute)}</option>\n) :
|
134
|
+
%(<option value="#{leading_zero_on_single_digits(minute)}">#{leading_zero_on_single_digits(minute)}</option>\n)
|
126
135
|
)
|
127
136
|
end
|
128
137
|
|
129
|
-
select_html(
|
138
|
+
select_html(options[:field_name] || 'minute', minute_options, options[:prefix], options[:include_blank], options[:discard_type])
|
130
139
|
end
|
131
140
|
|
132
141
|
# Returns a select tag with options for each of the hours 0 through 23 with the current hour selected.
|
133
142
|
# The <tt>hour</tt> can also be substituted for a hour number.
|
143
|
+
# Override the field name using the <tt>:field_name</tt> option, 'hour' by default.
|
134
144
|
def select_hour(datetime, options = {})
|
135
145
|
hour_options = []
|
136
146
|
|
137
147
|
0.upto(23) do |hour|
|
138
148
|
hour_options << ((datetime && (datetime.kind_of?(Fixnum) ? datetime : datetime.hour) == hour) ?
|
139
|
-
|
140
|
-
|
149
|
+
%(<option value="#{leading_zero_on_single_digits(hour)}" selected="selected">#{leading_zero_on_single_digits(hour)}</option>\n) :
|
150
|
+
%(<option value="#{leading_zero_on_single_digits(hour)}">#{leading_zero_on_single_digits(hour)}</option>\n)
|
141
151
|
)
|
142
152
|
end
|
143
153
|
|
144
|
-
select_html(
|
154
|
+
select_html(options[:field_name] || 'hour', hour_options, options[:prefix], options[:include_blank], options[:discard_type])
|
145
155
|
end
|
146
156
|
|
147
157
|
# Returns a select tag with options for each of the days 1 through 31 with the current day selected.
|
148
158
|
# The <tt>date</tt> can also be substituted for a hour number.
|
159
|
+
# Override the field name using the <tt>:field_name</tt> option, 'day' by default.
|
149
160
|
def select_day(date, options = {})
|
150
161
|
day_options = []
|
151
162
|
|
152
163
|
1.upto(31) do |day|
|
153
164
|
day_options << ((date && (date.kind_of?(Fixnum) ? date : date.day) == day) ?
|
154
|
-
|
155
|
-
|
165
|
+
%(<option value="#{day}" selected="selected">#{day}</option>\n) :
|
166
|
+
%(<option value="#{day}">#{day}</option>\n)
|
156
167
|
)
|
157
168
|
end
|
158
169
|
|
159
|
-
select_html(
|
170
|
+
select_html(options[:field_name] || 'day', day_options, options[:prefix], options[:include_blank], options[:discard_type])
|
160
171
|
end
|
161
172
|
|
162
173
|
# Returns a select tag with options for each of the months January through December with the current month selected.
|
@@ -168,6 +179,8 @@ module ActionView
|
|
168
179
|
# select_month(Date.today) # Will use keys like "January", "March"
|
169
180
|
# select_month(Date.today, :use_month_numbers => true) # Will use keys like "1", "3"
|
170
181
|
# select_month(Date.today, :add_month_numbers => true) # Will use keys like "1 - January", "3 - March"
|
182
|
+
#
|
183
|
+
# Override the field name using the <tt>:field_name</tt> option, 'month' by default.
|
171
184
|
def select_month(date, options = {})
|
172
185
|
month_options = []
|
173
186
|
|
@@ -175,7 +188,7 @@ module ActionView
|
|
175
188
|
month_name = if options[:use_month_numbers]
|
176
189
|
month_number
|
177
190
|
elsif options[:add_month_numbers]
|
178
|
-
month_number.to_s +
|
191
|
+
month_number.to_s + ' - ' + Date::MONTHNAMES[month_number]
|
179
192
|
else
|
180
193
|
Date::MONTHNAMES[month_number]
|
181
194
|
end
|
@@ -186,27 +199,33 @@ module ActionView
|
|
186
199
|
)
|
187
200
|
end
|
188
201
|
|
189
|
-
select_html(
|
202
|
+
select_html(options[:field_name] || 'month', month_options, options[:prefix], options[:include_blank], options[:discard_type])
|
190
203
|
end
|
191
204
|
|
192
205
|
# Returns a select tag with options for each of the five years on each side of the current, which is selected. The five year radius
|
193
|
-
# can be changed using the <tt>:start_year</tt> and <tt>:end_year</tt> keys in the +options+.
|
194
|
-
#
|
206
|
+
# can be changed using the <tt>:start_year</tt> and <tt>:end_year</tt> keys in the +options+. Both ascending and descending year
|
207
|
+
# lists are supported by making <tt>:start_year</tt> less than or greater than <tt>:end_year</tt>. The <tt>date</tt> can also be
|
208
|
+
# substituted for a year given as a number. Example:
|
195
209
|
#
|
196
|
-
# select_year(Date.today, :start_year => 1992, :end_year => 2007)
|
210
|
+
# select_year(Date.today, :start_year => 1992, :end_year => 2007) # ascending year values
|
211
|
+
# select_year(Date.today, :start_year => 2005, :end_year => 1900) # descending year values
|
212
|
+
#
|
213
|
+
# Override the field name using the <tt>:field_name</tt> option, 'year' by default.
|
197
214
|
def select_year(date, options = {})
|
198
215
|
year_options = []
|
199
216
|
y = date ? (date.kind_of?(Fixnum) ? (y = (date == 0) ? Date.today.year : date) : date.year) : Date.today.year
|
200
|
-
default_start_year, default_end_year = y-5, y+5
|
201
217
|
|
202
|
-
(options[:start_year] ||
|
218
|
+
start_year, end_year = (options[:start_year] || y-5), (options[:end_year] || y+5)
|
219
|
+
step_val = start_year < end_year ? 1 : -1
|
220
|
+
|
221
|
+
start_year.step(end_year, step_val) do |year|
|
203
222
|
year_options << ((date && (date.kind_of?(Fixnum) ? date : date.year) == year) ?
|
204
|
-
|
205
|
-
|
223
|
+
%(<option value="#{year}" selected="selected">#{year}</option>\n) :
|
224
|
+
%(<option value="#{year}">#{year}</option>\n)
|
206
225
|
)
|
207
226
|
end
|
208
227
|
|
209
|
-
select_html(
|
228
|
+
select_html(options[:field_name] || 'year', year_options, options[:prefix], options[:include_blank], options[:discard_type])
|
210
229
|
end
|
211
230
|
|
212
231
|
private
|
@@ -214,11 +233,9 @@ module ActionView
|
|
214
233
|
select_html = %(<select name="#{prefix || DEFAULT_PREFIX})
|
215
234
|
select_html << "[#{type}]" unless discard_type
|
216
235
|
select_html << %(">\n)
|
217
|
-
select_html <<
|
236
|
+
select_html << %(<option value=""></option>\n) if include_blank
|
218
237
|
select_html << options.to_s
|
219
238
|
select_html << "</select>\n"
|
220
|
-
|
221
|
-
return select_html
|
222
239
|
end
|
223
240
|
|
224
241
|
def leading_zero_on_single_digits(number)
|
@@ -235,7 +252,7 @@ module ActionView
|
|
235
252
|
options_with_prefix = Proc.new { |position| options.merge(:prefix => "#{@object_name}[#{@method_name}(#{position}i)]") }
|
236
253
|
date = options[:include_blank] ? (value || 0) : (value || Date.today)
|
237
254
|
|
238
|
-
date_select =
|
255
|
+
date_select = ''
|
239
256
|
options[:order] = [:month, :year, :day] if options[:month_before_year] # For backwards compatibility
|
240
257
|
options[:order] ||= [:year, :month, :day]
|
241
258
|
|
@@ -250,7 +267,7 @@ module ActionView
|
|
250
267
|
date_select << self.send("select_#{param}", date, options_with_prefix.call(position[param])) unless discard[param]
|
251
268
|
end
|
252
269
|
|
253
|
-
|
270
|
+
date_select
|
254
271
|
end
|
255
272
|
|
256
273
|
def to_datetime_select_tag(options = {})
|
@@ -262,11 +279,11 @@ module ActionView
|
|
262
279
|
datetime_select = select_year(datetime, options_with_prefix.call(1))
|
263
280
|
datetime_select << select_month(datetime, options_with_prefix.call(2)) unless options[:discard_month]
|
264
281
|
datetime_select << select_day(datetime, options_with_prefix.call(3)) unless options[:discard_day] || options[:discard_month]
|
265
|
-
datetime_select <<
|
266
|
-
datetime_select <<
|
282
|
+
datetime_select << ' — ' + select_hour(datetime, options_with_prefix.call(4)) unless options[:discard_hour]
|
283
|
+
datetime_select << ' : ' + select_minute(datetime, options_with_prefix.call(5)) unless options[:discard_minute] || options[:discard_hour]
|
267
284
|
|
268
|
-
|
285
|
+
datetime_select
|
269
286
|
end
|
270
287
|
end
|
271
288
|
end
|
272
|
-
end
|
289
|
+
end
|