diff options
author | José Valim <jose.valim@gmail.com> | 2010-07-21 12:51:14 +0200 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2010-07-21 12:51:14 +0200 |
commit | 508fba9e070e09f0a321f2dd7acf7938967468f7 (patch) | |
tree | 7ca2db1b3de47301b12a99323a44e40f3d892fa7 /actionpack/README.rdoc | |
parent | b70062f1e71dc8bda8e9b8159a1f202389a80a62 (diff) | |
download | rails-508fba9e070e09f0a321f2dd7acf7938967468f7.tar.gz rails-508fba9e070e09f0a321f2dd7acf7938967468f7.tar.bz2 rails-508fba9e070e09f0a321f2dd7acf7938967468f7.zip |
Add .rdoc extension to README files.
Diffstat (limited to 'actionpack/README.rdoc')
-rw-r--r-- | actionpack/README.rdoc | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/actionpack/README.rdoc b/actionpack/README.rdoc new file mode 100644 index 0000000000..272feb63d0 --- /dev/null +++ b/actionpack/README.rdoc @@ -0,0 +1,382 @@ += 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. + +A short rundown of the major features: + +* Actions grouped in controller as methods instead of separate command objects + and can therefore share helper methods + + CustomersController < ActionController::Base + def show + @customer = find_customer + end + + def update + @customer = find_customer + @customer.attributes = params[:customer] + @customer.save ? + redirect_to(:action => "show") : + render(:action => "edit") + end + + private + 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) + + <% for post in @posts %> + Title: <%= post.title %> + <% end %> + + All post titles: <%= @posts.collect{ |p| p.title }.join ", " %> + + <% unless @person.is_client? %> + Not for clients to see... + <% end %> + + {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" + + 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 + + {Learn more}[link:classes/ActionView/Base.html] + + +* Filters for pre and post processing of the response (as methods, procs, and classes) + + class WeblogController < ActionController::Base + before_filter :authenticate, :cache, :audit + after_filter { |c| c.response.body = Gzip::compress(c.response.body) } + after_filter LocalizeFilter + + def index + # Before this action is run, the user will be authenticated, the cache + # will be examined to see if a valid copy of the results already + # exists, and the action will be logged for auditing. + + # After this action has run, the output will first be localized then + # compressed to minimize bandwidth usage + end + + private + def authenticate + # Implement the filter with full access to both request and response + end + end + + {Learn more}[link:classes/ActionController/Filters/ClassMethods.html] + + +* Helpers for forms, dates, action links, and text + + <%= text_field "post", "title", "size" => 30 %> + <%= html_date_select(Date.today) %> + <%= 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]) + + class WeblogController < ActionController::Base + layout "weblog_layout" + + def hello_world + end + end + + Layout file (called weblog_layout): + <html><body><%= yield %></body></html> + + Template for hello_world action: + <h1>Hello world</h1> + + Result of running hello_world action: + <html><body><h1>Hello world</h1></body></html> + + {Learn more}[link:classes/ActionController/Layout/ClassMethods.html] + + +* Routing makes pretty urls incredibly easy + + map.connect '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] + + From that URL, you can rewrite the redirect in a number of ways: + + redirect_to(:action => "edit") => + /clients/37signals/basecamp/project/dash + + redirect_to(:client_name => "nextangle", :project_name => "rails") => + /clients/nextangle/rails/project/dash + + {Learn more}[link:classes/ActionController/Base.html] + + +* Easy testing of both controller and rendered template through ActionController::TestCase + + class LoginControllerTest < ActionController::TestCase + def test_failing_authenticate + process :authenticate, :user_name => "nop", :password => "" + assert flash.has_key?(:alert) + assert_redirected_to :action => "index" + end + end + + {Learn more}[link:classes/ActionController/TestCase.html] + + +* Automated benchmarking and integrated logging + + Started GET "/weblog" for 127.0.0.1 at Fri May 28 00:41:55 + Processing by WeblogController#index as HTML + Rendered weblog/index.html.erb within layouts/application (25.7ms) + Completed 200 OK in 29.3ms + + If Active Record is used as the model, you'll have the database debugging + as well: + + Started POST "/posts" for 127.0.0.1 at Sat Jun 19 14:04:23 + Processing by PostsController#create as HTML + Parameters: {"post"=>{"title"=>"this is good"}} + SQL (0.6ms) INSERT INTO posts (title) VALUES('this is good') + Redirected to http://example.com/posts/5 + Completed 302 Found in 221ms (Views: 215ms | ActiveRecord: 0.6ms) + + You specify a logger through a class method, such as: + + ActionController::Base.logger = Logger.new("Application Log") + 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] + + +* Powerful debugging mechanism for local requests + + All exceptions raised on actions performed on the request of a local user + will be presented with a tailored debugging screen that includes exception + message, stack trace, request parameters, session contents, and the + half-finished response. + + {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 +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" + + def index + @posts = Post.find(:all) + end + + def show + @post = Post.find(params[:id]) + end + + def new + @post = Post.new + end + + def create + @post = Post.create(params[:post]) + redirect_to :action => "show", :id => @post.id + end + end + + WeblogController::Base.view_paths = [ File.dirname(__FILE__) ] + WeblogController.process_cgi if $0 == __FILE__ + +The last two lines are responsible for telling ActionController where the +template files are located and actually running the controller on a new +request from the web-server (like to be Apache). + +And the templates look like this: + + weblog/layout.html.erb: + <html><body> + <%= yield %> + </body></html> + + weblog/index.html.erb: + <% for post in @posts %> + <p><%= link_to(post.title, :action => "show", :id => post.id) %></p> + <% end %> + + weblog/show.html.erb: + <p> + <b><%= @post.title %></b><br/> + <b><%= @post.content %></b> + </p> + + weblog/new.html.erb: + <%= form "post" %> + +This simple setup will list all the posts in the system on the index page, +which is called by accessing /weblog/. It uses the form builder for the Active +Record model to make the new screen, which in turn hands 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 show page using +an URL such as /weblog/5 (where 5 is the id of the post). + + +== Download + +The latest version of Action Pack can be installed with Rubygems: + +* gem install actionpack + +Documentation can be found at + +* http://api.rubyonrails.org + + +== License + +Action Pack is released under the MIT license. + + +== Support + +The Action Pack homepage is http://www.rubyonrails.org. You can find +the Action Pack RubyForge page at http://rubyforge.org/projects/actionpack. +And as Jim from Rake says: + + Feel free to submit commits or feature requests. If you send a patch, + remember to update the corresponding unit tests. If fact, I prefer + new feature to be submitted in the form of new unit tests. |