guides.rubyonrails.org 读书笔记(三)

    技术2022-05-20  36

    Action Controller Overview

    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.

     

    1. Methods and Actions

     

    A controller is a Ruby class which inherits from ApplicationController and has methods just like any other class. controller初始化过程:When your application receives a request, the routing will determine which controller and action to run, then Rails creates an instance of that controller and runs the method with the same name as the action.

     

    Note that the empty method from the example above could work just fine because Rails will by default render the new.html.erb view unless the action says otherwise.

    Only public methods are callable as actions. It is a best practice to lower the visibility of methods which are not intended to be actions, like auxiliary methods or filters.

     

    2. Parameters

    You will probably want to access data sent in by the user or other parameters in your controller actions. There are two kinds of parameters possible in a web application. The first are parameters that are sent as part of the URL , called query string parameters. The query string is everything after “?” in the URL . The second type of parameter is usually referred to as POST data. This information usually comes from an HTML form which has been filled in by the user. It’s called POST data because it can only be sent as part of an HTTP POST request. Rails does not make any distinction between query string parameters and POST parameters, and both are available in the params hash in your controller.

     

    2.1 Hash and Array Parameters

    The params hash is not limited to one-dimensional keys and values. It can contain arrays and (nested) hashes.

    There are two types:

    (1).  GET /clients?ids[]=1&ids[]=2&ids[]=3

    (2).

    < 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" />    < input type = "text" name = "client[address][city]" value = "Carrot City" /> </ form > Note that parameter values are always strings; Rails makes no attempt to guess or cast the type.

    Note that the params hash is actually an instance of HashWithIndifferentAccess from Active Support, which acts like a hash that lets you use symbols and strings interchangeably as keys.

     

    2.2 Routing Parameters

     

    The params hash will always contain the :controller and :action keys, but you should use the methods controller_name and action_name instead to access these values.

     

    2.3 default_url_options

    进一步分析实际作用

     

    3.  Session

    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 the view and can use one of a number of different storage mechanisms:

    CookieStore – Stores everything on the client.DRbStore – Stores the data on a DRb server.MemCacheStore – Stores the data in a memcache.ActiveRecordStore – Stores the data in a database using Active Record.

    3.1 Accessing the Session

     

     

    3.2  The Flash

     

    The flash is a special part of the session which is cleared with each request. This means that values stored there will only be available in the next request, which is useful for storing error messages etc.

     

    3.2.1 using flash normally

    flash[ :notice ] = "You have successfully logged out"

    Note it is also possible to assign a flash message as part of the redirection.

    redirect_to root_url, :notice => "You have successfully logged out"

     

    If you want a flash value to be carried over to another request, use the keep method:

    flash.keep

     

    3.2.2 flash now

    By default, adding values to the flash will make them available to the next request, but sometimes you may want to access those values in the same request . For example, if the create action fails to save a resource and you render the new template directly, that’s not going to result in a new request, but you may still want to display a message using the flash. 注意了,render是不产生new or next request的,所以需要:

    flash.now[ :error ] = "Could not save client"

           render :action => "new"

     

    4. Cookies

     

    Your application can store small amounts of data on the client — called cookies — that will be persisted across requests and even sessions.

    class CommentsController < ApplicationController   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 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         # Delete cookie for the commenter's name cookie, if any.         cookies.delete(:commenter_name)       end       redirect_to @comment.article     else       render :action => "new"     end   end end

     

    Note that while for session values you set the key to nil , to delete a cookie value you should use cookies.delete(:key) .

     

    5.  Rendering xml and json data

     

    6.  Filters

     

    Filters are methods that are run before, after or “around” a controller action. 常见于阻止action 运行,终止action运行等

    Filters are inherited, so if you set a filter on ApplicationController , it will be run on every controller in your application.

    (1) "Before filters" may halt the request cycle.

    before_filter :require_login

    skip_before_filter :require_login , :only => [ :new , :create ]

    (2) After Filters and Around Filters

     

    6.2 Other Ways to Use Filters

     

    7. Verification

     

    Verifications make sure certain criteria 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 criteria 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.

     

    8. Request Forgery Protection

    class LoginsController < ApplicationController

      verify :params => [:username, :password],          :render => {:action => "new"},          :add_flash => {            :error => "Username and password required to log in"          }

     

    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:

     

     

    9. Request Forgery Protection

    The first step to avoid this is to make sure all “destructive” actions (create, update and destroy) can only be accessed with non-GET requests. If you’re following RESTful conventions you’re already doing this.

     

    The form_authenticity_token generates a valid authentication token. That’s useful in places where Rails does not add it automatically, like in custom Ajax calls.

     

     

    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 and the response method returns a response object representing what is going to be sent back to the client.

     

     

    10.1

    Rails collects all of the parameters sent along with the request in the params hash, whether they are sent as part of the query string or the post body. The request object has three accessors that give you access to these parameters depending on where they came from.

     

     

    10.2 The response Object

    The response object is not usually used directly, but is built up during the execution of the action and rendering of the data that is being sent back to the user, but sometimes – like in an after filter – it can be useful to access the response directly.

     

     

    11. HTTP Authentications

     

    Rails comes with two built-in HTTP authentication mechanisms:

    Basic AuthenticationDigest Authentication

    11.1  Basic Authentication

     

    Using the built-in authentication is quite easy and only requires you to use one method, authenticate_or_request_with_http_basic .

    ???Digest:: SHA1 .hexdigest(password) == PASSWORD

     

    一个设计思路:

    With this in place, you can create namespaced controllers that inherit from AdminController . The before filter will thus be run for all actions in those controllers, protecting them with HTTP basic authentication.

     

     

    11.2  Digest Authentication

    具体使用场合和使用方法,需要了解

     

     

    12. 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 and the send_file methods, which will both stream data to the client.

     

    12.1  Send.data

     

    12.2  Sending Files

     

    12.3  RESTful Downloads

    Rails provides an easy and quite sleek way of doing “RESTful downloads”.

     

     

    设计要点:

    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. Although if you do need the request to go through Rails for some reason, you can set the :x_sendfile option to true, and Rails will let the web server handle sending the file to the user, freeing up the Rails process to do other things. Note that your web server needs to support the X-Sendfile header for this to work.

     

    13. Parameter Filtering

    The filter_parameter_logging method can be used to filter out sensitive information from the log. It works by replacing certain values in the params hash with “[FILTERED ]” as they are written to the log.

     

    14. Rescue

     

    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:

     

    14.1 The Default 500 and 404 Templates

     

    14.2 rescue_from

     

    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.

     

     

    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

     

    工作流程:

     

    (1)rescue_from自动直接地捕获exception,When an exception occurs which is caught by a rescue_from directive

    上例是User::NotAuthorized; 被父类 的rescue_from捕获;

    (2)the exception object is passed to the handle

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     


    最新回复(0)