一个action的process过程

ruby 代码
 
  1. def process(request, response, method = :perform_action, *arguments) #:nodoc:  
  2.    initialize_template_class(response)  
  3.    assign_shortcuts(request, response)  
  4.    initialize_current_url  
  5.    assign_names  
  6.    forget_variables_added_to_assigns  
  7.   
  8.    log_processing  
  9.    send(method, *arguments) #这一步调用perform_action方法,并且传入arguments数组作为参数(虽然perform_action不需要参数)  
  10.   
  11.    assign_default_content_type_and_charset  
  12.   
  13.    response.request = request  
  14.    response.prepare! unless component_request?  
  15.    response  
  16.  ensure  
  17.    process_cleanup  
  18.  end  
step 1:
初始化视图模板类
java 代码
 
  1. def initialize_template_class(response)  
  2.   raise "You must assign a template class through ActionController.template_class= before processing a request" unless @@template_class  
  3.   
  4.   response.template = ActionView::Base.new(view_paths, {}, self) #注意,ActionView这个时候出现了,传入本controller对应的view模板的路径  
  5.   response.template.extend self.class.master_helper_module  
  6.   response.redirected_to = nil  
  7.   @performed_render = @performed_redirect = false #标记render和redirect事件都没有发生  
  8. end  

step 2:
ruby 代码
 
  1. def assign_shortcuts(request, response)  
  2.   @_request@_params@_cookies = request, request.parameters, request.cookies  
  3.   
  4.   @_response         = response  
  5.   @_response.session = request.session  
  6.   
  7.   @_session = @_response.session  
  8.   @template = @_response.template  
  9.   @assigns  = @_response.template.assigns  
  10.   
  11.   @_headers = @_response.headers  
  12. end  

step 3:
ruby 代码
 
  1. def initialize_current_url  
  2.   @url = UrlRewriter.new(request, params.clone)  
  3. end  

step 4:
经过了这一步,就可以通过调用action_name来获得action的名称
ruby 代码
 
  1. def assign_names  
  2.    @action_name = (params['action'] || 'index') #取得当前action的名称,如果没有指定action,则默认action为index  
  3.  end  

step 5:
ruby 代码
 
  1. def forget_variables_added_to_assigns  
  2.   @variables_added = nil  
  3. end  


step 6:
ruby 代码
 
  1. def log_processing  
  2.   if logger  
  3.     logger.info "\n\nProcessing #{controller_class_name}\##{action_name} (for #{request_origin}) [#{request.method.to_s.upcase}]"  
  4.     logger.info "  Session ID: #{@_session.session_id}" if @_session and @_session.respond_to?(:session_id)  
  5.     logger.info "  Parameters: #{respond_to?(:filter_parameters) ? filter_parameters(params).inspect : params.inspect}"  
  6.   end  
  7. end  

step 7:
ruby 代码
 
  1. 默认对待一个请求的方式是perform_action  
  2. 可以看到对待一个action,rails的处理方式是:  
  3. 1。假设action存在,则执行action代码,如果action代码内没有调用过render方法,就调用render方法  
  4. 2。如果action不存在,则查找method_missing方法,若方法存在,调用之,如果action代码内没有调用过render方法,就调用render方法  
  5. 3。如果视图模板存在而且模板是public的,则直接调用render方法渲染  
  6. 4。以上都不满足,抛出UnkownAction异常。  
  7.       def perform_action  
  8.         if self.class.action_methods.include?(action_name)  
  9.           send(action_name)  
  10.           render unless performed?  
  11.         elsif respond_to? :method_missing  
  12.           send(:method_missing, action_name)  
  13.           render unless performed?  
  14.         elsif template_exists? && template_public?  
  15.           render  
  16.         else  
  17.           raise UnknownAction, "No action responded to #{action_name}", caller  
  18.         end  
  19.       end  
  20.   
  21.       def action_methods  
  22.         self.class.action_methods  
  23.       end  
  24.   
  25.       def self.action_methods  
  26.         @action_methods ||= Set.new(public_instance_methods - hidden_actions)  
  27.       end  

step 8:
ruby 代码
 
  1. step 8:  
  2.       def assign_default_content_type_and_charset  
  3.         response.content_type ||= Mime::HTML  
  4.         response.charset      ||= self.class.default_charset unless sending_file?  
  5.       end  
  6.   
  7. 最后,一个process完成后返回一个response  
  8.   
  9. 由这个process过程引出的,顺便简单看一下render方法  
  10.       def render(options = nil, &block) #:doc:  
  11.         raise DoubleRenderError, "Can only render or redirect once per action" if performed?  
  12.   
  13.     #可以看出来,在响应action的过程中,如果没有在action中使用过render方法,实际上每次默认都是调用render_for_file方法  
  14.     #参数中使用default_template_name方法获得与当前action同名的视图模板的相对路径  
  15.         if options.nil?  
  16.           return render_for_file(default_template_name, niltrue)  
  17.         else  
  18.     #render的参数只能是:update或者一个hash  
  19.           if options == :update  
  20.             options = { :update => true }  
  21.           elsif !options.is_a?(Hash)  
  22.             raise RenderError, "You called render with invalid options : #{options}"  
  23.           end  
  24.         end  
  25.   
  26.         if content_type = options[:content_type]  
  27.           response.content_type = content_type.to_s  
  28.         end  
  29.   
  30.         if location = options[:location]  
  31.           response.headers["Location"] = url_for(location)  
  32.         end  
  33.   
  34.     指定不同的渲染方式  
  35.         if text = options[:text]  
  36.           render_for_text(text, options[:status])  
  37.   
  38.         else  
  39.           if file = options[:file]  
  40.             render_for_file(file, options[:status], options[:use_full_path], options[:locals] || {})  
  41.   
  42.           elsif template = options[:template]  
  43.             render_for_file(template, options[:status], true)  
  44.   
  45.           elsif inline = options[:inline]  
  46.             add_variables_to_assigns  
  47.             render_for_text(@template.render_template(options[:type] || :erb, inline, nil, options[:locals] || {}), options[:status])  
  48.   
  49.     #当在action中显式调用render方式时会执行到此分支  
  50.           elsif action_name = options[:action]  
  51.             template = default_template_name(action_name.to_s)  
  52.     #根据:layout来决定调用那个方法  
  53.             if options[:layout] && !template_exempt_from_layout?(template)  
  54.               render_with_a_layout(:file => template, :status => options[:status], :use_full_path => true:layout => true)                
  55.             else  
  56.               render_with_no_layout(:file => template, :status => options[:status], :use_full_path => true)  
  57.             end              
  58.   
  59.           elsif xml = options[:xml]  
  60.             response.content_type = Mime::XML  
  61.             render_for_text(xml.respond_to?(:to_xml) ? xml.to_xml : xml, options[:status])  
  62.   
  63.           elsif json = options[:json]  
  64.             json = "#{options[:callback]}(#{json})" unless options[:callback].blank?  
  65.             response.content_type = Mime::JSON  
  66.             render_for_text(json, options[:status])  
  67.   
  68.           elsif partial = options[:partial]  
  69.             partial = default_template_name if partial == true  
  70.             add_variables_to_assigns  
  71.   
  72.             if collection = options[:collection]  
  73.               render_for_text(  
  74.                 @template.send(:render_partial_collection, partial, collection,   
  75.                 options[:spacer_template], options[:locals]), options[:status]  
  76.               )  
  77.             else  
  78.               render_for_text(  
  79.                 @template.send(:render_partial, partial,   
  80.                 ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]), options[:status]  
  81.               )  
  82.             end  
  83.   
  84.           elsif options[:update]  
  85.             add_variables_to_assigns  
  86.             @template.send :evaluate_assigns  
  87.   
  88.             generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(@template, &block)  
  89.             response.content_type = Mime::JS  
  90.             render_for_text(generator.to_s)  
  91.   
  92.           elsif options[:nothing]  
  93.             # Safari doesn't pass the headers of the return if the response is zero length  
  94.             render_for_text(" ", options[:status])  
  95.   
  96.           else  
  97.             render_for_file(default_template_name, options[:status], true)  
  98.           end  
  99.         end  
  100.       end  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值