segunda-feira, 2 de dezembro de 2013

Ruby on Rails-Action Controoler Overview

====
   Based on guides.rubyonrails.org


Controller is the C from MVC
Controller Name
                Preferable in plural: ClientsController
Methods and Actions
                Normal ruby class the inherits from ApplicationController
                Ex  /clients/new:
                               class ClientsController < ApplicationController
                                 def new
                                               @client = Client.new
                                 end
                               end       
Parameters
                Rails doesn't make any distinction between GET or POST parameters
                # In the example:
                def create
                    @client = Client.new(params[:client])
                    if @client.save
                      redirect_to @client
                    else
                      # This line overrides the default rendering behavior, which
                      # would have been to render the "create" view.
                      render "new"
                    end
                end
                # Values came from
           <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>
                             

                JSON parameters
                               If working with JSON, Rails convert automatically the parameters in parms hash.
Routing parameters
                Hash params always contains :controller and :action keys
Strong parameters
                Action Controller parameters can be used in Active Model mass assigments only after they pass through another method(whitelisted).  The params will be chosen to be exposed.
                Ex:
                               class PeopleController < ActionController::Base
                                               def update
                                                   person = current_account.people.find(params[:id])
                                                   person.update_attributes!(person_params)
                                                               redirect_to person
                                                               end
                                                               private
                                   def person_params
                                     params.require(:person).permit(:name, :age)
                                   end
                               end
Session
                Kinds of session:
                               ActionDispatch::Session::CookieStore - Stores everything on the client.
                               ActionDispatch::Session::CacheStore - Stores the data in the Rails cache.
                               ActionDispatch::Session::ActiveRecordStore - Stores the data in a database using Active Record. (require activerecord-session_store gem).
                               ActionDispatch::Session::MemCacheStore - Stores the data in a memcached cluster

                If you need a different session storage mechanism, you can change it in the config/initializers/session_store.rb file.
                ex:
                               RomaMoneyRails::Application.config.session_store :cookie_store, key: '_romaMoneyRails_session', domain: ".example.com"
                               #domain is optional
                CookieStore used for signing the session data
                               Can be changed in  config/initializers/secret_token.rb:
                               EX, create a random value:
                                               require 'securerandom'

                                               def secure_token
                                                 token_file = Rails.root.join('.secret')
                                                 if File.exist?(token_file)
                                                   # Use the existing token.
                                                   File.read(token_file).chomp
                                                 else
                                                   # Generate a new token and store it in token_file.
                                                   token = SecureRandom.hex(64)
                                                   File.write(token_file, token)
                                                   token
                                                 end
                                               end
                                               RomaMoneyRails::Application.config.secret_key_base = secure_token
                Accessing Session
                               def current_user
                                   @_current_user ||= session[:current_user_id] &&
                                     User.find_by(id: session[:current_user_id])
                               end

                               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                                      

                               To reset the intire session:
                                               reset_session
                Flash
                               Special part of session that is cleared in each request. It will available only in the next request.              
                               Ex:
                                               flash[:notice] = "You have successfully logged out."
Cookie
                To store cookie is similar to Session
                # Remember the commenter's name.
    cookies[:commenter_name] = @comment.author
Render xml and JSON data

                class UsersController < ApplicationController
                  def index
                    @users = User.all
                    respond_to do |format|
                      format.html # index.html.erb
                      format.xml  { render xml: @users} # automatically invokes @users.to_xml
                      format.json { render json: @users}
                    end
                  end
                end
Render JSON with JavaScript
                 @user = User.first
                 respond_to do |format|
                               format.html { redirect_to root_url }
                               format.js
     end
     Should have a file js.erb with the same name of the action
Filter
                Runs before, after or "arround" the controller action
                There are different ways to access Filters, but these are the most known ones
                before_action
                Ex:
                               class ApplicationController < ActionController::Base
                                                 before_action :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
                                               end

                                               - this will be run on every controller
                               Ex of before_action for user_controller.rb
                                               before_action :signed_in_user,
                only: [:index, :edit, :update, :destroy, :change_to_this, :change_account, :change_account_ajax]
                                               before_action :correct_user,   only: [:edit, :update]
                                               before_action :admin_user,     only: :destroy

                               Skiping before for some methods
                                               class LoginsController < ApplicationController
                                                 skip_before_action :require_login, only: [:new, :create]
                                               end
                after_action
                               After is similar to before. 
                               Has access to response.
                               Can't stop the action
                arround_action
                               Run the associated actions by yielding
Request Forgery Protection
                First step to protect destructive actions from forgery it prohibit GET requests(REST already does this)
Request and Response objects
                Request Object
                               query_parameters - sent as part of the query string
                               request_parameters - sent as part of the post body
                               path_parameters - parameters that were recognized by the routing as being part of the path leading to this particular controller and action.
                Response Object
                               response.headers["Content-Type"] = "application/pdf"
HTTP Authentications
                Basic Authentication
                               Very simple
                               class AdminsController < ApplicationController
                                 http_basic_authenticate_with name: "humbaba", password: "5baa61e4"
                               end
                Digest Authentication
                                only requires using one method, authenticate_or_request_with_http_digest
Streaming and File Downloads
                send_data
                               To stream data to the client, use send_data:
                               Ex:
                                               #Generate a stream and send it
                                               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"
                                                 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
                               To send a file
                               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") #default=application/octet-stream
                                 end
                               end

                               It read 4kb at time avoid loading the entire file to memory at once.  It can be configure.
                RESTFUL download
                               First include in config/initializers/mime_types.rb:
                                               Mime::Type.register "application/pdf", :pdf

                               class ClientsController < ApplicationController
                                 # The user can request to receive this resource as HTML or PDF.
                                 def show
                                   @client = Client.find(params[:id])
                                
                                   respond_to do |format|
                                     format.html
                                     format.pdf { render pdf: generate_pdf(@client) }
                                   end
                                 end
                               end
Log Filtering
                Uses a log file
Rescue
                Useful to send a specific exception to a page
                ex:
                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

Force ssl
                In config/environments/production.rb
                               # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
                               config.force_ssl = true
                Of for a specific action and controller
                class DinnerController
                                 force_ssl only: :cheeseburger
                                 # or
                                 force_ssl except: :cheeseburger

                               end

Nenhum comentário:

Postar um comentário