`
sillycat
  • 浏览: 2488255 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Rails Study(11)Action Controller Overviews - Cookies

阅读更多
Rails Study(11)Action Controller Overviews - Cookies

5. Cookies
You application can store small amounts of data on the client ----cookies, that will be persisted across requests and even sessions.

class CommentsController < ApplicationController
def new
  @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]
    cookies[:commenter_name] = @comment.name
   else
    cookies-delete(:commenter_name)
   end
   redirect_to @comment.article
  else
   render :action => "new"
  end
end
end

To delete a cookie value, we need to use cookies.delete(:key)

6 Rendering xml and json data
class UsersController < ApplicationController
def index
  @users = User.all
  respond_to do |format|
   format.html
   format.xml { renderml = > @users }
   format.json { render json: @users }
  end
end
end

Notice that in the above case code is renderml => @users and not renderml => @users.to_xml. That is because if the input is not string then rails automatically invokes to_xml.

7 Filters
Filters are methods that are run before, after or "around" a controller action.

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

A common before filter is one which requires that a user is logged in for an action to be run.

class ApplicationController < ActiveController::Base
before_filter :require_login

private

def require_logn
  unless logged_in?
   flash[:error] = "You must be logged in to access this section"
   redirect_to new_login_url
  end
end

def logged_in?
  !!current_user
end
end

!! is to convert something into true or false.

If a before filter renders or redirects, the action will not run. If there are additional filters scheduled to run after that filter they are also cancelled.

You can prevent this filter from running before particular actions with skip_before_filter:

class LoginsController < ApplicationController
skip_before_filter :reqire_login,nly => [:new, :create]
end

Thenly option is used to only skip this filter for these actions, and there is also an :except option which works the other way.

7.1 After Filters and Around Filters
Obviousl, after filters can not stop the action from running.

7.2 Other Ways to Use Filters
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 rewritten to use a block:

class ApplicationController < ActionController::Base
before_filter do |controller|
  redirect_to new_login_url unless controller.send(:logged_in?)
end
end

Note that the filter in this case uses send because the logged_in? method is private and the filter is not run in the scope of the controller.

Use a class to rewrite the login filter.

class ApplicationController < ActionControlller::Base
before_filter LoginFilter
end

class LoginFilter
def self.filter(controller)
  unless controller.send(:logged_in?)
   controller.flash[:error] = "you must be logged in"
   controller.redirect_to controller.new_login_url
  end
end
end

method will came after :, but class came after directly the *_filter keywords.

8. 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 i 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 make using XMLHttpRequest(AJAX).

The default action taken when these criteria are not met is to render a 400 Bad Request response.

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

There is something rather import 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 thenly and :except options just like a filter.

class LoginsController < ApplicationController
verify :params => [:username, :password],
         :render => {:action => "new"},
         :add_flash => {
:error => "username and password required to log in"
         },
        nly => :create
end

9 Request Forgery Protection
Cross-site request forgery is a type of attack in which a site tricks a user into making requests on another site.

1. make sure all "desructive" actions (create, update and destroy) can only be accessed with non-GET requests.
2. Add a non-guessable token which is only known to your server to each request. If a request comes in without the proper token, it will be denied access.

erb forms as follow:
<%= form_for @user do |f| %>
<%= f.text_field :username %>
<%= f.text_field :password %>
<% end %>

I got this in my form
<input name="authenticity_token" type="hidden" value="CKcVLfMFYxIEwOzEUMg4DK5VAY43Li/LhoQKypela70=" />

This is available through the method form_authenticity_token.

10. The Request and Response Objects
10.1 The request Object
There are some properties of request object.
host ------------------The hostname used for this request
domain(n=2)-------
format ---------------The content type requested by the client
method--------------
get?, post?, put?, delete?,head?
-------------------------Returns true if the HTTP method is GET/POST/PUT/DELETE/HEAD
headers--------------
port-------------------
protocol-------------Returns a string containing the protocol used plus "://", for example "http://"
query_string-------
remote_ip --------- The IP address of the client
url -------------------- The entire URL used for the request.

10.1.1 path_parameters, query_parameters, and request_parameters

10.2 The response Object
Properties of response
body ------------- This is the string of data being sent back to the client.
status ------------ The HTTP status code for the response, like 200 for a successful request or 404 for file not found.
location ---------- The URL the client is being redirected to, if any
content_type--- The content type of the response
charset ----------- The character set being used for the response. Default is "utf-8".
headers ----------

10.2.1 Setting Custom Headers
response.headers["Content-Type"] = "application/pdf"

11 HTTP Authentications
Rails comes with two built-in HTTP authentication mechanisms:
Basic Authentication
Digest Authentication

11.1 HTTP Basic Authentication
In my sample project, I have the experiences

  before_filter :authenticate, :except => [:index, :show]
  before_filter :authenticate,nly => :destroy

And authenticate in my ApplicationController

  private    
 
  def authenticate      
    authenticate_or_request_with_http_basic do |user_name, password|      
      user_name == 'admin' && password == 'password'  
    end
  end

Certainly, we can try to encode the password Digest::SHA1.hexdigest(password).

11.2 HTTP Digest Authentication
USERS = { "life" => "world" }
authenticate_or_request_with_http_digest do |username|
  USERS[username]
end

12 Streaming and File Downloads
Sometimes we want to send a file instead of rendering an HTML page.

send_file is a convennience method that lets you provide the name of a file on the disk.

To stream data to the client, use send_data.

require "prawn"
class ClientsController < ApplicationController
def download_pdf
  client = Client.find(params[:id])
  send_data generate_pdf(client),
                 :filename => "#{client.name}.pdf",
                 :type => "application/pdf"
  end

  private

  def generate_pdf(client)
   Prawn::Document.new do
    text client.name, :align => :center
    text "Address: #{client.address}"
    text "Email: #{client.email}}"
   end.render
  end
end

The download_pdf action above will generate the PDF document and returns it as a string. This string will then be streamed to the client as a file download and a filename will be suggested to the user.

12.1 Sending Files
Use send_file method to send a file that already exists on disk.

class ClientsController < ApplicationController
def download_pdf
  client = Client.find(params[:id])
  send_file("#{Rails.root}/files/clients/#{client.id}.pdf",
               :filename => "#{client.name}.pdf",
               :type => "application/pdf")
end
end

12.2 RESTful Downloads
class ClientsController < ApplicationController
def show
  @client = Client.find(params[:id])
 
  respond_to do |format|
   format.html
   format.pdf { render :pdf => generate_pdf(@client) }
  end
end
end

In order to make this work, we need to add the PDF MIME type of Rails. This can be done by adding the following line to the file
config/initializers/mime_types.rb:
Mime::Type.register "application/pdf", :pdf

Notices, configuration files are not reloaded on each request, so we need to restart the server.

13 Parameter Filtering
14 Rescue
14.1 The Default 500 and 404 Templates
These HTML files are in the public folder, 404.html and 500.html.

14.2 rescue_from

references:
http://guides.rubyonrails.org/action_controller_overview.html
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics