Changeset 780
- Timestamp:
- 02/24/05 01:29:43 (4 years ago)
- Files:
-
- trunk/actionpack/lib/action_controller/base.rb (modified) (7 diffs)
- trunk/actionpack/lib/action_controller/components.rb (modified) (2 diffs)
- trunk/actionpack/lib/action_controller/dependencies.rb (modified) (1 diff)
- trunk/actionpack/lib/action_controller/helpers.rb (modified) (1 diff)
- trunk/actionpack/lib/action_controller/routing.rb (modified) (2 diffs)
- trunk/actionpack/README (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/actionpack/lib/action_controller/base.rb
r766 r780 15 15 class MissingTemplate < ActionControllerError #:nodoc: 16 16 end 17 class RoutingError < ActionControllerError 17 class RoutingError < ActionControllerError#:nodoc: 18 18 attr_reader :failures 19 19 def initialize(message, failures=[]) … … 87 87 # <input type="text" name="post[address]" value="hyacintvej"> 88 88 # 89 # A request stemming from a form holding these inputs will include { "post" # => { "name" => "david", "address" => "hyacintvej" } }.89 # A request stemming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>. 90 90 # If the address input had been named "post[address][street]", the @params would have included 91 # { "post" => { "address" => { "street" => "hyacintvej" } } }. There's no limit to the depth of the nesting.91 # <tt>{ "post" => { "address" => { "street" => "hyacintvej" } } }</tt>. There's no limit to the depth of the nesting. 92 92 # 93 93 # == Sessions … … 157 157 # Redirects work by rewriting the URL of the current action. So if the show action was called by "/library/books/ISBN/0743536703/show", 158 158 # we can redirect to an edit action simply by doing <tt>redirect_to(:action => "edit")</tt>, which could throw the user to 159 # "/library/books/ISBN/0743536703/edit". Naturally, you'll need to setup the .htaccess (or other means of URL rewriting for the web server)160 # to point to the proper controllerand action in the first place, but once you have, it can be rewritten with ease.159 # "/library/books/ISBN/0743536703/edit". Naturally, you'll need to setup the routes configuration file to point to the proper controller 160 # and action in the first place, but once you have, it can be rewritten with ease. 161 161 # 162 # Let's consider a bunch of examples on how to go from "/library/books/ISBN/0743536703/edit" to somewhere else: 163 # 164 # redirect_to(:action => "show", :action_prefix => "XTC/123") => 165 # "http://www.singlefile.com/library/books/XTC/123/show" 166 # 167 # redirect_to(:path_params => {"type" => "EXBC"}) => 168 # "http://www.singlefile.com/library/books/EXBC/0743536703/show" 169 # 170 # redirect_to(:controller => "settings") => 171 # "http://www.singlefile.com/library/settings/" 172 # 173 # For more examples of redirecting options, have a look at the unit test in test/controller/url_test.rb. It's very readable and will give 174 # you an excellent understanding of the different options and what they do. 162 # Let's consider a bunch of examples on how to go from "/clients/37signals/basecamp/project/dash" to somewhere else: 163 # 164 # redirect_to(:action => "edit") => 165 # /clients/37signals/basecamp/project/dash 166 # 167 # redirect_to(:client_name => "nextangle", :project_name => "rails") => 168 # /clients/nextangle/rails/project/dash 169 # 170 # Those redirects happen under the configuration of: 171 # 172 # map.connect 'clients/:client_name/:project_name/:controller/:action' 175 173 # 176 174 # == Calling multiple redirects or renders … … 338 336 # <tt>url_for :controller => 'posts', :action => 'show', :id => 10, :anchor => 'comments'</tt> 339 337 # will produce "/posts/show/10#comments". 340 # * <tt>:only -path</tt> -- if true, returns the absolute URL (omitting the protocol, host name, and port)338 # * <tt>:only_path</tt> -- if true, returns the absolute URL (omitting the protocol, host name, and port) 341 339 # * <tt>:host</tt> -- overrides the default (current) host if provided 342 340 # * <tt>:protocol</tt> -- overrides the default (current) protocol if provided 343 # 341 # 344 342 # The URL is generated from the remaining keys in the hash. A URL contains two key parts: the <base> and a query string. 345 343 # Routes composes a query string as the key/value pairs not included in the <base>. 346 # 344 # 347 345 # The default Routes setup supports a typical Rails path of "controller/action/id" where action and id are optional, with 348 346 # action defaulting to 'index' when not given. Here are some typical url_for statements and their corresponding URLs: … … 351 349 # url_for :controller => 'posts', :action => 'index' # => 'proto://host.com/posts' 352 350 # url_for :controller => 'posts', :action => 'show', :id => 10 # => 'proto://host.com/posts/show/10' 353 # 351 # 354 352 # When generating a new URL, missing values may be filled in from the current request's parameters. For example, 355 353 # <tt>url_for :action => 'some_action'</tt> will retain the current controller, as expected. This behavior extends to … … 360 358 # missing values in the current request's parameters. Routes attempts to guess when a value should and should not be 361 359 # taken from the defaults. There are a few simple rules on how this is performed: 362 # 360 # 363 361 # * If the controller name begins with a slash, no defaults are used: <tt>url_for :controller => '/home'</tt> 364 362 # * If the controller changes, the action will default to index unless provided 365 # 363 # 366 364 # The final rule is applied while the URL is being generated and is best illustrated by an example. Let us consider the 367 365 # route given by <tt>map.connect 'people/:last/:first/:action', :action => 'bio', :controller => 'people'</tt>. 368 # 366 # 369 367 # Suppose that the current URL is "people/hh/david/contacts". Let's consider a few different cases URLs which are generated 370 368 # from this page. 371 # 369 # 372 370 # * <tt>url_for :action => 'bio'</tt> -- During the generation of this URL, default values will be used for the first and 373 371 # last components, and the action shall change. The generated URL will be, "people/david/hh/bio". 374 372 # * <tt>url_for :first => 'davids-little-brother'</tt> This generates the URL 'people/hh/davids-little-brother' -- note 375 373 # that this URL leaves out the assumed action of 'bio'. 376 # 374 # 377 375 # However, you might ask why the action from the current request, 'contacts', isn't carried over into the new URL. The 378 376 # answer has to do with the order in which the parameters appear in the generated path. In a nutshell, since the … … 473 471 # Renders an empty response that can be used when the request is only interested in triggering an effect. Do note that good 474 472 # HTTP manners mandate that you don't use GET requests to trigger data changes. 475 def render_nothing(status = nil) 473 def render_nothing(status = nil) #:doc: 476 474 render_text "", status 477 475 end 478 476 479 477 # Returns the result of the render as a string. 480 def render_to_string(template_name = default_template_name) 478 def render_to_string(template_name = default_template_name) #:doc: 481 479 add_variables_to_assigns 482 480 @template.render_file(template_name) trunk/actionpack/lib/action_controller/components.rb
r769 r780 1 1 module ActionController #:nodoc: 2 # TODO: Cookies and session variables set in render_component that happens inside a view should be copied over. 3 module Components #:nodoc: 4 def self.append_features(base) 2 # Components allows you to call other actions for their rendered response while execution another action. You can either delegate 3 # the entire response rendering or you can mix a partial response in with your other content. 4 # 5 # class WeblogController < ActionController::Base 6 # # Performs a method and then lets hello_world output its render 7 # def delegate_action 8 # do_other_stuff_before_hello_world 9 # render_component :controller => "greeter", :action => "hello_world" 10 # end 11 # end 12 # 13 # class GreeterController < ActionController::Base 14 # def hello_world 15 # render_text "Hello World!" 16 # end 17 # end 18 # 19 # The same can be done in a view to do a partial rendering: 20 # 21 # Let's see a greeting: 22 # <%= render_component :controller => "greeter", :action => "hello_world" %> 23 module Components 24 def self.append_features(base) #:nodoc: 5 25 super 6 26 base.helper do … … 12 32 13 33 protected 34 # Renders the component specified as the response for the current method 14 35 def render_component(options = {}) #:doc: 15 36 component_logging(options) { render_text(component_response(options).body, response.headers["Status"]) } 16 37 end 17 38 39 # Returns the component response as a string 18 40 def render_component_as_string(options) #:doc: 19 41 component_logging(options) { component_response(options, false).body } trunk/actionpack/lib/action_controller/dependencies.rb
r713 r780 27 27 # # helper :post (already required) 28 28 # end 29 # 30 # Also note, that if the models follow the pattern of just 1 class per file in the form of MyClass => my_class.rb, then these 31 # classes doesn't have to be required as Active Support will auto-require them. 29 32 module ClassMethods 30 33 # Specifies a variable number of models that this controller depends on. Models are normally Active Record classes or a similar trunk/actionpack/lib/action_controller/helpers.rb
r617 r780 36 36 end 37 37 38 # Declare a helper. If you use this method in your controller, you don't 39 # have to do the +self.append_features+ incantation in your helper class. 38 # Declare a helper: 40 39 # helper :foo 41 40 # requires 'foo_helper' and includes FooHelper in the template class. trunk/actionpack/lib/action_controller/routing.rb
r728 r780 3 3 ROUTE_FILE = defined?(RAILS_ROOT) ? File.expand_path(File.join(RAILS_ROOT, 'config', 'routes')) : nil 4 4 5 class Route 5 class Route #:nodoc: 6 6 attr_reader :defaults # The defaults hash 7 7 … … 186 186 end 187 187 188 class RouteSet 188 class RouteSet#:nodoc: 189 189 def initialize 190 190 @routes = [] trunk/actionpack/README
r438 r780 51 51 end 52 52 53 Learn more in link:classes/ActionController/Base.html53 {Learn more}[link:classes/ActionController/Base.html] 54 54 55 55 … … 66 66 <% end %> 67 67 68 Learn more in link:classes/ActionView.html68 {Learn more}[link:classes/ActionView.html] 69 69 70 70 71 71 * Builder-based templates (great for XML content, like RSS) 72 72 73 xml.rss("version" => "2.0") do 74 xml.channel do 75 xml.title(@feed_title) 76 xml.link(@url) 77 xml.description "Basecamp: Recent items" 78 xml.language "en-us" 79 xml.ttl "40" 80 81 for item in @recent_items 82 xml.item do 83 xml.title(item_title(item)) 84 xml.description(item_description(item)) 85 xml.pubDate(item_pubDate(item)) 86 xml.guid(@recent_items.url(item)) 87 xml.link(@recent_items.url(item)) 73 xml.rss("version" => "2.0") do 74 xml.channel do 75 xml.title(@feed_title) 76 xml.link(@url) 77 xml.description "Basecamp: Recent items" 78 xml.language "en-us" 79 xml.ttl "40" 80 81 for item in @recent_items 82 xml.item do 83 xml.title(item_title(item)) 84 xml.description(item_description(item)) 85 xml.pubDate(item_pubDate(item)) 86 xml.guid(@recent_items.url(item)) 87 xml.link(@recent_items.url(item)) 88 end 88 89 end 89 90 end 90 91 end 91 end 92 93 {Learn more}[link:classes/ActionView/Base.html] 92 94 93 95 … … 114 116 end 115 117 116 Learn more in link:classes/ActionController/Filters/ClassMethods.html118 {Learn more}[link:classes/ActionController/Filters/ClassMethods.html] 117 119 118 120 … … 124 126 <%= truncate(post.title, 25) %> 125 127 126 Learn more in link:classes/ActionView/Helpers.html128 {Learn more}[link:classes/ActionView/Helpers.html] 127 129 128 130 … … 146 148 <html><body><h1>Hello world</h1></body></html> 147 149 148 Learn more in link:classes/ActionController/Layout/ClassMethods.html149 150 151 * Advanced redirection that makes pretty urlseasy152 153 RewriteRule ^/library/books/([A-Z]+)([0-9]+)/([-_a-zA-Z0-9]+)$ \154 /books_controller.cgi?action=$3&type=$1&code=$2 [QSA] [L] 155 156 Accessing /library/books/ISBN/0743536703/show calls BooksController#show150 {Learn more}[link:classes/ActionController/Layout/ClassMethods.html] 151 152 153 * Routing makes pretty urls incredibly easy 154 155 map.connect 'clients/:client_name/:project_name/:controller/:action' 156 157 Accessing /clients/37signals/basecamp/project/dash calls ProjectController#dash with 158 { "client_name" => "37signals", "project_name" => "basecamp" } in @params["params"] 157 159 158 160 From that URL, you can rewrite the redirect in a number of ways: 159 161 160 162 redirect_to(:action => "edit") => 161 /library/books/ISBN/0743536703/edit 162 163 redirect_to(:path_params => { "type" => "XTC", "code" => "12354345" }) => 164 /library/books/XTC/12354345/show 165 166 redirect_to(:controller_prefix => "admin", :controller => "accounts") => 167 /admin/accounts/ 168 169 Learn more in link:classes/ActionController/Base.html 163 /clients/37signals/basecamp/project/dash 164 165 redirect_to(:client_name => "nextangle", :project_name => "rails") => 166 /clients/nextangle/rails/project/dash 167 168 {Learn more}[link:classes/ActionController/Base.html] 170 169 171 170 … … 186 185 end 187 186 188 Learn more in link:classes/ActionController/TestRequest.html187 {Learn more}[link:classes/ActionController/TestRequest.html] 189 188 190 189 … … 212 211 213 212 213 * Caching at three levels of granularity (page, action, fragment) 214 215 class WeblogController < ActionController::Base 216 caches_page :show 217 caches_action :account 218 219 def show 220 # the output of the method will be cached as 221 # ActionController::Base.page_cache_directory + "/weblog/show/n.html" 222 # and the web server will pick it up without even hitting Rails 223 end 224 225 def account 226 # the output of the method will be cached in the fragment store 227 # but Rails is hit to retrieve it, so filters are run 228 end 229 230 def update 231 List.update(@params["list"]["id"], @params["list"]) 232 expire_page :action => "show", :id => @params["list"]["id"] 233 expire_action :action => "account" 234 redirect_to :action => "show", :id => @params["list"]["id"] 235 end 236 end 237 238 {Learn more}[link:classes/ActionController/Caching.html] 239 240 241 * Component requests from one controller to another 242 243 class WeblogController < ActionController::Base 244 # Performs a method and then lets hello_world output its render 245 def delegate_action 246 do_other_stuff_before_hello_world 247 render_component :controller => "greeter", :action => "hello_world" 248 end 249 end 250 251 class GreeterController < ActionController::Base 252 def hello_world 253 render_text "Hello World!" 254 end 255 end 256 257 The same can be done in a view to do a partial rendering: 258 259 Let's see a greeting: 260 <%= render_component :controller => "greeter", :action => "hello_world" %> 261 262 {Learn more}[link:classes/ActionController/Components.html] 263 264 214 265 * Powerful debugging mechanism for local requests 215 266 … … 219 270 half-finished response. 220 271 221 Learn more in link:classes/ActionController/Rescue.html272 {Learn more}[link:classes/ActionController/Rescue.html] 222 273 223 274 … … 232 283 templates: list, show, destroy, new, create, edit, update 233 284 234 Learn more inlink:classes/ActionController/Scaffolding/ClassMethods.html285 {Learn more}link:classes/ActionController/Scaffolding/ClassMethods.html 235 286 236 287 … … 273 324 end 274 325 275 Learn more in link:classes/ActionView/Helpers/ActiveRecordHelper.html 276 277 278 * Automated mapping of URLs to controller/action pairs through Apache's 279 mod_rewrite 280 281 Requesting /blog/display/5 will call BlogController#display and 282 make 5 available as an instance variable through @params["id"] 283 284 285 * Runs on top of CGI, FCGI, and mod_ruby 286 287 See the address_book_controller example for all three forms 326 {Learn more}[link:classes/ActionView/Helpers/ActiveRecordHelper.html] 327 328 329 * Runs on top of WEBrick, CGI, FCGI, and mod_ruby 288 330 289 331 … … 291 333 292 334 This example will implement a simple weblog system using inline templates and 293 an Active Record model. The first thing we need to do is setup an .htaccess to 294 interpret pretty URLs into something the controller can use. Let's use the 295 simplest form for starters: 296 297 RewriteRule ^weblog/([-_a-zA-Z0-9]+)/([0-9]+)$ \ 298 /weblog_controller.cgi?action=$2&id=$3 [QSA] 299 RewriteRule ^weblog/([-_a-zA-Z0-9]+)$ \ 300 /weblog_controller.cgi?action=$2 [QSA] 301 RewriteRule ^weblog/$ \ 302 /weblog_controller.cgi?action=index [QSA] 303 304 Now we'll be able to access URLs like weblog/display/5 and have 305 WeblogController#display called with { "id" => 5 } in the @params array 306 available for the action. So let's build that WeblogController with just a few 335 an Active Record model. So let's build that WeblogController with just a few 307 336 methods: 308 337 309 338 require 'action_controller' 310 339 require 'post' 340 311 341 class WeblogController < ActionController::Base 312 342 layout "weblog/layout" … … 363 393 the create action (that's the default target for the form builder when given a 364 394 new model). After creating the post, it'll redirect to the display page using 365 an URL such as /weblog/display/5 (where 5 is the id of the post .395 an URL such as /weblog/display/5 (where 5 is the id of the post). 366 396 367 397 … … 387 417 Documentation can be found at 388 418 389 * http://a ctionpack.rubyonrails.org419 * http://ap.rubyonrails.com 390 420 391 421 … … 406 436 == Support 407 437 408 The Action Pack homepage is http:// actionpack.rubyonrails.org. You can find438 The Action Pack homepage is http://www.rubyonrails.com. You can find 409 439 the Action Pack RubyForge page at http://rubyforge.org/projects/actionpack. 410 440 And as Jim from Rake says: