actionpack 3.0.0.rc2 → 3.0.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 +4 -18
- data/lib/abstract_controller.rb +1 -0
- data/lib/abstract_controller/base.rb +15 -13
- data/lib/abstract_controller/callbacks.rb +22 -23
- data/lib/abstract_controller/helpers.rb +24 -7
- data/lib/abstract_controller/layouts.rb +12 -10
- data/lib/abstract_controller/view_paths.rb +7 -7
- data/lib/action_controller/base.rb +164 -1
- data/lib/action_controller/test_case.rb +1 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +1 -1
- data/lib/action_dispatch/http/parameters.rb +2 -2
- data/lib/action_dispatch/http/url.rb +2 -2
- data/lib/action_dispatch/middleware/cookies.rb +11 -2
- data/lib/action_dispatch/middleware/flash.rb +7 -2
- data/lib/action_dispatch/routing/mapper.rb +87 -117
- data/lib/action_dispatch/routing/polymorphic_routes.rb +10 -10
- data/lib/action_dispatch/testing/assertions/dom.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +5 -5
- data/lib/action_dispatch/testing/assertions/routing.rb +2 -2
- data/lib/action_pack/version.rb +1 -2
- data/lib/action_view/helpers/capture_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +13 -17
- data/lib/action_view/helpers/form_helper.rb +12 -7
- data/lib/action_view/helpers/url_helper.rb +2 -2
- data/lib/action_view/template.rb +3 -3
- metadata +12 -17
data/CHANGELOG
CHANGED
@@ -1,14 +1,13 @@
|
|
1
|
-
*Rails 3.0.0
|
1
|
+
*Rails 3.0.0 (August 29, 2010)*
|
2
2
|
|
3
|
-
*
|
3
|
+
* Symbols and strings in routes should yield the same behavior. Note this may break existing apps that were using symbols with the new routes API [José Valim]
|
4
|
+
|
5
|
+
* Add clear_helpers as a way to clean up all helpers added to this controller, maintaing just the helper with the same name as the controller. [José Valim]
|
4
6
|
|
5
7
|
* Support routing constraints in functional tests. [Andrew White]
|
6
8
|
|
7
9
|
* Add a header that tells Internet Explorer (all versions) to use the best available standards support. [Yehuda Katz]
|
8
10
|
|
9
|
-
|
10
|
-
*Rails 3.0.0 [release candidate] (July 26th, 2010)*
|
11
|
-
|
12
11
|
* Allow stylesheet/javascript extensions to be changed through railties. [Josh Kalderimis]
|
13
12
|
|
14
13
|
* link_to, button_to, and tag/tag_options now rely on html_escape instead of escape_once. [fxn]
|
@@ -42,9 +41,6 @@
|
|
42
41
|
|
43
42
|
* Removed textilize, textilize_without_paragraph and markdown helpers. [Santiago Pastorino]
|
44
43
|
|
45
|
-
|
46
|
-
*Rails 3.0.0 [beta 4] (June 8th, 2010)*
|
47
|
-
|
48
44
|
* Remove middleware laziness [José Valim]
|
49
45
|
|
50
46
|
* Make session stores rely on request.cookie_jar and change set_session semantics to return the cookie value instead of a boolean. [José Valim]
|
@@ -61,9 +57,6 @@
|
|
61
57
|
|
62
58
|
* Changed translate helper so that it doesn’t mark every translation as safe HTML. Only keys with a "_html" suffix and keys named "html" are considered to be safe HTML. All other translations are left untouched. [Craig Davey]
|
63
59
|
|
64
|
-
|
65
|
-
*Rails 3.0.0 [beta 3] (April 13th, 2010)*
|
66
|
-
|
67
60
|
* New option :as added to form_for allows to change the object name. The old <% form_for :client, @post %> becomes <% form_for @post, :as => :client %> [spastorino]
|
68
61
|
|
69
62
|
* Removed verify method in controllers. [JV]
|
@@ -98,9 +91,6 @@
|
|
98
91
|
"HEAD" and #request_method returns "GET" in HEAD requests). This
|
99
92
|
is for compatibility with Rack::Request [YK]
|
100
93
|
|
101
|
-
|
102
|
-
*Rails 3.0.0 [beta 2] (April 1st, 2010)*
|
103
|
-
|
104
94
|
* #concat is now deprecated in favor of using <%= %> helpers [YK]
|
105
95
|
|
106
96
|
* Block helpers now return Strings, so you can use <%= form_for @foo do |f| %>.
|
@@ -129,9 +119,6 @@
|
|
129
119
|
# for just url_for
|
130
120
|
include Rails.application.router.url_for
|
131
121
|
|
132
|
-
|
133
|
-
*Rails 3.0.0 [beta 1] (February 4, 2010)*
|
134
|
-
|
135
122
|
* Fixed that PrototypeHelper#update_page should return html_safe [DHH]
|
136
123
|
|
137
124
|
* Fixed that much of DateHelper wouldn't return html_safe? strings [DHH]
|
@@ -153,7 +140,6 @@
|
|
153
140
|
|
154
141
|
* Added ActionController::Base#notice/= and ActionController::Base#alert/= as a convenience accessors in both the controller and the view for flash[:notice]/= and flash[:alert]/= [DHH]
|
155
142
|
|
156
|
-
|
157
143
|
* Introduce grouped_collection_select helper. #1249 [Dan Codeape, Erik Ostrom]
|
158
144
|
|
159
145
|
* Make sure javascript_include_tag/stylesheet_link_tag does not append ".js" or ".css" onto external urls. #1664 [Matthew Rudy Jacobs]
|
data/lib/abstract_controller.rb
CHANGED
@@ -2,6 +2,7 @@ activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
|
|
2
2
|
$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
|
3
3
|
|
4
4
|
require 'action_pack'
|
5
|
+
require 'active_support/concern'
|
5
6
|
require 'active_support/ruby/shim'
|
6
7
|
require 'active_support/dependencies/autoload'
|
7
8
|
require 'active_support/core_ext/class/attribute'
|
@@ -6,6 +6,10 @@ module AbstractController
|
|
6
6
|
class Error < StandardError; end
|
7
7
|
class ActionNotFound < StandardError; end
|
8
8
|
|
9
|
+
# <tt>AbstractController::Base</tt> is a low-level API. Nobody should be
|
10
|
+
# using it directly, and subclasses (like ActionController::Base) are
|
11
|
+
# expected to provide their own +render+ method, since rendering means
|
12
|
+
# different things depending on the context.
|
9
13
|
class Base
|
10
14
|
attr_internal :response_body
|
11
15
|
attr_internal :action_name
|
@@ -36,13 +40,12 @@ module AbstractController
|
|
36
40
|
controller.public_instance_methods(true)
|
37
41
|
end
|
38
42
|
|
39
|
-
# The list of hidden actions to an empty
|
40
|
-
# empty
|
43
|
+
# The list of hidden actions to an empty array. Defaults to an
|
44
|
+
# empty array. This can be modified by other modules or subclasses
|
41
45
|
# to specify particular actions as hidden.
|
42
46
|
#
|
43
47
|
# ==== Returns
|
44
|
-
#
|
45
|
-
# considered actions.
|
48
|
+
# * <tt>array</tt> - An array of method names that should not be considered actions.
|
46
49
|
def hidden_actions
|
47
50
|
[]
|
48
51
|
end
|
@@ -54,8 +57,7 @@ module AbstractController
|
|
54
57
|
# itself. Finally, #hidden_actions are removed.
|
55
58
|
#
|
56
59
|
# ==== Returns
|
57
|
-
#
|
58
|
-
# actions.
|
60
|
+
# * <tt>array</tt> - A list of all methods that should be considered actions.
|
59
61
|
def action_methods
|
60
62
|
@action_methods ||= begin
|
61
63
|
# All public instance methods of this class, including ancestors
|
@@ -84,7 +86,7 @@ module AbstractController
|
|
84
86
|
# controller_name.
|
85
87
|
#
|
86
88
|
# ==== Returns
|
87
|
-
#
|
89
|
+
# * <tt>string</tt>
|
88
90
|
def controller_path
|
89
91
|
@controller_path ||= name.sub(/Controller$/, '').underscore unless anonymous?
|
90
92
|
end
|
@@ -104,7 +106,7 @@ module AbstractController
|
|
104
106
|
# ActionNotFound error is raised.
|
105
107
|
#
|
106
108
|
# ==== Returns
|
107
|
-
# self
|
109
|
+
# * <tt>self</tt>
|
108
110
|
def process(action, *args)
|
109
111
|
@_action_name = action_name = action.to_s
|
110
112
|
|
@@ -133,10 +135,10 @@ module AbstractController
|
|
133
135
|
# can be considered an action.
|
134
136
|
#
|
135
137
|
# ==== Parameters
|
136
|
-
# name
|
138
|
+
# * <tt>name</tt> - The name of an action to be tested
|
137
139
|
#
|
138
140
|
# ==== Returns
|
139
|
-
# TrueClass
|
141
|
+
# * <tt>TrueClass</tt>, <tt>FalseClass</tt>
|
140
142
|
def action_method?(name)
|
141
143
|
self.class.action_methods.include?(name)
|
142
144
|
end
|
@@ -180,11 +182,11 @@ module AbstractController
|
|
180
182
|
# returns nil, an ActionNotFound exception will be raised.
|
181
183
|
#
|
182
184
|
# ==== Parameters
|
183
|
-
# action_name
|
185
|
+
# * <tt>action_name</tt> - An action name to find a method name for
|
184
186
|
#
|
185
187
|
# ==== Returns
|
186
|
-
#
|
187
|
-
# nil
|
188
|
+
# * <tt>string</tt> - The name of the method that handles the action
|
189
|
+
# * <tt>nil</tt> - No method name could be found. Raise ActionNotFound.
|
188
190
|
def method_for_action(action_name)
|
189
191
|
if action_method?(action_name) then action_name
|
190
192
|
elsif respond_to?(:action_missing, true) then "_handle_action_missing"
|
@@ -28,9 +28,8 @@ module AbstractController
|
|
28
28
|
# a Rails process.
|
29
29
|
#
|
30
30
|
# ==== Options
|
31
|
-
#
|
32
|
-
#
|
33
|
-
# except this action
|
31
|
+
# * <tt>only</tt> - The callback should be run only for this action
|
32
|
+
# * <tt>except<tt> - The callback should be run for all actions except this action
|
34
33
|
def _normalize_callback_options(options)
|
35
34
|
if only = options[:only]
|
36
35
|
only = Array(only).map {|o| "action_name == '#{o}'"}.join(" || ")
|
@@ -45,7 +44,7 @@ module AbstractController
|
|
45
44
|
# Skip before, after, and around filters matching any of the names
|
46
45
|
#
|
47
46
|
# ==== Parameters
|
48
|
-
# *names
|
47
|
+
# * <tt>names</tt> - A list of valid names that could be used for
|
49
48
|
# callbacks. Note that skipping uses Ruby equality, so it's
|
50
49
|
# impossible to skip a callback defined using an anonymous proc
|
51
50
|
# using #skip_filter
|
@@ -60,13 +59,13 @@ module AbstractController
|
|
60
59
|
# the normalization across several methods that use it.
|
61
60
|
#
|
62
61
|
# ==== Parameters
|
63
|
-
#
|
62
|
+
# * <tt>callbacks</tt> - An array of callbacks, with an optional
|
64
63
|
# options hash as the last parameter.
|
65
|
-
# block
|
64
|
+
# * <tt>block</tt> - A proc that should be added to the callbacks.
|
66
65
|
#
|
67
66
|
# ==== Block Parameters
|
68
|
-
# name
|
69
|
-
# options
|
67
|
+
# * <tt>name</tt> - The callback to be added
|
68
|
+
# * <tt>options</tt> - A hash of options to be used when adding the callback
|
70
69
|
def _insert_callbacks(callbacks, block)
|
71
70
|
options = callbacks.last.is_a?(Hash) ? callbacks.pop : {}
|
72
71
|
_normalize_callback_options(options)
|
@@ -82,27 +81,27 @@ module AbstractController
|
|
82
81
|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
83
82
|
# Append a before, after or around filter. See _insert_callbacks
|
84
83
|
# for details on the allowed parameters.
|
85
|
-
def #{filter}_filter(*names, &blk)
|
86
|
-
_insert_callbacks(names, blk) do |name, options|
|
87
|
-
set_callback(:process_action, :#{filter}, name, options)
|
88
|
-
end
|
89
|
-
end
|
84
|
+
def #{filter}_filter(*names, &blk) # def before_filter(*names, &blk)
|
85
|
+
_insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options}
|
86
|
+
set_callback(:process_action, :#{filter}, name, options) # set_callback(:process_action, :before_filter, name, options)
|
87
|
+
end # end
|
88
|
+
end # end
|
90
89
|
|
91
90
|
# Prepend a before, after or around filter. See _insert_callbacks
|
92
91
|
# for details on the allowed parameters.
|
93
|
-
def prepend_#{filter}_filter(*names, &blk)
|
94
|
-
_insert_callbacks(names, blk) do |name, options|
|
95
|
-
set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true))
|
96
|
-
end
|
97
|
-
end
|
92
|
+
def prepend_#{filter}_filter(*names, &blk) # def prepend_before_filter(*names, &blk)
|
93
|
+
_insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
|
94
|
+
set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true))
|
95
|
+
end # end
|
96
|
+
end # end
|
98
97
|
|
99
98
|
# Skip a before, after or around filter. See _insert_callbacks
|
100
99
|
# for details on the allowed parameters.
|
101
|
-
def skip_#{filter}_filter(*names, &blk)
|
102
|
-
_insert_callbacks(names, blk) do |name, options|
|
103
|
-
skip_callback(:process_action, :#{filter}, name, options)
|
104
|
-
end
|
105
|
-
end
|
100
|
+
def skip_#{filter}_filter(*names, &blk) # def skip_before_filter(*names, &blk)
|
101
|
+
_insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
|
102
|
+
skip_callback(:process_action, :#{filter}, name, options) # skip_callback(:process_action, :before, name, options)
|
103
|
+
end # end
|
104
|
+
end # end
|
106
105
|
|
107
106
|
# *_filter is the same as append_*_filter
|
108
107
|
alias_method :append_#{filter}_filter, :#{filter}_filter
|
@@ -9,6 +9,9 @@ module AbstractController
|
|
9
9
|
included do
|
10
10
|
class_attribute :_helpers
|
11
11
|
self._helpers = Module.new
|
12
|
+
|
13
|
+
class_attribute :_helper_methods
|
14
|
+
self._helper_methods = Array.new
|
12
15
|
end
|
13
16
|
|
14
17
|
module ClassMethods
|
@@ -40,10 +43,13 @@ module AbstractController
|
|
40
43
|
# <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
|
41
44
|
#
|
42
45
|
# ==== Parameters
|
43
|
-
#
|
46
|
+
# * <tt>method[, method]</tt> - A name or names of a method on the controller
|
44
47
|
# to be made available on the view.
|
45
48
|
def helper_method(*meths)
|
46
|
-
meths.flatten
|
49
|
+
meths.flatten!
|
50
|
+
self._helper_methods += meths
|
51
|
+
|
52
|
+
meths.each do |meth|
|
47
53
|
_helpers.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
|
48
54
|
def #{meth}(*args, &blk)
|
49
55
|
controller.send(%(#{meth}), *args, &blk)
|
@@ -55,8 +61,8 @@ module AbstractController
|
|
55
61
|
# The +helper+ class method can take a series of helper module names, a block, or both.
|
56
62
|
#
|
57
63
|
# ==== Parameters
|
58
|
-
# *args
|
59
|
-
# block
|
64
|
+
# * <tt>*args</tt> - Module, Symbol, String, :all
|
65
|
+
# * <tt>block</tt> - A block defining helper methods
|
60
66
|
#
|
61
67
|
# ==== Examples
|
62
68
|
# When the argument is a module it will be included directly in the template class.
|
@@ -95,12 +101,23 @@ module AbstractController
|
|
95
101
|
_helpers.module_eval(&block) if block_given?
|
96
102
|
end
|
97
103
|
|
104
|
+
# Clears up all existing helpers in this class, only keeping the helper
|
105
|
+
# with the same name as this class.
|
106
|
+
def clear_helpers
|
107
|
+
inherited_helper_methods = _helper_methods
|
108
|
+
self._helpers = Module.new
|
109
|
+
self._helper_methods = Array.new
|
110
|
+
|
111
|
+
inherited_helper_methods.each { |meth| helper_method meth }
|
112
|
+
default_helper_module! unless anonymous?
|
113
|
+
end
|
114
|
+
|
98
115
|
private
|
99
116
|
# Makes all the (instance) methods in the helper module available to templates
|
100
117
|
# rendered through this controller.
|
101
118
|
#
|
102
119
|
# ==== Parameters
|
103
|
-
#
|
120
|
+
# * <tt>module</tt> - The module to include into the current helper module
|
104
121
|
# for the class
|
105
122
|
def add_template_helper(mod)
|
106
123
|
_helpers.module_eval { include mod }
|
@@ -118,10 +135,10 @@ module AbstractController
|
|
118
135
|
# are returned.
|
119
136
|
#
|
120
137
|
# ==== Parameters
|
121
|
-
# args
|
138
|
+
# * <tt>args</tt> - An array of helpers
|
122
139
|
#
|
123
140
|
# ==== Returns
|
124
|
-
# Array
|
141
|
+
# * <tt>Array</tt> - A normalized list of modules for the list of
|
125
142
|
# helpers provided.
|
126
143
|
def modules_for_helpers(args)
|
127
144
|
args.flatten.map! do |arg|
|
@@ -114,11 +114,13 @@ module AbstractController
|
|
114
114
|
#
|
115
115
|
# class WeblogController < ActionController::Base
|
116
116
|
# layout proc{ |controller| controller.logged_in? ? "writer_layout" : "reader_layout" }
|
117
|
+
# end
|
117
118
|
#
|
118
119
|
# Of course, the most common way of specifying a layout is still just as a plain template name:
|
119
120
|
#
|
120
121
|
# class WeblogController < ActionController::Base
|
121
122
|
# layout "weblog_standard"
|
123
|
+
# end
|
122
124
|
#
|
123
125
|
# If no directory is specified for the template name, the template will by default be looked for in <tt>app/views/layouts/</tt>.
|
124
126
|
# Otherwise, it will be looked up relative to the template root.
|
@@ -183,7 +185,7 @@ module AbstractController
|
|
183
185
|
# layout.
|
184
186
|
#
|
185
187
|
# ==== Returns
|
186
|
-
# Boolean
|
188
|
+
# * <tt> Boolean</tt> - True if the action has a layout, false otherwise.
|
187
189
|
def action_has_layout?
|
188
190
|
return unless super
|
189
191
|
|
@@ -209,11 +211,11 @@ module AbstractController
|
|
209
211
|
# true:: raise an ArgumentError
|
210
212
|
#
|
211
213
|
# ==== Parameters
|
212
|
-
#
|
214
|
+
# * <tt>String, Symbol, false</tt> - The layout to use.
|
213
215
|
#
|
214
216
|
# ==== Options (conditions)
|
215
|
-
# :only
|
216
|
-
# :except
|
217
|
+
# * :only - A list of actions to apply this layout to.
|
218
|
+
# * :except - Apply this layout to all actions but this one.
|
217
219
|
def layout(layout, conditions = {})
|
218
220
|
include LayoutConditions unless conditions.empty?
|
219
221
|
|
@@ -228,7 +230,7 @@ module AbstractController
|
|
228
230
|
# value of this method.
|
229
231
|
#
|
230
232
|
# ==== Returns
|
231
|
-
# String
|
233
|
+
# * <tt>String</tt> - A template name
|
232
234
|
def _implied_layout_name
|
233
235
|
controller_path
|
234
236
|
end
|
@@ -313,8 +315,8 @@ module AbstractController
|
|
313
315
|
# the name type.
|
314
316
|
#
|
315
317
|
# ==== Parameters
|
316
|
-
# name
|
317
|
-
# details
|
318
|
+
# * <tt>name</tt> - The name of the template
|
319
|
+
# * <tt>details</tt> - A list of details to restrict
|
318
320
|
# the lookup to. By default, layout lookup is limited to the
|
319
321
|
# formats specified for the current request.
|
320
322
|
def _layout_for_option(name)
|
@@ -333,14 +335,14 @@ module AbstractController
|
|
333
335
|
# Optionally raises an exception if the layout could not be found.
|
334
336
|
#
|
335
337
|
# ==== Parameters
|
336
|
-
# details
|
338
|
+
# * <tt>details</tt> - A list of details to restrict the search by. This
|
337
339
|
# might include details like the format or locale of the template.
|
338
|
-
#
|
340
|
+
# * <tt>require_logout</tt> - If this is true, raise an ArgumentError
|
339
341
|
# with details about the fact that the exception could not be
|
340
342
|
# found (defaults to false)
|
341
343
|
#
|
342
344
|
# ==== Returns
|
343
|
-
#
|
345
|
+
# * <tt>template</tt> - The template object for the default layout (or nil)
|
344
346
|
def _default_layout(require_layout = false)
|
345
347
|
begin
|
346
348
|
layout_name = _layout if action_has_layout?
|
@@ -34,9 +34,9 @@ module AbstractController
|
|
34
34
|
# Append a path to the list of view paths for this controller.
|
35
35
|
#
|
36
36
|
# ==== Parameters
|
37
|
-
# path
|
38
|
-
#
|
39
|
-
#
|
37
|
+
# * <tt>path</tt> - If a String is provided, it gets converted into
|
38
|
+
# the default view path. You may also provide a custom view path
|
39
|
+
# (see ActionView::ViewPathSet for more information)
|
40
40
|
def append_view_path(path)
|
41
41
|
self.view_paths = view_paths.dup + Array(path)
|
42
42
|
end
|
@@ -44,9 +44,9 @@ module AbstractController
|
|
44
44
|
# Prepend a path to the list of view paths for this controller.
|
45
45
|
#
|
46
46
|
# ==== Parameters
|
47
|
-
# path
|
48
|
-
#
|
49
|
-
#
|
47
|
+
# * <tt>path</tt> - If a String is provided, it gets converted into
|
48
|
+
# the default view path. You may also provide a custom view path
|
49
|
+
# (see ActionView::ViewPathSet for more information)
|
50
50
|
def prepend_view_path(path)
|
51
51
|
self.view_paths = Array(path) + view_paths.dup
|
52
52
|
end
|
@@ -59,7 +59,7 @@ module AbstractController
|
|
59
59
|
# Set the view paths.
|
60
60
|
#
|
61
61
|
# ==== Parameters
|
62
|
-
# paths
|
62
|
+
# * <tt>paths</tt> - If a ViewPathSet is provided, use that;
|
63
63
|
# otherwise, process the parameter into a ViewPathSet.
|
64
64
|
def view_paths=(paths)
|
65
65
|
self._view_paths = ActionView::Base.process_view_paths(paths)
|
@@ -1,6 +1,169 @@
|
|
1
1
|
require "action_controller/log_subscriber"
|
2
2
|
|
3
3
|
module ActionController
|
4
|
+
# Action Controllers are the core of a web request in \Rails. They are made up of one or more actions that are executed
|
5
|
+
# on request and then either render a template or redirect to another action. An action is defined as a public method
|
6
|
+
# on the controller, which will automatically be made accessible to the web-server through \Rails Routes.
|
7
|
+
#
|
8
|
+
# By default, only the ApplicationController in a \Rails application inherits from <tt>ActionController::Base</tt>. All other
|
9
|
+
# controllers in turn inherit from ApplicationController. This gives you one class to configure things such as
|
10
|
+
# request forgery protection and filtering of sensitive request parameters.
|
11
|
+
#
|
12
|
+
# A sample controller could look like this:
|
13
|
+
#
|
14
|
+
# class PostsController < ApplicationController
|
15
|
+
# def index
|
16
|
+
# @posts = Post.all
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# def create
|
20
|
+
# @post = Post.create params[:post]
|
21
|
+
# redirect_to posts_path
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# Actions, by default, render a template in the <tt>app/views</tt> directory corresponding to the name of the controller and action
|
26
|
+
# after executing code in the action. For example, the +index+ action of the PostsController would render the
|
27
|
+
# template <tt>app/views/posts/index.erb</tt> by default after populating the <tt>@posts</tt> instance variable.
|
28
|
+
#
|
29
|
+
# Unlike index, the create action will not render a template. After performing its main purpose (creating a
|
30
|
+
# new post), it initiates a redirect instead. This redirect works by returning an external
|
31
|
+
# "302 Moved" HTTP response that takes the user to the index action.
|
32
|
+
#
|
33
|
+
# These two methods represent the two basic action archetypes used in Action Controllers. Get-and-show and do-and-redirect.
|
34
|
+
# Most actions are variations of these themes.
|
35
|
+
#
|
36
|
+
# == Requests
|
37
|
+
#
|
38
|
+
# For every request, the router determines the value of the +controller+ and +action+ keys. These determine which controller
|
39
|
+
# and action are called. The remaining request parameters, the session (if one is available), and the full request with
|
40
|
+
# all the HTTP headers are made available to the action through accessor methods. Then the action is performed.
|
41
|
+
#
|
42
|
+
# The full request object is available via the request accessor and is primarily used to query for HTTP headers:
|
43
|
+
#
|
44
|
+
# def server_ip
|
45
|
+
# location = request.env["SERVER_ADDR"]
|
46
|
+
# render :text => "This server hosted at #{location}"
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# == Parameters
|
50
|
+
#
|
51
|
+
# All request parameters, whether they come from a GET or POST request, or from the URL, are available through the params method
|
52
|
+
# which returns a hash. For example, an action that was performed through <tt>/posts?category=All&limit=5</tt> will include
|
53
|
+
# <tt>{ "category" => "All", "limit" => 5 }</tt> in params.
|
54
|
+
#
|
55
|
+
# It's also possible to construct multi-dimensional parameter hashes by specifying keys using brackets, such as:
|
56
|
+
#
|
57
|
+
# <input type="text" name="post[name]" value="david">
|
58
|
+
# <input type="text" name="post[address]" value="hyacintvej">
|
59
|
+
#
|
60
|
+
# A request stemming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>.
|
61
|
+
# If the address input had been named "post[address][street]", the params would have included
|
62
|
+
# <tt>{ "post" => { "address" => { "street" => "hyacintvej" } } }</tt>. There's no limit to the depth of the nesting.
|
63
|
+
#
|
64
|
+
# == Sessions
|
65
|
+
#
|
66
|
+
# Sessions allows you to store objects in between requests. This is useful for objects that are not yet ready to be persisted,
|
67
|
+
# 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
|
68
|
+
# 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
|
69
|
+
# they could be changed unknowingly. It's usually too much work to keep it all synchronized -- something databases already excel at.
|
70
|
+
#
|
71
|
+
# You can place objects in the session by using the <tt>session</tt> method, which accesses a hash:
|
72
|
+
#
|
73
|
+
# session[:person] = Person.authenticate(user_name, password)
|
74
|
+
#
|
75
|
+
# And retrieved again through the same hash:
|
76
|
+
#
|
77
|
+
# Hello #{session[:person]}
|
78
|
+
#
|
79
|
+
# For removing objects from the session, you can either assign a single key to +nil+:
|
80
|
+
#
|
81
|
+
# # removes :person from session
|
82
|
+
# session[:person] = nil
|
83
|
+
#
|
84
|
+
# or you can remove the entire session with +reset_session+.
|
85
|
+
#
|
86
|
+
# Sessions are stored by default in a browser cookie that's cryptographically signed, but unencrypted.
|
87
|
+
# This prevents the user from tampering with the session but also allows him to see its contents.
|
88
|
+
#
|
89
|
+
# Do not put secret information in cookie-based sessions!
|
90
|
+
#
|
91
|
+
# Other options for session storage:
|
92
|
+
#
|
93
|
+
# * ActiveRecord::SessionStore - Sessions are stored in your database, which works better than PStore with multiple app servers and,
|
94
|
+
# unlike CookieStore, hides your session contents from the user. To use ActiveRecord::SessionStore, set
|
95
|
+
#
|
96
|
+
# config.action_controller.session_store = :active_record_store
|
97
|
+
#
|
98
|
+
# in your <tt>config/environment.rb</tt> and run <tt>rake db:sessions:create</tt>.
|
99
|
+
#
|
100
|
+
# == Responses
|
101
|
+
#
|
102
|
+
# Each action results in a response, which holds the headers and document to be sent to the user's browser. The actual response
|
103
|
+
# object is generated automatically through the use of renders and redirects and requires no user intervention.
|
104
|
+
#
|
105
|
+
# == Renders
|
106
|
+
#
|
107
|
+
# Action Controller sends content to the user by using one of five rendering methods. The most versatile and common is the rendering
|
108
|
+
# of a template. Included in the Action Pack is the Action View, which enables rendering of ERb templates. It's automatically configured.
|
109
|
+
# The controller passes objects to the view by assigning instance variables:
|
110
|
+
#
|
111
|
+
# def show
|
112
|
+
# @post = Post.find(params[:id])
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
# Which are then automatically available to the view:
|
116
|
+
#
|
117
|
+
# Title: <%= @post.title %>
|
118
|
+
#
|
119
|
+
# You don't have to rely on the automated rendering. Especially actions that could result in the rendering of different templates will use
|
120
|
+
# the manual rendering methods:
|
121
|
+
#
|
122
|
+
# def search
|
123
|
+
# @results = Search.find(params[:query])
|
124
|
+
# case @results
|
125
|
+
# when 0 then render :action => "no_results"
|
126
|
+
# when 1 then render :action => "show"
|
127
|
+
# when 2..10 then render :action => "show_many"
|
128
|
+
# end
|
129
|
+
# end
|
130
|
+
#
|
131
|
+
# Read more about writing ERb and Builder templates in ActionView::Base.
|
132
|
+
#
|
133
|
+
# == Redirects
|
134
|
+
#
|
135
|
+
# Redirects are used to move from one action to another. For example, after a <tt>create</tt> action, which stores a blog entry to a database,
|
136
|
+
# we might like to show the user the new entry. Because we're following good DRY principles (Don't Repeat Yourself), we're going to reuse (and redirect to)
|
137
|
+
# a <tt>show</tt> action that we'll assume has already been created. The code might look like this:
|
138
|
+
#
|
139
|
+
# def create
|
140
|
+
# @entry = Entry.new(params[:entry])
|
141
|
+
# if @entry.save
|
142
|
+
# # The entry was saved correctly, redirect to show
|
143
|
+
# redirect_to :action => 'show', :id => @entry.id
|
144
|
+
# else
|
145
|
+
# # things didn't go so well, do something else
|
146
|
+
# end
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# In this case, after saving our new entry to the database, the user is redirected to the <tt>show</tt> method which is then executed.
|
150
|
+
#
|
151
|
+
# == Calling multiple redirects or renders
|
152
|
+
#
|
153
|
+
# An action may contain only a single render or a single redirect. Attempting to try to do either again will result in a DoubleRenderError:
|
154
|
+
#
|
155
|
+
# def do_something
|
156
|
+
# redirect_to :action => "elsewhere"
|
157
|
+
# render :action => "overthere" # raises DoubleRenderError
|
158
|
+
# end
|
159
|
+
#
|
160
|
+
# If you need to redirect on the condition of something, then be sure to add "and return" to halt execution.
|
161
|
+
#
|
162
|
+
# def do_something
|
163
|
+
# redirect_to(:action => "elsewhere") and return if monkeys.nil?
|
164
|
+
# render :action => "overthere" # won't be called if monkeys is nil
|
165
|
+
# end
|
166
|
+
#
|
4
167
|
class Base < Metal
|
5
168
|
abstract!
|
6
169
|
|
@@ -60,7 +223,7 @@ module ActionController
|
|
60
223
|
|
61
224
|
def self.inherited(klass)
|
62
225
|
super
|
63
|
-
klass.helper :all
|
226
|
+
klass.helper :all if klass.superclass == ActionController::Base
|
64
227
|
end
|
65
228
|
|
66
229
|
require "action_controller/deprecated/base"
|