Action Controller
Overview
Ror lab. season 2
- the 15th round -
February 2th, 2013
Hyoseong Choi
A Controller
• RESTful applications
• like an orchestra conductor
• as a middle man btw models and views
REST
GET /books HTTP/1.1
Host: rorlab.org
Accept: application/xml
#index
POST /books HTTP/1.1
Host: rorlab.org
Accept: application/xml
#create
GET /books/1 HTTP/1.1
Host: rorlab.org
Accept: application/xml
#show
PUT /books/1 HTTP/1.1
Host: rorlab.org
Accept: application/xml
#update
GET /books/new HTTP/1.1
Host: rorlab.org
Accept: application/xml
#new
DELETE /books/1 HTTP/1.1
Host: rorlab.org
Accept: application/xml
#destroy
GET /books/1/edit HTTP/1.1
Host: rorlab.org
Accept: application/xml
#edit
URI with HTTP methods
URI?
• Uniform Resource Identifier
= URL + URN
= Uniform Resource Locator
+ Uniform Resource Name
http://domain_name/posts/114
Routing
$ rake routes CONTROLLER=books
books GET /books(.:format) books#index
POST /books(.:format) books#create
new_book GET /books/new(.:format) books#new
edit_book GET /books/:id/edit(.:format) books#edit
book GET /books/:id(.:format) books#show
PUT /books/:id(.:format) books#update
DELETE /books/:id(.:format) books#destroy
named
routes
HTTP
verbs
resource
URI
Controllers
Actions
MVC
MVC
View Model
Controller
Methods & Actions
• A “class” has methods
• A controller < ApplicationController
• public methods => “action” <= routing
$ rake routes CONTROLLER=clients
clients GET /clients(.:format) clients#index
POST /clients(.:format) clients#create
new_client GET /clients/new(.:format) clients#new
edit_client GET /clients/:id/edit(.:format) clients#edit
client GET /clients/:id(.:format) clients#show
PUT /clients/:id(.:format) clients#update
DELETE /clients/:id(.:format) clients#destroy
actions
Parameters
• Two kinds of parameters
- Query string
- POST data
• by params hash for both of these
• “Routing” parameters
Hash & Array Params
GET /clients?ids[]=1&ids[]=2&ids[]=3
params[:ids] ?
[ “1”, “2”, “3”]
for Query String
Hash & Array Params
<form accept-charset="UTF-8" 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>
for POST data
params[:client] ?
{
“name” => “Acme”,
“phone” => “12345”,
“address” => {
“postcode” => “12345”,
“city” => “Carrot City”
}
}
JSON/XML Params
{ "company": { "name": "acme", "address": "123 Carrot Street" } }
JSON parameter
automatically converted to
params hash by Rails
{ :name => “acme”, “address” => “123 Carrot Street” }
params[:company]
default_url_options
➙ global default parameter
class PostsController < ApplicationController
  # The options parameter is the hash passed in to 'url_for'
  def default_url_options(options)
    {:locale => I18n.locale}
  end
end
url_for
<%= url_for(:action => 'index') %>
# => /blog/
<%= url_for(:action => 'find', :controller => 'books') %>
# => /books/find
<%= url_for(:action => 'login', :controller => 'members', :only_path => false, :protocol => 'https') %>
# => https://www.example.com/members/login/
<%= url_for(:action => 'play', :anchor => 'player') %>
# => /messages/play/#player
<%= url_for(:action => 'jump', :anchor => 'tax&ship') %>
# => /testing/jump/#tax&ship
<%= url_for(Workshop.new) %>
# relies on Workshop answering a persisted? call (and in this case returning false)
# => /workshops
<%= url_for(@workshop) %>
# calls @workshop.to_param which by default returns the id
# => /workshops/5
# to_param can be re-defined in a model to provide different URL names:
# => /workshops/1-workshop-name
<%= url_for("http://www.example.com") %>
# => http://www.example.com
<%= url_for(:back) %>
# if request.env["HTTP_REFERER"] is set to "http://www.example.com"
# => http://www.example.com
<%= url_for(:back) %>
# if request.env["HTTP_REFERER"] is not set or is blank
# => javascript:history.back()
Session
• ActionDispatch::Session::CookieStore
• ActionDispatch::Session::CacheStore
• ActionDispatch::Session:: ActiveRecordStore
• ActionDispatch::Session::MemCacheStore
stateless ➤ stateful in controllers
Session Repositories :
class LoginsController < ApplicationController
  # "Create" a login, aka "log the user in"
  def create
    if user = User.authenticate(params[:username], params[:password])
      # Save the user ID in the session so it can be used in
      # subsequent requests
      session[:current_user_id] = user.id
      redirect_to root_url
    end
  end
end
Session
Accessing the Session
lazily loaded
class LoginsController < ApplicationController
  # "Delete" a login, aka "log the user out"
  def destroy
    # Remove the user id from the session
    @_current_user = session[:current_user_id] = nil
    redirect_to root_url
  end
end
Session
Removing a Session Key
cf. reset_session
Session
• special session : Hash
• cleared with each request
• only available in the next request
• useful for storing error messages etc
Flash
a disposable session
redirect_to root_url, notice: "You have successfully logged out."
redirect_to root_url, alert: "You're stuck here!"
redirect_to root_url, flash: { referral_code: 1234 }
Session
Flash
<html>
  <!-- <head/> -->
  <body>
    <% flash.each do |name, msg| -%>
      <%= content_tag :div, msg, class: name %>
    <% end -%>
 
    <!-- more content -->
  </body>
</html>
Session
Flash
<% if flash[:just_signed_up] %>
  <p class="welcome">Welcome to our site!</p>
<% end %>
Session
Flash
class MainController < ApplicationController
  # Let's say this action corresponds to root_url, but you want
  # all requests here to be redirected to UsersController#index.
  # If an action sets the flash and redirects here, the values
  # would normally be lost when another redirect happens, but you
  # can use 'keep' to make it persist for another request.
  def index
    # Will persist all flash values.
    flash.keep
 
    # You can also use a key to keep only some kind of value.
    # flash.keep(:notice)
    redirect_to users_url
  end
end
Session
Flash
flash.keep
class ClientsController < ApplicationController
  def create
    @client = Client.new(params[:client])
    if @client.save
      # ...
    else
      flash.now[:error] = "Could not save client"
      render :action => "new"
    end
  end
end
Session
Flash
flash.now
Cookies
• persisted across request 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
• to delete a cookie value
cookies.delete(:key)
Cookies
xml & json data
class UsersController < ApplicationController
  def index
    @users = User.all
    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @users}
      format.json { render :json => @users}
    end
  end
end
Filters
Action
before after
around
methods inherited
not to halt action
to halt action
Filters
class ApplicationController < ActionController::Base
  before_filter :require_login
 
  private
 
  def require_login
    unless logged_in?
      flash[:error] = "You must be logged in to access this section"
      redirect_to new_login_url # halts request cycle
    end
  end
 
  # The logged_in? method simply returns true if the user is logged
  # in and false otherwise. It does this by "booleanizing" the
  # current_user method we created previously using a double ! operator.
  # Note that this is not common in Ruby and is discouraged unless you
  # really mean to convert something into true or false.
  def logged_in?
    !!current_user
  end
end
booleanizing operator
Filters
class LoginsController < ApplicationController
  skip_before_filter :require_login, :only => [:new, :create]
end
• skip_before_filter
Filters
class ChangesController < ActionController::Base
  around_filter :wrap_in_transaction, :only => :show
 
  private
 
  def wrap_in_transaction
    ActiveRecord::Base.transaction do
      begin
        yield
      ensure
        raise ActiveRecord::Rollback
      end
    end
  end
end
• around_filter
Filters
• Three Ways to use Filters
- a private method
- a block
- a class
Filters
• Using a Block in more simple cases
class ApplicationController < ActionController::Base
  before_filter do |controller|
    redirect_to new_login_url unless controller.send(:logged_in?)
  end
end
Filters
• Using a Class in more complex cases
class ApplicationController < ActionController::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
CSRF
• Site to site hacking
• First step for this
:create/update/destroy with non-GET request
• RESTful default to protect CSRF
• Nevertheless, non-GET request still
vulnerable
CSRF
• To add a non-guessable token with form helpers
<%= form_for @user do |f| %>
  <%= f.text_field :username %>
  <%= f.text_field :password %>
<% end %>
<form accept-charset="UTF-8" action="/users/1"
method="post">
<input type="hidden"
       value="67250ab105eb5ad10851c00a5621854a23af5489"
       name="authenticity_token"/>
<!-- fields -->
</form>
CSRF
• form_authenticity_token in custom Ajax calls
Request & Response
Objects
• Two methods in every controller
- `request` method => request object
- `response` method => response object
Request Objects
Request Objects
• Three hash parameters for request objects
-path_parameters
-query_parameters : query string
-request_parameters : post data
Response Objects
• like in an `after` filter
Response Objects
response.headers["Content-Type"] = "application/pdf"
HTTP
Authentications
HTTP
Authentications
• Two types
- Basic authentication
: using base 64 encoding
- Digest authentication
: using MD5 encoding
HTTP
Authentications
• Basic authentication
class AdminController < ApplicationController
  http_basic_authenticate_with :name => "humbaba", :password => "5baa61e4"
end
HTTP
Authentications
• Digest authentication
class AdminController < ApplicationController
  USERS = { "lifo" => "world" }
 
  before_filter :authenticate
 
  private
 
  def authenticate
    authenticate_or_request_with_http_digest do |username|
      USERS[username]
    end
  end
end
Safari v 6.0.2
undefined method `unpack' for nil:NilClass
Streaming & File
Downloads
require "prawn"
class ClientsController < ApplicationController
  # Generates a PDF document with information on the client and
  # returns it. The user will get the PDF as a file download.
  def download_pdf
    client = Client.find(params[:id])
    send_data generate_pdf(client),
              :filename => "#{client.name}.pdf",
              :type => "application/pdf",
:disposition => "attachement"
  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
send_data
•send_data
•send_file
Streaming & File
Downloads
class ClientsController < ApplicationController
  # Stream a file that has already been generated and stored on disk.
  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
send_file
Streaming & File
Downloads
send_file
in
a
RESTful
application
require "prawn"
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
  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
#153(revised)
Streaming & File
Downloads
send_file
in
a
RESTful
application
• in config/initializer/mime_types.rb
Mime::Type.register "application/pdf", :pdf
Parameter
Filtering
config.filter_parameters << :password
• in config/application.rb
Rescue
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
Force HTTPS
protocol
class DinnerController
  force_ssl
end
class DinnerController
  force_ssl :only => :cheeseburger
  # or
  force_ssl :except => :cheeseburger
end
# Force all access to the app over SSL, use Strict-Transport-
Security, and use secure cookies.
config.force_ssl = true
감사합니다.

Action Controller Overview, Season 2

  • 1.
    Action Controller Overview Ror lab.season 2 - the 15th round - February 2th, 2013 Hyoseong Choi
  • 2.
    A Controller • RESTfulapplications • like an orchestra conductor • as a middle man btw models and views
  • 3.
    REST GET /books HTTP/1.1 Host:rorlab.org Accept: application/xml #index POST /books HTTP/1.1 Host: rorlab.org Accept: application/xml #create GET /books/1 HTTP/1.1 Host: rorlab.org Accept: application/xml #show PUT /books/1 HTTP/1.1 Host: rorlab.org Accept: application/xml #update GET /books/new HTTP/1.1 Host: rorlab.org Accept: application/xml #new DELETE /books/1 HTTP/1.1 Host: rorlab.org Accept: application/xml #destroy GET /books/1/edit HTTP/1.1 Host: rorlab.org Accept: application/xml #edit URI with HTTP methods
  • 4.
    URI? • Uniform ResourceIdentifier = URL + URN = Uniform Resource Locator + Uniform Resource Name http://domain_name/posts/114
  • 5.
    Routing $ rake routesCONTROLLER=books books GET /books(.:format) books#index POST /books(.:format) books#create new_book GET /books/new(.:format) books#new edit_book GET /books/:id/edit(.:format) books#edit book GET /books/:id(.:format) books#show PUT /books/:id(.:format) books#update DELETE /books/:id(.:format) books#destroy named routes HTTP verbs resource URI Controllers Actions
  • 6.
  • 7.
  • 8.
    Methods & Actions •A “class” has methods • A controller < ApplicationController • public methods => “action” <= routing $ rake routes CONTROLLER=clients clients GET /clients(.:format) clients#index POST /clients(.:format) clients#create new_client GET /clients/new(.:format) clients#new edit_client GET /clients/:id/edit(.:format) clients#edit client GET /clients/:id(.:format) clients#show PUT /clients/:id(.:format) clients#update DELETE /clients/:id(.:format) clients#destroy actions
  • 9.
    Parameters • Two kindsof parameters - Query string - POST data • by params hash for both of these • “Routing” parameters
  • 10.
    Hash & ArrayParams GET /clients?ids[]=1&ids[]=2&ids[]=3 params[:ids] ? [ “1”, “2”, “3”] for Query String
  • 11.
    Hash & ArrayParams <form accept-charset="UTF-8" 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> for POST data params[:client] ? { “name” => “Acme”, “phone” => “12345”, “address” => { “postcode” => “12345”, “city” => “Carrot City” } }
  • 12.
    JSON/XML Params { "company":{ "name": "acme", "address": "123 Carrot Street" } } JSON parameter automatically converted to params hash by Rails { :name => “acme”, “address” => “123 Carrot Street” } params[:company]
  • 13.
    default_url_options ➙ global defaultparameter class PostsController < ApplicationController   # The options parameter is the hash passed in to 'url_for'   def default_url_options(options)     {:locale => I18n.locale}   end end
  • 14.
    url_for <%= url_for(:action =>'index') %> # => /blog/ <%= url_for(:action => 'find', :controller => 'books') %> # => /books/find <%= url_for(:action => 'login', :controller => 'members', :only_path => false, :protocol => 'https') %> # => https://www.example.com/members/login/ <%= url_for(:action => 'play', :anchor => 'player') %> # => /messages/play/#player <%= url_for(:action => 'jump', :anchor => 'tax&ship') %> # => /testing/jump/#tax&ship <%= url_for(Workshop.new) %> # relies on Workshop answering a persisted? call (and in this case returning false) # => /workshops <%= url_for(@workshop) %> # calls @workshop.to_param which by default returns the id # => /workshops/5 # to_param can be re-defined in a model to provide different URL names: # => /workshops/1-workshop-name <%= url_for("http://www.example.com") %> # => http://www.example.com <%= url_for(:back) %> # if request.env["HTTP_REFERER"] is set to "http://www.example.com" # => http://www.example.com <%= url_for(:back) %> # if request.env["HTTP_REFERER"] is not set or is blank # => javascript:history.back()
  • 15.
    Session • ActionDispatch::Session::CookieStore • ActionDispatch::Session::CacheStore •ActionDispatch::Session:: ActiveRecordStore • ActionDispatch::Session::MemCacheStore stateless ➤ stateful in controllers Session Repositories :
  • 16.
    class LoginsController <ApplicationController   # "Create" a login, aka "log the user in"   def create     if user = User.authenticate(params[:username], params[:password])       # Save the user ID in the session so it can be used in       # subsequent requests       session[:current_user_id] = user.id       redirect_to root_url     end   end end Session Accessing the Session lazily loaded
  • 17.
    class LoginsController <ApplicationController   # "Delete" a login, aka "log the user out"   def destroy     # Remove the user id from the session     @_current_user = session[:current_user_id] = nil     redirect_to root_url   end end Session Removing a Session Key cf. reset_session
  • 18.
    Session • special session: Hash • cleared with each request • only available in the next request • useful for storing error messages etc Flash a disposable session
  • 19.
    redirect_to root_url, notice:"You have successfully logged out." redirect_to root_url, alert: "You're stuck here!" redirect_to root_url, flash: { referral_code: 1234 } Session Flash
  • 20.
    <html>   <!-- <head/> -->   <body>     <%flash.each do |name, msg| -%>       <%= content_tag :div, msg, class: name %>     <% end -%>       <!-- more content -->   </body> </html> Session Flash
  • 21.
    <% if flash[:just_signed_up]%>   <p class="welcome">Welcome to our site!</p> <% end %> Session Flash
  • 22.
    class MainController <ApplicationController   # Let's say this action corresponds to root_url, but you want   # all requests here to be redirected to UsersController#index.   # If an action sets the flash and redirects here, the values   # would normally be lost when another redirect happens, but you   # can use 'keep' to make it persist for another request.   def index     # Will persist all flash values.     flash.keep       # You can also use a key to keep only some kind of value.     # flash.keep(:notice)     redirect_to users_url   end end Session Flash flash.keep
  • 23.
    class ClientsController <ApplicationController   def create     @client = Client.new(params[:client])     if @client.save       # ...     else       flash.now[:error] = "Could not save client"       render :action => "new"     end   end end Session Flash flash.now
  • 24.
    Cookies • persisted acrossrequest 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
  • 25.
    • to deletea cookie value cookies.delete(:key) Cookies
  • 26.
    xml & jsondata class UsersController < ApplicationController   def index     @users = User.all     respond_to do |format|       format.html # index.html.erb       format.xml  { render :xml => @users}       format.json { render :json => @users}     end   end end
  • 27.
  • 28.
    Filters class ApplicationController <ActionController::Base   before_filter :require_login     private     def require_login     unless logged_in?       flash[:error] = "You must be logged in to access this section"       redirect_to new_login_url # halts request cycle     end   end     # The logged_in? method simply returns true if the user is logged   # in and false otherwise. It does this by "booleanizing" the   # current_user method we created previously using a double ! operator.   # Note that this is not common in Ruby and is discouraged unless you   # really mean to convert something into true or false.   def logged_in?     !!current_user   end end booleanizing operator
  • 29.
    Filters class LoginsController <ApplicationController   skip_before_filter :require_login, :only => [:new, :create] end • skip_before_filter
  • 30.
    Filters class ChangesController <ActionController::Base   around_filter :wrap_in_transaction, :only => :show     private     def wrap_in_transaction     ActiveRecord::Base.transaction do       begin         yield       ensure         raise ActiveRecord::Rollback       end     end   end end • around_filter
  • 31.
    Filters • Three Waysto use Filters - a private method - a block - a class
  • 32.
    Filters • Using aBlock in more simple cases class ApplicationController < ActionController::Base   before_filter do |controller|     redirect_to new_login_url unless controller.send(:logged_in?)   end end
  • 33.
    Filters • Using aClass in more complex cases class ApplicationController < ActionController::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
  • 34.
    CSRF • Site tosite hacking • First step for this :create/update/destroy with non-GET request • RESTful default to protect CSRF • Nevertheless, non-GET request still vulnerable
  • 35.
    CSRF • To adda non-guessable token with form helpers <%= form_for @user do |f| %>   <%= f.text_field :username %>   <%= f.text_field :password %> <% end %> <form accept-charset="UTF-8" action="/users/1" method="post"> <input type="hidden"        value="67250ab105eb5ad10851c00a5621854a23af5489"        name="authenticity_token"/> <!-- fields --> </form>
  • 36.
  • 37.
    Request & Response Objects •Two methods in every controller - `request` method => request object - `response` method => response object
  • 38.
  • 39.
    Request Objects • Threehash parameters for request objects -path_parameters -query_parameters : query string -request_parameters : post data
  • 40.
    Response Objects • likein an `after` filter
  • 41.
  • 42.
  • 43.
    HTTP Authentications • Two types -Basic authentication : using base 64 encoding - Digest authentication : using MD5 encoding
  • 44.
    HTTP Authentications • Basic authentication classAdminController < ApplicationController   http_basic_authenticate_with :name => "humbaba", :password => "5baa61e4" end
  • 45.
    HTTP Authentications • Digest authentication classAdminController < ApplicationController   USERS = { "lifo" => "world" }     before_filter :authenticate     private     def authenticate     authenticate_or_request_with_http_digest do |username|       USERS[username]     end   end end Safari v 6.0.2 undefined method `unpack' for nil:NilClass
  • 46.
    Streaming & File Downloads require"prawn" class ClientsController < ApplicationController   # Generates a PDF document with information on the client and   # returns it. The user will get the PDF as a file download.   def download_pdf     client = Client.find(params[:id])     send_data generate_pdf(client),               :filename => "#{client.name}.pdf",               :type => "application/pdf", :disposition => "attachement"   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 send_data •send_data •send_file
  • 47.
    Streaming & File Downloads classClientsController < ApplicationController   # Stream a file that has already been generated and stored on disk.   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 send_file
  • 48.
    Streaming & File Downloads send_file in a RESTful application require"prawn" 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   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 #153(revised)
  • 49.
    Streaming & File Downloads send_file in a RESTful application •in config/initializer/mime_types.rb Mime::Type.register "application/pdf", :pdf
  • 50.
  • 51.
    Rescue 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
  • 52.
    Force HTTPS protocol class DinnerController   force_ssl end classDinnerController   force_ssl :only => :cheeseburger   # or   force_ssl :except => :cheeseburger end # Force all access to the app over SSL, use Strict-Transport- Security, and use secure cookies. config.force_ssl = true
  • 53.