Skip to content
Browse files

Merge branch 'master' of git@github.com:lifo/docrails

  • Loading branch information...
2 parents 224060a + b4da5f6 commit 3979d267522f9aaef92b5f21a65abab5046cefaa @radar radar committed Oct 9, 2008
View
5 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 <tt>Base#save</tt> call:
+ # the <tt>Base#save</tt> call for a new record:
#
# * (-) <tt>save</tt>
# * (-) <tt>valid</tt>
@@ -22,7 +22,8 @@ module ActiveRecord
# * (8) <tt>after_save</tt>
#
# 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 <tt>Base#save</tt> an existing record is similar, except that each
+ # <tt>_on_create</tt> callback is replaced by the corresponding <tt>_on_update</tt> callback.
#
# Examples:
# class CreditCard < ActiveRecord::Base
View
4 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[]
View
30 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
View
23 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]
---------------------------------
@@ -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:
@@ -115,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].
View
2 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]
-------------------------------------
View
2 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.
View
2 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]
----------------------------------------------
View
2 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 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]
-------------------------
View
4 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:
-------------------------------------
-<form action="/clients">
+<form action="/clients" method="post">
<input type="text" name="client[name]" value="Acme" />
<input type="text" name="client[phone]" value="12345" />
<input type="text" name="client[address][postcode]" value="12345" />
View
4 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").
View
117 railties/doc/guides/actioncontroller/rescue.txt
@@ -1,3 +1,118 @@
== Rescue ==
-Describe how to use rescue_from et al to rescue exceptions in controllers.
+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 ===
+
+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 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.
+
+[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 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 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]
+----------------------------------------
+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
+----------------------------------------
View
72 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 link:http://api.rubyonrails.org/classes/ActionController/SessionManagement/ClassMethods.html#M000649[session] 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 link:http://api.rubyonrails.org/classes/ActionController/Base.html#M000855[reset_session].
=== 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]
------------------------------------------
-<!-- head, etc -->
-<body>
- <% if flash[:notice] -%>
- <p class="notice"><%= flash[:notice] %></p>
- <% end -%>
- <% if flash[:error] -%>
- <p class="error"><%= flash[:error] %></p>
- <% end -%>
- <!-- more content -->
-</body>
+<html>
+ <!-- <head/> -->
+ <body>
+ <% if flash[:notice] -%>
+ <p class="notice"><%= flash[:notice] %></p>
+ <% end -%>
+ <% if flash[:error] -%>
+ <p class="error"><%= flash[:error] %></p>
+ <% end -%>
+ <!-- more content -->
+ </body>
</html>
------------------------------------------
View
10 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`:
@@ -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]
----------------------------
View
39 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 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:
+
+[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
+---------------------------------------
View
18 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 +<image>+ 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:
View
20 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:

0 comments on commit 3979d26

Please sign in to comment.
Something went wrong with that request. Please try again.