1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Updated documentation

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@780 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
David Heinemeier Hansson 2005-02-24 01:29:43 +00:00
parent 5d94fb33c6
commit e4efcfd43e
6 changed files with 147 additions and 95 deletions

View file

@ -50,7 +50,7 @@ A short rundown of the major features:
def find_customer() Customer.find(@params["id"]) end
end
Learn more in link:classes/ActionController/Base.html
{Learn more}[link:classes/ActionController/Base.html]
* Embedded Ruby for templates (no new "easy" template language)
@ -65,30 +65,32 @@ A short rundown of the major features:
Not for clients to see...
<% end %>
Learn more in link:classes/ActionView.html
{Learn more}[link:classes/ActionView.html]
* Builder-based templates (great for XML content, like RSS)
xml.rss("version" => "2.0") do
xml.channel do
xml.title(@feed_title)
xml.link(@url)
xml.description "Basecamp: Recent items"
xml.language "en-us"
xml.ttl "40"
xml.rss("version" => "2.0") do
xml.channel do
xml.title(@feed_title)
xml.link(@url)
xml.description "Basecamp: Recent items"
xml.language "en-us"
xml.ttl "40"
for item in @recent_items
xml.item do
xml.title(item_title(item))
xml.description(item_description(item))
xml.pubDate(item_pubDate(item))
xml.guid(@recent_items.url(item))
xml.link(@recent_items.url(item))
for item in @recent_items
xml.item do
xml.title(item_title(item))
xml.description(item_description(item))
xml.pubDate(item_pubDate(item))
xml.guid(@recent_items.url(item))
xml.link(@recent_items.url(item))
end
end
end
end
end
{Learn more}[link:classes/ActionView/Base.html]
* Filters for pre and post processing of the response (as methods, procs, and classes)
@ -113,7 +115,7 @@ A short rundown of the major features:
end
end
Learn more in link:classes/ActionController/Filters/ClassMethods.html
{Learn more}[link:classes/ActionController/Filters/ClassMethods.html]
* Helpers for forms, dates, action links, and text
@ -123,7 +125,7 @@ A short rundown of the major features:
<%= link_to "New post", :controller => "post", :action => "new" %>
<%= truncate(post.title, 25) %>
Learn more in link:classes/ActionView/Helpers.html
{Learn more}[link:classes/ActionView/Helpers.html]
* Layout sharing for template reuse (think simple version of Struts
@ -145,28 +147,25 @@ A short rundown of the major features:
Result of running hello_world action:
<html><body><h1>Hello world</h1></body></html>
Learn more in link:classes/ActionController/Layout/ClassMethods.html
{Learn more}[link:classes/ActionController/Layout/ClassMethods.html]
* Advanced redirection that makes pretty urls easy
* Routing makes pretty urls incredibly easy
RewriteRule ^/library/books/([A-Z]+)([0-9]+)/([-_a-zA-Z0-9]+)$ \
/books_controller.cgi?action=$3&type=$1&code=$2 [QSA] [L]
map.connect 'clients/:client_name/:project_name/:controller/:action'
Accessing /library/books/ISBN/0743536703/show calls BooksController#show
Accessing /clients/37signals/basecamp/project/dash calls ProjectController#dash with
{ "client_name" => "37signals", "project_name" => "basecamp" } in @params["params"]
From that URL, you can rewrite the redirect in a number of ways:
redirect_to(:action => "edit") =>
/library/books/ISBN/0743536703/edit
/clients/37signals/basecamp/project/dash
redirect_to(:path_params => { "type" => "XTC", "code" => "12354345" }) =>
/library/books/XTC/12354345/show
redirect_to(:client_name => "nextangle", :project_name => "rails") =>
/clients/nextangle/rails/project/dash
redirect_to(:controller_prefix => "admin", :controller => "accounts") =>
/admin/accounts/
Learn more in link:classes/ActionController/Base.html
{Learn more}[link:classes/ActionController/Base.html]
* Easy testing of both controller and template result through TestRequest/Response
@ -185,7 +184,7 @@ A short rundown of the major features:
end
end
Learn more in link:classes/ActionController/TestRequest.html
{Learn more}[link:classes/ActionController/TestRequest.html]
* Automated benchmarking and integrated logging
@ -211,6 +210,58 @@ A short rundown of the major features:
ActionController::Base.logger = Log4r::Logger.new("Application Log")
* Caching at three levels of granularity (page, action, fragment)
class WeblogController < ActionController::Base
caches_page :show
caches_action :account
def show
# the output of the method will be cached as
# ActionController::Base.page_cache_directory + "/weblog/show/n.html"
# and the web server will pick it up without even hitting Rails
end
def account
# the output of the method will be cached in the fragment store
# but Rails is hit to retrieve it, so filters are run
end
def update
List.update(@params["list"]["id"], @params["list"])
expire_page :action => "show", :id => @params["list"]["id"]
expire_action :action => "account"
redirect_to :action => "show", :id => @params["list"]["id"]
end
end
{Learn more}[link:classes/ActionController/Caching.html]
* Component requests from one controller to another
class WeblogController < ActionController::Base
# Performs a method and then lets hello_world output its render
def delegate_action
do_other_stuff_before_hello_world
render_component :controller => "greeter", :action => "hello_world"
end
end
class GreeterController < ActionController::Base
def hello_world
render_text "Hello World!"
end
end
The same can be done in a view to do a partial rendering:
Let's see a greeting:
<%= render_component :controller => "greeter", :action => "hello_world" %>
{Learn more}[link:classes/ActionController/Components.html]
* Powerful debugging mechanism for local requests
All exceptions raised on actions performed on the request of a local user
@ -218,7 +269,7 @@ A short rundown of the major features:
message, stack trace, request parameters, session contents, and the
half-finished response.
Learn more in link:classes/ActionController/Rescue.html
{Learn more}[link:classes/ActionController/Rescue.html]
* Scaffolding for Action Record model objects
@ -231,7 +282,7 @@ A short rundown of the major features:
The AccountController now has the full CRUD range of actions and default
templates: list, show, destroy, new, create, edit, update
Learn more in link:classes/ActionController/Scaffolding/ClassMethods.html
{Learn more}link:classes/ActionController/Scaffolding/ClassMethods.html
* Form building for Active Record model objects
@ -272,42 +323,21 @@ A short rundown of the major features:
end
end
Learn more in link:classes/ActionView/Helpers/ActiveRecordHelper.html
{Learn more}[link:classes/ActionView/Helpers/ActiveRecordHelper.html]
* Automated mapping of URLs to controller/action pairs through Apache's
mod_rewrite
Requesting /blog/display/5 will call BlogController#display and
make 5 available as an instance variable through @params["id"]
* Runs on top of CGI, FCGI, and mod_ruby
See the address_book_controller example for all three forms
* Runs on top of WEBrick, CGI, FCGI, and mod_ruby
== Simple example
This example will implement a simple weblog system using inline templates and
an Active Record model. The first thing we need to do is setup an .htaccess to
interpret pretty URLs into something the controller can use. Let's use the
simplest form for starters:
RewriteRule ^weblog/([-_a-zA-Z0-9]+)/([0-9]+)$ \
/weblog_controller.cgi?action=$2&id=$3 [QSA]
RewriteRule ^weblog/([-_a-zA-Z0-9]+)$ \
/weblog_controller.cgi?action=$2 [QSA]
RewriteRule ^weblog/$ \
/weblog_controller.cgi?action=index [QSA]
Now we'll be able to access URLs like weblog/display/5 and have
WeblogController#display called with { "id" => 5 } in the @params array
available for the action. So let's build that WeblogController with just a few
an Active Record model. So let's build that WeblogController with just a few
methods:
require 'action_controller'
require 'post'
class WeblogController < ActionController::Base
layout "weblog/layout"
@ -362,7 +392,7 @@ which is called by accessing /weblog/. It uses the form builder for the Active
Record model to make the new screen, which in turns hand everything over to
the create action (that's the default target for the form builder when given a
new model). After creating the post, it'll redirect to the display page using
an URL such as /weblog/display/5 (where 5 is the id of the post.
an URL such as /weblog/display/5 (where 5 is the id of the post).
== Examples
@ -386,7 +416,7 @@ The latest version of Action Pack can be found at
Documentation can be found at
* http://actionpack.rubyonrails.org
* http://ap.rubyonrails.com
== Installation
@ -405,7 +435,7 @@ Action Pack is released under the same license as Ruby.
== Support
The Action Pack homepage is http://actionpack.rubyonrails.org. You can find
The Action Pack homepage is http://www.rubyonrails.com. You can find
the Action Pack RubyForge page at http://rubyforge.org/projects/actionpack.
And as Jim from Rake says:

View file

@ -14,7 +14,7 @@ module ActionController #:nodoc:
end
class MissingTemplate < ActionControllerError #:nodoc:
end
class RoutingError < ActionControllerError
class RoutingError < ActionControllerError#:nodoc:
attr_reader :failures
def initialize(message, failures=[])
super(message)
@ -86,9 +86,9 @@ module ActionController #:nodoc:
# <input type="text" name="post[name]" value="david">
# <input type="text" name="post[address]" value="hyacintvej">
#
# A request stemming from a form holding these inputs will include { "post" # => { "name" => "david", "address" => "hyacintvej" } }.
# A request stemming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>.
# If the address input had been named "post[address][street]", the @params would have included
# { "post" => { "address" => { "street" => "hyacintvej" } } }. There's no limit to the depth of the nesting.
# <tt>{ "post" => { "address" => { "street" => "hyacintvej" } } }</tt>. There's no limit to the depth of the nesting.
#
# == Sessions
#
@ -156,22 +156,20 @@ module ActionController #:nodoc:
#
# Redirects work by rewriting the URL of the current action. So if the show action was called by "/library/books/ISBN/0743536703/show",
# we can redirect to an edit action simply by doing <tt>redirect_to(:action => "edit")</tt>, which could throw the user to
# "/library/books/ISBN/0743536703/edit". Naturally, you'll need to setup the .htaccess (or other means of URL rewriting for the web server)
# to point to the proper controller and action in the first place, but once you have, it can be rewritten with ease.
# "/library/books/ISBN/0743536703/edit". Naturally, you'll need to setup the routes configuration file to point to the proper controller
# and action in the first place, but once you have, it can be rewritten with ease.
#
# Let's consider a bunch of examples on how to go from "/library/books/ISBN/0743536703/edit" to somewhere else:
# Let's consider a bunch of examples on how to go from "/clients/37signals/basecamp/project/dash" to somewhere else:
#
# redirect_to(:action => "show", :action_prefix => "XTC/123") =>
# "http://www.singlefile.com/library/books/XTC/123/show"
# redirect_to(:action => "edit") =>
# /clients/37signals/basecamp/project/dash
#
# redirect_to(:client_name => "nextangle", :project_name => "rails") =>
# /clients/nextangle/rails/project/dash
#
# redirect_to(:path_params => {"type" => "EXBC"}) =>
# "http://www.singlefile.com/library/books/EXBC/0743536703/show"
# Those redirects happen under the configuration of:
#
# redirect_to(:controller => "settings") =>
# "http://www.singlefile.com/library/settings/"
#
# 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
# you an excellent understanding of the different options and what they do.
# map.connect 'clients/:client_name/:project_name/:controller/:action'
#
# == Calling multiple redirects or renders
#
@ -337,20 +335,20 @@ module ActionController #:nodoc:
# * <tt>:anchor</tt> -- specifies the anchor name to be appended to the path. For example,
# <tt>url_for :controller => 'posts', :action => 'show', :id => 10, :anchor => 'comments'</tt>
# will produce "/posts/show/10#comments".
# * <tt>:only-path</tt> -- if true, returns the absolute URL (omitting the protocol, host name, and port)
# * <tt>:only_path</tt> -- if true, returns the absolute URL (omitting the protocol, host name, and port)
# * <tt>:host</tt> -- overrides the default (current) host if provided
# * <tt>:protocol</tt> -- overrides the default (current) protocol if provided
#  
#
# The URL is generated from the remaining keys in the hash. A URL contains two key parts: the <base> and a query string.
# Routes composes a query string as the key/value pairs not included in the <base>.
#  
#
# The default Routes setup supports a typical Rails path of "controller/action/id" where action and id are optional, with
# action defaulting to 'index' when not given. Here are some typical url_for statements and their corresponding URLs:
#  
# url_for :controller => 'posts', :action => 'recent' # => 'proto://host.com/posts/recent'
# url_for :controller => 'posts', :action => 'index' # => 'proto://host.com/posts'
# url_for :controller => 'posts', :action => 'show', :id => 10 # => 'proto://host.com/posts/show/10'
#  
#
# When generating a new URL, missing values may be filled in from the current request's parameters. For example,
# <tt>url_for :action => 'some_action'</tt> will retain the current controller, as expected. This behavior extends to
# other parameters, including <tt>:controller</tt>, <tt>:id</tt>, and any other parameters that are placed into a Route's
@ -359,21 +357,21 @@ module ActionController #:nodoc:
# The URL helpers such as <tt>url_for</tt> have a limited form of memory: when generating a new URL, they can look for
# missing values in the current request's parameters. Routes attempts to guess when a value should and should not be
# taken from the defaults. There are a few simple rules on how this is performed:
#  
#
# * If the controller name begins with a slash, no defaults are used: <tt>url_for :controller => '/home'</tt>
# * If the controller changes, the action will default to index unless provided
#  
#
# The final rule is applied while the URL is being generated and is best illustrated by an example. Let us consider the
# route given by <tt>map.connect 'people/:last/:first/:action', :action => 'bio', :controller => 'people'</tt>.
#  
#
# Suppose that the current URL is "people/hh/david/contacts". Let's consider a few different cases URLs which are generated
# from this page.
#  
#
# * <tt>url_for :action => 'bio'</tt> -- During the generation of this URL, default values will be used for the first and
# last components, and the action shall change. The generated URL will be, "people/david/hh/bio".
# * <tt>url_for :first => 'davids-little-brother'</tt> This generates the URL 'people/hh/davids-little-brother' -- note
# that this URL leaves out the assumed action of 'bio'.
#  
#
# However, you might ask why the action from the current request, 'contacts', isn't carried over into the new URL. The
# answer has to do with the order in which the parameters appear in the generated path. In a nutshell, since the
# value that appears in the slot for <tt>:first</tt> is not equal to default value for <tt>:first</tt> we stop using
@ -472,12 +470,12 @@ module ActionController #:nodoc:
# Renders an empty response that can be used when the request is only interested in triggering an effect. Do note that good
# HTTP manners mandate that you don't use GET requests to trigger data changes.
def render_nothing(status = nil)
def render_nothing(status = nil) #:doc:
render_text "", status
end
# Returns the result of the render as a string.
def render_to_string(template_name = default_template_name)
def render_to_string(template_name = default_template_name) #:doc:
add_variables_to_assigns
@template.render_file(template_name)
end

View file

@ -1,7 +1,27 @@
module ActionController #:nodoc:
# TODO: Cookies and session variables set in render_component that happens inside a view should be copied over.
module Components #:nodoc:
def self.append_features(base)
# Components allows you to call other actions for their rendered response while execution another action. You can either delegate
# the entire response rendering or you can mix a partial response in with your other content.
#
# class WeblogController < ActionController::Base
# # Performs a method and then lets hello_world output its render
# def delegate_action
# do_other_stuff_before_hello_world
# render_component :controller => "greeter", :action => "hello_world"
# end
# end
#
# class GreeterController < ActionController::Base
# def hello_world
# render_text "Hello World!"
# end
# end
#
# The same can be done in a view to do a partial rendering:
#
# Let's see a greeting:
# <%= render_component :controller => "greeter", :action => "hello_world" %>
module Components
def self.append_features(base) #:nodoc:
super
base.helper do
def render_component(options)
@ -11,10 +31,12 @@ module ActionController #:nodoc:
end
protected
# Renders the component specified as the response for the current method
def render_component(options = {}) #:doc:
component_logging(options) { render_text(component_response(options).body, response.headers["Status"]) }
end
# Returns the component response as a string
def render_component_as_string(options) #:doc:
component_logging(options) { component_response(options, false).body }
end

View file

@ -26,6 +26,9 @@ module ActionController #:nodoc:
# # model :post (already required)
# # helper :post (already required)
# end
#
# 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
# classes doesn't have to be required as Active Support will auto-require them.
module ClassMethods
# Specifies a variable number of models that this controller depends on. Models are normally Active Record classes or a similar
# backend for modelling entity classes.

View file

@ -35,8 +35,7 @@ module ActionController #:nodoc:
template_class.class_eval "include #{helper_module}"
end
# Declare a helper. If you use this method in your controller, you don't
# have to do the +self.append_features+ incantation in your helper class.
# Declare a helper:
# helper :foo
# requires 'foo_helper' and includes FooHelper in the template class.
# helper FooHelper

View file

@ -2,7 +2,7 @@ module ActionController
module Routing
ROUTE_FILE = defined?(RAILS_ROOT) ? File.expand_path(File.join(RAILS_ROOT, 'config', 'routes')) : nil
class Route
class Route #:nodoc:
attr_reader :defaults # The defaults hash
def initialize(path, hash={})
@ -185,7 +185,7 @@ module ActionController
end
end
class RouteSet
class RouteSet#:nodoc:
def initialize
@routes = []
end