From 7a920bca4df1809e6e4583df54b3580f8ed05ab7 Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Mon, 6 Oct 2008 07:53:09 -0500 Subject: Clarify that the event sequence shown in the comments applies to new records only. --- activerecord/lib/active_record/callbacks.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index dd7ae51096..42bfe34505 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -5,7 +5,7 @@ module ActiveRecord # before or after an alteration of the object state. This can be used to make sure that associated and # dependent objects are deleted when +destroy+ is called (by overwriting +before_destroy+) or to massage attributes # before they're validated (by overwriting +before_validation+). As an example of the callbacks initiated, consider - # the Base#save call: + # the Base#save call for a new record: # # * (-) save # * (-) valid @@ -22,7 +22,8 @@ module ActiveRecord # * (8) after_save # # That's a total of eight callbacks, which gives you immense power to react and prepare for each state in the - # Active Record lifecycle. + # Active Record lifecycle. The sequence for calling Base#save an existing record is similar, except that each + # _on_create callback is replaced by the corresponding _on_update callback. # # Examples: # class CreditCard < ActiveRecord::Base -- cgit v1.2.3 From 973bd54d83f38747015e3d85d7f9fa1ee86b6270 Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Tue, 7 Oct 2008 05:43:44 -0500 Subject: Added some additional detail on asset caching syntax. --- .../doc/guides/actionview/layouts_and_rendering.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/railties/doc/guides/actionview/layouts_and_rendering.txt b/railties/doc/guides/actionview/layouts_and_rendering.txt index 278cca20a6..01fd8256f4 100644 --- a/railties/doc/guides/actionview/layouts_and_rendering.txt +++ b/railties/doc/guides/actionview/layouts_and_rendering.txt @@ -427,6 +427,15 @@ If you're loading multiple javascript files, you can create a better user experi ------------------------------------------------------- <%= javascript_include_tag "main", "columns", :cache => true %> ------------------------------------------------------- + +By default, the combined file will be delivered as +javascripts/all.js+. You can specify a location for the cached asset file instead: + +[source, ruby] +------------------------------------------------------- +<%= javascript_include_tag "main", "columns", :cache => 'cache/main/display' %> +------------------------------------------------------- + +You can even use dynamic paths such as "cache/#{current_site}/main/display"+. ==== Linking to CSS Files with +stylesheet_link_tag+ @@ -486,6 +495,15 @@ If you're loading multiple CSS files, you can create a better user experience by <%= stylesheet_link_tag "main", "columns", :cache => true %> ------------------------------------------------------- +By default, the combined file will be delivered as +stylesheets/all.css+. You can specify a location for the cached asset file instead: + +[source, ruby] +------------------------------------------------------- +<%= stylesheet_link_tag "main", "columns", :cache => 'cache/main/display' %> +------------------------------------------------------- + +You can even use dynamic paths such as "cache/#{current_site}/main/display"+. + ==== Linking to Images with +image_tag+ The +image_tag+ helper builds an HTML ++ tag to the specified file. By default, files are loaded from +public/images+. If you don't specify an extension, .png is assumed by default: -- cgit v1.2.3 From 3da0c0a8424ce018fa756e906e824698dfdcb65e Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Tue, 7 Oct 2008 06:03:53 -0500 Subject: Additional detail on routes for namespaced controllers. --- railties/doc/guides/routing/routing_outside_in.txt | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/railties/doc/guides/routing/routing_outside_in.txt b/railties/doc/guides/routing/routing_outside_in.txt index f35ac0cebd..c3dc60c8bf 100644 --- a/railties/doc/guides/routing/routing_outside_in.txt +++ b/railties/doc/guides/routing/routing_outside_in.txt @@ -267,10 +267,28 @@ Rails allows you to group your controllers into namespaces by saving them in fol map.resources :adminphotos, :controller => "admin/photos" ------------------------------------------------------- -If you use controller namespaces, you need to be aware of a subtlety in the Rails routing code: it always tries to preserve as much of the namespace from the previous request as possible. For example, if you are on a view generated from the +adminphoto_path+ helper, and you follow a link generated with +<%= link_to "show", adminphoto(1) %> you will end up on the view generated by +admin/photos/show+ but you will also end up in the same place if you have +<%= link_to "show", {:controller => "photos", :action => "show"} %>+ because Rails will generate the show URL relative to the current URL. +If you use controller namespaces, you need to be aware of a subtlety in the Rails routing code: it always tries to preserve as much of the namespace from the previous request as possible. For example, if you are on a view generated from the +adminphoto_path+ helper, and you follow a link generated with +<%= link_to "show", adminphoto(1) %>+ you will end up on the view generated by +admin/photos/show+ but you will also end up in the same place if you have +<%= link_to "show", {:controller => "photos", :action => "show"} %>+ because Rails will generate the show URL relative to the current URL. TIP: If you want to guarantee that a link goes to a top-level controller, use a preceding slash to anchor the controller name: +<%= link_to "show", {:controller => "/photos", :action => "show"} %>+ +You can also specify a controller namespace with the +:namespace+ option instead of a path: + +[source, ruby] +------------------------------------------------------- +map.resources :adminphotos, :namespace => "admin", :controller => "photos" +------------------------------------------------------- + +This can be especially useful when combined with +with_options+ to map multiple namespaced routes together: + +[source, ruby] +------------------------------------------------------- +map.with_options(:namespace => "admin") do |admin| + admin.resources :photos, :videos +end +------------------------------------------------------- + +That would give you routing for +admin/photos+ and +admin/videos+ controllers. + ==== Using :singular If for some reason Rails isn't doing what you want in converting the plural resource name to a singular name in member routes, you can override its judgment with the +:singular+ option: -- cgit v1.2.3 From dfc0b1a716d17085224a375977a10407ba9bea24 Mon Sep 17 00:00:00 2001 From: Tore Darell Date: Tue, 7 Oct 2008 20:51:00 +0200 Subject: Add verification, rescue + fixes to AC basics --- .../guides/actioncontroller/actioncontroller.txt | 4 +- railties/doc/guides/actioncontroller/cookies.txt | 30 ++++-- railties/doc/guides/actioncontroller/filters.txt | 17 +-- .../doc/guides/actioncontroller/introduction.txt | 2 +- railties/doc/guides/actioncontroller/methods.txt | 2 +- .../actioncontroller/parameter_filtering.txt | 2 +- railties/doc/guides/actioncontroller/params.txt | 4 +- railties/doc/guides/actioncontroller/rescue.txt | 119 ++++++++++++++++++++- railties/doc/guides/actioncontroller/session.txt | 72 +++++++++---- railties/doc/guides/actioncontroller/streaming.txt | 8 +- .../doc/guides/actioncontroller/verification.txt | 39 ++++++- 11 files changed, 249 insertions(+), 50 deletions(-) diff --git a/railties/doc/guides/actioncontroller/actioncontroller.txt b/railties/doc/guides/actioncontroller/actioncontroller.txt index c5a594d713..0b884e590b 100644 --- a/railties/doc/guides/actioncontroller/actioncontroller.txt +++ b/railties/doc/guides/actioncontroller/actioncontroller.txt @@ -15,6 +15,8 @@ include::cookies.txt[] include::filters.txt[] +include::verification.txt[] + include::request_response_objects.txt[] include::http_auth.txt[] @@ -23,6 +25,4 @@ include::streaming.txt[] include::parameter_filtering.txt[] -include::verification.txt[] - include::rescue.txt[] diff --git a/railties/doc/guides/actioncontroller/cookies.txt b/railties/doc/guides/actioncontroller/cookies.txt index a845e452b2..d451f3f7a6 100644 --- a/railties/doc/guides/actioncontroller/cookies.txt +++ b/railties/doc/guides/actioncontroller/cookies.txt @@ -2,22 +2,30 @@ Your application can store small amounts of data on the client - called cookies - that will be persisted across requests and even sessions. Rails provides easy access to cookies via the `cookies` method, which - much like the `session` - works like a hash: -TODO: Find a real-world example where cookies are used - [source, ruby] ----------------------------------------- -class FooController < ApplicationController - - def foo - cookies[:foo] = "bar" - end +class CommentsController < ApplicationController - def display_foo - @foo = cookies[:foo] + def new + #Auto-fill the commenter's name if it has been stored in a cookie + @comment = Comment.new(:name => cookies[:commenter_name]) end - def remove_foo - cookies.delete(:foo) + def create + @comment = Comment.new(params[:comment]) + if @comment.save + flash[:notice] = "Thanks for your comment!" + if params[:remember_name] + # Remember the commenter's name + cookies[:commenter_name] = @comment.name + else + # Don't remember, and delete the name if it has been remembered before + cookies.delete(:commenter_name) + end + redirect_to @comment.article + else + render :action => "new" + end end end diff --git a/railties/doc/guides/actioncontroller/filters.txt b/railties/doc/guides/actioncontroller/filters.txt index 2baf92d6ef..bc67147102 100644 --- a/railties/doc/guides/actioncontroller/filters.txt +++ b/railties/doc/guides/actioncontroller/filters.txt @@ -59,24 +59,27 @@ TODO: Find a real example for an around filter [source, ruby] --------------------------------- +# Example taken from the Rails API filter documentation: +# http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html class ApplicationController < Application - around_filter :foo + around_filter :catch_exceptions private - def foo - logger.debug("Action has not been run yet") - yield #Run the action - logger.debug("Action has been run") + def catch_exceptions + yield + rescue => exception + logger.debug "Caught exception! #{exception}" + raise end end --------------------------------- -=== Other types of filters === +=== Other ways to use filters === -While the most common way to use filters is by creating private methods and using *_filter to add them, there are two other ways. +While the most common way to use filters is by creating private methods and using *_filter to add them, there are two other ways to do the same thing. The first is to use a block directly with the *_filter methods. The block receives the controller as an argument, and the `require_login` filter from above could be rewritte to use a block: diff --git a/railties/doc/guides/actioncontroller/introduction.txt b/railties/doc/guides/actioncontroller/introduction.txt index 35540bbc09..e4b0953b95 100644 --- a/railties/doc/guides/actioncontroller/introduction.txt +++ b/railties/doc/guides/actioncontroller/introduction.txt @@ -2,6 +2,6 @@ Action Controller is the C in MVC. After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output. Luckily, Action Controller does most of the groundwork for you and uses smart conventions to make this as straight-forward as possible. -For most conventional RESTful applications, the controller will receive the request (this is invisible to the developer), fetch or save data from a model and use a view to create HTML output. If your controller needs to do things a little differently, that's not a problem, this is just the most common way for a controller to work. +For most conventional RESTful applications, the controller will receive the request (this is invisible to you as the developer), fetch or save data from a model and use a view to create HTML output. If your controller needs to do things a little differently, that's not a problem, this is just the most common way for a controller to work. A controller can thus be thought of as a middle man between models and views. It makes the model data available to the view so it can display it to the user, and it saves or updates data from the user to the model. diff --git a/railties/doc/guides/actioncontroller/methods.txt b/railties/doc/guides/actioncontroller/methods.txt index 0818dbb849..a1ef204adb 100644 --- a/railties/doc/guides/actioncontroller/methods.txt +++ b/railties/doc/guides/actioncontroller/methods.txt @@ -1,6 +1,6 @@ == Methods and actions == -A controller is a Ruby class which inherits from ActionController::Base and has methods just like any other class. Usually these methods correspond to actions in MVC, but they can just as well be helpful methods which can be called by actions. When your application receives a request, the routing will determine which controller and action to run. Then an instance of that controller will be created and the method corresponding to the action (the method with the same name as the action) is run. +A controller is a Ruby class which inherits from ActionController::Base and has methods just like any other class. Usually these methods correspond to actions in MVC, but they can just as well be helpful methods which can be called by actions. When your application receives a request, the routing will determine which controller and action to run. Then an instance of that controller will be created and the method corresponding to the action (the method with the same name as the action) gets run. [source, ruby] ---------------------------------------------- diff --git a/railties/doc/guides/actioncontroller/parameter_filtering.txt b/railties/doc/guides/actioncontroller/parameter_filtering.txt index dce4b252c3..663549d130 100644 --- a/railties/doc/guides/actioncontroller/parameter_filtering.txt +++ b/railties/doc/guides/actioncontroller/parameter_filtering.txt @@ -1,6 +1,6 @@ == Parameter filtering == -Rails keeps a log file for each environment (development, test and production) in the "log" folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. The "filter_parameter_logging":http://api.rubyonrails.org/classes/ActionController/Base.html#M000837 can be used to filter out sensitive information from the log. It works by replacing certain keys in the `params` hash with "[FILTERED]" before they are written to the log. As an example, let's see how to filter all parameters with keys that include "password": +Rails keeps a log file for each environment (development, test and production) in the "log" folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. The "filter_parameter_logging":http://api.rubyonrails.org/classes/ActionController/Base.html#M000837 method can be used to filter out sensitive information from the log. It works by replacing certain keys in the `params` hash with "[FILTERED]" as they are written to the log. As an example, let's see how to filter all parameters with keys that include "password": [source, ruby] ------------------------- diff --git a/railties/doc/guides/actioncontroller/params.txt b/railties/doc/guides/actioncontroller/params.txt index 67f97b6135..7f494d7c9b 100644 --- a/railties/doc/guides/actioncontroller/params.txt +++ b/railties/doc/guides/actioncontroller/params.txt @@ -8,7 +8,7 @@ class ClientsController < ActionController::Base # This action uses query string parameters because it gets run by a HTTP GET request, # but this does not make any difference to the way in which the parameters are accessed. - # The URL for this action would look like this in order to list activated clients: /clients/?status=activated + # The URL for this action would look like this in order to list activated clients: /clients?status=activated def index if params[:status] = "activated" @clients = Client.activated @@ -47,7 +47,7 @@ The value of `params[:ids]` will now be `["1", "2", "3"]`. Note that parameter v To send a hash you include the key name inside the brackets: ------------------------------------- -
+ diff --git a/railties/doc/guides/actioncontroller/rescue.txt b/railties/doc/guides/actioncontroller/rescue.txt index 6ff7ea67d8..134469e6e4 100644 --- a/railties/doc/guides/actioncontroller/rescue.txt +++ b/railties/doc/guides/actioncontroller/rescue.txt @@ -1,3 +1,120 @@ == Rescue == -Describe how to use rescue_from et al to rescue exceptions in controllers. +TODO: s/environment/local or public/ + +Most likely your application is going to contain bugs or otherwise throw an exception that needs to be handled. For example, if the user follows a link to a resource that no longer exists in the database, Active Record will throw the ActiveRecord::RecordNotFound exception. Rails' default exception handling displays a 500 Server Error message for all exceptions. If the application is running in the development environment, a nice traceback and some added information gets displayed so you can figure out what went wrong and deal with it. If the application is in production Rails will just display a simple "500 Server Error" message to the user, or a "404 Not Found" if there was a routing error or a record could not be found. Sometimes you might want to customize how these errors are caught and how they're displayed to the user. There are several levels of exception handling available in a Rails application: + +=== The default 500 and 404 templates === + +By default a production application will render either a 404 or a 500 error message. These messages are contained in static HTML files in the `public` folder, in `404.html` and `500.html` respectively. You can customize these files to add some extra information and layout, but remember that they are static; i.e. you can't use RHTML or layouts in them, just plain HTML. + +=== `rescue_from` === + +If you want to do something a bit more elaborate when catching errors, you can use "rescue_from":http://api.rubyonrails.org/classes/ActionController/Rescue/ClassMethods.html#M000620, which handles exceptions of a certain type (or multiple types) in an entire controller and its subclasses. When an exception occurs which is caught by a rescue_from directive, the exception object is passed to the handler. The handler can be a method or a Proc object passed to the `:with` option. You can also use a block directly instead of an explicit Proc object. + +Let's see how we can use rescue_from to intercept all ActiveRecord::RecordNotFound errors and do something with them. + +[source, ruby] +----------------------------------- +class ApplicationController < ActionController::Base + + rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found + +private + + def record_not_found + render :text => "404 Not Found", :status => 404 + end + +end +----------------------------------- + +Of course, this example is anything but elaborate and doesn't improve the default exception handling at all, but once you can catch all those exceptions you're free to do whatever you want with them. For example, you could create custom exception classes that will be thrown when a user doesn't have access to a certain section of your application: + +[source, ruby] +----------------------------------- +class ApplicationController < ActionController::Base + + rescue_from User::NotAuthorized, :with => :user_not_authorized + +private + + def user_not_authorized + flash[:error] = "You don't have access to this section." + redirect_to :back + end + +end + +class ClientsController < ApplicationController + + # Check that the user has the right authorization to access clients. + before_filter :check_authorization + + # Note how the actions don't have to worry about all the auth stuff. + def edit + @client = Client.find(params[:id]) + end + +private + + # If the user is not authorized, just throw the exception. + def check_authorization + raise User::NotAuthorized unless current_user.admin? + end + +end +----------------------------------- + +NOTE: Certain exceptions are only rescuable from the ApplicationController class, as they are raised before the controller gets initialized and the action gets executed. See Partik Naik's "article":http://m.onkey.org/2008/7/20/rescue-from-dispatching on the subject for more information. + +=== `rescue_action` === + +The `rescue_from` method was added to make it easier to rescue different kinds of exceptions and deal with each separately. Action Controller has a default method which intercepts *all* exceptions raised, `rescue_action`. You can override this method in a controller or in ApplicationController to rescue all exceptions raised in that particular context. You can get a little bit more granular by using the "rescue_action_in_public":http://api.rubyonrails.org/classes/ActionController/Rescue.html#M000615 and "rescue_action_locally":http://api.rubyonrails.org/classes/ActionController/Rescue.html#M000618 methods which are used to rescue actions for public and local requests. Let's see how the User::NotAuthorized exception could be caught using this technique: + +[source, ruby] +---------------------------------------- +class ApplicationController < ActionController::Base + +private + + def rescue_action_in_public(exception) + case exception + when User::NotAuthorized + user_not_authorized + else + super + end + end + +end +---------------------------------------- + +As you can see, this gets a bit messy once you start rescuing various types of error that require separate handlers, so it's a good idea to use `rescue_from` instead. + +=== Getting down and dirty === + +Of course you can still use Ruby's `rescue` to rescue exceptions wherever you want. This is usually constrained to single methods, i.e. actions, but is still a very useful technique that should be used when appropriate. For example, you might use an API that raises a timeout error in one of your actions, and you have to handle that if it's raised: + +[source, ruby] +---------------------------------------- +require 'clients_international' +class ClientsController < ApplicationController + + def update + @client = Client.find(params[:id]) + @client.attributes = params[:client] + if @client.save + flash[:notice] = "Client was updated" + ClientsInternational.send_update(@client.to_xml) + redirect_to clients_url + else + render :action => "new" + end + rescue ClientsInternational::TimeoutError + flash[:error] = "Couldn't send API update" + redirect_to @client + end + +end +---------------------------------------- diff --git a/railties/doc/guides/actioncontroller/session.txt b/railties/doc/guides/actioncontroller/session.txt index 50ed76e3ae..44c21af8ed 100644 --- a/railties/doc/guides/actioncontroller/session.txt +++ b/railties/doc/guides/actioncontroller/session.txt @@ -1,30 +1,62 @@ == Session == -Your application sets up a session for each user which can persist small amounts of data between requests. The session is only available in the controller. It can be stored in a number of different session stores: - -TODO: Not sure if all of these are available by default. +Your application has a session for each user in which you can store small amounts of data that will be persisted between requests. The session is only available in the controller and can use one of a number of different storage mechanisms: * CookieStore - Stores everything on the client. - * SQLSessionStore - Stores the data in a database using SQL. * DRBStore - Stores the data on a DRb client. * MemCacheStore - Stores the data in MemCache. * ActiveRecordStore - Stores the data in a database using Active Record. All session stores store the session id in a cookie - there is no other way of passing it to the server. Most stores also use this key to locate the session data on the server. -The default and recommended store, the Cookie Store, does not store session data on the server, but in the cookie itself. The data is cryptographically signed to make it tamper-proof, but it is not encrypted, so anyone with access to it can read its contents. It can only store 4Kb of data - much less than the others - but this is usually enough. Storing large amounts of data is discouraged no matter which session store your application uses. Expecially discouraged is storing complex objects (anything other than basic Ruby objects) in the session, as the server might not be able to reassemble them between requests, which will result in an error. The Cookie Store has the added advantage that it does not require any setting up beforehand - Rails will generate a "secret key" which will be used to sign the cookie when you create the application. +The default and recommended store, the Cookie Store, does not store session data on the server, but in the cookie itself. The data is cryptographically signed to make it tamper-proof, but it is not encrypted, so anyone with access to it can read its contents. It can only store about 4kB of data - much less than the others - but this is usually enough. Storing large amounts of data is discouraged no matter which session store your application uses. Expecially discouraged is storing complex objects (anything other than basic Ruby objects, the primary example being model instances) in the session, as the server might not be able to reassemble them between requests, which will result in an error. The Cookie Store has the added advantage that it does not require any setting up beforehand - Rails will generate a "secret key" which will be used to sign the cookie when you create the application. If you need a different session storage mechanism, you can change it in the `config/environment.rb` file: [source, ruby] ------------------------------------------ -# Set to one of [:active_record_store, :sql_session_store, :drb_store, :mem_cache_store, :cookie_store] +# Set to one of [:active_record_store, :drb_store, :mem_cache_store, :cookie_store] config.action_controller.session_store = :active_record_store ------------------------------------------ +=== Disabling the session === + +Sometimes you don't need a session, and you can turn it off to avoid the unnecessary overhead. To do this, use the "session":http://api.rubyonrails.org/classes/ActionController/SessionManagement/ClassMethods.html#M000649 class method in your controller: + +[source, ruby] +------------------------------------------ +class ApplicationController < ActionController::Base + session :off +end +------------------------------------------ + +You can also turn the session on or off for a single controller: + +[source, ruby] +------------------------------------------ +# The session is turned off by default in ApplicationController, but we +# want to turn it on for log in/out. +class LoginsController < ActionController::Base + session :on +end +------------------------------------------ + +Or even a single action: + +[source, ruby] +------------------------------------------ +class ProductsController < ActionController::Base + session :on, :only => [:create, :update] +end +------------------------------------------ + === Accessing the session === -In your controller you can access the session through the `session` method. Session values are stored using key/value pairs like a hash: +In your controller you can access the session through the `session` instance method. + +NOTE: There are two `session` methods, the class and the instance method. The class method which is described above is used to turn the session on and off while the instance method described below is used to access session values. The class method is used outside of method definitions while the instance methods is used inside methods, in actions or filters. + +Session values are stored using key/value pairs like a hash: [source, ruby] ------------------------------------------ @@ -33,6 +65,8 @@ class ApplicationController < ActionController::Base private # Finds the User with the ID stored in the session with the key :current_user_id + # This is a common way to do user login in a Rails application; logging in sets the + # session value and logging out removes it. def current_user @_current_user ||= session[:current_user_id] && User.find(session[:current_user_id]) end @@ -74,7 +108,7 @@ class LoginsController < ApplicationController end ------------------------------------------ -To reset the entire session, use `reset_session`. +To reset the entire session, use "reset_session":http://api.rubyonrails.org/classes/ActionController/Base.html#M000855 === The flash === @@ -95,18 +129,18 @@ end The `destroy` action redirects to the application's `root_url`, where the message will be displayed. Note that it's entirely up to the next action to decide what, if anything, it will do with what the previous action put in the flash. It's conventional to a display eventual errors or notices from the flash in the application's layout: -[source, ruby] ------------------------------------------ - - - <% if flash[:notice] -%> -

<%= flash[:notice] %>

- <% end -%> - <% if flash[:error] -%> -

<%= flash[:error] %>

- <% end -%> - - + + + + <% if flash[:notice] -%> +

<%= flash[:notice] %>

+ <% end -%> + <% if flash[:error] -%> +

<%= flash[:error] %>

+ <% end -%> + + ------------------------------------------ diff --git a/railties/doc/guides/actioncontroller/streaming.txt b/railties/doc/guides/actioncontroller/streaming.txt index 6026a8c51b..bca0254f43 100644 --- a/railties/doc/guides/actioncontroller/streaming.txt +++ b/railties/doc/guides/actioncontroller/streaming.txt @@ -48,15 +48,15 @@ class ClientsController < ApplicationController end ---------------------------- -NOTE: Be careful when using (or just don't use) "outside" data (params, cookies, etc) to locate the file on disk, as this is a security risk as someone could gain access to files they are not meant to have access to. +This will read and stream the file 4Kb at the time, avoiding loading the entire file into memory at once. You can turn off streaming with the `stream` option or adjust the block size with the `buffer_size` option. -NOTE: It is not recommended that you stream static files through Rails if you can instead keep them in a public folder on your web server. It is much more efficient to let the user download the file directly using Apache or another web server, keeping the request from unnecessarily going through the whole Rails stack. +WARNING: Be careful when using (or just don't use) "outside" data (params, cookies, etc) to locate the file on disk, as this is a security risk as someone could gain access to files they are not meant to have access to. -This will read and stream the file 4Kb at the time, avoiding loading the entire file into memory at once. You can turn off streaming with the `stream` option or adjust the block size with the `buffer_size` option. +TIP: It is not recommended that you stream static files through Rails if you can instead keep them in a public folder on your web server. It is much more efficient to let the user download the file directly using Apache or another web server, keeping the request from unnecessarily going through the whole Rails stack. === RESTful downloads === -While `send_data` works just fine, if you are creating a RESTful application having separate actions for file downloads is a bit ugly. In REST terminology, the PDF file from the example above can be considered just another representation of the client resource. Rails provides an easy and quite sleek way of doing "RESTful downloads". Let's try to rewrite the example so that the PDF download is a part of the `show` action: +While `send_data` works just fine, if you are creating a RESTful application having separate actions for file downloads is usually not necessary. In REST terminology, the PDF file from the example above can be considered just another representation of the client resource. Rails provides an easy and quite sleek way of doing "RESTful downloads". Let's try to rewrite the example so that the PDF download is a part of the `show` action: [source, ruby] ---------------------------- diff --git a/railties/doc/guides/actioncontroller/verification.txt b/railties/doc/guides/actioncontroller/verification.txt index 129ff7e7b0..1a4f7a8de5 100644 --- a/railties/doc/guides/actioncontroller/verification.txt +++ b/railties/doc/guides/actioncontroller/verification.txt @@ -1,3 +1,40 @@ == Verification == -Describe how to use the verify methods to make sure some prerequisites are met before an action gets run +Verifications make sure certain criterias are met in order for a controller or action to run. They can specify that a certain key (or several keys in the form of an array) is present in the `params`, `session` or `flash` hashes or that a certain HTTP method was used or that the request was made using XMLHTTPRequest (Ajax). The default action taken when these criterias are not met is to render a 400 Bad Request response, but you can customize this by specifying a redirect URL or rendering something else and you can also add flash messages and HTTP headers to the response. It is described in the "API documentation":http://api.rubyonrails.org/classes/ActionController/Verification/ClassMethods.html as "essentially a special kind of before_filter". + +Let's see how we can use verification to make sure the user supplies a username and a password in order to log in: + +[source, ruby] +--------------------------------------- +class LoginsController < ApplicationController + + verify :params => [:username, :password], + :render => {:action => "new"}, + :add_flash => {:error => "Username and password required to log in"} + + def create + @user = User.authenticate(params[:username], params[:password]) + if @user + flash[:notice] = "You're logged in" + redirect_to root_url + else + render :action => "new" + end + end + +end +--------------------------------------- + +Now the `create` action won't run unless the "username" and "password" parameters are present, and if they're not, an error message will be added to the flash and the "new" action will be rendered. But there's something rather important missing from the verification above: It will be used for *every* action in LoginsController, which is not what we want. You can limit which actions it will be used for with the `:only` and `:except` options just like a filter: + +[source, ruby] +--------------------------------------- +class LoginsController < ApplicationController + + verify :params => [:username, :password], + :render => {:action => "new"}, + :add_flash => {:error => "Username and password required to log in"}, + :only => :create #Only run this verification for the "create" action + +end +--------------------------------------- -- cgit v1.2.3 From b4da5f67708b2699a21f8bb39f4d10865c1814d4 Mon Sep 17 00:00:00 2001 From: Tore Darell Date: Tue, 7 Oct 2008 22:16:28 +0200 Subject: Fix links in AC guide --- railties/doc/guides/actioncontroller/filters.txt | 6 +++--- railties/doc/guides/actioncontroller/http_auth.txt | 2 +- railties/doc/guides/actioncontroller/parameter_filtering.txt | 2 +- .../doc/guides/actioncontroller/request_response_objects.txt | 4 ++-- railties/doc/guides/actioncontroller/rescue.txt | 10 ++++------ railties/doc/guides/actioncontroller/session.txt | 4 ++-- railties/doc/guides/actioncontroller/streaming.txt | 2 +- railties/doc/guides/actioncontroller/verification.txt | 2 +- 8 files changed, 15 insertions(+), 17 deletions(-) diff --git a/railties/doc/guides/actioncontroller/filters.txt b/railties/doc/guides/actioncontroller/filters.txt index bc67147102..a7b8d9727f 100644 --- a/railties/doc/guides/actioncontroller/filters.txt +++ b/railties/doc/guides/actioncontroller/filters.txt @@ -27,7 +27,7 @@ private end --------------------------------- -The method simply stores an error message in the flash and redirects to the login form if the user is not logged in. If a before filter (a filter which is run before the action) renders or redirects, the action will not run. If there are additional filters scheduled to run after the rendering/redirecting filter, they are also cancelled. To use this filter in a controller, use the "before_filter":http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000704 method: +The method simply stores an error message in the flash and redirects to the login form if the user is not logged in. If a before filter (a filter which is run before the action) renders or redirects, the action will not run. If there are additional filters scheduled to run after the rendering/redirecting filter, they are also cancelled. To use this filter in a controller, use the link:http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000704[before_filter] method: [source, ruby] --------------------------------- @@ -38,7 +38,7 @@ class ApplicationController < ActionController::Base end --------------------------------- -In this example, the filter is added to ApplicationController and thus all controllers in the application. This will make everything in the application require the user to be logged in in order to use it. For obvious reasons (the user wouldn't be able to log in in the first place!), not all controllers or actions should require this, so to prevent this filter from running you can use "skip_before_filter":http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000711 : +In this example, the filter is added to ApplicationController and thus all controllers in the application. This will make everything in the application require the user to be logged in in order to use it. For obvious reasons (the user wouldn't be able to log in in the first place!), not all controllers or actions should require this, so to prevent this filter from running you can use link:http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000711[skip_before_filter] : [source, ruby] --------------------------------- @@ -118,4 +118,4 @@ end Again, this is not an ideal example for this filter, because it's not run in the scope of the controller but gets it passed as an argument. The filter class has a class method `filter` which gets run before or after the action, depending on if it's a before or after filter. Classes used as around filters can also use the same `filter` method, which will get run in the same way. The method must `yield` to execute the action. Alternatively, it can have both a `before` and an `after` method that are run before and after the action. -The Rails API documentation has "more information and detail on using filters":http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html +The Rails API documentation has link:http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html[more information on using filters]. diff --git a/railties/doc/guides/actioncontroller/http_auth.txt b/railties/doc/guides/actioncontroller/http_auth.txt index 5a95de0bb3..7df0e635bf 100644 --- a/railties/doc/guides/actioncontroller/http_auth.txt +++ b/railties/doc/guides/actioncontroller/http_auth.txt @@ -1,6 +1,6 @@ == HTTP Basic Authentication == -Rails comes with built-in HTTP Basic authentication. This is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, we will create an administration section which will only be available by entering a username and a password into the browser's HTTP Basic dialog window. Using the built-in authentication is quite easy and only requires you to use one method, "authenticate_or_request_with_http_basic":http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic/ControllerMethods.html#M000610 +Rails comes with built-in HTTP Basic authentication. This is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, we will create an administration section which will only be available by entering a username and a password into the browser's HTTP Basic dialog window. Using the built-in authentication is quite easy and only requires you to use one method, link:http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic/ControllerMethods.html#M000610[authenticate_or_request_with_http_basic]. [source, ruby] ------------------------------------- diff --git a/railties/doc/guides/actioncontroller/parameter_filtering.txt b/railties/doc/guides/actioncontroller/parameter_filtering.txt index 663549d130..c4577d4f6d 100644 --- a/railties/doc/guides/actioncontroller/parameter_filtering.txt +++ b/railties/doc/guides/actioncontroller/parameter_filtering.txt @@ -1,6 +1,6 @@ == Parameter filtering == -Rails keeps a log file for each environment (development, test and production) in the "log" folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. The "filter_parameter_logging":http://api.rubyonrails.org/classes/ActionController/Base.html#M000837 method can be used to filter out sensitive information from the log. It works by replacing certain keys in the `params` hash with "[FILTERED]" as they are written to the log. As an example, let's see how to filter all parameters with keys that include "password": +Rails keeps a log file for each environment (development, test and production) in the "log" folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. The link:http://api.rubyonrails.org/classes/ActionController/Base.html#M000837[filter_parameter_logging] method can be used to filter out sensitive information from the log. It works by replacing certain keys in the `params` hash with "[FILTERED]" as they are written to the log. As an example, let's see how to filter all parameters with keys that include "password": [source, ruby] ------------------------- diff --git a/railties/doc/guides/actioncontroller/request_response_objects.txt b/railties/doc/guides/actioncontroller/request_response_objects.txt index d335523a25..493bd4cb43 100644 --- a/railties/doc/guides/actioncontroller/request_response_objects.txt +++ b/railties/doc/guides/actioncontroller/request_response_objects.txt @@ -1,10 +1,10 @@ == The request and response objects == -In every controller there are two accessor methods pointing to the request and the response objects associated with the request cycle that is currently in execution. The `request` method contains an instance of "AbstractRequest":http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html and the `response` method contains the "response object":http://github.com/rails/rails/tree/master/actionpack/lib/action_controller/response.rb representing what is going to be sent back to the client. +In every controller there are two accessor methods pointing to the request and the response objects associated with the request cycle that is currently in execution. The `request` method contains an instance of link:http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html[AbstractRequest] and the `response` method contains the link:http://github.com/rails/rails/tree/master/actionpack/lib/action_controller/response.rb[response object] representing what is going to be sent back to the client. === The request === -The request object contains a lot of useful information about the request coming in from the client. To get a full list of the available methods, refer to the "Rails API documentation":http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html +The request object contains a lot of useful information about the request coming in from the client. To get a full list of the available methods, refer to the link:http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html[API documentation]. * host - The hostname used for this request. * domain - The hostname without the first part (usually "www"). diff --git a/railties/doc/guides/actioncontroller/rescue.txt b/railties/doc/guides/actioncontroller/rescue.txt index 134469e6e4..50583bb71e 100644 --- a/railties/doc/guides/actioncontroller/rescue.txt +++ b/railties/doc/guides/actioncontroller/rescue.txt @@ -1,8 +1,6 @@ == Rescue == -TODO: s/environment/local or public/ - -Most likely your application is going to contain bugs or otherwise throw an exception that needs to be handled. For example, if the user follows a link to a resource that no longer exists in the database, Active Record will throw the ActiveRecord::RecordNotFound exception. Rails' default exception handling displays a 500 Server Error message for all exceptions. If the application is running in the development environment, a nice traceback and some added information gets displayed so you can figure out what went wrong and deal with it. If the application is in production Rails will just display a simple "500 Server Error" message to the user, or a "404 Not Found" if there was a routing error or a record could not be found. Sometimes you might want to customize how these errors are caught and how they're displayed to the user. There are several levels of exception handling available in a Rails application: +Most likely your application is going to contain bugs or otherwise throw an exception that needs to be handled. For example, if the user follows a link to a resource that no longer exists in the database, Active Record will throw the ActiveRecord::RecordNotFound exception. Rails' default exception handling displays a 500 Server Error message for all exceptions. If the request was made locally, a nice traceback and some added information gets displayed so you can figure out what went wrong and deal with it. If the request was remote Rails will just display a simple "500 Server Error" message to the user, or a "404 Not Found" if there was a routing error or a record could not be found. Sometimes you might want to customize how these errors are caught and how they're displayed to the user. There are several levels of exception handling available in a Rails application: === The default 500 and 404 templates === @@ -10,7 +8,7 @@ By default a production application will render either a 404 or a 500 error mess === `rescue_from` === -If you want to do something a bit more elaborate when catching errors, you can use "rescue_from":http://api.rubyonrails.org/classes/ActionController/Rescue/ClassMethods.html#M000620, which handles exceptions of a certain type (or multiple types) in an entire controller and its subclasses. When an exception occurs which is caught by a rescue_from directive, the exception object is passed to the handler. The handler can be a method or a Proc object passed to the `:with` option. You can also use a block directly instead of an explicit Proc object. +If you want to do something a bit more elaborate when catching errors, you can use link::http://api.rubyonrails.org/classes/ActionController/Rescue/ClassMethods.html#M000620[rescue_from], which handles exceptions of a certain type (or multiple types) in an entire controller and its subclasses. When an exception occurs which is caught by a rescue_from directive, the exception object is passed to the handler. The handler can be a method or a Proc object passed to the `:with` option. You can also use a block directly instead of an explicit Proc object. Let's see how we can use rescue_from to intercept all ActiveRecord::RecordNotFound errors and do something with them. @@ -66,11 +64,11 @@ private end ----------------------------------- -NOTE: Certain exceptions are only rescuable from the ApplicationController class, as they are raised before the controller gets initialized and the action gets executed. See Partik Naik's "article":http://m.onkey.org/2008/7/20/rescue-from-dispatching on the subject for more information. +NOTE: Certain exceptions are only rescuable from the ApplicationController class, as they are raised before the controller gets initialized and the action gets executed. See Partik Naik's link:http://m.onkey.org/2008/7/20/rescue-from-dispatching[article] on the subject for more information. === `rescue_action` === -The `rescue_from` method was added to make it easier to rescue different kinds of exceptions and deal with each separately. Action Controller has a default method which intercepts *all* exceptions raised, `rescue_action`. You can override this method in a controller or in ApplicationController to rescue all exceptions raised in that particular context. You can get a little bit more granular by using the "rescue_action_in_public":http://api.rubyonrails.org/classes/ActionController/Rescue.html#M000615 and "rescue_action_locally":http://api.rubyonrails.org/classes/ActionController/Rescue.html#M000618 methods which are used to rescue actions for public and local requests. Let's see how the User::NotAuthorized exception could be caught using this technique: +The `rescue_from` method was added to make it easier to rescue different kinds of exceptions and deal with each separately. Action Controller has a default method which intercepts *all* exceptions raised, `rescue_action`. You can override this method in a controller or in ApplicationController to rescue all exceptions raised in that particular context. You can get a little bit more granular by using the link:http://api.rubyonrails.org/classes/ActionController/Rescue.html#M000615[rescue_action_in_public] and link:http://api.rubyonrails.org/classes/ActionController/Rescue.html#M000618[rescue_action_locally] methods which are used to rescue actions for public and local requests. Let's see how the User::NotAuthorized exception could be caught using this technique: [source, ruby] ---------------------------------------- diff --git a/railties/doc/guides/actioncontroller/session.txt b/railties/doc/guides/actioncontroller/session.txt index 44c21af8ed..0a44bfd802 100644 --- a/railties/doc/guides/actioncontroller/session.txt +++ b/railties/doc/guides/actioncontroller/session.txt @@ -21,7 +21,7 @@ config.action_controller.session_store = :active_record_store === Disabling the session === -Sometimes you don't need a session, and you can turn it off to avoid the unnecessary overhead. To do this, use the "session":http://api.rubyonrails.org/classes/ActionController/SessionManagement/ClassMethods.html#M000649 class method in your controller: +Sometimes you don't need a session, and you can turn it off to avoid the unnecessary overhead. To do this, use the link:http://api.rubyonrails.org/classes/ActionController/SessionManagement/ClassMethods.html#M000649[session] class method in your controller: [source, ruby] ------------------------------------------ @@ -108,7 +108,7 @@ class LoginsController < ApplicationController end ------------------------------------------ -To reset the entire session, use "reset_session":http://api.rubyonrails.org/classes/ActionController/Base.html#M000855 +To reset the entire session, use link:http://api.rubyonrails.org/classes/ActionController/Base.html#M000855[reset_session]. === The flash === diff --git a/railties/doc/guides/actioncontroller/streaming.txt b/railties/doc/guides/actioncontroller/streaming.txt index bca0254f43..41d56935b9 100644 --- a/railties/doc/guides/actioncontroller/streaming.txt +++ b/railties/doc/guides/actioncontroller/streaming.txt @@ -1,6 +1,6 @@ == Streaming and file downloads == -Sometimes you may want to send a file to the user instead of rendering an HTML page. All controllers in Rails have the "send_data":http://api.rubyonrails.org/classes/ActionController/Streaming.html#M000624 and the "send_file":http://api.rubyonrails.org/classes/ActionController/Streaming.html#M000623 methods, that will both stream data to the client. `send_file` is a convenience method which lets you provide the name of a file on the disk and it will stream the contents of that file for you. +Sometimes you may want to send a file to the user instead of rendering an HTML page. All controllers in Rails have the link:http://api.rubyonrails.org/classes/ActionController/Streaming.html#M000624[send_data] and the link:http://api.rubyonrails.org/classes/ActionController/Streaming.html#M000623[send_file] methods, that will both stream data to the client. `send_file` is a convenience method which lets you provide the name of a file on the disk and it will stream the contents of that file for you. To stream data to the client, use `send_data`: diff --git a/railties/doc/guides/actioncontroller/verification.txt b/railties/doc/guides/actioncontroller/verification.txt index 1a4f7a8de5..39046eee85 100644 --- a/railties/doc/guides/actioncontroller/verification.txt +++ b/railties/doc/guides/actioncontroller/verification.txt @@ -1,6 +1,6 @@ == Verification == -Verifications make sure certain criterias are met in order for a controller or action to run. They can specify that a certain key (or several keys in the form of an array) is present in the `params`, `session` or `flash` hashes or that a certain HTTP method was used or that the request was made using XMLHTTPRequest (Ajax). The default action taken when these criterias are not met is to render a 400 Bad Request response, but you can customize this by specifying a redirect URL or rendering something else and you can also add flash messages and HTTP headers to the response. It is described in the "API documentation":http://api.rubyonrails.org/classes/ActionController/Verification/ClassMethods.html as "essentially a special kind of before_filter". +Verifications make sure certain criterias are met in order for a controller or action to run. They can specify that a certain key (or several keys in the form of an array) is present in the `params`, `session` or `flash` hashes or that a certain HTTP method was used or that the request was made using XMLHTTPRequest (Ajax). The default action taken when these criterias are not met is to render a 400 Bad Request response, but you can customize this by specifying a redirect URL or rendering something else and you can also add flash messages and HTTP headers to the response. It is described in the link:http://api.rubyonrails.org/classes/ActionController/Verification/ClassMethods.html[API codumentation] as "essentially a special kind of before_filter". Let's see how we can use verification to make sure the user supplies a username and a password in order to log in: -- cgit v1.2.3