X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=vendor%2Frails%2Factionpack%2FREADME;fp=vendor%2Frails%2Factionpack%2FREADME;h=6090089bb9e9ee0d6191ec1b07eecd66eb51bb7e;hb=d115f2e23823271635bad69229a42cd8ac68debe;hp=0000000000000000000000000000000000000000;hpb=37cb670bf3ddde90b214e591f100ed4446469484;p=depot.git diff --git a/vendor/rails/actionpack/README b/vendor/rails/actionpack/README new file mode 100644 index 0000000..6090089 --- /dev/null +++ b/vendor/rails/actionpack/README @@ -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): + <%= yield %> + + Template for hello_world action: +

Hello world

+ + Result of running hello_world action: +

Hello world

+ + {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): + +
+

+ Title:
+ +

+

+ Content:
+ +

+

+ Written on:
+ + + +

+ + +
+ + 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: + + <%= yield %> + + + weblog/index.erb: + <% for post in @posts %> +

<%= link_to(post.title, :action => "display", :id => post.id %>

+ <% end %> + + weblog/display.erb: +

+ <%= post.title %>
+ <%= post.content %> +

+ + 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