Skip to content

Commit

Permalink
improve Action Pack README
Browse files Browse the repository at this point in the history
 - revise introductory text
 - list modules contained in the package
 - improve examples
 - remove obsolete `scaffold` and `form` examples
  • Loading branch information
mislav committed Jul 19, 2010
1 parent d6c3a4d commit b1fb2e4
Showing 1 changed file with 59 additions and 108 deletions.
167 changes: 59 additions & 108 deletions actionpack/README
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
= Action Pack -- On rails from request to response

Action Pack splits the response to a web request into a controller part
(performing the logic) and a view part (rendering a template). This two-step
approach is known as an action, which will normally create, read, update, or
delete (CRUD for short) some sort of model part (often backed by a database)
before choosing either to render a template or redirecting to another action.

Action Pack implements these actions as public methods on Action Controllers
and uses Action Views to implement the template rendering. Action Controllers
are then responsible for handling all the actions relating to a certain part
of an application. This grouping usually consists of actions for lists and for
CRUDs revolving around a single (or a few) model objects. So ContactsController
would be responsible for listing contacts, creating, deleting, and updating
contacts. A WeblogController could be responsible for both posts and comments.

Action View templates are written using embedded Ruby in tags mingled in with
the HTML. To avoid cluttering the templates with code, a bunch of helper
classes provide common behavior for forms, dates, and strings. And it's easy
to add specific helpers to keep the separation as the application evolves.

Note: Some of the features, such as scaffolding and form building, are tied to
ActiveRecord[http://activerecord.rubyonrails.org] (an object-relational
mapping package), but that doesn't mean that Action Pack depends on Active
Record. Action Pack is an independent package that can be used with any sort
of backend (Instiki[http://www.instiki.org], which is based on an older version
of Action Pack, used Madeleine for example). Read more about the role Action
Pack can play when used together with Active Record on
http://www.rubyonrails.org.

A short rundown of the major features:
= Action Pack -- From request to response

Action Pack is a framework for handling and responding to web requests. It it
provides mechanisms for *routing* (mapping request URLs to actions), defining
*controllers* that implement actions, and generating responses by rendering
*views*, which are templates of various formats. In short, Action Pack
provides the view and controller layers in the MVC paradigm.

It consists of several modules:

* Action Dispatch, which parses information about the web request, handles
routing as defined by the user, and does advanced processing related to HTTP
such as MIME-type negotiation, decoding parameters in POST/PUT bodies,
handling HTTP caching logic, cookies and sessions.

* Action Controller, which provides a base controller class that can be
subclassed to implement filters and actions to handle requests. The result
of an action is typically content generated from views.

* Action View, which handles view template lookup and rendering, and provides
view helpers that assist when building HTML forms, Atom feeds and more.
Template formats that Action View handles are ERb (embedded Ruby, typically
used to inline short Ruby snippets inside HTML), XML Builder and RJS
(dynamically generated JavaScript from Ruby code).

With Ruby on Rails framework, users only interface directly with Action
Controller module. Necessary Action Dispatch functionality is activated by
default and Action View rendering is implicitly triggered by Action
Controller. However, these modules are designed to function on their own and
can be used outside of Rails.

A short rundown of some of the major features:

* Actions grouped in controller as methods instead of separate command objects
and can therefore share helper methods
Expand All @@ -40,26 +41,29 @@ A short rundown of the major features:

def update
@customer = find_customer
@customer.attributes = params[:customer]
@customer.save ?
redirect_to(:action => "show") :
render(:action => "edit")
if @customer.update_attributes(params[:customer])
redirect_to :action => "show"
else
render :action => "edit"
end
end

private
def find_customer() Customer.find(params[:id]) end
def find_customer
Customer.find params[:id]
end
end

{Learn more}[link:classes/ActionController/Base.html]


* Embedded Ruby for templates (no new "easy" template language)
* ERb templates (static content mixed with dynamic output from ruby)

<% for post in @posts %>
Title: <%= post.title %>
<% end %>

All post titles: <%= @posts.collect{ |p| p.title }.join ", " %>
All post titles: <%= @posts.collect{ |p| p.title }.join(", ") %>

<% unless @person.is_client? %>
Not for clients to see...
Expand All @@ -68,7 +72,7 @@ A short rundown of the major features:
{Learn more}[link:classes/ActionView.html]


* Builder-based templates (great for XML content, like RSS)
* "Builder" templates (great for XML content, like RSS)

xml.rss("version" => "2.0") do
xml.channel do
Expand All @@ -93,11 +97,16 @@ A short rundown of the major features:
{Learn more}[link:classes/ActionView/Base.html]


* Filters for pre and post processing of the response (as methods, procs, and classes)
* Filters for pre- and post-processing of the response

class WeblogController < ActionController::Base
# filters as methods
before_filter :authenticate, :cache, :audit

# filter as a proc
after_filter { |c| c.response.body = Gzip::compress(c.response.body) }

# class filter
after_filter LocalizeFilter

def index
Expand All @@ -120,16 +129,14 @@ A short rundown of the major features:

* Helpers for forms, dates, action links, and text

<%= text_field "post", "title", "size" => 30 %>
<%= html_date_select(Date.today) %>
<%= text_field_tag "post", "title", "size" => 30 %>
<%= link_to "New post", :controller => "post", :action => "new" %>
<%= truncate(post.title, :length => 25) %>

{Learn more}[link:classes/ActionView/Helpers.html]


* Layout sharing for template reuse (think simple version of Struts
Tiles[http://jakarta.apache.org/struts/userGuide/dev_tiles.html])
* Layout sharing for template reuse

class WeblogController < ActionController::Base
layout "weblog_layout"
Expand All @@ -150,22 +157,22 @@ A short rundown of the major features:
{Learn more}[link:classes/ActionController/Layout/ClassMethods.html]


* Routing makes pretty urls incredibly easy
* Routing makes pretty URLs incredibly easy

map.connect 'clients/:client_name/:project_name/:controller/:action'
match 'clients/:client_name/:project_name/:controller/:action'

Accessing /clients/37signals/basecamp/project/dash calls ProjectController#dash with
{ "client_name" => "37signals", "project_name" => "basecamp" } in params[:params]
Accessing "/clients/37signals/basecamp/project/index" calls ProjectController#index with
{ "client_name" => "37signals", "project_name" => "basecamp" } in `params`

From that URL, you can rewrite the redirect in a number of ways:
From that action, you can write the redirect in a number of ways:

redirect_to(:action => "edit") =>
/clients/37signals/basecamp/project/dash
/clients/37signals/basecamp/project/edit

redirect_to(:client_name => "nextangle", :project_name => "rails") =>
/clients/nextangle/rails/project/dash
/clients/nextangle/rails/project/index

{Learn more}[link:classes/ActionController/Base.html]
{Learn more}[link:classes/ActionDispatch/Routing.html]


* Easy testing of both controller and rendered template through ActionController::TestCase
Expand Down Expand Up @@ -242,62 +249,6 @@ A short rundown of the major features:
{Learn more}[link:classes/ActionController/Rescue.html]


* Scaffolding for Active Record model objects

class AccountController < ActionController::Base
scaffold :account
end

The AccountController now has the full CRUD range of actions and default
templates: list, show, destroy, new, create, edit, update

{Learn more}[link:classes/ActionController/Scaffolding/ClassMethods.html]


* Form building for Active Record model objects

The post object has a title (varchar), content (text), and
written_on (date)

<%= form "post" %>

...will generate something like (the selects will have more options, of
course):

<form action="create" method="POST">
<p>
<b>Title:</b><br/>
<input type="text" name="post[title]" value="<%= @post.title %>" />
</p>
<p>
<b>Content:</b><br/>
<textarea name="post[content]"><%= @post.title %></textarea>
</p>
<p>
<b>Written on:</b><br/>
<select name='post[written_on(3i)]'><option>18</option></select>
<select name='post[written_on(2i)]'><option value='7'>July</option></select>
<select name='post[written_on(1i)]'><option>2004</option></select>
</p>

<input type="submit" value="Create">
</form>

This form generates a params[:post] array that can be used directly in a save action:

class WeblogController < ActionController::Base
def create
post = Post.create(params[:post])
redirect_to :action => "show", :id => post.id
end
end

{Learn more}[link:classes/ActionView/Helpers/ActiveRecordHelper.html]


* Runs on top of WEBrick, Mongrel, CGI, FCGI, and mod_ruby


== Simple example (from outside of Rails)

This example will implement a simple weblog system using inline templates and
Expand Down

0 comments on commit b1fb2e4

Please sign in to comment.