Froze rails gems
[depot.git] / vendor / rails / actionpack / README
diff --git a/vendor/rails/actionpack/README b/vendor/rails/actionpack/README
new file mode 100644 (file)
index 0000000..6090089
--- /dev/null
@@ -0,0 +1,463 @@
+= 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 ContactController
+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:
+
+* Actions grouped in controller as methods instead of separate command objects
+  and can therefore share helper methods
+
+    BlogController < ActionController::Base
+      def show
+        @customer = find_customer
+      end
+      
+      def update
+        @customer = find_customer
+        @customer.attributes = params[:customer]
+        @customer.save ? 
+          redirect_to(:action => "display") : 
+          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: <%= @post.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, 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]
+
+
+* Javascript and Ajax integration
+
+    link_to_function "Greeting", "alert('Hello world!')"
+    link_to_remote "Delete this post", :update => "posts", 
+                   :url => { :action => "destroy", :id => post.id }
+  
+  {Learn more}[link:classes/ActionView/Helpers/JavaScriptHelper.html]
+
+
+* Pagination for navigating lists of results
+
+    # controller
+    def list
+      @pages, @people =
+        paginate :people, :order => 'last_name, first_name'
+    end
+
+    # view
+    <%= link_to "Previous page", { :page => @pages.current.previous } if @pages.current.previous %>
+    <%= link_to "Next page", { :page => @pages.current.next } if @pages.current.next %>
+
+  {Learn more}[link:classes/ActionController/Pagination.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
+
+    Processing WeblogController#index (for 127.0.0.1 at Fri May 28 00:41:55)
+    Parameters: {"action"=>"index", "controller"=>"weblog"}
+    Rendering weblog/index (200 OK)
+    Completed in 0.029281 (34 reqs/sec)
+
+    If Active Record is used as the model, you'll have the database debugging
+    as well:
+
+    Processing WeblogController#create (for 127.0.0.1 at Sat Jun 19 14:04:23)
+    Params: {"controller"=>"weblog", "action"=>"create",  
+             "post"=>{"title"=>"this is good"} }
+    SQL (0.000627) INSERT INTO posts (title) VALUES('this is good')
+    Redirected to http://test/weblog/display/5
+    Completed in 0.221764 (4 reqs/sec) | DB: 0.059920 (27%)
+
+    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]
+
+
+* 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
+    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 => "display", :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 display
+      @post = Post.find(params[:id])
+    end
+    
+    def new
+      @post = Post.new
+    end
+    
+    def create
+      @post = Post.create(params[:post])
+      redirect_to :action => "display", :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.erb:
+    <html><body>
+    <%= yield %>
+    </body></html>
+
+  weblog/index.erb:
+    <% for post in @posts %>
+      <p><%= link_to(post.title, :action => "display", :id => post.id %></p>
+    <% end %>
+
+  weblog/display.erb:
+    <p>
+      <b><%= post.title %></b><br/>
+      <b><%= post.content %></b>
+    </p>
+
+  weblog/new.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 display page using
+an URL such as /weblog/display/5 (where 5 is the id of the post).
+
+
+== Examples
+
+Action Pack ships with three examples that all demonstrate an increasingly
+detailed view of the possibilities. First is blog_controller that is just a
+single file for the whole MVC (but still split into separate parts). Second is
+the debate_controller that uses separate template files and multiple screens.
+Third is the address_book_controller that uses the layout feature to separate
+template casing from content.
+
+Please note that you might need to change the "shebang" line to 
+#!/usr/local/env ruby, if your Ruby is not placed in /usr/local/bin/ruby
+
+Also note that these examples are all for demonstrating using Action Pack on
+its own. Not for when it's used inside of Rails.
+
+== Download
+
+The latest version of Action Pack can be found at
+
+* http://rubyforge.org/project/showfiles.php?group_id=249
+
+Documentation can be found at 
+
+* http://api.rubyonrails.com
+
+
+== Installation
+
+You can install Action Pack with the following command.
+
+  % [sudo] ruby install.rb
+
+from its distribution directory.
+
+
+== 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.
\ No newline at end of file