Your SlideShare is downloading. ×
0
×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Action Controller Overview, Season 2

3,039

Published on

Published in: Education
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,039
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
20
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  1. Ror lab. season 2 - the 15th round -Action Controller Overview February 2th, 2013 Hyoseong Choi
  2. A Controller• RESTful applications• like an orchestra conductor• as a middle man btw models and views
  3. REST URI with HTTP methods#index #new #edit GET /books HTTP/1.1 GET /books/new HTTP/1.1 GET /books/1/edit HTTP/1.1 Host: rorlab.org Host: rorlab.org Host: rorlab.org Accept: application/xml Accept: application/xml Accept: application/xml#show #create #update GET /books/1 HTTP/1.1 POST /books HTTP/1.1 PUT /books/1 HTTP/1.1 Host: rorlab.org Host: rorlab.org Host: rorlab.org Accept: application/xml Accept: application/xml Accept: application/xml #destroy DELETE /books/1 HTTP/1.1 Host: rorlab.org Accept: application/xml
  4. URI? http://domain_name/posts/114• Uniform Resource Identifier = URL + URN = Uniform Resource Locator + Uniform Resource Name
  5. Routing$ rake routes CONTROLLER=books books GET /books(.:format) books#index POST /books(.:format) books#create new_book GET /books/new(.:format) books#newedit_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 HTTP resource Controllers routes verbs URI Actions
  6. MVC
  7. MVC Controller View Model
  8. Methods & Actions• A “class” has methods• A controller < ApplicationController• public methods => “action” <= routing actions $ 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
  9. Parameters• Two kinds of parameters - Query string - POST data• by params hash for both of these• “Routing” parameters
  10. Hash & Array Params for Query String GET /clients?ids[]=1&ids[]=2&ids[]=3 params[:ids] ? [ “1”, “2”, “3”]
  11. Hash & Array Params for POST data<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> { “name” => “Acme”, “phone” => “12345”,params[:client] ? “address” => { “postcode” => “12345”, “city” => “Carrot City” } }
  12. JSON/XML ParamsJSON parameter{ "company": { "name": "acme", "address": "123 Carrot Street" } } automatically converted to params hash by Railsparams[:company]{ :name => “acme”, “address” => “123 Carrot Street” }
  13. 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
  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 stateless ➤ stateful in controllersSession Repositories :• ActionDispatch::Session::CookieStore• ActionDispatch::Session::CacheStore• ActionDispatch::Session:: ActiveRecordStore• ActionDispatch::Session::MemCacheStore
  16. Session Accessing the Session lazily loadedclass 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  endend
  17. Session Removing a Session Keyclass 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  endendcf. reset_session
  18. Session Flash a disposable session• special session : Hash• cleared with each request• only available in the next request• useful for storing error messages etc
  19. Session Flashredirect_to root_url, notice: "You have successfully logged out."redirect_to root_url, alert: "Youre stuck here!"redirect_to root_url, flash: { referral_code: 1234 }
  20. Session Flash<html>  <!-- <head/> -->  <body>    <% flash.each do |name, msg| -%>      <%= content_tag :div, msg, class: name %>    <% end -%>     <!-- more content -->  </body></html>
  21. Session Flash<% if flash[:just_signed_up] %>  <p class="welcome">Welcome to our site!</p><% end %>
  22. Session Flash flash.keepclass MainController < ApplicationController  # Lets 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  endend
  23. Session Flash flash.nowclass ClientsController < ApplicationController  def create    @client = Client.new(params[:client])    if @client.save      # ...    else      flash.now[:error] = "Could not save client"      render :action => "new"    end  endend
  24. Cookies• persisted across request and even sessions class CommentsController < ApplicationController   def new     # Auto-fill the commenters 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 commenters name.         cookies[:commenter_name] = @comment.name       else         # Delete cookie for the commenters name cookie, if any.         cookies.delete(:commenter_name)       end       redirect_to @comment.article     else       render :action => "new"     end   end end
  25. Cookies• to delete a cookie value cookies.delete(:key)
  26. xml & json dataclass 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  endend
  27. Filters methods inherited before Action afterto halt action not to halt action around
  28. Filtersclass 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  endend booleanizing operator
  29. Filters• skip_before_filter class LoginsController < ApplicationController   skip_before_filter :require_login, :only => [:new, :create] end
  30. Filters• around_filter 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
  31. Filters• Three Ways to use Filters - a private method - a block - a class
  32. 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
  33. 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
  34. CSRF• Site to site hacking• First step for this with non-GET request :create/update/destroy• RESTful default to protect CSRF• Nevertheless, non-GET request still vulnerable
  35. 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>
  36. CSRF• form_authenticity_token in custom Ajax calls
  37. Request & Response Objects• Two methods in every controller - `request` method => request object - `response` method => response object
  38. Request Objects
  39. Request Objects• Three hash parameters for request objects - path_parameters - query_parameters : query string - request_parameters : post data
  40. Response Objects• like in an `after` filter
  41. Response Objects response.headers["Content-Type"] = "application/pdf"
  42. HTTPAuthentications
  43. HTTP Authentications• Two types - Basic authentication : using base 64 encoding - Digest authentication : using MD5 encoding
  44. HTTP Authentications• Basic authentication class AdminController < ApplicationController   http_basic_authenticate_with :name => "humbaba", :password => "5baa61e4" end
  45. 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
  46. Streaming & File Downloads•send_data•send_file 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
  47. Streaming & File Downloadsclass 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")  endend send_file
  48. Streaming & File Downloadsin a RESTful application #153(revised) 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 send_file
  49. Streaming & File Downloads • in config/initializer/mime_types.rbin a RESTful application Mime::Type.register "application/pdf", :pdf send_file
  50. Parameter Filtering• in config/application.rbconfig.filter_parameters << :password
  51. Rescueclass ApplicationController < ActionController::Base  rescue_from User::NotAuthorized, :with => :user_not_authorized   private   def user_not_authorized    flash[:error] = "You dont have access to this section."    redirect_to :back  endend class ClientsController < ApplicationController  # Check that the user has the right authorization to access clients.  before_filter :check_authorization   # Note how the actions dont 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?  endend
  52. Force HTTPS protocolclass DinnerController  force_sslendclass DinnerController  force_ssl :only => :cheeseburger  # or  force_ssl :except => :cheeseburgerend # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. config.force_ssl = true
  53. 감사합니다.
  54.  

×