actionpack 1.12.5 → 1.13.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 +517 -15
- data/MIT-LICENSE +1 -1
- data/README +18 -20
- data/Rakefile +7 -4
- data/examples/address_book_controller.rb +3 -3
- data/examples/blog_controller.cgi +3 -3
- data/examples/debate_controller.cgi +5 -5
- data/lib/action_controller.rb +2 -2
- data/lib/action_controller/assertions.rb +73 -311
- data/lib/action_controller/{deprecated_assertions.rb → assertions/deprecated_assertions.rb} +32 -8
- data/lib/action_controller/assertions/dom_assertions.rb +25 -0
- data/lib/action_controller/assertions/model_assertions.rb +12 -0
- data/lib/action_controller/assertions/response_assertions.rb +140 -0
- data/lib/action_controller/assertions/routing_assertions.rb +82 -0
- data/lib/action_controller/assertions/selector_assertions.rb +571 -0
- data/lib/action_controller/assertions/tag_assertions.rb +117 -0
- data/lib/action_controller/base.rb +334 -163
- data/lib/action_controller/benchmarking.rb +3 -6
- data/lib/action_controller/caching.rb +83 -22
- data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -7
- data/lib/action_controller/cgi_ext/cgi_methods.rb +167 -173
- data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +43 -22
- data/lib/action_controller/cgi_process.rb +50 -27
- data/lib/action_controller/components.rb +21 -25
- data/lib/action_controller/cookies.rb +10 -9
- data/lib/action_controller/{dependencies.rb → deprecated_dependencies.rb} +9 -27
- data/lib/action_controller/filters.rb +448 -225
- data/lib/action_controller/flash.rb +24 -20
- data/lib/action_controller/helpers.rb +2 -5
- data/lib/action_controller/integration.rb +40 -16
- data/lib/action_controller/layout.rb +11 -8
- data/lib/action_controller/macros/auto_complete.rb +3 -2
- data/lib/action_controller/macros/in_place_editing.rb +3 -2
- data/lib/action_controller/mime_responds.rb +41 -29
- data/lib/action_controller/mime_type.rb +68 -10
- data/lib/action_controller/pagination.rb +4 -3
- data/lib/action_controller/request.rb +22 -14
- data/lib/action_controller/rescue.rb +25 -22
- data/lib/action_controller/resources.rb +302 -0
- data/lib/action_controller/response.rb +20 -2
- data/lib/action_controller/response.rb.rej +17 -0
- data/lib/action_controller/routing.rb +1165 -567
- data/lib/action_controller/scaffolding.rb +30 -31
- data/lib/action_controller/session/active_record_store.rb +2 -0
- data/lib/action_controller/session/drb_store.rb +4 -0
- data/lib/action_controller/session/mem_cache_store.rb +4 -0
- data/lib/action_controller/session_management.rb +6 -9
- data/lib/action_controller/status_codes.rb +89 -0
- data/lib/action_controller/streaming.rb +6 -15
- data/lib/action_controller/templates/rescues/_request_and_response.rhtml +5 -5
- data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -2
- data/lib/action_controller/templates/rescues/routing_error.rhtml +4 -4
- data/lib/action_controller/templates/rescues/template_error.rhtml +1 -1
- data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
- data/lib/action_controller/test_process.rb +52 -30
- data/lib/action_controller/url_rewriter.rb +63 -29
- data/lib/action_controller/vendor/html-scanner/html/document.rb +1 -0
- data/lib/action_controller/vendor/html-scanner/html/node.rb +3 -4
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +822 -0
- data/lib/action_controller/verification.rb +22 -11
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +2 -2
- data/lib/action_view.rb +1 -1
- data/lib/action_view/base.rb +46 -43
- data/lib/action_view/compiled_templates.rb +1 -1
- data/lib/action_view/helpers/active_record_helper.rb +54 -17
- data/lib/action_view/helpers/asset_tag_helper.rb +97 -46
- data/lib/action_view/helpers/capture_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +258 -136
- data/lib/action_view/helpers/debug_helper.rb +1 -1
- data/lib/action_view/helpers/deprecated_helper.rb +34 -0
- data/lib/action_view/helpers/form_helper.rb +75 -35
- data/lib/action_view/helpers/form_options_helper.rb +7 -5
- data/lib/action_view/helpers/form_tag_helper.rb +44 -6
- data/lib/action_view/helpers/java_script_macros_helper.rb +59 -46
- data/lib/action_view/helpers/javascript_helper.rb +71 -10
- data/lib/action_view/helpers/javascripts/controls.js +41 -23
- data/lib/action_view/helpers/javascripts/dragdrop.js +105 -76
- data/lib/action_view/helpers/javascripts/effects.js +293 -163
- data/lib/action_view/helpers/javascripts/prototype.js +897 -389
- data/lib/action_view/helpers/javascripts/prototype.js.rej +561 -0
- data/lib/action_view/helpers/number_helper.rb +111 -65
- data/lib/action_view/helpers/prototype_helper.rb +84 -109
- data/lib/action_view/helpers/scriptaculous_helper.rb +5 -0
- data/lib/action_view/helpers/tag_helper.rb +69 -16
- data/lib/action_view/helpers/text_helper.rb +149 -112
- data/lib/action_view/helpers/url_helper.rb +200 -107
- data/lib/action_view/template_error.rb +66 -42
- data/test/abstract_unit.rb +4 -2
- data/test/active_record_unit.rb +84 -56
- data/test/activerecord/active_record_assertions_test.rb +26 -18
- data/test/activerecord/active_record_store_test.rb +4 -36
- data/test/activerecord/pagination_test.rb +1 -6
- data/test/controller/action_pack_assertions_test.rb +230 -113
- data/test/controller/addresses_render_test.rb +2 -6
- data/test/controller/assert_select_test.rb +576 -0
- data/test/controller/base_test.rb +73 -3
- data/test/controller/caching_test.rb +228 -0
- data/test/controller/capture_test.rb +12 -10
- data/test/controller/cgi_test.rb +89 -12
- data/test/controller/components_test.rb +24 -2
- data/test/controller/content_type_test.rb +139 -0
- data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
- data/test/controller/cookie_test.rb +33 -25
- data/test/controller/deprecated_instance_variables_test.rb +48 -0
- data/test/controller/deprecation/deprecated_base_methods_test.rb +60 -0
- data/test/controller/fake_controllers.rb +0 -1
- data/test/controller/filters_test.rb +301 -16
- data/test/controller/flash_test.rb +19 -2
- data/test/controller/helper_test.rb +2 -2
- data/test/controller/integration_test.rb +154 -0
- data/test/controller/layout_test.rb +115 -1
- data/test/controller/mime_responds_test.rb +94 -0
- data/test/controller/mime_type_test.rb +9 -0
- data/test/controller/new_render_test.rb +161 -11
- data/test/controller/raw_post_test.rb +52 -15
- data/test/controller/redirect_test.rb +27 -14
- data/test/controller/render_test.rb +76 -29
- data/test/controller/request_test.rb +55 -4
- data/test/controller/resources_test.rb +274 -0
- data/test/controller/routing_test.rb +1533 -824
- data/test/controller/selector_test.rb +628 -0
- data/test/controller/send_file_test.rb +9 -1
- data/test/controller/session_management_test.rb +51 -0
- data/test/controller/test_test.rb +113 -29
- data/test/controller/url_rewriter_test.rb +86 -17
- data/test/controller/verification_test.rb +19 -17
- data/test/controller/webservice_test.rb +0 -7
- data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
- data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
- data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +1 -0
- data/test/fixtures/multipart/binary_file +0 -0
- data/test/fixtures/public/javascripts/application.js +1 -0
- data/test/fixtures/test/_hello.rxml +1 -0
- data/test/fixtures/test/hello_world_container.rxml +3 -0
- data/test/fixtures/topic.rb +2 -2
- data/test/template/active_record_helper_test.rb +83 -12
- data/test/template/asset_tag_helper_test.rb +75 -95
- data/test/template/compiled_templates_test.rb +1 -0
- data/test/template/date_helper_test.rb +873 -181
- data/test/template/deprecated_helper_test.rb +36 -0
- data/test/template/deprecated_instance_variables_test.rb +43 -0
- data/test/template/form_helper_test.rb +77 -1
- data/test/template/form_options_helper_test.rb +4 -0
- data/test/template/form_tag_helper_test.rb +66 -2
- data/test/template/java_script_macros_helper_test.rb +4 -1
- data/test/template/javascript_helper_test.rb +29 -0
- data/test/template/number_helper_test.rb +63 -27
- data/test/template/prototype_helper_test.rb +77 -34
- data/test/template/tag_helper_test.rb +34 -6
- data/test/template/text_helper_test.rb +69 -34
- data/test/template/url_helper_test.rb +168 -16
- data/test/testing_sandbox.rb +7 -22
- metadata +66 -20
- data/filler.txt +0 -50
- data/lib/action_controller/code_generation.rb +0 -235
- data/lib/action_controller/vendor/xml_simple.rb +0 -1019
- data/test/controller/caching_filestore.rb +0 -74
- data/test/fixtures/application_root/app/controllers/a_class_that_contains_a_controller/poorly_placed_controller.rb +0 -7
- data/test/fixtures/application_root/app/controllers/module_that_holds_controllers/nested_controller.rb +0 -3
- data/test/fixtures/application_root/app/models/a_class_that_contains_a_controller.rb +0 -7
- data/test/fixtures/dont_load.rb +0 -3
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require File.dirname(__FILE__) + "/../vendor/html-scanner/html/document"
|
3
|
+
|
4
|
+
module ActionController
|
5
|
+
module Assertions
|
6
|
+
module TagAssertions
|
7
|
+
# Asserts that there is a tag/node/element in the body of the response
|
8
|
+
# that meets all of the given conditions. The +conditions+ parameter must
|
9
|
+
# be a hash of any of the following keys (all are optional):
|
10
|
+
#
|
11
|
+
# * <tt>:tag</tt>: the node type must match the corresponding value
|
12
|
+
# * <tt>:attributes</tt>: a hash. The node's attributes must match the
|
13
|
+
# corresponding values in the hash.
|
14
|
+
# * <tt>:parent</tt>: a hash. The node's parent must match the
|
15
|
+
# corresponding hash.
|
16
|
+
# * <tt>:child</tt>: a hash. At least one of the node's immediate children
|
17
|
+
# must meet the criteria described by the hash.
|
18
|
+
# * <tt>:ancestor</tt>: a hash. At least one of the node's ancestors must
|
19
|
+
# meet the criteria described by the hash.
|
20
|
+
# * <tt>:descendant</tt>: a hash. At least one of the node's descendants
|
21
|
+
# must meet the criteria described by the hash.
|
22
|
+
# * <tt>:sibling</tt>: a hash. At least one of the node's siblings must
|
23
|
+
# meet the criteria described by the hash.
|
24
|
+
# * <tt>:after</tt>: a hash. The node must be after any sibling meeting
|
25
|
+
# the criteria described by the hash, and at least one sibling must match.
|
26
|
+
# * <tt>:before</tt>: a hash. The node must be before any sibling meeting
|
27
|
+
# the criteria described by the hash, and at least one sibling must match.
|
28
|
+
# * <tt>:children</tt>: a hash, for counting children of a node. Accepts
|
29
|
+
# the keys:
|
30
|
+
# * <tt>:count</tt>: either a number or a range which must equal (or
|
31
|
+
# include) the number of children that match.
|
32
|
+
# * <tt>:less_than</tt>: the number of matching children must be less
|
33
|
+
# than this number.
|
34
|
+
# * <tt>:greater_than</tt>: the number of matching children must be
|
35
|
+
# greater than this number.
|
36
|
+
# * <tt>:only</tt>: another hash consisting of the keys to use
|
37
|
+
# to match on the children, and only matching children will be
|
38
|
+
# counted.
|
39
|
+
# * <tt>:content</tt>: the textual content of the node must match the
|
40
|
+
# given value. This will not match HTML tags in the body of a
|
41
|
+
# tag--only text.
|
42
|
+
#
|
43
|
+
# Conditions are matched using the following algorithm:
|
44
|
+
#
|
45
|
+
# * if the condition is a string, it must be a substring of the value.
|
46
|
+
# * if the condition is a regexp, it must match the value.
|
47
|
+
# * if the condition is a number, the value must match number.to_s.
|
48
|
+
# * if the condition is +true+, the value must not be +nil+.
|
49
|
+
# * if the condition is +false+ or +nil+, the value must be +nil+.
|
50
|
+
#
|
51
|
+
# Usage:
|
52
|
+
#
|
53
|
+
# # assert that there is a "span" tag
|
54
|
+
# assert_tag :tag => "span"
|
55
|
+
#
|
56
|
+
# # assert that there is a "span" tag with id="x"
|
57
|
+
# assert_tag :tag => "span", :attributes => { :id => "x" }
|
58
|
+
#
|
59
|
+
# # assert that there is a "span" tag using the short-hand
|
60
|
+
# assert_tag :span
|
61
|
+
#
|
62
|
+
# # assert that there is a "span" tag with id="x" using the short-hand
|
63
|
+
# assert_tag :span, :attributes => { :id => "x" }
|
64
|
+
#
|
65
|
+
# # assert that there is a "span" inside of a "div"
|
66
|
+
# assert_tag :tag => "span", :parent => { :tag => "div" }
|
67
|
+
#
|
68
|
+
# # assert that there is a "span" somewhere inside a table
|
69
|
+
# assert_tag :tag => "span", :ancestor => { :tag => "table" }
|
70
|
+
#
|
71
|
+
# # assert that there is a "span" with at least one "em" child
|
72
|
+
# assert_tag :tag => "span", :child => { :tag => "em" }
|
73
|
+
#
|
74
|
+
# # assert that there is a "span" containing a (possibly nested)
|
75
|
+
# # "strong" tag.
|
76
|
+
# assert_tag :tag => "span", :descendant => { :tag => "strong" }
|
77
|
+
#
|
78
|
+
# # assert that there is a "span" containing between 2 and 4 "em" tags
|
79
|
+
# # as immediate children
|
80
|
+
# assert_tag :tag => "span",
|
81
|
+
# :children => { :count => 2..4, :only => { :tag => "em" } }
|
82
|
+
#
|
83
|
+
# # get funky: assert that there is a "div", with an "ul" ancestor
|
84
|
+
# # and an "li" parent (with "class" = "enum"), and containing a
|
85
|
+
# # "span" descendant that contains text matching /hello world/
|
86
|
+
# assert_tag :tag => "div",
|
87
|
+
# :ancestor => { :tag => "ul" },
|
88
|
+
# :parent => { :tag => "li",
|
89
|
+
# :attributes => { :class => "enum" } },
|
90
|
+
# :descendant => { :tag => "span",
|
91
|
+
# :child => /hello world/ }
|
92
|
+
#
|
93
|
+
# <strong>Please note</strong: #assert_tag and #assert_no_tag only work
|
94
|
+
# with well-formed XHTML. They recognize a few tags as implicitly self-closing
|
95
|
+
# (like br and hr and such) but will not work correctly with tags
|
96
|
+
# that allow optional closing tags (p, li, td). <em>You must explicitly
|
97
|
+
# close all of your tags to use these assertions.</em>
|
98
|
+
def assert_tag(*opts)
|
99
|
+
clean_backtrace do
|
100
|
+
opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
|
101
|
+
tag = find_tag(opts)
|
102
|
+
assert tag, "expected tag, but no tag found matching #{opts.inspect} in:\n#{@response.body.inspect}"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Identical to #assert_tag, but asserts that a matching tag does _not_
|
107
|
+
# exist. (See #assert_tag for a full discussion of the syntax.)
|
108
|
+
def assert_no_tag(*opts)
|
109
|
+
clean_backtrace do
|
110
|
+
opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
|
111
|
+
tag = find_tag(opts)
|
112
|
+
assert !tag, "expected no tag, but found tag matching #{opts.inspect} in:\n#{@response.body.inspect}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -2,8 +2,9 @@ require 'action_controller/mime_type'
|
|
2
2
|
require 'action_controller/request'
|
3
3
|
require 'action_controller/response'
|
4
4
|
require 'action_controller/routing'
|
5
|
-
require 'action_controller/
|
5
|
+
require 'action_controller/resources'
|
6
6
|
require 'action_controller/url_rewriter'
|
7
|
+
require 'action_controller/status_codes'
|
7
8
|
require 'drb'
|
8
9
|
require 'set'
|
9
10
|
|
@@ -27,6 +28,8 @@ module ActionController #:nodoc:
|
|
27
28
|
end
|
28
29
|
class MissingFile < ActionControllerError #:nodoc:
|
29
30
|
end
|
31
|
+
class RenderError < ActionControllerError #:nodoc:
|
32
|
+
end
|
30
33
|
class SessionOverflowError < ActionControllerError #:nodoc:
|
31
34
|
DEFAULT_MESSAGE = 'Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.'
|
32
35
|
|
@@ -35,23 +38,23 @@ module ActionController #:nodoc:
|
|
35
38
|
end
|
36
39
|
end
|
37
40
|
class DoubleRenderError < ActionControllerError #:nodoc:
|
38
|
-
DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and only once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\". Finally, note that to cause a before filter to halt execution of the rest of the filter chain, the filter must return false, explicitly, so \"render(...) and return false\"."
|
41
|
+
DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and only once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\". Finally, note that to cause a before filter to halt execution of the rest of the filter chain, the filter must return false, explicitly, so \"render(...) and return false\"."
|
39
42
|
|
40
43
|
def initialize(message = nil)
|
41
44
|
super(message || DEFAULT_MESSAGE)
|
42
45
|
end
|
43
46
|
end
|
44
47
|
class RedirectBackError < ActionControllerError #:nodoc:
|
45
|
-
DEFAULT_MESSAGE = 'No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify
|
46
|
-
|
48
|
+
DEFAULT_MESSAGE = 'No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify request.env["HTTP_REFERER"].'
|
49
|
+
|
47
50
|
def initialize(message = nil)
|
48
51
|
super(message || DEFAULT_MESSAGE)
|
49
52
|
end
|
50
53
|
end
|
51
54
|
|
52
|
-
# Action Controllers are the core of a web request in Rails. They are made up of one or more actions that are executed
|
55
|
+
# Action Controllers are the core of a web request in Rails. They are made up of one or more actions that are executed
|
53
56
|
# on request and then either render a template or redirect to another action. An action is defined as a public method
|
54
|
-
# on the controller, which will automatically be made accessible to the web-server through Rails Routes.
|
57
|
+
# on the controller, which will automatically be made accessible to the web-server through Rails Routes.
|
55
58
|
#
|
56
59
|
# A sample controller could look like this:
|
57
60
|
#
|
@@ -59,7 +62,7 @@ module ActionController #:nodoc:
|
|
59
62
|
# def index
|
60
63
|
# @entries = Entry.find(:all)
|
61
64
|
# end
|
62
|
-
#
|
65
|
+
#
|
63
66
|
# def sign
|
64
67
|
# Entry.create(params[:entry])
|
65
68
|
# redirect_to :action => "index"
|
@@ -67,11 +70,11 @@ module ActionController #:nodoc:
|
|
67
70
|
# end
|
68
71
|
#
|
69
72
|
# Actions, by default, render a template in the <tt>app/views</tt> directory corresponding to the name of the controller and action
|
70
|
-
# after executing code in the action. For example, the +index+ action of the +GuestBookController+ would render the
|
73
|
+
# after executing code in the action. For example, the +index+ action of the +GuestBookController+ would render the
|
71
74
|
# template <tt>app/views/guestbook/index.rhtml</tt> by default after populating the <tt>@entries</tt> instance variable.
|
72
75
|
#
|
73
|
-
# Unlike index, the sign action will not render a template. After performing its main purpose (creating a
|
74
|
-
# new entry in the guest book), it initiates a redirect instead. This redirect works by returning an external
|
76
|
+
# Unlike index, the sign action will not render a template. After performing its main purpose (creating a
|
77
|
+
# new entry in the guest book), it initiates a redirect instead. This redirect works by returning an external
|
75
78
|
# "302 Moved" HTTP response that takes the user to the index action.
|
76
79
|
#
|
77
80
|
# The index and sign represent the two basic action archetypes used in Action Controllers. Get-and-show and do-and-redirect.
|
@@ -95,7 +98,7 @@ module ActionController #:nodoc:
|
|
95
98
|
# == Parameters
|
96
99
|
#
|
97
100
|
# All request parameters, whether they come from a GET or POST request, or from the URL, are available through the params method
|
98
|
-
# which returns a hash. For example, an action that was performed through <tt>/weblog/list?category=All&limit=5</tt> will include
|
101
|
+
# which returns a hash. For example, an action that was performed through <tt>/weblog/list?category=All&limit=5</tt> will include
|
99
102
|
# <tt>{ "category" => "All", "limit" => 5 }</tt> in params.
|
100
103
|
#
|
101
104
|
# It's also possible to construct multi-dimensional parameter hashes by specifying keys using brackets, such as:
|
@@ -104,14 +107,14 @@ module ActionController #:nodoc:
|
|
104
107
|
# <input type="text" name="post[address]" value="hyacintvej">
|
105
108
|
#
|
106
109
|
# A request stemming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>.
|
107
|
-
# If the address input had been named "post[address][street]", the params would have included
|
110
|
+
# If the address input had been named "post[address][street]", the params would have included
|
108
111
|
# <tt>{ "post" => { "address" => { "street" => "hyacintvej" } } }</tt>. There's no limit to the depth of the nesting.
|
109
112
|
#
|
110
113
|
# == Sessions
|
111
114
|
#
|
112
115
|
# Sessions allows you to store objects in between requests. This is useful for objects that are not yet ready to be persisted,
|
113
116
|
# such as a Signup object constructed in a multi-paged process, or objects that don't change much and are needed all the time, such
|
114
|
-
# as a User object for a system that requires login. The session should not be used, however, as a cache for objects where it's likely
|
117
|
+
# as a User object for a system that requires login. The session should not be used, however, as a cache for objects where it's likely
|
115
118
|
# they could be changed unknowingly. It's usually too much work to keep it all synchronized -- something databases already excel at.
|
116
119
|
#
|
117
120
|
# You can place objects in the session by using the <tt>session</tt> method, which accesses a hash:
|
@@ -125,13 +128,13 @@ module ActionController #:nodoc:
|
|
125
128
|
# For removing objects from the session, you can either assign a single key to nil, like <tt>session[:person] = nil</tt>, or you can
|
126
129
|
# remove the entire session with reset_session.
|
127
130
|
#
|
128
|
-
# By default, sessions are stored on the file system in <tt>RAILS_ROOT/tmp/sessions</tt>. Any object can be placed in the session
|
131
|
+
# By default, sessions are stored on the file system in <tt>RAILS_ROOT/tmp/sessions</tt>. Any object can be placed in the session
|
129
132
|
# (as long as it can be Marshalled). But remember that 1000 active sessions each storing a 50kb object could lead to a 50MB store on the filesystem.
|
130
133
|
# In other words, think carefully about size and caching before resorting to the use of the session on the filesystem.
|
131
134
|
#
|
132
135
|
# An alternative to storing sessions on disk is to use ActiveRecordStore to store sessions in your database, which can solve problems
|
133
136
|
# caused by storing sessions in the file system and may speed up your application. To use ActiveRecordStore, uncomment the line:
|
134
|
-
#
|
137
|
+
#
|
135
138
|
# config.action_controller.session_store = :active_record_store
|
136
139
|
#
|
137
140
|
# in your <tt>environment.rb</tt> and run <tt>rake db:sessions:create</tt>.
|
@@ -205,9 +208,10 @@ module ActionController #:nodoc:
|
|
205
208
|
#
|
206
209
|
class Base
|
207
210
|
DEFAULT_RENDER_STATUS_CODE = "200 OK"
|
208
|
-
|
209
|
-
include Reloadable::
|
210
|
-
|
211
|
+
|
212
|
+
include Reloadable::Deprecated
|
213
|
+
include StatusCodes
|
214
|
+
|
211
215
|
# Determines whether the view has access to controller internals @request, @response, @session, and @template.
|
212
216
|
# By default, it does.
|
213
217
|
@@view_controller_internals = true
|
@@ -217,8 +221,8 @@ module ActionController #:nodoc:
|
|
217
221
|
@@protected_variables_cache = nil
|
218
222
|
cattr_accessor :protected_variables_cache
|
219
223
|
|
220
|
-
# Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets,
|
221
|
-
# and images to a dedicated asset server away from the main web server. Example:
|
224
|
+
# Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets,
|
225
|
+
# and images to a dedicated asset server away from the main web server. Example:
|
222
226
|
# ActionController::Base.asset_host = "http://assets.example.com"
|
223
227
|
@@asset_host = ""
|
224
228
|
cattr_accessor :asset_host
|
@@ -228,7 +232,7 @@ module ActionController #:nodoc:
|
|
228
232
|
# should instead be implemented in the controller to determine when debugging screens should be shown.
|
229
233
|
@@consider_all_requests_local = true
|
230
234
|
cattr_accessor :consider_all_requests_local
|
231
|
-
|
235
|
+
|
232
236
|
# Enable or disable the collection of failure information for RoutingErrors.
|
233
237
|
# This information can be extremely useful when tweaking custom routes, but is
|
234
238
|
# pointless once routes have been tested and verified.
|
@@ -241,43 +245,47 @@ module ActionController #:nodoc:
|
|
241
245
|
@@allow_concurrency = false
|
242
246
|
cattr_accessor :allow_concurrency
|
243
247
|
|
244
|
-
# Modern REST web services often need to submit complex data to the web application.
|
245
|
-
# The param_parsers hash lets you register handlers
|
248
|
+
# Modern REST web services often need to submit complex data to the web application.
|
249
|
+
# The param_parsers hash lets you register handlers which will process the http body and add parameters to the
|
246
250
|
# <tt>params</tt> hash. These handlers are invoked for post and put requests.
|
247
251
|
#
|
248
|
-
# By default application/xml is enabled. A XmlSimple class with the same param name as the root will be instanciated
|
252
|
+
# By default application/xml is enabled. A XmlSimple class with the same param name as the root will be instanciated
|
249
253
|
# in the <tt>params</tt>. This allows XML requests to mask themselves as regular form submissions, so you can have one
|
250
254
|
# action serve both regular forms and web service requests.
|
251
|
-
#
|
255
|
+
#
|
252
256
|
# Example of doing your own parser for a custom content type:
|
253
257
|
#
|
254
|
-
# ActionController::Base.param_parsers[Mime::Type.lookup('application/atom+xml')] = Proc.new do |data|
|
255
|
-
# node = REXML::Document.new(post)
|
258
|
+
# ActionController::Base.param_parsers[Mime::Type.lookup('application/atom+xml')] = Proc.new do |data|
|
259
|
+
# node = REXML::Document.new(post)
|
256
260
|
# { node.root.name => node.root }
|
257
261
|
# end
|
258
262
|
#
|
259
|
-
# Note: Up until release 1.1 of Rails, Action Controller would default to using XmlSimple configured to discard the
|
263
|
+
# Note: Up until release 1.1 of Rails, Action Controller would default to using XmlSimple configured to discard the
|
260
264
|
# root node for such requests. The new default is to keep the root, such that "<r><name>David</name></r>" results
|
261
|
-
# in params[:r][:name] for "David" instead of params[:name]. To get the old behavior, you can
|
265
|
+
# in params[:r][:name] for "David" instead of params[:name]. To get the old behavior, you can
|
262
266
|
# re-register XmlSimple as application/xml handler ike this:
|
263
267
|
#
|
264
|
-
# ActionController::Base.param_parsers[Mime::XML] =
|
268
|
+
# ActionController::Base.param_parsers[Mime::XML] =
|
265
269
|
# Proc.new { |data| XmlSimple.xml_in(data, 'ForceArray' => false) }
|
266
270
|
#
|
267
271
|
# A YAML parser is also available and can be turned on with:
|
268
272
|
#
|
269
273
|
# ActionController::Base.param_parsers[Mime::YAML] = :yaml
|
270
274
|
@@param_parsers = { Mime::XML => :xml_simple }
|
271
|
-
cattr_accessor :param_parsers
|
275
|
+
cattr_accessor :param_parsers
|
276
|
+
|
277
|
+
# Controls the default charset for all renders.
|
278
|
+
@@default_charset = "utf-8"
|
279
|
+
cattr_accessor :default_charset
|
272
280
|
|
273
281
|
# Template root determines the base from which template references will be made. So a call to render("test/template")
|
274
282
|
# will be converted to "#{template_root}/test/template.rhtml".
|
275
283
|
class_inheritable_accessor :template_root
|
276
|
-
|
284
|
+
|
277
285
|
# The logger is used for generating information on the action run-time (including benchmarking) if available.
|
278
286
|
# Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.
|
279
287
|
cattr_accessor :logger
|
280
|
-
|
288
|
+
|
281
289
|
# Determines which template class should be used by ActionController.
|
282
290
|
cattr_accessor :template_class
|
283
291
|
|
@@ -286,39 +294,42 @@ module ActionController #:nodoc:
|
|
286
294
|
|
287
295
|
# Holds the request object that's primarily used to get environment variables through access like
|
288
296
|
# <tt>request.env["REQUEST_URI"]</tt>.
|
289
|
-
|
290
|
-
|
297
|
+
attr_internal :request
|
298
|
+
|
291
299
|
# Holds a hash of all the GET, POST, and Url parameters passed to the action. Accessed like <tt>params["post_id"]</tt>
|
292
300
|
# to get the post_id. No type casts are made, so all values are returned as strings.
|
293
|
-
|
294
|
-
|
295
|
-
# Holds the response object that's primarily used to set additional HTTP headers through access like
|
301
|
+
attr_internal :params
|
302
|
+
|
303
|
+
# Holds the response object that's primarily used to set additional HTTP headers through access like
|
296
304
|
# <tt>response.headers["Cache-Control"] = "no-cache"</tt>. Can also be used to access the final body HTML after a template
|
297
305
|
# has been rendered through response.body -- useful for <tt>after_filter</tt>s that wants to manipulate the output,
|
298
306
|
# such as a OutputCompressionFilter.
|
299
|
-
|
300
|
-
|
307
|
+
attr_internal :response
|
308
|
+
|
301
309
|
# Holds a hash of objects in the session. Accessed like <tt>session[:person]</tt> to get the object tied to the "person"
|
302
310
|
# key. The session will hold any type of object as values, but the key should be a string or symbol.
|
303
|
-
|
304
|
-
|
311
|
+
attr_internal :session
|
312
|
+
|
305
313
|
# Holds a hash of header names and values. Accessed like <tt>headers["Cache-Control"]</tt> to get the value of the Cache-Control
|
306
314
|
# directive. Values should always be specified as strings.
|
307
|
-
|
308
|
-
|
315
|
+
attr_internal :headers
|
316
|
+
|
309
317
|
# Holds the hash of variables that are passed on to the template class to be made available to the view. This hash
|
310
318
|
# is generated by taking a snapshot of all the instance variables in the current scope just before a template is rendered.
|
311
319
|
attr_accessor :assigns
|
312
320
|
|
313
321
|
# Returns the name of the action this controller is processing.
|
314
322
|
attr_accessor :action_name
|
315
|
-
|
323
|
+
|
324
|
+
# Templates that are exempt from layouts
|
325
|
+
@@exempt_from_layout = Set.new([/\.rjs$/])
|
326
|
+
|
316
327
|
class << self
|
317
328
|
# Factory for the standard create, process loop where the controller is discarded after processing.
|
318
329
|
def process(request, response) #:nodoc:
|
319
330
|
new.process(request, response)
|
320
331
|
end
|
321
|
-
|
332
|
+
|
322
333
|
# Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController".
|
323
334
|
def controller_class_name
|
324
335
|
@controller_class_name ||= name.demodulize
|
@@ -328,7 +339,7 @@ module ActionController #:nodoc:
|
|
328
339
|
def controller_name
|
329
340
|
@controller_name ||= controller_class_name.sub(/Controller$/, '').underscore
|
330
341
|
end
|
331
|
-
|
342
|
+
|
332
343
|
# Converts the class name from something like "OneModule::TwoModule::NeatController" to "one_module/two_module/neat".
|
333
344
|
def controller_path
|
334
345
|
@controller_path ||= name.gsub(/Controller$/, '').underscore
|
@@ -346,7 +357,7 @@ module ActionController #:nodoc:
|
|
346
357
|
def hide_action(*names)
|
347
358
|
write_inheritable_attribute(:hidden_actions, hidden_actions | names.collect { |n| n.to_s })
|
348
359
|
end
|
349
|
-
|
360
|
+
|
350
361
|
# Replace sensitive paramater data from the request log.
|
351
362
|
# Filters paramaters that have any of the arguments as a substring.
|
352
363
|
# Looks in all subhashes of the param hash for keys to filter.
|
@@ -368,7 +379,7 @@ module ActionController #:nodoc:
|
|
368
379
|
# => reverses the value to all keys matching /secret/i
|
369
380
|
#
|
370
381
|
# filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i }
|
371
|
-
# => reverses the value to all keys matching /secret/i, and
|
382
|
+
# => reverses the value to all keys matching /secret/i, and
|
372
383
|
# replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
|
373
384
|
def filter_parameter_logging(*filter_words, &block)
|
374
385
|
parameter_filter = Regexp.new(filter_words.collect{ |s| s.to_s }.join('|'), true) if filter_words.length > 0
|
@@ -380,12 +391,12 @@ module ActionController #:nodoc:
|
|
380
391
|
if key =~ parameter_filter
|
381
392
|
filtered_parameters[key] = '[FILTERED]'
|
382
393
|
elsif value.is_a?(Hash)
|
383
|
-
filtered_parameters[key] = filter_parameters(value)
|
394
|
+
filtered_parameters[key] = filter_parameters(value)
|
384
395
|
elsif block_given?
|
385
396
|
key, value = key.dup, value.dup
|
386
397
|
yield key, value
|
387
398
|
filtered_parameters[key] = value
|
388
|
-
else
|
399
|
+
else
|
389
400
|
filtered_parameters[key] = value
|
390
401
|
end
|
391
402
|
end
|
@@ -393,9 +404,20 @@ module ActionController #:nodoc:
|
|
393
404
|
filtered_parameters
|
394
405
|
end
|
395
406
|
end
|
407
|
+
|
408
|
+
# Don't render layouts for templates with the given extensions.
|
409
|
+
def exempt_from_layout(*extensions)
|
410
|
+
@@exempt_from_layout.merge extensions.collect { |extension|
|
411
|
+
if extension.is_a?(Regexp)
|
412
|
+
extension
|
413
|
+
else
|
414
|
+
/\.#{Regexp.escape(extension.to_s)}$/
|
415
|
+
end
|
416
|
+
}
|
417
|
+
end
|
396
418
|
end
|
397
419
|
|
398
|
-
public
|
420
|
+
public
|
399
421
|
# Extracts the action_name from the request parameters and performs that action.
|
400
422
|
def process(request, response, method = :perform_action, *arguments) #:nodoc:
|
401
423
|
initialize_template_class(response)
|
@@ -403,25 +425,26 @@ module ActionController #:nodoc:
|
|
403
425
|
initialize_current_url
|
404
426
|
assign_names
|
405
427
|
forget_variables_added_to_assigns
|
406
|
-
|
428
|
+
|
407
429
|
log_processing
|
408
430
|
send(method, *arguments)
|
409
|
-
|
431
|
+
|
432
|
+
assign_default_content_type_and_charset
|
410
433
|
response
|
411
434
|
ensure
|
412
435
|
process_cleanup
|
413
436
|
end
|
414
437
|
|
415
|
-
# Returns a URL that has been rewritten according to the options hash and the defined Routes.
|
438
|
+
# Returns a URL that has been rewritten according to the options hash and the defined Routes.
|
416
439
|
# (For doing a complete redirect, use redirect_to).
|
417
440
|
#
|
418
441
|
# <tt>url_for</tt> is used to:
|
419
442
|
#
|
420
443
|
# All keys given to url_for are forwarded to the Route module, save for the following:
|
421
|
-
# * <tt>:anchor</tt> -- specifies the anchor name to be appended to the path. For example,
|
422
|
-
# <tt>url_for :controller => 'posts', :action => 'show', :id => 10, :anchor => 'comments'</tt>
|
444
|
+
# * <tt>:anchor</tt> -- specifies the anchor name to be appended to the path. For example,
|
445
|
+
# <tt>url_for :controller => 'posts', :action => 'show', :id => 10, :anchor => 'comments'</tt>
|
423
446
|
# will produce "/posts/show/10#comments".
|
424
|
-
# * <tt>:only_path</tt> -- if true, returns the
|
447
|
+
# * <tt>:only_path</tt> -- if true, returns the relative URL (omitting the protocol, host name, and port) (<tt>false</tt> by default)
|
425
448
|
# * <tt>:trailing_slash</tt> -- if true, adds a trailing slash, as in "/archive/2005/". Note that this
|
426
449
|
# is currently not recommended since it breaks caching.
|
427
450
|
# * <tt>:host</tt> -- overrides the default (current) host if provided
|
@@ -472,7 +495,7 @@ module ActionController #:nodoc:
|
|
472
495
|
# displayed on:
|
473
496
|
#
|
474
497
|
# url_for :controller => 'posts', :action => nil
|
475
|
-
#
|
498
|
+
#
|
476
499
|
# If you explicitly want to create a URL that's almost the same as the current URL, you can do so using the
|
477
500
|
# :overwrite_params options. Say for your posts you have different views for showing and printing them.
|
478
501
|
# Then, in the show view, you get the URL for the print view like this
|
@@ -483,9 +506,20 @@ module ActionController #:nodoc:
|
|
483
506
|
# would have slashed-off the path components after the changed action.
|
484
507
|
def url_for(options = {}, *parameters_for_method_reference) #:doc:
|
485
508
|
case options
|
486
|
-
when String
|
487
|
-
|
488
|
-
|
509
|
+
when String
|
510
|
+
options
|
511
|
+
|
512
|
+
when Symbol
|
513
|
+
ActiveSupport::Deprecation.warn(
|
514
|
+
"You called url_for(:#{options}), which is a deprecated API call. Instead you should use the named " +
|
515
|
+
"route directly, like #{options}(). Using symbols and parameters with url_for will be removed from Rails 2.0.",
|
516
|
+
caller
|
517
|
+
)
|
518
|
+
|
519
|
+
send(options, *parameters_for_method_reference)
|
520
|
+
|
521
|
+
when Hash
|
522
|
+
@url.rewrite(rewrite_options(options))
|
489
523
|
end
|
490
524
|
end
|
491
525
|
|
@@ -499,6 +533,11 @@ module ActionController #:nodoc:
|
|
499
533
|
self.class.controller_name
|
500
534
|
end
|
501
535
|
|
536
|
+
# Converts the class name from something like "OneModule::TwoModule::NeatController" to "one_module/two_module/neat".
|
537
|
+
def controller_path
|
538
|
+
self.class.controller_path
|
539
|
+
end
|
540
|
+
|
502
541
|
def session_enabled?
|
503
542
|
request.session_options[:disabled] != false
|
504
543
|
end
|
@@ -507,7 +546,7 @@ module ActionController #:nodoc:
|
|
507
546
|
# Renders the content that will be returned to the browser as the response body.
|
508
547
|
#
|
509
548
|
# === Rendering an action
|
510
|
-
#
|
549
|
+
#
|
511
550
|
# Action rendering is the most common form and the type used automatically by Action Controller when nothing else is
|
512
551
|
# specified. By default, actions are rendered within the current layout (if one exists).
|
513
552
|
#
|
@@ -523,47 +562,54 @@ module ActionController #:nodoc:
|
|
523
562
|
# render :action => "long_goal", :layout => "spectacular"
|
524
563
|
#
|
525
564
|
# _Deprecation_ _notice_: This used to have the signatures <tt>render_action("action", status = 200)</tt>,
|
526
|
-
# <tt>render_without_layout("controller/action", status = 200)</tt>, and
|
565
|
+
# <tt>render_without_layout("controller/action", status = 200)</tt>, and
|
527
566
|
# <tt>render_with_layout("controller/action", status = 200, layout)</tt>.
|
528
567
|
#
|
529
568
|
# === Rendering partials
|
530
|
-
#
|
531
|
-
# Partial rendering is most commonly used together with Ajax calls that only update one or a few elements on a page
|
569
|
+
#
|
570
|
+
# Partial rendering in a controller is most commonly used together with Ajax calls that only update one or a few elements on a page
|
532
571
|
# without reloading. Rendering of partials from the controller makes it possible to use the same partial template in
|
533
572
|
# both the full-page rendering (by calling it from within the template) and when sub-page updates happen (from the
|
534
573
|
# controller action responding to Ajax calls). By default, the current layout is not used.
|
535
574
|
#
|
536
|
-
# # Renders the partial
|
537
|
-
# render :partial => "
|
575
|
+
# # Renders the same partial with a local variable.
|
576
|
+
# render :partial => "person", :locals => { :name => "david" }
|
538
577
|
#
|
539
|
-
# # Renders
|
540
|
-
#
|
578
|
+
# # Renders a collection of the same partial by making each element
|
579
|
+
# # of @winners available through the local variable "person" as it
|
580
|
+
# # builds the complete response.
|
581
|
+
# render :partial => "person", :collection => @winners
|
582
|
+
#
|
583
|
+
# # Renders the same collection of partials, but also renders the
|
584
|
+
# # person_divider partial between each person partial.
|
585
|
+
# render :partial => "person", :collection => @winners, :spacer_template => "person_divider"
|
541
586
|
#
|
542
|
-
# # Renders
|
543
|
-
#
|
587
|
+
# # Renders a collection of partials located in a view subfolder
|
588
|
+
# # outside of our current controller. In this example we will be
|
589
|
+
# # rendering app/views/shared/_note.r(html|xml) Inside the partial
|
590
|
+
# # each element of @new_notes is available as the local var "note".
|
591
|
+
# render :partial => "shared/note", :collection => @new_notes
|
544
592
|
#
|
545
|
-
# # Renders
|
546
|
-
#
|
547
|
-
# render :partial => "win", :collection => @wins
|
593
|
+
# # Renders the partial with a status code of 500 (internal error).
|
594
|
+
# render :partial => "broken", :status => 500
|
548
595
|
#
|
549
|
-
#
|
550
|
-
#
|
551
|
-
# render :partial => "win", :collection => @wins, :spacer_template => "win_divider"
|
596
|
+
# Note that the partial filename must also be a valid Ruby variable name,
|
597
|
+
# so e.g. 2005 and register-user are invalid.
|
552
598
|
#
|
553
|
-
# _Deprecation_ _notice_: This used to have the signatures
|
599
|
+
# _Deprecation_ _notice_: This used to have the signatures
|
554
600
|
# <tt>render_partial(partial_path = default_template_name, object = nil, local_assigns = {})</tt> and
|
555
601
|
# <tt>render_partial_collection(partial_name, collection, partial_spacer_template = nil, local_assigns = {})</tt>.
|
556
602
|
#
|
557
603
|
# === Rendering a template
|
558
|
-
#
|
559
|
-
# Template rendering works just like action rendering except that it takes a path relative to the template root.
|
604
|
+
#
|
605
|
+
# Template rendering works just like action rendering except that it takes a path relative to the template root.
|
560
606
|
# The current layout is automatically applied.
|
561
607
|
#
|
562
608
|
# # Renders the template located in [TEMPLATE_ROOT]/weblog/show.r(html|xml) (in Rails, app/views/weblog/show.rhtml)
|
563
609
|
# render :template => "weblog/show"
|
564
610
|
#
|
565
611
|
# === Rendering a file
|
566
|
-
#
|
612
|
+
#
|
567
613
|
# File rendering works just like action rendering except that it takes a filesystem path. By default, the path
|
568
614
|
# is assumed to be absolute, and the current layout is not applied.
|
569
615
|
#
|
@@ -581,7 +627,7 @@ module ActionController #:nodoc:
|
|
581
627
|
# _Deprecation_ _notice_: This used to have the signature <tt>render_file(path, status = 200)</tt>
|
582
628
|
#
|
583
629
|
# === Rendering text
|
584
|
-
#
|
630
|
+
#
|
585
631
|
# Rendering of text is usually used for tests or for rendering prepared content, such as a cache. By default, text
|
586
632
|
# rendering is not done within the active layout.
|
587
633
|
#
|
@@ -589,17 +635,38 @@ module ActionController #:nodoc:
|
|
589
635
|
# render :text => "hello world!"
|
590
636
|
#
|
591
637
|
# # Renders the clear text "Explosion!" with status code 500
|
592
|
-
# render :text => "Explosion!", :status => 500
|
638
|
+
# render :text => "Explosion!", :status => 500
|
593
639
|
#
|
594
640
|
# # Renders the clear text "Hi there!" within the current active layout (if one exists)
|
595
641
|
# render :text => "Explosion!", :layout => true
|
596
642
|
#
|
597
|
-
# # Renders the clear text "Hi there!" within the layout
|
643
|
+
# # Renders the clear text "Hi there!" within the layout
|
598
644
|
# # placed in "app/views/layouts/special.r(html|xml)"
|
599
645
|
# render :text => "Explosion!", :layout => "special"
|
600
646
|
#
|
647
|
+
# The :text option can also accept a Proc object, which can be used to manually control the page generation. This should
|
648
|
+
# generally be avoided, as it violates the separation between code and content, and because almost everything that can be
|
649
|
+
# done with this method can also be done more cleanly using one of the other rendering methods, most notably templates.
|
650
|
+
#
|
651
|
+
# # Renders "Hello from code!"
|
652
|
+
# render :text => proc { |response, output| output.write("Hello from code!") }
|
653
|
+
#
|
601
654
|
# _Deprecation_ _notice_: This used to have the signature <tt>render_text("text", status = 200)</tt>
|
602
655
|
#
|
656
|
+
# === Rendering JSON
|
657
|
+
#
|
658
|
+
# Rendering JSON sets the content type to text/x-json and optionally wraps the JSON in a callback. It is expected
|
659
|
+
# that the response will be eval'd for use as a data structure.
|
660
|
+
#
|
661
|
+
# # Renders '{name: "David"}'
|
662
|
+
# render :json => {:name => "David"}.to_json
|
663
|
+
#
|
664
|
+
# Sometimes the result isn't handled directly by a script (such as when the request comes from a SCRIPT tag),
|
665
|
+
# so the callback option is provided for these cases.
|
666
|
+
#
|
667
|
+
# # Renders 'show({name: "David"})'
|
668
|
+
# render :json => {:name => "David"}.to_json, :callback => 'show'
|
669
|
+
#
|
603
670
|
# === Rendering an inline template
|
604
671
|
#
|
605
672
|
# Rendering of an inline template works as a cross between text and action rendering where the source for the template
|
@@ -607,7 +674,7 @@ module ActionController #:nodoc:
|
|
607
674
|
# and the current layout is not used.
|
608
675
|
#
|
609
676
|
# # Renders "hello, hello, hello, again"
|
610
|
-
# render :inline => "<%= 'hello, ' * 3 + 'again' %>"
|
677
|
+
# render :inline => "<%= 'hello, ' * 3 + 'again' %>"
|
611
678
|
#
|
612
679
|
# # Renders "<p>Good seeing you!</p>" using Builder
|
613
680
|
# render :inline => "xml.p { 'Good seeing you!' }", :type => :rxml
|
@@ -640,17 +707,27 @@ module ActionController #:nodoc:
|
|
640
707
|
def render(options = nil, deprecated_status = nil, &block) #:doc:
|
641
708
|
raise DoubleRenderError, "Can only render or redirect once per action" if performed?
|
642
709
|
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
710
|
+
if options.nil?
|
711
|
+
return render_file(default_template_name, deprecated_status, true)
|
712
|
+
else
|
713
|
+
# Backwards compatibility
|
714
|
+
unless options.is_a?(Hash)
|
715
|
+
if options == :update
|
716
|
+
options = { :update => true }
|
717
|
+
else
|
718
|
+
ActiveSupport::Deprecation.warn(
|
719
|
+
"You called render('#{options}'), which is a deprecated API call. Instead you use " +
|
720
|
+
"render :file => #{options}. Calling render with just a string will be removed from Rails 2.0.",
|
721
|
+
caller
|
722
|
+
)
|
723
|
+
|
724
|
+
return render_file(options, deprecated_status, true)
|
725
|
+
end
|
649
726
|
end
|
650
727
|
end
|
651
728
|
|
652
729
|
if content_type = options[:content_type]
|
653
|
-
|
730
|
+
response.content_type = content_type.to_s
|
654
731
|
end
|
655
732
|
|
656
733
|
if text = options[:text]
|
@@ -662,16 +739,21 @@ module ActionController #:nodoc:
|
|
662
739
|
|
663
740
|
elsif template = options[:template]
|
664
741
|
render_file(template, options[:status], true)
|
665
|
-
|
742
|
+
|
666
743
|
elsif inline = options[:inline]
|
667
744
|
render_template(inline, options[:status], options[:type], options[:locals] || {})
|
668
|
-
|
745
|
+
|
669
746
|
elsif action_name = options[:action]
|
670
|
-
|
747
|
+
ActiveSupport::Deprecation.silence do
|
748
|
+
render_action(action_name, options[:status], options[:layout])
|
749
|
+
end
|
671
750
|
|
672
751
|
elsif xml = options[:xml]
|
673
752
|
render_xml(xml, options[:status])
|
674
753
|
|
754
|
+
elsif json = options[:json]
|
755
|
+
render_json(json, options[:callback], options[:status])
|
756
|
+
|
675
757
|
elsif partial = options[:partial]
|
676
758
|
partial = default_template_name if partial == true
|
677
759
|
if collection = options[:collection]
|
@@ -683,17 +765,17 @@ module ActionController #:nodoc:
|
|
683
765
|
elsif options[:update]
|
684
766
|
add_variables_to_assigns
|
685
767
|
@template.send :evaluate_assigns
|
686
|
-
|
768
|
+
|
687
769
|
generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(@template, &block)
|
688
770
|
render_javascript(generator.to_s)
|
689
771
|
|
690
772
|
elsif options[:nothing]
|
691
773
|
# Safari doesn't pass the headers of the return if the response is zero length
|
692
774
|
render_text(" ", options[:status])
|
693
|
-
|
775
|
+
|
694
776
|
else
|
695
777
|
render_file(default_template_name, options[:status], true)
|
696
|
-
|
778
|
+
|
697
779
|
end
|
698
780
|
end
|
699
781
|
end
|
@@ -701,21 +783,19 @@ module ActionController #:nodoc:
|
|
701
783
|
# Renders according to the same rules as <tt>render</tt>, but returns the result in a string instead
|
702
784
|
# of sending it as the response body to the browser.
|
703
785
|
def render_to_string(options = nil, &block) #:doc:
|
704
|
-
|
705
|
-
|
786
|
+
ActiveSupport::Deprecation.silence { render(options, &block) }
|
787
|
+
ensure
|
706
788
|
erase_render_results
|
707
789
|
forget_variables_added_to_assigns
|
708
790
|
reset_variables_added_to_assigns
|
709
|
-
|
710
|
-
result
|
711
|
-
end
|
791
|
+
end
|
712
792
|
|
713
793
|
def render_action(action_name, status = nil, with_layout = true) #:nodoc:
|
714
794
|
template = default_template_name(action_name.to_s)
|
715
|
-
if with_layout && !template_exempt_from_layout?(template)
|
716
|
-
render_with_layout(template, status)
|
795
|
+
if with_layout && !template_exempt_from_layout?(template)
|
796
|
+
render_with_layout(:file => template, :status => status, :use_full_path => true, :layout => true)
|
717
797
|
else
|
718
|
-
render_without_layout(template, status)
|
798
|
+
render_without_layout(:file => template, :status => status, :use_full_path => true)
|
719
799
|
end
|
720
800
|
end
|
721
801
|
|
@@ -731,22 +811,36 @@ module ActionController #:nodoc:
|
|
731
811
|
render_text(@template.render_template(type, template, nil, local_assigns), status)
|
732
812
|
end
|
733
813
|
|
734
|
-
def render_text(text = nil, status = nil) #:nodoc:
|
814
|
+
def render_text(text = nil, status = nil, append_response = false) #:nodoc:
|
735
815
|
@performed_render = true
|
736
|
-
|
737
|
-
|
816
|
+
|
817
|
+
response.headers['Status'] = interpret_status(status || DEFAULT_RENDER_STATUS_CODE)
|
818
|
+
|
819
|
+
if append_response
|
820
|
+
response.body ||= ''
|
821
|
+
response.body << text
|
822
|
+
else
|
823
|
+
response.body = text
|
824
|
+
end
|
738
825
|
end
|
739
826
|
|
740
|
-
def render_javascript(javascript, status = nil) #:nodoc:
|
741
|
-
|
742
|
-
render_text(javascript, status)
|
827
|
+
def render_javascript(javascript, status = nil, append_response = true) #:nodoc:
|
828
|
+
response.content_type = Mime::JS
|
829
|
+
render_text(javascript, status, append_response)
|
743
830
|
end
|
744
831
|
|
745
832
|
def render_xml(xml, status = nil) #:nodoc:
|
746
|
-
|
833
|
+
response.content_type = Mime::XML
|
747
834
|
render_text(xml, status)
|
748
835
|
end
|
749
836
|
|
837
|
+
def render_json(json, callback = nil, status = nil) #:nodoc:
|
838
|
+
json = "#{callback}(#{json})" unless callback.blank?
|
839
|
+
|
840
|
+
response.content_type = Mime::JSON
|
841
|
+
render_text(json, status)
|
842
|
+
end
|
843
|
+
|
750
844
|
def render_nothing(status = nil) #:nodoc:
|
751
845
|
render_text(' ', status)
|
752
846
|
end
|
@@ -770,13 +864,52 @@ module ActionController #:nodoc:
|
|
770
864
|
end
|
771
865
|
|
772
866
|
|
867
|
+
# Return a response that has no content (merely headers). The options
|
868
|
+
# argument is interpreted to be a hash of header names and values.
|
869
|
+
# This allows you to easily return a response that consists only of
|
870
|
+
# significant headers:
|
871
|
+
#
|
872
|
+
# head :created, :location => person_path(@person)
|
873
|
+
#
|
874
|
+
# It can also be used to return exceptional conditions:
|
875
|
+
#
|
876
|
+
# return head(:method_not_allowed) unless request.post?
|
877
|
+
# return head(:bad_request) unless valid_request?
|
878
|
+
# render
|
879
|
+
def head(*args)
|
880
|
+
if args.length > 2
|
881
|
+
raise ArgumentError, "too many arguments to head"
|
882
|
+
elsif args.empty?
|
883
|
+
raise ArgumentError, "too few arguments to head"
|
884
|
+
elsif args.length == 2
|
885
|
+
status = args.shift
|
886
|
+
options = args.shift
|
887
|
+
elsif args.first.is_a?(Hash)
|
888
|
+
options = args.first
|
889
|
+
else
|
890
|
+
status = args.first
|
891
|
+
options = {}
|
892
|
+
end
|
893
|
+
|
894
|
+
raise ArgumentError, "head requires an options hash" if !options.is_a?(Hash)
|
895
|
+
|
896
|
+
status = interpret_status(status || options.delete(:status) || :ok)
|
897
|
+
|
898
|
+
options.each do |key, value|
|
899
|
+
headers[key.to_s.dasherize.split(/-/).map { |v| v.capitalize }.join("-")] = value.to_s
|
900
|
+
end
|
901
|
+
|
902
|
+
render :nothing => true, :status => status
|
903
|
+
end
|
904
|
+
|
905
|
+
|
773
906
|
# Clears the rendered results, allowing for another render to be performed.
|
774
907
|
def erase_render_results #:nodoc:
|
775
|
-
|
908
|
+
response.body = nil
|
776
909
|
@performed_render = false
|
777
910
|
end
|
778
|
-
|
779
|
-
# Clears the redirected results from the headers, resets the status to 200 and returns
|
911
|
+
|
912
|
+
# Clears the redirected results from the headers, resets the status to 200 and returns
|
780
913
|
# the URL that was used to redirect or nil if there was no redirected URL
|
781
914
|
# Note that +redirect_to+ will change the body of the response to indicate a redirection.
|
782
915
|
# The response body is not reset here, see +erase_render_results+
|
@@ -785,7 +918,7 @@ module ActionController #:nodoc:
|
|
785
918
|
response.redirected_to = nil
|
786
919
|
response.redirected_to_method_params = nil
|
787
920
|
response.headers['Status'] = DEFAULT_RENDER_STATUS_CODE
|
788
|
-
response.headers.delete('
|
921
|
+
response.headers.delete('Location')
|
789
922
|
end
|
790
923
|
|
791
924
|
# Erase both render and redirect results
|
@@ -801,7 +934,7 @@ module ActionController #:nodoc:
|
|
801
934
|
options
|
802
935
|
end
|
803
936
|
end
|
804
|
-
|
937
|
+
|
805
938
|
# Overwrite to implement a number of default options that all url_for-based methods will use. The default options should come in
|
806
939
|
# the form of a hash, just like the one you would use for url_for directly. Example:
|
807
940
|
#
|
@@ -814,7 +947,7 @@ module ActionController #:nodoc:
|
|
814
947
|
# by this method.
|
815
948
|
def default_url_options(options) #:doc:
|
816
949
|
end
|
817
|
-
|
950
|
+
|
818
951
|
# Redirects the browser to the target specified in +options+. This parameter can take one of three forms:
|
819
952
|
#
|
820
953
|
# * <tt>Hash</tt>: The URL will be generated by calling url_for with the +options+.
|
@@ -822,7 +955,7 @@ module ActionController #:nodoc:
|
|
822
955
|
# * <tt>String not containing a protocol</tt>: The current protocol and host is prepended to the string.
|
823
956
|
# * <tt>:back</tt>: Back to the page that issued the request. Useful for forms that are triggered from multiple places.
|
824
957
|
# Short-hand for redirect_to(request.env["HTTP_REFERER"])
|
825
|
-
#
|
958
|
+
#
|
826
959
|
# Examples:
|
827
960
|
# redirect_to :action => "show", :id => 5
|
828
961
|
# redirect_to "http://www.rubyonrails.org"
|
@@ -845,7 +978,7 @@ module ActionController #:nodoc:
|
|
845
978
|
|
846
979
|
when String
|
847
980
|
redirect_to(request.protocol + request.host_with_port + options)
|
848
|
-
|
981
|
+
|
849
982
|
when :back
|
850
983
|
request.env["HTTP_REFERER"] ? redirect_to(request.env["HTTP_REFERER"]) : raise(RedirectBackError)
|
851
984
|
|
@@ -854,12 +987,13 @@ module ActionController #:nodoc:
|
|
854
987
|
redirect_to(url_for(options))
|
855
988
|
response.redirected_to = options
|
856
989
|
else
|
990
|
+
# TOOD: Deprecate me!
|
857
991
|
redirect_to(url_for(options, *parameters_for_method_reference))
|
858
992
|
response.redirected_to, response.redirected_to_method_params = options, parameters_for_method_reference
|
859
993
|
end
|
860
994
|
end
|
861
995
|
end
|
862
|
-
|
996
|
+
|
863
997
|
# Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a "private" instruction, so that
|
864
998
|
# intermediate caches shouldn't cache the response.
|
865
999
|
#
|
@@ -867,29 +1001,29 @@ module ActionController #:nodoc:
|
|
867
1001
|
# expires_in 20.minutes
|
868
1002
|
# expires_in 3.hours, :private => false
|
869
1003
|
# expires in 3.hours, 'max-stale' => 5.hours, :private => nil, :public => true
|
870
|
-
#
|
1004
|
+
#
|
871
1005
|
# This method will overwrite an existing Cache-Control header.
|
872
1006
|
# See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
|
873
1007
|
def expires_in(seconds, options = {}) #:doc:
|
874
1008
|
cache_options = { 'max-age' => seconds, 'private' => true }.symbolize_keys.merge!(options.symbolize_keys)
|
875
1009
|
cache_options.delete_if { |k,v| v.nil? or v == false }
|
876
1010
|
cache_control = cache_options.map{ |k,v| v == true ? k.to_s : "#{k.to_s}=#{v.to_s}"}
|
877
|
-
|
1011
|
+
response.headers["Cache-Control"] = cache_control.join(', ')
|
878
1012
|
end
|
879
|
-
|
1013
|
+
|
880
1014
|
# Sets a HTTP 1.1 Cache-Control header of "no-cache" so no caching should occur by the browser or
|
881
1015
|
# intermediate caches (like caching proxy servers).
|
882
1016
|
def expires_now #:doc:
|
883
|
-
|
1017
|
+
response.headers["Cache-Control"] = "no-cache"
|
884
1018
|
end
|
885
1019
|
|
886
1020
|
# Resets the session by clearing out all the objects stored within and initializing a new session object.
|
887
1021
|
def reset_session #:doc:
|
888
|
-
|
889
|
-
@
|
890
|
-
|
1022
|
+
request.reset_session
|
1023
|
+
@_session = request.session
|
1024
|
+
response.session = @_session
|
891
1025
|
end
|
892
|
-
|
1026
|
+
|
893
1027
|
private
|
894
1028
|
def self.view_class
|
895
1029
|
@view_class ||=
|
@@ -905,48 +1039,71 @@ module ActionController #:nodoc:
|
|
905
1039
|
|
906
1040
|
def initialize_template_class(response)
|
907
1041
|
raise "You must assign a template class through ActionController.template_class= before processing a request" unless @@template_class
|
908
|
-
|
1042
|
+
|
909
1043
|
response.template = self.class.view_class.new(self.class.view_root, {}, self)
|
910
1044
|
response.redirected_to = nil
|
911
1045
|
@performed_render = @performed_redirect = false
|
912
1046
|
end
|
913
|
-
|
1047
|
+
|
914
1048
|
def assign_shortcuts(request, response)
|
915
|
-
@
|
1049
|
+
@_request, @_params, @_cookies = request, request.parameters, request.cookies
|
1050
|
+
|
1051
|
+
@_response = response
|
1052
|
+
@_response.session = request.session
|
1053
|
+
|
1054
|
+
@_session = @_response.session
|
1055
|
+
@template = @_response.template
|
1056
|
+
@assigns = @_response.template.assigns
|
916
1057
|
|
917
|
-
@
|
918
|
-
@response.session = request.session
|
1058
|
+
@_headers = @_response.headers
|
919
1059
|
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
1060
|
+
assign_deprecated_shortcuts(request, response)
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
|
1064
|
+
# TODO: assigns cookies headers params request response template
|
1065
|
+
DEPRECATED_INSTANCE_VARIABLES = %w(cookies flash headers params request response session)
|
1066
|
+
|
1067
|
+
# Gone after 1.2.
|
1068
|
+
def assign_deprecated_shortcuts(request, response)
|
1069
|
+
DEPRECATED_INSTANCE_VARIABLES.each do |method|
|
1070
|
+
var = "@#{method}"
|
1071
|
+
if instance_variables.include?(var)
|
1072
|
+
value = instance_variable_get(var)
|
1073
|
+
unless ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy === value
|
1074
|
+
raise "Deprecating #{var}, but it's already set to #{value.inspect}! Use the #{method}= writer method instead of setting #{var} directly."
|
1075
|
+
end
|
1076
|
+
end
|
1077
|
+
instance_variable_set var, ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, method)
|
1078
|
+
end
|
925
1079
|
end
|
926
|
-
|
1080
|
+
|
927
1081
|
def initialize_current_url
|
928
|
-
@url = UrlRewriter.new(
|
1082
|
+
@url = UrlRewriter.new(request, params.clone)
|
929
1083
|
end
|
930
1084
|
|
931
1085
|
def log_processing
|
932
1086
|
if logger
|
933
1087
|
logger.info "\n\nProcessing #{controller_class_name}\##{action_name} (for #{request_origin}) [#{request.method.to_s.upcase}]"
|
934
|
-
logger.info " Session ID: #{@
|
935
|
-
logger.info " Parameters: #{respond_to?(:filter_parameters) ? filter_parameters(
|
1088
|
+
logger.info " Session ID: #{@_session.session_id}" if @_session and @_session.respond_to?(:session_id)
|
1089
|
+
logger.info " Parameters: #{respond_to?(:filter_parameters) ? filter_parameters(params).inspect : params.inspect}"
|
936
1090
|
end
|
937
1091
|
end
|
938
|
-
|
1092
|
+
|
939
1093
|
def perform_action
|
940
|
-
if self.class.action_methods.include?(action_name)
|
1094
|
+
if self.class.action_methods.include?(action_name)
|
941
1095
|
send(action_name)
|
942
1096
|
render unless performed?
|
1097
|
+
elsif respond_to? :method_missing
|
1098
|
+
send(:method_missing, action_name)
|
1099
|
+
render unless performed?
|
943
1100
|
elsif template_exists? && template_public?
|
944
1101
|
render
|
945
1102
|
else
|
946
1103
|
raise UnknownAction, "No action responded to #{action_name}", caller
|
947
1104
|
end
|
948
1105
|
end
|
949
|
-
|
1106
|
+
|
950
1107
|
def performed?
|
951
1108
|
@performed_render || @performed_redirect
|
952
1109
|
end
|
@@ -954,7 +1111,16 @@ module ActionController #:nodoc:
|
|
954
1111
|
def assign_names
|
955
1112
|
@action_name = (params['action'] || 'index')
|
956
1113
|
end
|
957
|
-
|
1114
|
+
|
1115
|
+
def assign_default_content_type_and_charset
|
1116
|
+
response.content_type ||= Mime::HTML
|
1117
|
+
response.charset ||= self.class.default_charset unless sending_file?
|
1118
|
+
end
|
1119
|
+
|
1120
|
+
def sending_file?
|
1121
|
+
response.headers["Content-Transfer-Encoding"] == "binary"
|
1122
|
+
end
|
1123
|
+
|
958
1124
|
def action_methods
|
959
1125
|
self.class.action_methods
|
960
1126
|
end
|
@@ -970,17 +1136,17 @@ module ActionController #:nodoc:
|
|
970
1136
|
@variables_added = true
|
971
1137
|
end
|
972
1138
|
end
|
973
|
-
|
1139
|
+
|
974
1140
|
def forget_variables_added_to_assigns
|
975
1141
|
@variables_added = nil
|
976
1142
|
end
|
977
|
-
|
1143
|
+
|
978
1144
|
def reset_variables_added_to_assigns
|
979
1145
|
@template.instance_variable_set("@assigns_added", nil)
|
980
1146
|
end
|
981
1147
|
|
982
1148
|
def add_instance_variables_to_assigns
|
983
|
-
@@protected_variables_cache ||=
|
1149
|
+
@@protected_variables_cache ||= Set.new(protected_instance_variables)
|
984
1150
|
instance_variables.each do |var|
|
985
1151
|
next if @@protected_variables_cache.include?(var)
|
986
1152
|
@assigns[var[1..-1]] = instance_variable_get(var)
|
@@ -988,33 +1154,36 @@ module ActionController #:nodoc:
|
|
988
1154
|
end
|
989
1155
|
|
990
1156
|
def add_class_variables_to_assigns
|
991
|
-
%w(
|
1157
|
+
%w(template_root logger template_class ignore_missing_templates).each do |cvar|
|
992
1158
|
@assigns[cvar] = self.send(cvar)
|
993
1159
|
end
|
994
1160
|
end
|
995
1161
|
|
996
1162
|
def protected_instance_variables
|
997
1163
|
if view_controller_internals
|
998
|
-
|
1164
|
+
%w(@assigns @performed_redirect @performed_render)
|
999
1165
|
else
|
1000
|
-
|
1166
|
+
%w(@assigns @performed_redirect @performed_render
|
1167
|
+
@_request @request @_response @response @_params @params
|
1168
|
+
@_session @session @_cookies @cookies
|
1169
|
+
@template @request_origin @parent_controller)
|
1001
1170
|
end
|
1002
1171
|
end
|
1003
1172
|
|
1004
1173
|
def request_origin
|
1005
1174
|
# this *needs* to be cached!
|
1006
1175
|
# otherwise you'd get different results if calling it more than once
|
1007
|
-
@request_origin ||= "#{
|
1176
|
+
@request_origin ||= "#{request.remote_ip} at #{Time.now.to_s(:db)}"
|
1008
1177
|
end
|
1009
|
-
|
1178
|
+
|
1010
1179
|
def complete_request_uri
|
1011
|
-
"#{
|
1180
|
+
"#{request.protocol}#{request.host}#{request.request_uri}"
|
1012
1181
|
end
|
1013
1182
|
|
1014
1183
|
def close_session
|
1015
|
-
@
|
1184
|
+
@_session.close if @_session && @_session.respond_to?(:close)
|
1016
1185
|
end
|
1017
|
-
|
1186
|
+
|
1018
1187
|
def template_exists?(template_name = default_template_name)
|
1019
1188
|
@template.file_exists?(template_name)
|
1020
1189
|
end
|
@@ -1024,7 +1193,9 @@ module ActionController #:nodoc:
|
|
1024
1193
|
end
|
1025
1194
|
|
1026
1195
|
def template_exempt_from_layout?(template_name = default_template_name)
|
1027
|
-
|
1196
|
+
extension = @template.pick_template_extension(template_name) rescue nil
|
1197
|
+
name_with_extension = !template_name.include?('.') && extension ? "#{template_name}.#{extension}" : template_name
|
1198
|
+
extension == :rjs || @@exempt_from_layout.any? { |ext| name_with_extension =~ ext }
|
1028
1199
|
end
|
1029
1200
|
|
1030
1201
|
def assert_existence_of_template_file(template_name)
|
@@ -1044,11 +1215,11 @@ module ActionController #:nodoc:
|
|
1044
1215
|
end
|
1045
1216
|
"#{self.class.controller_path}/#{action_name}"
|
1046
1217
|
end
|
1047
|
-
|
1218
|
+
|
1048
1219
|
def strip_out_controller(path)
|
1049
1220
|
path.split('/', 2).last
|
1050
1221
|
end
|
1051
|
-
|
1222
|
+
|
1052
1223
|
def template_path_includes_controller?(path)
|
1053
1224
|
self.class.controller_path.split('/')[-1] == path.split('/')[0]
|
1054
1225
|
end
|